maleo-identity 0.0.91__py3-none-any.whl → 0.0.93__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of maleo-identity might be problematic. Click here for more details.

Files changed (109) hide show
  1. maleo/identity/constants/organization.py +15 -8
  2. maleo/identity/constants/organization_registration_code.py +10 -7
  3. maleo/identity/constants/user.py +11 -13
  4. maleo/identity/constants/user_profile.py +9 -12
  5. maleo/identity/enums/organization.py +4 -4
  6. maleo/identity/enums/organization_registration_code.py +5 -0
  7. maleo/identity/enums/user.py +4 -8
  8. maleo/identity/enums/user_profile.py +4 -10
  9. maleo/identity/mixins/organization.py +10 -8
  10. maleo/identity/mixins/organization_registration_code.py +8 -11
  11. maleo/identity/mixins/user.py +17 -31
  12. maleo/identity/mixins/user_profile.py +37 -67
  13. maleo/identity/models.py +317 -0
  14. maleo/identity/schemas/common.py +257 -0
  15. maleo/identity/schemas/organization.py +162 -0
  16. maleo/identity/schemas/organization_registration_code.py +162 -0
  17. maleo/identity/schemas/user.py +181 -0
  18. maleo/identity/schemas/user_profile.py +212 -0
  19. maleo/identity/types/{base/organization_registration_code.py → user_profile.py} +2 -1
  20. maleo_identity-0.0.93.dist-info/METADATA +118 -0
  21. maleo_identity-0.0.93.dist-info/RECORD +33 -0
  22. maleo_identity-0.0.93.dist-info/licenses/LICENSE +57 -0
  23. maleo/identity/client/__init__.py +0 -0
  24. maleo/identity/client/manager.py +0 -157
  25. maleo/identity/client/services/__init__.py +0 -0
  26. maleo/identity/client/services/organization.py +0 -1944
  27. maleo/identity/client/services/organization_registration_code.py +0 -470
  28. maleo/identity/client/services/organization_role.py +0 -276
  29. maleo/identity/client/services/user.py +0 -1559
  30. maleo/identity/client/services/user_organization.py +0 -276
  31. maleo/identity/client/services/user_organization_role.py +0 -278
  32. maleo/identity/client/services/user_profile.py +0 -276
  33. maleo/identity/client/services/user_system_role.py +0 -276
  34. maleo/identity/constants/organization_role.py +0 -35
  35. maleo/identity/constants/user_organization.py +0 -58
  36. maleo/identity/constants/user_organization_role.py +0 -47
  37. maleo/identity/constants/user_system_role.py +0 -16
  38. maleo/identity/db.py +0 -4
  39. maleo/identity/dtos/__init__.py +0 -0
  40. maleo/identity/dtos/configuration.py +0 -15
  41. maleo/identity/dtos/data/__init__.py +0 -0
  42. maleo/identity/dtos/data/organization_registration_code.py +0 -15
  43. maleo/identity/dtos/data/user_profile.py +0 -33
  44. maleo/identity/dtos/data/user_system_role.py +0 -9
  45. maleo/identity/dtos/settings.py +0 -17
  46. maleo/identity/enums/general.py +0 -5
  47. maleo/identity/enums/organization_role.py +0 -7
  48. maleo/identity/enums/user_organization.py +0 -14
  49. maleo/identity/enums/user_organization_role.py +0 -15
  50. maleo/identity/enums/user_system_role.py +0 -5
  51. maleo/identity/mixins/organization_role.py +0 -15
  52. maleo/identity/mixins/user_organization.py +0 -6
  53. maleo/identity/mixins/user_organization_role.py +0 -6
  54. maleo/identity/mixins/user_system_role.py +0 -6
  55. maleo/identity/models/__init__.py +0 -0
  56. maleo/identity/models/organization.py +0 -62
  57. maleo/identity/models/organization_registration_code.py +0 -33
  58. maleo/identity/models/organization_role.py +0 -37
  59. maleo/identity/models/user.py +0 -39
  60. maleo/identity/models/user_organization.py +0 -48
  61. maleo/identity/models/user_organization_role.py +0 -61
  62. maleo/identity/models/user_profile.py +0 -33
  63. maleo/identity/models/user_system_role.py +0 -26
  64. maleo/identity/schemas/data/__init__.py +0 -0
  65. maleo/identity/schemas/data/organization.py +0 -36
  66. maleo/identity/schemas/data/organization_registration_code.py +0 -27
  67. maleo/identity/schemas/data/organization_role.py +0 -32
  68. maleo/identity/schemas/data/user.py +0 -33
  69. maleo/identity/schemas/data/user_organization.py +0 -23
  70. maleo/identity/schemas/data/user_organization_role.py +0 -13
  71. maleo/identity/schemas/data/user_profile.py +0 -59
  72. maleo/identity/schemas/data/user_system_role.py +0 -25
  73. maleo/identity/schemas/metadata/__init__.py +0 -0
  74. maleo/identity/schemas/metadata/user.py +0 -6
  75. maleo/identity/schemas/parameter/__init__.py +0 -0
  76. maleo/identity/schemas/parameter/client/__init__.py +0 -0
  77. maleo/identity/schemas/parameter/client/organization.py +0 -74
  78. maleo/identity/schemas/parameter/client/organization_registration_code.py +0 -24
  79. maleo/identity/schemas/parameter/client/organization_role.py +0 -42
  80. maleo/identity/schemas/parameter/client/user.py +0 -44
  81. maleo/identity/schemas/parameter/client/user_organization.py +0 -62
  82. maleo/identity/schemas/parameter/client/user_organization_role.py +0 -49
  83. maleo/identity/schemas/parameter/client/user_profile.py +0 -28
  84. maleo/identity/schemas/parameter/client/user_system_role.py +0 -43
  85. maleo/identity/schemas/parameter/general/__init__.py +0 -0
  86. maleo/identity/schemas/parameter/general/organization.py +0 -92
  87. maleo/identity/schemas/parameter/general/organization_registration_code.py +0 -86
  88. maleo/identity/schemas/parameter/general/organization_role.py +0 -14
  89. maleo/identity/schemas/parameter/general/user.py +0 -150
  90. maleo/identity/schemas/parameter/general/user_organization.py +0 -18
  91. maleo/identity/schemas/parameter/general/user_organization_role.py +0 -15
  92. maleo/identity/schemas/parameter/general/user_profile.py +0 -119
  93. maleo/identity/schemas/parameter/general/user_system_role.py +0 -30
  94. maleo/identity/schemas/parameter/service/__init__.py +0 -0
  95. maleo/identity/schemas/parameter/service/organization.py +0 -60
  96. maleo/identity/schemas/parameter/service/organization_registration_code.py +0 -24
  97. maleo/identity/schemas/parameter/service/organization_role.py +0 -35
  98. maleo/identity/schemas/parameter/service/user.py +0 -47
  99. maleo/identity/schemas/parameter/service/user_organization_role.py +0 -36
  100. maleo/identity/schemas/parameter/service/user_profile.py +0 -28
  101. maleo/identity/schemas/parameter/service/user_system_role.py +0 -31
  102. maleo/identity/types/base/__init__.py +0 -0
  103. maleo_identity-0.0.91.dist-info/METADATA +0 -39
  104. maleo_identity-0.0.91.dist-info/RECORD +0 -106
  105. /maleo/identity/types/{base/organization.py → organization.py} +0 -0
  106. /maleo/identity/types/{base/user.py → organization_registration_code.py} +0 -0
  107. /maleo/identity/types/{base/user_profile.py → user.py} +0 -0
  108. {maleo_identity-0.0.91.dist-info → maleo_identity-0.0.93.dist-info}/WHEEL +0 -0
  109. {maleo_identity-0.0.91.dist-info → maleo_identity-0.0.93.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,317 @@
1
+ from datetime import date
2
+ from sqlalchemy import ForeignKey, UniqueConstraint, and_
3
+ from sqlalchemy.dialects.postgresql import UUID as PostgreSQLUUID
4
+ from sqlalchemy.orm import Mapped, declared_attr, mapped_column, relationship
5
+ from sqlalchemy.types import Date, Enum, Integer, String, Text
6
+ from uuid import UUID, uuid4
7
+ from maleo.enums.identity import BloodType, OptBloodType, Gender, OptGender
8
+ from maleo.enums.organization import OrganizationType, OrganizationRole
9
+ from maleo.enums.medical import MedicalRole
10
+ from maleo.enums.system import SystemRole
11
+ from maleo.enums.user import UserType
12
+ from maleo.schemas.model import DataIdentifier, DataStatus, DataTimestamp
13
+ from maleo.types.integer import OptInt
14
+ from maleo.types.string import OptStr
15
+
16
+
17
+ class APIKey(
18
+ DataStatus,
19
+ DataTimestamp,
20
+ DataIdentifier,
21
+ ):
22
+ __tablename__ = "api_keys"
23
+ user_id: Mapped[int] = mapped_column(
24
+ Integer,
25
+ ForeignKey("users.id", ondelete="CASCADE", onupdate="CASCADE"),
26
+ nullable=False,
27
+ )
28
+
29
+ organization_id: Mapped[OptInt] = mapped_column(
30
+ Integer,
31
+ ForeignKey("organizations.id", ondelete="CASCADE", onupdate="CASCADE"),
32
+ )
33
+
34
+ api_key: Mapped[str] = mapped_column(
35
+ name="api_key", type_=String(255), unique=True, nullable=False
36
+ )
37
+
38
+ __table_args__ = (
39
+ UniqueConstraint("user_id", "organization_id", name="uq_user_organization"),
40
+ )
41
+
42
+
43
+ class OrganizationRegistrationCode(
44
+ DataStatus,
45
+ DataTimestamp,
46
+ DataIdentifier,
47
+ ):
48
+ __tablename__ = "organization_registration_codes"
49
+ organization_id: Mapped[int] = mapped_column(
50
+ Integer,
51
+ ForeignKey("organizations.id", ondelete="CASCADE", onupdate="CASCADE"),
52
+ unique=True,
53
+ nullable=False,
54
+ )
55
+ code: Mapped[str] = mapped_column(
56
+ name="code", type_=String(36), unique=True, nullable=False
57
+ )
58
+ max_uses: Mapped[int] = mapped_column(
59
+ name="max_uses", type_=Integer, nullable=False, default=1
60
+ )
61
+ current_uses: Mapped[int] = mapped_column(
62
+ name="current_uses", type_=Integer, nullable=False, default=0
63
+ )
64
+
65
+ # Relationship
66
+ @declared_attr
67
+ def organization(cls) -> Mapped["Organization"]:
68
+ return relationship(
69
+ "Organization",
70
+ back_populates="registration_code",
71
+ uselist=False, # 👈 ensures one-to-one, not one-to-many
72
+ )
73
+
74
+
75
+ class Organization(
76
+ DataStatus,
77
+ DataTimestamp,
78
+ DataIdentifier,
79
+ ):
80
+ __tablename__ = "organizations"
81
+ organization_type: Mapped[OrganizationType] = mapped_column(
82
+ name="organization_type",
83
+ type_=Enum(OrganizationType, name="organization_type"),
84
+ default=OrganizationType.REGULAR,
85
+ nullable=False,
86
+ )
87
+ key: Mapped[str] = mapped_column(
88
+ name="key", type_=String(255), unique=True, nullable=False
89
+ )
90
+ name: Mapped[str] = mapped_column(name="name", type_=String(255), nullable=False)
91
+ secret: Mapped[UUID] = mapped_column(
92
+ name="secret",
93
+ type_=PostgreSQLUUID(as_uuid=True),
94
+ default=uuid4,
95
+ unique=True,
96
+ nullable=False,
97
+ )
98
+
99
+ # Relationship
100
+ @declared_attr
101
+ def registration_code(cls) -> Mapped["OrganizationRegistrationCode | None"]:
102
+ return relationship(
103
+ "OrganizationRegistrationCode",
104
+ back_populates="organization",
105
+ uselist=False,
106
+ cascade="all, delete-orphan",
107
+ )
108
+
109
+ @declared_attr
110
+ def users(cls) -> Mapped[list["UserOrganization"]]:
111
+ return relationship(
112
+ "UserOrganization",
113
+ back_populates="organization",
114
+ cascade="all, delete-orphan",
115
+ )
116
+
117
+
118
+ class UserMedicalRole(DataStatus, DataTimestamp, DataIdentifier):
119
+ __tablename__ = "user_medical_roles"
120
+ user_id: Mapped[int] = mapped_column(
121
+ Integer,
122
+ ForeignKey("users.id", ondelete="CASCADE", onupdate="CASCADE"),
123
+ nullable=False,
124
+ )
125
+ organization_id: Mapped[int] = mapped_column(
126
+ Integer,
127
+ ForeignKey("organizations.id", ondelete="CASCADE", onupdate="CASCADE"),
128
+ nullable=False,
129
+ )
130
+ medical_role: Mapped[MedicalRole] = mapped_column(
131
+ name="medical_role",
132
+ type_=Enum(MedicalRole, name="medical_role"),
133
+ nullable=False,
134
+ )
135
+
136
+ __table_args__ = (
137
+ UniqueConstraint(
138
+ "user_id", "organization_id", "medical_role", name="uq_user_medical_role"
139
+ ),
140
+ )
141
+
142
+
143
+ class UserOrganizationRole(DataStatus, DataTimestamp, DataIdentifier):
144
+ __tablename__ = "user_organization_roles_v2"
145
+ user_id: Mapped[int] = mapped_column(
146
+ Integer,
147
+ ForeignKey("users.id", ondelete="CASCADE", onupdate="CASCADE"),
148
+ nullable=False,
149
+ )
150
+ organization_id: Mapped[int] = mapped_column(
151
+ Integer,
152
+ ForeignKey("organizations.id", ondelete="CASCADE", onupdate="CASCADE"),
153
+ nullable=False,
154
+ )
155
+ organization_role: Mapped[OrganizationRole] = mapped_column(
156
+ name="organization_role",
157
+ type_=Enum(OrganizationRole, name="organization_role"),
158
+ nullable=False,
159
+ )
160
+
161
+ __table_args__ = (
162
+ UniqueConstraint(
163
+ "user_id",
164
+ "organization_id",
165
+ "organization_role",
166
+ name="uq_user_organization_role",
167
+ ),
168
+ )
169
+
170
+
171
+ class UserProfile(
172
+ DataStatus,
173
+ DataTimestamp,
174
+ DataIdentifier,
175
+ ):
176
+ __tablename__ = "user_profiles"
177
+ user_id: Mapped[int] = mapped_column(
178
+ Integer,
179
+ ForeignKey("users.id", ondelete="CASCADE", onupdate="CASCADE"),
180
+ nullable=False,
181
+ )
182
+ id_card: Mapped[OptStr] = mapped_column(name="id_card", type_=String(16))
183
+ leading_title: Mapped[OptStr] = mapped_column(
184
+ name="leading_title", type_=String(25)
185
+ )
186
+ first_name: Mapped[str] = mapped_column(
187
+ name="first_name", type_=String(50), nullable=False
188
+ )
189
+ middle_name: Mapped[OptStr] = mapped_column(name="middle_name", type_=String(50))
190
+ last_name: Mapped[str] = mapped_column(
191
+ name="last_name", type_=String(50), nullable=False
192
+ )
193
+ ending_title: Mapped[OptStr] = mapped_column(name="ending_title", type_=String(25))
194
+ full_name: Mapped[str] = mapped_column(
195
+ name="full_name", type_=String(200), nullable=False
196
+ )
197
+ birth_place: Mapped[OptStr] = mapped_column(name="birth_place", type_=String(50))
198
+ birth_date: Mapped[date] = mapped_column(name="birth_date", type_=Date)
199
+ gender: Mapped[OptGender] = mapped_column(
200
+ name="gender", type_=Enum(Gender, name="gender")
201
+ )
202
+ blood_type: Mapped[OptBloodType] = mapped_column(
203
+ name="blood_type", type_=Enum(BloodType, name="blood_type")
204
+ )
205
+ avatar_name: Mapped[str] = mapped_column(
206
+ name="avatar_name", type_=Text, nullable=False
207
+ )
208
+
209
+
210
+ class UserSystemRole(
211
+ DataStatus,
212
+ DataTimestamp,
213
+ DataIdentifier,
214
+ ):
215
+ __tablename__ = "user_system_roles"
216
+ user_id: Mapped[int] = mapped_column(
217
+ Integer,
218
+ ForeignKey("users.id", ondelete="CASCADE", onupdate="CASCADE"),
219
+ nullable=False,
220
+ )
221
+ system_role: Mapped[SystemRole] = mapped_column(
222
+ name="system_role",
223
+ type_=Enum(SystemRole, name="system_role"),
224
+ default=SystemRole.USER,
225
+ nullable=False,
226
+ )
227
+
228
+ __table_args__ = (
229
+ UniqueConstraint("user_id", "system_role", name="uq_user_system_role"),
230
+ )
231
+
232
+
233
+ class User(
234
+ DataStatus,
235
+ DataTimestamp,
236
+ DataIdentifier,
237
+ ):
238
+ __tablename__ = "users"
239
+ user_type: Mapped[UserType] = mapped_column(
240
+ name="user_type",
241
+ type_=Enum(UserType, name="user_type"),
242
+ default=UserType.REGULAR,
243
+ nullable=False,
244
+ )
245
+ username: Mapped[str] = mapped_column(
246
+ name="username", type_=String(50), unique=True, nullable=False
247
+ )
248
+ email: Mapped[str] = mapped_column(
249
+ name="email", type_=String(255), unique=True, nullable=False
250
+ )
251
+ phone: Mapped[str] = mapped_column(name="phone", type_=String(15), nullable=False)
252
+ password: Mapped[str] = mapped_column(
253
+ name="password", type_=String(255), nullable=False
254
+ )
255
+
256
+ @declared_attr
257
+ def organizations(cls) -> Mapped[list["UserOrganization"]]:
258
+ return relationship(
259
+ "UserOrganization", back_populates="user", cascade="all, delete-orphan"
260
+ )
261
+
262
+
263
+ class UserOrganization(
264
+ DataStatus,
265
+ DataTimestamp,
266
+ DataIdentifier,
267
+ ):
268
+ __tablename__ = "user_organizations"
269
+ user_id: Mapped[int] = mapped_column(
270
+ Integer,
271
+ ForeignKey("users.id", ondelete="CASCADE", onupdate="CASCADE"),
272
+ nullable=False,
273
+ )
274
+
275
+ organization_id: Mapped[int] = mapped_column(
276
+ Integer,
277
+ ForeignKey("organizations.id", ondelete="CASCADE", onupdate="CASCADE"),
278
+ nullable=False,
279
+ )
280
+
281
+ __table_args__ = (
282
+ UniqueConstraint("user_id", "organization_id", name="uq_user_organization"),
283
+ )
284
+
285
+ # Relationships
286
+ @declared_attr
287
+ def user(cls) -> Mapped["User"]:
288
+ return relationship("User", back_populates="organizations")
289
+
290
+ @declared_attr
291
+ def organization(cls) -> Mapped["Organization"]:
292
+ return relationship("Organization", back_populates="users")
293
+
294
+ @declared_attr
295
+ def organization_roles(cls) -> Mapped[list["UserOrganizationRole"]]:
296
+ return relationship(
297
+ "UserOrganizationRole",
298
+ primaryjoin=and_(
299
+ UserOrganization.user_id == UserOrganizationRole.user_id,
300
+ UserOrganization.organization_id
301
+ == UserOrganizationRole.organization_id,
302
+ ),
303
+ viewonly=True,
304
+ lazy="selectin",
305
+ )
306
+
307
+ @declared_attr
308
+ def medical_roles(cls) -> Mapped[list["UserMedicalRole"]]:
309
+ return relationship(
310
+ "UserMedicalRole",
311
+ primaryjoin=and_(
312
+ UserOrganization.user_id == UserMedicalRole.user_id,
313
+ UserOrganization.organization_id == UserMedicalRole.organization_id,
314
+ ),
315
+ viewonly=True,
316
+ lazy="selectin",
317
+ )
@@ -0,0 +1,257 @@
1
+ from pydantic import BaseModel, Field
2
+ from typing import Annotated, Generic, TypeVar
3
+ from maleo.enums.identity import OptBloodType, BloodTypeMixin, OptGender, GenderMixin
4
+ from maleo.enums.medical import MedicalRole, FullMedicalRoleMixin
5
+ from maleo.enums.organization import (
6
+ OrganizationRole,
7
+ FullOrganizationRoleMixin,
8
+ OrganizationType,
9
+ FullOrganizationTypeMixin,
10
+ )
11
+ from maleo.enums.status import DataStatus as DataStatusEnum, SimpleDataStatusMixin
12
+ from maleo.enums.system import SystemRole, FullSystemRoleMixin
13
+ from maleo.enums.user import UserType, FullUserTypeMixin
14
+ from maleo.schemas.mixins.identity import DataIdentifier, IntOrganizationId, IntUserId
15
+ from maleo.schemas.mixins.timestamp import DataTimestamp
16
+ from maleo.types.datetime import OptDate
17
+ from maleo.types.string import OptStr
18
+ from ..mixins.organization_registration_code import Code, MaxUses, CurrentUses
19
+ from ..mixins.organization import Key as OrganizationKey, Name as OrganizationName
20
+ from ..mixins.user_profile import (
21
+ IdCard,
22
+ LeadingTitle,
23
+ FirstName,
24
+ MiddleName,
25
+ LastName,
26
+ EndingTitle,
27
+ FullName,
28
+ BirthPlace,
29
+ BirthDate,
30
+ AvatarName,
31
+ )
32
+ from ..mixins.user import Username, Email, Phone
33
+
34
+
35
+ class OrganizationRegistrationCodeSchema(
36
+ CurrentUses,
37
+ MaxUses[int],
38
+ Code[str],
39
+ IntOrganizationId[int],
40
+ SimpleDataStatusMixin[DataStatusEnum],
41
+ DataTimestamp,
42
+ DataIdentifier,
43
+ ):
44
+ pass
45
+
46
+
47
+ OptOrganizationRegistrationCodeSchema = OrganizationRegistrationCodeSchema | None
48
+
49
+
50
+ class OrganizationRegistrationCodeSchemaMixin(BaseModel):
51
+ registration_code: Annotated[
52
+ OptOrganizationRegistrationCodeSchema,
53
+ Field(None, description="Organization's registration code"),
54
+ ] = None
55
+
56
+
57
+ class StandardOrganizationCoreSchema(
58
+ OrganizationName[str],
59
+ OrganizationKey[str],
60
+ FullOrganizationTypeMixin[OrganizationType],
61
+ SimpleDataStatusMixin[DataStatusEnum],
62
+ DataTimestamp,
63
+ DataIdentifier,
64
+ ):
65
+ pass
66
+
67
+
68
+ class FullOrganizationCoreSchema(
69
+ OrganizationRegistrationCodeSchemaMixin,
70
+ StandardOrganizationCoreSchema,
71
+ ):
72
+ pass
73
+
74
+
75
+ AnyOrganizationCoreSchema = StandardOrganizationCoreSchema | FullOrganizationCoreSchema
76
+ AnyOrganizationCoreSchemaT = TypeVar(
77
+ "AnyOrganizationCoreSchemaT", bound=AnyOrganizationCoreSchema
78
+ )
79
+
80
+
81
+ class OrganizationCoreSchemaMixin(BaseModel, Generic[AnyOrganizationCoreSchemaT]):
82
+ organization: Annotated[
83
+ AnyOrganizationCoreSchemaT, Field(..., description="Organization")
84
+ ]
85
+
86
+
87
+ class UserMedicalRoleSchema(
88
+ FullMedicalRoleMixin[MedicalRole],
89
+ IntOrganizationId[int],
90
+ IntUserId[int],
91
+ SimpleDataStatusMixin[DataStatusEnum],
92
+ DataTimestamp,
93
+ DataIdentifier,
94
+ ):
95
+ pass
96
+
97
+
98
+ class UserMedicalRolesSchemaMixin(BaseModel):
99
+ medical_roles: Annotated[
100
+ list[UserMedicalRoleSchema],
101
+ Field(list[UserMedicalRoleSchema](), description="Medical roles"),
102
+ ] = list[UserMedicalRoleSchema]()
103
+
104
+
105
+ class UserOrganizationRoleSchema(
106
+ FullOrganizationRoleMixin[OrganizationRole],
107
+ IntOrganizationId[int],
108
+ IntUserId[int],
109
+ SimpleDataStatusMixin[DataStatusEnum],
110
+ DataTimestamp,
111
+ DataIdentifier,
112
+ ):
113
+ pass
114
+
115
+
116
+ class UserOrganizationRolesSchemaMixin(BaseModel):
117
+ organization_roles: Annotated[
118
+ list[UserOrganizationRoleSchema],
119
+ Field(list[UserOrganizationRoleSchema](), description="Organization roles"),
120
+ ] = list[UserOrganizationRoleSchema]()
121
+
122
+
123
+ class UserProfileCoreSchema(
124
+ AvatarName[str],
125
+ BloodTypeMixin[OptBloodType],
126
+ GenderMixin[OptGender],
127
+ BirthDate[OptDate],
128
+ BirthPlace[OptStr],
129
+ FullName[str],
130
+ EndingTitle[OptStr],
131
+ LastName[str],
132
+ MiddleName[OptStr],
133
+ FirstName[str],
134
+ LeadingTitle[OptStr],
135
+ IdCard[OptStr],
136
+ IntUserId[int],
137
+ SimpleDataStatusMixin[DataStatusEnum],
138
+ DataTimestamp,
139
+ DataIdentifier,
140
+ ):
141
+ pass
142
+
143
+
144
+ OptUserProfileCoreSchema = UserProfileCoreSchema | None
145
+
146
+
147
+ class UserProfileCoreSchemaMixin(BaseModel):
148
+ profile: Annotated[
149
+ OptUserProfileCoreSchema, Field(None, description="User's Profile")
150
+ ] = None
151
+
152
+
153
+ class UserSystemRoleCoreSchema(
154
+ FullSystemRoleMixin[SystemRole],
155
+ IntUserId[int],
156
+ SimpleDataStatusMixin[DataStatusEnum],
157
+ DataTimestamp,
158
+ DataIdentifier,
159
+ ):
160
+ pass
161
+
162
+
163
+ class UserSystemRolesCoreSchemaMixin(BaseModel):
164
+ system_roles: Annotated[
165
+ list[UserSystemRoleCoreSchema],
166
+ Field(
167
+ list[UserSystemRoleCoreSchema](),
168
+ description="User's system roles",
169
+ min_length=1,
170
+ ),
171
+ ] = list[UserSystemRoleCoreSchema]()
172
+
173
+
174
+ class StandardUserCoreSchema(
175
+ UserProfileCoreSchemaMixin,
176
+ Phone[str],
177
+ Email[str],
178
+ Username[str],
179
+ FullUserTypeMixin[UserType],
180
+ SimpleDataStatusMixin[DataStatusEnum],
181
+ DataTimestamp,
182
+ DataIdentifier,
183
+ ):
184
+ pass
185
+
186
+
187
+ class FullUserCoreSchema(UserSystemRolesCoreSchemaMixin, StandardUserCoreSchema):
188
+ pass
189
+
190
+
191
+ AnyUserCoreSchema = StandardUserCoreSchema | FullUserCoreSchema
192
+ AnyUserCoreSchemaT = TypeVar("AnyUserCoreSchemaT", bound=AnyUserCoreSchema)
193
+
194
+
195
+ class UserCoreSchemaMixin(BaseModel, Generic[AnyUserCoreSchemaT]):
196
+ user: Annotated[AnyUserCoreSchemaT, Field(..., description="User")]
197
+
198
+
199
+ class UserAndOrganizationSchema(
200
+ UserMedicalRolesSchemaMixin,
201
+ UserOrganizationRolesSchemaMixin,
202
+ ):
203
+ pass
204
+
205
+
206
+ class UserOrganizationSchema(
207
+ UserAndOrganizationSchema,
208
+ OrganizationCoreSchemaMixin[StandardOrganizationCoreSchema],
209
+ SimpleDataStatusMixin[DataStatusEnum],
210
+ DataTimestamp,
211
+ DataIdentifier,
212
+ ):
213
+ pass
214
+
215
+
216
+ class UserOrganizationsSchemaMixin(BaseModel):
217
+ organizations: Annotated[
218
+ list[UserOrganizationSchema],
219
+ Field(list[UserOrganizationSchema](), description="Organizations"),
220
+ ] = list[UserOrganizationSchema]()
221
+
222
+
223
+ class StandardUserCompleteSchema(UserOrganizationsSchemaMixin, StandardUserCoreSchema):
224
+ pass
225
+
226
+
227
+ class FullUserCompleteSchema(UserOrganizationsSchemaMixin, FullUserCoreSchema):
228
+ pass
229
+
230
+
231
+ class OrganizationUserSchema(
232
+ UserAndOrganizationSchema,
233
+ UserCoreSchemaMixin[StandardUserCoreSchema],
234
+ SimpleDataStatusMixin[DataStatusEnum],
235
+ DataTimestamp,
236
+ DataIdentifier,
237
+ ):
238
+ pass
239
+
240
+
241
+ class OrganizationUsersSchemaMixin(BaseModel):
242
+ users: Annotated[
243
+ list[OrganizationUserSchema],
244
+ Field(list[OrganizationUserSchema](), description="Users"),
245
+ ] = list[OrganizationUserSchema]()
246
+
247
+
248
+ class StandardOrganizationCompleteSchema(
249
+ OrganizationUsersSchemaMixin, StandardOrganizationCoreSchema
250
+ ):
251
+ pass
252
+
253
+
254
+ class FullOrganizationCompleteSchema(
255
+ OrganizationUsersSchemaMixin, FullOrganizationCoreSchema
256
+ ):
257
+ pass