mohamedhuggig commited on
Commit
f71cc05
·
verified ·
1 Parent(s): 2e8be6e

Update database.py

Browse files
Files changed (1) hide show
  1. database.py +235 -235
database.py CHANGED
@@ -1,236 +1,236 @@
1
- import sys
2
- import os
3
- sys.stdout.reconfigure(encoding='utf-8')
4
-
5
- from sqlalchemy import create_engine, Column, Integer, String, Text, DateTime, ForeignKey, JSON, Float, Boolean, Date
6
- from sqlalchemy.orm import declarative_base, sessionmaker, relationship
7
- from datetime import datetime
8
- from passlib.context import CryptContext
9
-
10
- import os
11
-
12
- # ✅ التعديل هنا: استخدام SQLite افتراضياً للتشغيل المحلي
13
- SQLALCHEMY_DATABASE_URL = os.getenv("DATABASE_URL", "sqlite:///./blueprint.db")
14
-
15
- # دعم كل من PostgreSQL و SQLite
16
- if SQLALCHEMY_DATABASE_URL.startswith("postgresql"):
17
- engine = create_engine(SQLALCHEMY_DATABASE_URL)
18
- else:
19
- # SQLite يحتاج connect_args
20
- engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False})
21
-
22
- SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
23
- Base = declarative_base()
24
-
25
- pwd_context = CryptContext(schemes=["sha256_crypt"], deprecated="auto")
26
-
27
- # ---------- نماذج المستخدمين والصلاحيات ----------
28
- class User(Base):
29
- __tablename__ = "users"
30
- id = Column(Integer, primary_key=True, index=True)
31
- username = Column(String, unique=True, index=True, nullable=False)
32
- email = Column(String, unique=True, index=True, nullable=False)
33
- hashed_password = Column(String, nullable=False)
34
- full_name = Column(String)
35
- role = Column(String, default="viewer") # admin, engineer, viewer
36
- is_active = Column(Boolean, default=True)
37
- created_at = Column(DateTime, default=datetime.utcnow)
38
-
39
- projects = relationship("ProjectUser", back_populates="user")
40
-
41
- class ProjectUser(Base):
42
- __tablename__ = "project_users"
43
- id = Column(Integer, primary_key=True)
44
- project_id = Column(Integer, ForeignKey("projects.id"))
45
- user_id = Column(Integer, ForeignKey("users.id"))
46
- permission = Column(String, default="read") # read, write, admin
47
-
48
- user = relationship("User", back_populates="projects")
49
- project = relationship("Project", back_populates="users")
50
-
51
- # ---------- المشاريع ----------
52
- class Project(Base):
53
- __tablename__ = "projects"
54
- id = Column(Integer, primary_key=True, index=True)
55
- name = Column(String, nullable=False, index=True)
56
- location = Column(String, nullable=True)
57
- created_at = Column(DateTime, default=datetime.utcnow)
58
-
59
- analyses = relationship("Analysis", back_populates="project", cascade="all, delete-orphan")
60
- site_reports = relationship("SiteReport", back_populates="project", cascade="all, delete-orphan")
61
- boq_items = relationship("BOQItem", back_populates="project", cascade="all, delete-orphan")
62
- files = relationship("UploadedFile", back_populates="project", cascade="all, delete-orphan")
63
- defects = relationship("Defect", back_populates="project", cascade="all, delete-orphan")
64
- users = relationship("ProjectUser", back_populates="project", cascade="all, delete-orphan")
65
- site_visits = relationship("SiteVisit", back_populates="project", cascade="all, delete-orphan")
66
- memory_entries = relationship("MemoryEntry", back_populates="project", cascade="all, delete-orphan")
67
- workflows = relationship("Workflow", back_populates="project", cascade="all, delete-orphan")
68
- tasks = relationship("Task", back_populates="project", cascade="all, delete-orphan") # NEW
69
-
70
- # ---------- التحليلات ----------
71
- class Analysis(Base):
72
- __tablename__ = "analyses"
73
- id = Column(Integer, primary_key=True, index=True)
74
- project_id = Column(Integer, ForeignKey("projects.id"), index=True)
75
- task_type = Column(String)
76
- input_text = Column(Text)
77
- result_json = Column(JSON)
78
- safety_status = Column(String, default="Pending")
79
- created_at = Column(DateTime, default=datetime.utcnow, index=True)
80
- project = relationship("Project", back_populates="analyses")
81
-
82
- class SiteReport(Base):
83
- __tablename__ = "site_reports"
84
- id = Column(Integer, primary_key=True, index=True)
85
- project_id = Column(Integer, ForeignKey("projects.id"))
86
- report_date = Column(DateTime, default=datetime.utcnow)
87
- weather = Column(String)
88
- workers_count = Column(Integer)
89
- summary = Column(Text)
90
- issues = Column(Text)
91
- created_at = Column(DateTime, default=datetime.utcnow)
92
- project = relationship("Project", back_populates="site_reports")
93
-
94
- # ---------- حصر الكميات ----------
95
- class BOQItem(Base):
96
- __tablename__ = "boq_items"
97
- id = Column(Integer, primary_key=True, index=True)
98
- project_id = Column(Integer, ForeignKey("projects.id"), index=True)
99
- description = Column(String)
100
- unit = Column(String)
101
- quantity = Column(Float)
102
- unit_price = Column(Float)
103
- total_price = Column(Float)
104
- project = relationship("Project", back_populates="boq_items")
105
-
106
- # ---------- الملفات المرفوعة ----------
107
- class UploadedFile(Base):
108
- __tablename__ = "uploaded_files"
109
- id = Column(Integer, primary_key=True, index=True)
110
- project_id = Column(Integer, ForeignKey("projects.id"), index=True)
111
- filename = Column(String)
112
- file_type = Column(String)
113
- file_path = Column(String)
114
- analyzed = Column(Boolean, default=False)
115
- created_at = Column(DateTime, default=datetime.utcnow)
116
- project = relationship("Project", back_populates="files")
117
-
118
- # ---------- العيوب ----------
119
- class Defect(Base):
120
- __tablename__ = "defects"
121
- id = Column(Integer, primary_key=True, index=True)
122
- project_id = Column(Integer, ForeignKey("projects.id"), index=True)
123
- description = Column(Text)
124
- severity = Column(String) # High, Medium, Low
125
- status = Column(String, default="Open") # Open, Resolved
126
- image_id = Column(Integer, ForeignKey("uploaded_files.id"), nullable=True)
127
- assigned_to = Column(Integer, ForeignKey("users.id"), nullable=True)
128
- created_at = Column(DateTime, default=datetime.utcnow)
129
- project = relationship("Project", back_populates="defects")
130
- assignee = relationship("User", foreign_keys=[assigned_to])
131
-
132
- # ---------- إعدادات المشروع ----------
133
- class ProjectSettings(Base):
134
- __tablename__ = "project_settings"
135
- id = Column(Integer, primary_key=True, index=True)
136
- project_id = Column(Integer, ForeignKey("projects.id"), unique=True, index=True)
137
- concrete_price = Column(Float, default=1000.0)
138
- steel_price = Column(Float, default=35000.0)
139
- preferred_ai_model = Column(String, default="gemini")
140
- created_at = Column(DateTime, default=datetime.utcnow)
141
- project = relationship("Project", backref="settings", uselist=False)
142
-
143
- # ---------- زيارات الموقع ----------
144
- class SiteVisit(Base):
145
- __tablename__ = "site_visits"
146
- id = Column(Integer, primary_key=True, index=True)
147
- project_id = Column(Integer, ForeignKey("projects.id"), index=True)
148
- visit_date = Column(DateTime, default=datetime.utcnow)
149
- location_name = Column(String, nullable=True)
150
- latitude = Column(Float, nullable=True)
151
- longitude = Column(Float, nullable=True)
152
- notes = Column(Text, nullable=True)
153
- created_by = Column(Integer, ForeignKey("users.id"), nullable=True)
154
- created_at = Column(DateTime, default=datetime.utcnow)
155
-
156
- project = relationship("Project", back_populates="site_visits")
157
- creator = relationship("User", foreign_keys=[created_by])
158
- images = relationship("SiteVisitImage", back_populates="site_visit", cascade="all, delete-orphan")
159
-
160
- class SiteVisitImage(Base):
161
- __tablename__ = "site_visit_images"
162
- id = Column(Integer, primary_key=True, index=True)
163
- site_visit_id = Column(Integer, ForeignKey("site_visits.id"), index=True)
164
- image_path = Column(String)
165
- caption = Column(String, nullable=True)
166
- timestamp = Column(DateTime, nullable=True)
167
- latitude = Column(Float, nullable=True)
168
- longitude = Column(Float, nullable=True)
169
- created_at = Column(DateTime, default=datetime.utcnow)
170
-
171
- site_visit = relationship("SiteVisit", back_populates="images")
172
-
173
- # ---------- الذاكرة طويلة المدى ----------
174
- class MemoryEntry(Base):
175
- __tablename__ = "memory_entries"
176
- id = Column(Integer, primary_key=True, index=True)
177
- project_id = Column(Integer, ForeignKey("projects.id"), index=True)
178
- entry_type = Column(String) # decision, pattern, context, progress
179
- title = Column(String)
180
- content = Column(Text)
181
- tags = Column(String) # مفصول بفواصل
182
- created_at = Column(DateTime, default=datetime.utcnow)
183
- updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
184
-
185
- project = relationship("Project", back_populates="memory_entries")
186
-
187
- # ---------- سير العمل الآلي ----------
188
- class Workflow(Base):
189
- __tablename__ = "workflows"
190
- id = Column(Integer, primary_key=True, index=True)
191
- project_id = Column(Integer, ForeignKey("projects.id"), index=True)
192
- name = Column(String)
193
- trigger_event = Column(String) # image_upload, defect_created, design_completed
194
- action_type = Column(String) # notify, create_defect, update_boq, send_message
195
- action_params = Column(JSON)
196
- is_active = Column(Boolean, default=True)
197
- created_at = Column(DateTime, default=datetime.utcnow)
198
-
199
- project = relationship("Project", back_populates="workflows")
200
-
201
- class WorkflowLog(Base):
202
- __tablename__ = "workflow_logs"
203
- id = Column(Integer, primary_key=True, index=True)
204
- workflow_id = Column(Integer, ForeignKey("workflows.id"))
205
- triggered_by = Column(String)
206
- status = Column(String) # success, failed
207
- result = Column(JSON)
208
- created_at = Column(DateTime, default=datetime.utcnow)
209
-
210
- workflow = relationship("Workflow")
211
-
212
- # ---------- المهام (NEW) ----------
213
- class Task(Base):
214
- __tablename__ = "tasks"
215
- id = Column(Integer, primary_key=True, index=True)
216
- project_id = Column(Integer, ForeignKey("projects.id"), index=True)
217
- description = Column(String, nullable=False)
218
- assignee = Column(String, nullable=False)
219
- due_date = Column(Date, nullable=False)
220
- priority = Column(String, nullable=False) # منخفضة، متوسطة، عالية
221
- status = Column(String, default="قيد الانتظار") # قيد الانتظار، جاري، منتهية
222
- created_at = Column(DateTime, default=datetime.utcnow)
223
- updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
224
-
225
- project = relationship("Project", back_populates="tasks")
226
-
227
- # ---------- دالة تهيئة قاعدة البيانات ----------
228
- def init_db():
229
- Base.metadata.create_all(bind=engine)
230
-
231
- # ---------- دوال مساعدة للمستخدمين ----------
232
- def get_password_hash(password):
233
- return pwd_context.hash(password)
234
-
235
- def verify_password(plain_password, hashed_password):
236
  return pwd_context.verify(plain_password, hashed_password)
 
