kamau1 commited on
Commit
2fc3d0f
·
1 Parent(s): 215c34c

chore(models): add missing model stubs and fix INET import to restore profile API startup

Browse files
docs/hflogs/runtimeerror.txt CHANGED
@@ -1,4 +1,4 @@
1
- ===== Application Startup at 2025-11-16 00:14:51 =====
2
 
3
  Traceback (most recent call last):
4
  File "/usr/local/bin/uvicorn", line 8, in <module>
@@ -35,6 +35,8 @@ Traceback (most recent call last):
35
  File "/usr/local/lib/python3.11/site-packages/uvicorn/config.py", line 467, in load
36
  self.loaded_app = import_from_string(self.app)
37
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 
38
  File "/usr/local/lib/python3.11/site-packages/uvicorn/importer.py", line 21, in import_from_string
39
  module = importlib.import_module(module_str)
40
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -51,10 +53,62 @@ Traceback (most recent call last):
51
  from app.api.v1.router import api_router
52
  File "/app/src/app/api/v1/router.py", line 5, in <module>
53
  from app.api.v1 import auth, clients, contractors, invitations, profile
54
- File "/app/src/app/api/v1/auth.py", line 14, in <module>
55
- from app.services.audit_service import AuditService
56
- File "/app/src/app/services/audit_service.py", line 9, in <module>
57
- from app.models.audit_log import AuditLog
58
- File "/app/src/app/models/audit_log.py", line 4, in <module>
59
- from sqlalchemy import Column, String, Text, INET
60
- ImportError: cannot import name 'INET' from 'sqlalchemy' (/usr/local/lib/python3.11/site-packages/sqlalchemy/__init__.py)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ===== Application Startup at 2025-11-16 00:17:04 =====
2
 
3
  Traceback (most recent call last):
4
  File "/usr/local/bin/uvicorn", line 8, in <module>
 
35
  File "/usr/local/lib/python3.11/site-packages/uvicorn/config.py", line 467, in load
36
  self.loaded_app = import_from_string(self.app)
37
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
38
+ File "/usr/local/lib/python3.11/site-packages/uvicorn/importer.py", line 24, in import_from_string
39
+ raise exc from None
40
  File "/usr/local/lib/python3.11/site-packages/uvicorn/importer.py", line 21, in import_from_string
41
  module = importlib.import_module(module_str)
42
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
53
  from app.api.v1.router import api_router
54
  File "/app/src/app/api/v1/router.py", line 5, in <module>
55
  from app.api.v1 import auth, clients, contractors, invitations, profile