1
+ import sys
2
+ import os
3
+ sys.stdout.reconfigure(encoding='utf-8')
4
+
5
+ from sqlalchemy import create_engine, Column, Integer, String, Text, DateTime, ForeignKey, JSON, Float, Boolean, Date
6
+ from sqlalchemy.orm import declarative_base, sessionmaker, relationship
7
+ from datetime import datetime
8
+ from passlib.context import CryptContext
9
+
10
+ import os
11
+
12
+ # ✅ التعديل هنا: استخدام SQLite افتراضياً للتشغيل المحلي
13
+ SQLALCHEMY_DATABASE_URL = os.getenv("DATABASE_URL", "sqlite:///./blueprint.db")
14
+
15
+ # دعم كل من PostgreSQL و SQLite
16
+ if SQLALCHEMY_DATABASE_URL.startswith("postgresql"):
17
+ engine = create_engine(SQLALCHEMY_DATABASE_URL)
18
+ else:
19
+ # SQLite يحتاج connect_args
20
+ engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False})
21
+
22
+ SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
23
+ Base = declarative_base()
24
+
25
+ pwd_context = CryptContext(schemes=["sha256_crypt"], deprecated="auto")
26
+
27
+ # ---------- نماذج المستخدمين والصلاحيات ----------
28
+ class User(Base):
29
+ __tablename__ = "users"
30
+ id = Column(Integer, primary_key=True, index=True)
31
+ username = Column(String, unique=True, index=True, nullable=False)
32
+ email = Column(String, unique=True, index=True, nullable=False)
33
+ hashed_password = Column(String, nullable=False)
34
+ full_name = Column(String)
35
+ role = Column(String, default="viewer") # admin, engineer, viewer
36
+ is_active = Column(Boolean, default=True)
37
+ created_at = Column(DateTime, default=datetime.utcnow)
38
+
39
+ projects = relationship("ProjectUser", back_populates="user")
40
+
41
+ class ProjectUser(Base):
42
+ __tablename__ = "project_users"
43
+ id = Column(Integer, primary_key=True)
44
+ project_id = Column(Integer, ForeignKey("projects.id"))
45
+ user_id = Column(Integer, ForeignKey("users.id"))
46
+ permission = Column(String, default="read") # read, write, admin
47
+
48
+ user = relationship("User", back_populates="projects")
49
+ project = relationship("Project", back_populates="users")
50
+
51
+ # ---------- المشاريع ----------
52
+ class Project(Base):
53
+ __tablename__ = "projects"
54
+ id = Column(Integer, primary_key=True, index=True)
55
+ name = Column(String, nullable=False, index=True)
56
+ location = Column(String, nullable=True)
57
+ created_at = Column(DateTime, default=datetime.utcnow)
58
+
59
+ analyses = relationship("Analysis", back_populates="project", cascade="all, delete-orphan")
60
+ site_reports = relationship("SiteReport", back_populates="project", cascade="all, delete-orphan")
61
+ boq_items = relationship("BOQItem", back_populates="project", cascade="all, delete-orphan")
62
+ files = relationship("UploadedFile", back_populates="project", cascade="all, delete-orphan")
63
+ defects = relationship("Defect", back_populates="project", cascade="all, delete-orphan")
64
+ users = relationship("ProjectUser", back_populates="project", cascade="all, delete-orphan")
65
+ site_visits = relationship("SiteVisit", back_populates="project", cascade="all, delete-orphan")
66
+ memory_entries = relationship("MemoryEntry", back_populates="project", cascade="all, delete-orphan")
67
+ workflows = relationship("Workflow", back_populates="project", cascade="all, delete-orphan")
68
+ tasks = relationship("Task", back_populates="project", cascade="all, delete-orphan") # NEW
69
+
70
+ # ---------- التحليلات ----------
71
+ class Analysis(Base):
72
+ __tablename__ = "analyses"
73
+ id = Column(Integer, primary_key=True, index=True)
74
+ project_id = Column(Integer, ForeignKey("projects.id"), index=True)
75
+ task_type = Column(String)
76
+ input_text = Column(Text)
77
+ result_json = Column(JSON)
78
+ safety_status = Column(String, default="Pending")
79
+ created_at = Column(DateTime, default=datetime.utcnow, index=True)
80
+ project = relationship("Project", back_populates="analyses")
81
+
82
+ class SiteReport(Base):
83
+ __tablename__ = "site_reports"
84
+ id = Column(Integer, primary_key=True, index=True)
85
+ project_id = Column(Integer, ForeignKey("projects.id"))
86
+ report_date = Column(DateTime, default=datetime.utcnow)
87
+ weather = Column(String)
88
+ workers_count = Column(Integer)
89
+ summary = Column(Text)
90
+ issues = Column(Text)
91
+ created_at = Column(DateTime, default=datetime.utcnow)
92
+ project = relationship("Project", back_populates="site_reports")
93
+
94
+ # ---------- حصر الكميات ----------
95
+ class BOQItem(Base):
96
+ __tablename__ = "boq_items"
97
+ id = Column(Integer, primary_key=True, index=True)
98
+ project_id = Column(Integer, ForeignKey("projects.id"), index=True)
99
+ description = Column(String)
100
+ unit = Column(String)
101
+ quantity = Column(Float)
102
+ unit_price = Column(Float)
103
+ total_price = Column(Float)
104
+ project = relationship("Project", back_populates="boq_items")
105
+
106
+ # ---------- الملفات المرفوعة ----------
107
+ class UploadedFile(Base):
108
+ __tablename__ = "uploaded_files"
109
+ id = Column(Integer, primary_key=True, index=True)
110
+ project_id = Column(Integer, ForeignKey("projects.id"), index=True)
111
+ filename = Column(String)
112
+ file_type = Column(String)
113
+ file_path = Column(String)
114
+ analyzed = Column(Boolean, default=False)
115
+ created_at = Column(DateTime, default=datetime.utcnow)
116
+ project = relationship("Project", back_populates="files")
117
+
118
+ # ---------- العيوب ----------
119
+ class Defect(Base):
120
+ __tablename__ = "defects"
121
+ id = Column(Integer, primary_key=True, index=True)
122
+ project_id = Column(Integer, ForeignKey("projects.id"), index=True)
123
+ description = Column(Text)
124
+ severity = Column(String) # High, Medium, Low
125
+ status = Column(String, default="Open") # Open, Resolved
126
+ image_id = Column(Integer, ForeignKey("uploaded_files.id"), nullable=True)
127
+ assigned_to = Column(Integer, ForeignKey("users.id"), nullable=True)
128
+ created_at = Column(DateTime, default=datetime.utcnow)
129
+ project = relationship("Project", back_populates="defects")
130
+ assignee = relationship("User", foreign_keys=[assigned_to])
131
+
132
+ # ---------- إعدادات المشروع ----------
133
+ class ProjectSettings(Base):
134
+ __tablename__ = "project_settings"
135
+ id = Column(Integer, primary_key=True, index=True)
136
+ project_id = Column(Integer, ForeignKey("projects.id"), unique=True, index=True)
137
+ concrete_price = Column(Float, default=1000.0)
138
+ steel_price = Column(Float, default=35000.0)
139
+ preferred_ai_model = Column(String, default="gemini")
140
+ created_at = Column(DateTime, default=datetime.utcnow)
141
+ project = relationship("Project", backref="settings", uselist=False)
142
+
143
+ # ---------- زيارات الموقع ----------
144
+ class SiteVisit(Base):
145
+ __tablename__ = "site_visits"
146
+ id = Column(Integer, primary_key=True, index=True)
147
+ project_id = Column(Integer, ForeignKey("projects.id"), index=True)
148
+ visit_date = Column(DateTime, default=datetime.utcnow)
149
+ location_name = Column(String, nullable=True)
150
+ latitude = Column(Float, nullable=True)
151
+ longitude = Column(Float, nullable=True)
152
+ notes = Column(Text, nullable=True)
153
+ created_by = Column(Integer, ForeignKey("users.id"), nullable=True)
154
+ created_at = Column(DateTime, default=datetime.utcnow)
155
+
156
+ project = relationship("Project", back_populates="site_visits")
157
+ creator = relationship("User", foreign_keys=[created_by])
158
+ images = relationship("SiteVisitImage", back_populates="site_visit", cascade="all, delete-orphan")
159
+
160
+ class SiteVisitImage(Base):
161
+ __tablename__ = "site_visit_images"
162
+ id = Column(Integer, primary_key=True, index=True)
163
+ site_visit_id = Column(Integer, ForeignKey("site_visits.id"), index=True)
164
+ image_path = Column(String)
165
+ caption = Column(String, nullable=True)
166
+ timestamp = Column(DateTime, nullable=True)
167
+ latitude = Column(Float, nullable=True)
168
+ longitude = Column(Float, nullable=True)
169
+ created_at = Column(DateTime, default=datetime.utcnow)
170
+
171
+ site_visit = relationship("SiteVisit", back_populates="images")
172
+
173
+ # ---------- الذاكرة طويلة المدى ----------
174
+ class MemoryEntry(Base):
175
+ __tablename__ = "memory_entries"
176
+ id = Column(Integer, primary_key=True, index=True)
177
+ project_id = Column(Integer, ForeignKey("projects.id"), index=True)
178
+ entry_type = Column(String) # decision, pattern, context, progress
179
+ title = Column(String)
180
+ content = Column(Text)
181
+ tags = Column(String) # مفصول بفواصل
182
+ created_at = Column(DateTime, default=datetime.utcnow)
183
+ updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
184
+
185
+ project = relationship("Project", back_populates="memory_entries")
186
+
187
+ # ---------- سير العمل الآلي ----------
188
+ class Workflow(Base):
189
+ __tablename__ = "workflows"
190
+ id = Column(Integer, primary_key=True, index=True)
191
+ project_id = Column(Integer, ForeignKey("projects.id"), index=True)
192
+ name = Column(String)
193
+ trigger_event = Column(String) # image_upload, defect_created, design_completed
194
+ action_type = Column(String) # notify, create_defect, update_boq, send_message
195
+ action_params = Column(JSON)
196
+ is_active = Column(Boolean, default=True)
197
+ created_at = Column(DateTime, default=datetime.utcnow)
198
+
199
+ project = relationship("Project", back_populates="workflows")
200
+
201
+ class WorkflowLog(Base):
202
+ __tablename__ = "workflow_logs"
203
+ id = Column(Integer, primary_key=True, index=True)
204
+ workflow_id = Column(Integer, ForeignKey("workflows.id"))
205
+ triggered_by = Column(String)
206
+ status = Column(String) # success, failed
207
+ result = Column(JSON)
208
+ created_at = Column(DateTime, default=datetime.utcnow)
209
+
210
+ workflow = relationship("Workflow")
211
+
212
+ # ---------- المهام (NEW) ----------
213
+ class Task(Base):
214
+ __tablename__ = "tasks"
215
+ id = Column(Integer, primary_key=True, index=True)
216
+ project_id = Column(Integer, ForeignKey("projects.id"), index=True)
217
+ description = Column(String, nullable=False)
218
+ assignee = Column(String, nullable=False)
219
+ due_date = Column(Date, nullable=False)
220
+ priority = Column(String, nullable=False) # منخفضة، متوسطة، عالية
221
+ status = Column(String, default="قيد الانتظار") # قيد الانتظار، جاري، منتهية
222
+ created_at = Column(DateTime, default=datetime.utcnow)
223
+ updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
224
+
225
+ project = relationship("Project", back_populates="tasks")
226
+
227
+ # ---------- دالة تهيئة قاعدة البيانات ----------
228
+ def init_db():
229
+ Base.metadata.create_all(bind=engine)
230
+
231
+ # ---------- دوال مساعدة للمستخدمين ----------
232
+ def get_password_hash(password):
233
+ return pwd_context.hash(password)
234
+
235
+ def verify_password(plain_password, hashed_password):
236
  return pwd_context.verify(plain_password, hashed_password)