56
+ File "/app/src/app/api/v1/profile.py", line 12, in <module>
57
+ from app.models.user_financial_account import UserFinancialAccount
58
+ ModuleNotFoundError: No module named 'app.models.user_financial_account'
59
+ Traceback (most recent call last):
60
+ File "/usr/local/bin/uvicorn", line 8, in <module>
61
+ sys.exit(main())
62
+ ^^^^^^
63
+ File "/usr/local/lib/python3.11/site-packages/click/core.py", line 1485, in __call__
64
+ return self.main(*args, **kwargs)
65
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^
66
+ File "/usr/local/lib/python3.11/site-packages/click/core.py", line 1406, in main
67
+ rv = self.invoke(ctx)
68
+ ^^^^^^^^^^^^^^^^
69
+ File "/usr/local/lib/python3.11/site-packages/click/core.py", line 1269, in invoke
70
+ return ctx.invoke(self.callback, **ctx.params)
71
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
72
+ File "/usr/local/lib/python3.11/site-packages/click/core.py", line 824, in invoke
73
+ return callback(*args, **kwargs)
74
+ ^^^^^^^^^^^^^^^^^^^^^^^^^
75
+ File "/usr/local/lib/python3.11/site-packages/uvicorn/main.py", line 416, in main
76
+ run(
77
+ File "/usr/local/lib/python3.11/site-packages/uvicorn/main.py", line 587, in run
78
+ server.run()
79
+ File "/usr/local/lib/python3.11/site-packages/uvicorn/server.py", line 61, in run
80
+ return asyncio.run(self.serve(sockets=sockets))
81
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
82
+ File "/usr/local/lib/python3.11/asyncio/runners.py", line 190, in run
83
+ return runner.run(main)
84
+ ^^^^^^^^^^^^^^^^
85
+ File "/usr/local/lib/python3.11/asyncio/runners.py", line 118, in run
86
+ return self._loop.run_until_complete(task)
87
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
88
+ File "uvloop/loop.pyx", line 1518, in uvloop.loop.Loop.run_until_complete
89
+ File "/usr/local/lib/python3.11/site-packages/uvicorn/server.py", line 68, in serve
90
+ config.load()
91
+ File "/usr/local/lib/python3.11/site-packages/uvicorn/config.py", line 467, in load
92
+ self.loaded_app = import_from_string(self.app)
93
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
94
+ File "/usr/local/lib/python3.11/site-packages/uvicorn/importer.py", line 24, in import_from_string
95
+ raise exc from None
96
+ File "/usr/local/lib/python3.11/site-packages/uvicorn/importer.py", line 21, in import_from_string
97
+ module = importlib.import_module(module_str)
98
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
99
+ File "/usr/local/lib/python3.11/importlib/__init__.py", line 126, in import_module
100
+ return _bootstrap._gcd_import(name[level:], package, level)
101
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
102
+ File "<frozen importlib._bootstrap>", line 1204, in _gcd_import
103
+ File "<frozen importlib._bootstrap>", line 1176, in _find_and_load
104
+ File "<frozen importlib._bootstrap>", line 1147, in _find_and_load_unlocked
105
+ File "<frozen importlib._bootstrap>", line 690, in _load_unlocked
106
+ File "<frozen importlib._bootstrap_external>", line 940, in exec_module
107
+ File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
108
+ File "/app/src/app/main.py", line 187, in <module>
109
+ from app.api.v1.router import api_router
110
+ File "/app/src/app/api/v1/router.py", line 5, in <module>
111
+ from app.api.v1 import auth, clients, contractors, invitations, profile
112
+ File "/app/src/app/api/v1/profile.py", line 12, in <module>
113
+ from app.models.user_financial_account import UserFinancialAccount
114
+ ModuleNotFoundError: No module named 'app.models.user_financial_account'
src/app/models/project_team.py ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Project Team Model
3
+ """
4
+ from sqlalchemy import Column, String, Boolean
5
+ from sqlalchemy.dialects.postgresql import UUID
6
+ from datetime import datetime
7
+ from app.core.database import Base
8
+ import uuid
9
+
10
+
11
+ class ProjectTeam(Base):
12
+ """
13
+ Project Team model - Links users to projects with their roles
14
+ """
15
+ __tablename__ = "project_team"
16
+
17
+ id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
18
+ project_id = Column(UUID(as_uuid=True), nullable=False)
19
+ user_id = Column(UUID(as_uuid=True), nullable=False)
20
+ project_role_id = Column(UUID(as_uuid=True), nullable=True)
21
+
22
+ # Status
23
+ is_assigned_slot = Column(Boolean, default=True)
24
+
25
+ # Timestamps
26
+ assigned_at = Column(String(50), default=lambda: datetime.utcnow().isoformat())
27
+ removed_at = Column(String(50), nullable=True)
28
+ created_at = Column(String(50), default=lambda: datetime.utcnow().isoformat())
29
+ updated_at = Column(String(50), default=lambda: datetime.utcnow().isoformat())
30
+ deleted_at = Column(String(50), nullable=True)
31
+
32
+ def __repr__(self):
33
+ return f"<ProjectTeam(project_id='{self.project_id}', user_id='{self.user_id}')>"
src/app/models/user_asset_assignment.py ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ User Asset Assignment Model
3
+ """
4
+ from sqlalchemy import Column, String, Boolean, DECIMAL, Text
5
+ from sqlalchemy.dialects.postgresql import UUID
6
+ from datetime import datetime
7
+ from app.core.database import Base
8
+ import uuid
9
+
10
+
11
+ class UserAssetAssignment(Base):
12
+ """
13
+ User Asset Assignment model - Long-term equipment assigned to users
14
+ """
15
+ __tablename__ = "user_asset_assignments"
16
+
17
+ id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
18
+ user_id = Column(UUID(as_uuid=True), nullable=False)
19
+
20
+ # Asset descriptors
21
+ asset_type = Column(Text, nullable=False) # 'PPE', 'Laptop', 'Phone', 'Vehicle', 'Tools'
22
+ asset_name = Column(Text, nullable=False)
23
+ asset_description = Column(Text)
24
+ serial_number = Column(Text)
25
+ registration_number = Column(Text)
26
+
27
+ # Valuation
28
+ asset_value = Column(DECIMAL(12, 2))
29
+ currency = Column(Text, default='KES')
30
+
31
+ # Status
32
+ is_active = Column(Boolean, default=True)
33
+
34
+ # Timestamps
35
+ assigned_at = Column(String(50), default=lambda: datetime.utcnow().isoformat())
36
+ returned_at = Column(String(50), nullable=True)
37
+ created_at = Column(String(50), default=lambda: datetime.utcnow().isoformat())
38
+ updated_at = Column(String(50), default=lambda: datetime.utcnow().isoformat())
39
+ deleted_at = Column(String(50), nullable=True)
40
+
41
+ def __repr__(self):
42
+ return f"<UserAssetAssignment(user_id='{self.user_id}', asset='{self.asset_name}')>"
src/app/models/user_document_link.py ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ User Document Link Model
3
+ """
4
+ from sqlalchemy import Column, String, Text, Date
5
+ from sqlalchemy.dialects.postgresql import UUID, JSONB
6
+ from datetime import datetime
7
+ from app.core.database import Base
8
+ import uuid
9
+
10
+
11
+ class UserDocumentLink(Base):
12
+ """
13
+ User Document Link model - Links users to their identity/compliance documents
14
+ """
15
+ __tablename__ = "user_document_links"
16
+
17
+ id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
18
+ user_id = Column(UUID(as_uuid=True), nullable=False)
19
+ document_id = Column(UUID(as_uuid=True), nullable=False)
20
+
21
+ # Document type
22
+ document_link_type = Column(Text, nullable=False) # 'national_id', 'driver_license', etc.
23
+
24
+ # Expiry tracking
25
+ issued_at = Column(Date)
26
+ expires_at = Column(Date)
27
+
28
+ # Metadata
29
+ notes = Column(Text)
30
+ additional_metadata = Column(JSONB, default=dict)
31
+
32
+ # Timestamps
33
+ created_at = Column(String(50), default=lambda: datetime.utcnow().isoformat())
34
+ updated_at = Column(String(50), default=lambda: datetime.utcnow().isoformat())
35
+
36
+ def __repr__(self):
37
+ return f"<UserDocumentLink(user_id='{self.user_id}', type='{self.document_link_type}')>"
src/app/models/user_financial_account.py ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ User Financial Account Model
3
+ """
4
+ from sqlalchemy import Column, String, Boolean, DECIMAL, Text
5
+ from sqlalchemy.dialects.postgresql import UUID
6
+ from datetime import datetime
7
+ from app.core.database import Base
8
+ import uuid
9
+
10
+
11
+ class UserFinancialAccount(Base):
12
+ """
13
+ User Financial Account model - Payout details for users
14
+ """
15
+ __tablename__ = "user_financial_accounts"
16
+
17
+ id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
18
+ user_id = Column(UUID(as_uuid=True), nullable=False)
19
+
20
+ # Account Details
21
+ account_name = Column(Text, nullable=False)
22
+ payout_method = Column(String(50), nullable=False)
23
+
24
+ # Mobile money details
25
+ mobile_money_provider = Column(Text)
26
+ mobile_money_phone = Column(Text)
27
+ mobile_money_account_name = Column(Text)
28
+
29
+ # Bank details
30
+ bank_name = Column(Text)
31
+ bank_account_name = Column(Text)
32
+ bank_account_number = Column(Text)
33
+ bank_branch = Column(Text)
34
+ bank_swift_code = Column(Text)
35
+
36
+ # Status
37
+ is_primary = Column(Boolean, default=False)
38
+ is_active = Column(Boolean, default=True)
39
+ is_verified = Column(Boolean, default=False)
40
+
41
+ # Timestamps
42
+ created_at = Column(String(50), default=lambda: datetime.utcnow().isoformat())
43
+ updated_at = Column(String(50), default=lambda: datetime.utcnow().isoformat())
44
+ deleted_at = Column(String(50), nullable=True)
45
+
46
+ def __repr__(self):
47
+ return f"<UserFinancialAccount(user_id='{self.user_id}', method='{self.payout_method}')>"