zou 0.20.37__py3-none-any.whl → 0.20.39__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.
Files changed (41) hide show
  1. zou/__init__.py +1 -1
  2. zou/app/api.py +32 -41
  3. zou/app/blueprints/crud/__init__.py +6 -0
  4. zou/app/blueprints/crud/budget.py +21 -0
  5. zou/app/blueprints/crud/budget_entry.py +15 -0
  6. zou/app/blueprints/crud/plugin.py +13 -0
  7. zou/app/blueprints/crud/salary_scale.py +73 -0
  8. zou/app/blueprints/playlists/resources.py +15 -0
  9. zou/app/blueprints/projects/__init__.py +17 -0
  10. zou/app/blueprints/projects/resources.py +402 -7
  11. zou/app/blueprints/shots/resources.py +1 -0
  12. zou/app/mixin.py +12 -1
  13. zou/app/models/budget.py +39 -0
  14. zou/app/models/budget_entry.py +65 -0
  15. zou/app/models/person.py +17 -1
  16. zou/app/models/plugin.py +21 -0
  17. zou/app/models/salary_scale.py +28 -0
  18. zou/app/services/budget_service.py +195 -0
  19. zou/app/services/comments_service.py +1 -1
  20. zou/app/services/exception.py +8 -0
  21. zou/app/services/plugin_service.py +195 -0
  22. zou/app/services/tasks_service.py +1 -0
  23. zou/app/services/user_service.py +1 -3
  24. zou/app/utils/fields.py +10 -0
  25. zou/cli.py +109 -1
  26. zou/event_stream.py +23 -5
  27. zou/migrations/versions/2762a797f1f9_add_people_salary_information.py +52 -0
  28. zou/migrations/versions/45f739ef962a_add_people_salary_scale_table.py +70 -0
  29. zou/migrations/versions/4aab1f84ad72_introduce_plugin_table.py +68 -0
  30. zou/migrations/versions/7a16258f2fab_add_currency_field_to_budgets.py +33 -0
  31. zou/migrations/versions/83e2f33a9b14_add_project_bugdet_table.py +57 -0
  32. zou/migrations/versions/8ab98c178903_add_budget_entry_table.py +123 -0
  33. zou/migrations/versions/d25118cddcaa_modify_salary_scale_model.py +133 -0
  34. zou/plugin_template/__init__.py +39 -0
  35. zou/plugin_template/routes.py +6 -0
  36. {zou-0.20.37.dist-info → zou-0.20.39.dist-info}/METADATA +7 -4
  37. {zou-0.20.37.dist-info → zou-0.20.39.dist-info}/RECORD +41 -22
  38. {zou-0.20.37.dist-info → zou-0.20.39.dist-info}/WHEEL +1 -1
  39. {zou-0.20.37.dist-info → zou-0.20.39.dist-info}/entry_points.txt +0 -0
  40. {zou-0.20.37.dist-info → zou-0.20.39.dist-info}/licenses/LICENSE +0 -0
  41. {zou-0.20.37.dist-info → zou-0.20.39.dist-info}/top_level.txt +0 -0
@@ -2,6 +2,7 @@ from flask_restful import Resource
2
2
  from flask_jwt_extended import jwt_required
3
3
 
4
4
 
5
+ from zou.app.services import budget_service
5
6
  from zou.app.mixin import ArgsMixin
6
7
  from zou.app.services import (
7
8
  projects_service,
@@ -165,7 +166,7 @@ class ProductionTeamRemoveResource(Resource):
165
166
  x-example: a24a6ea4-ce75-4665-a070-57453082c25
166
167
  responses:
167
168
  204:
168
- description: Person removed from production team
169
+ description: Empty response
169
170
  """
170
171
  user_service.check_manager_project_access(project_id)
171
172
  projects_service.remove_team_member(project_id, person_id)
@@ -237,7 +238,7 @@ class ProductionAssetTypeRemoveResource(Resource):
237
238
  x-example: a24a6ea4-ce75-4665-a070-57453082c25
238
239
  responses:
239
240
  204:
240
- description: Asset type removed from production
241
+ description: Empty response
241
242
  """
242
243
  user_service.check_manager_project_access(project_id)
243
244
  projects_service.remove_asset_type_setting(project_id, asset_type_id)
@@ -343,7 +344,7 @@ class ProductionTaskTypeRemoveResource(Resource):
343
344
  x-example: a24a6ea4-ce75-4665-a070-57453082c25
344
345
  responses:
345
346
  204:
346
- description: Task type removed from production
347
+ description: Empty response
347
348
  """
348
349
  user_service.check_manager_project_access(project_id)
349
350
  projects_service.remove_task_type_setting(project_id, task_type_id)
@@ -436,7 +437,7 @@ class ProductionTaskStatusRemoveResource(Resource):
436
437
  x-example: a24a6ea4-ce75-4665-a070-57453082c25
437
438
  responses:
438
439
  204:
439
- description: Task status removed from production
440
+ description: Empty response
440
441
  """
441
442
  user_service.check_manager_project_access(project_id)
442
443
  projects_service.remove_task_status_setting(project_id, task_status_id)
@@ -529,7 +530,7 @@ class ProductionStatusAutomationRemoveResource(Resource):
529
530
  x-example: a24a6ea4-ce75-4665-a070-57453082c25
530
531
  responses:
531
532
  204:
532
- description: Status automation removed from production
533
+ description: Empty response
533
534
  """
534
535
  user_service.check_manager_project_access(project_id)
535
536
  projects_service.remove_status_automation_setting(
@@ -626,7 +627,7 @@ class ProductionPreviewBackgroundFileRemoveResource(Resource):
626
627
  x-example: a24a6ea4-ce75-4665-a070-57453082c25
627
628
  responses:
628
629
  204:
629
- description: Preview background file removed from production
630
+ description: Empty response
630
631
  """
631
632
  user_service.check_manager_project_access(project_id)
632
633
  projects_service.remove_preview_background_file_setting(
@@ -864,7 +865,7 @@ class ProductionMetadataDescriptorResource(Resource, ArgsMixin):
864
865
  x-example: a24a6ea4-ce75-4665-a070-57453082c25
865
866
  responses:
866
867
  204:
867
- description: Metadata descriptor deleted
868
+ description: Empty response
868
869
  """
869
870
  user_service.check_all_departments_access(
870
871
  project_id,
@@ -1092,3 +1093,397 @@ class ProductionSequencesScheduleItemsResource(Resource):
1092
1093
  return schedule_service.get_sequences_schedule_items(
1093
1094
  project_id, task_type_id
1094
1095
  )
1096
+
1097
+
1098
+ class ProductionBudgetsResource(Resource, ArgsMixin):
1099
+
1100
+ @jwt_required()
1101
+ def get(self, project_id):
1102
+ """
1103
+ Retrieve budgets for given production
1104
+ ---
1105
+ tags:
1106
+ - Projects
1107
+ parameters:
1108
+ - in: path
1109
+ name: project_id
1110
+ required: true
1111
+ type: string
1112
+ format: UUID
1113
+ x-example: a24a6ea4-ce75-4665-a070-57453082c25
1114
+ responses:
1115
+ 200:
1116
+ description: All budgets of given production
1117
+ """
1118
+ user_service.check_manager_project_access(project_id)
1119
+ self.check_id_parameter(project_id)
1120
+ return budget_service.get_budgets(project_id)
1121
+
1122
+ @jwt_required()
1123
+ def post(self, project_id):
1124
+ """
1125
+ Create a budget for given production.
1126
+ ---
1127
+ tags:
1128
+ - Projects
1129
+ parameters:
1130
+ - in: path
1131
+ name: project_id
1132
+ required: true
1133
+ type: string
1134
+ format: UUID
1135
+ x-example: a24a6ea4-ce75-4665-a070-57453082c25
1136
+ - in: formData
1137
+ name: name
1138
+ required: true
1139
+ type: string
1140
+ x-example: "New Budget"
1141
+ - in: formData
1142
+ name: currency
1143
+ required: false
1144
+ type: string
1145
+ x-example: "USD"
1146
+ responses:
1147
+ 201:
1148
+ description: Budget created
1149
+ """
1150
+ self.check_id_parameter(project_id)
1151
+ user_service.check_manager_project_access(project_id)
1152
+ data = self.get_args([("name", None, True), ("currency", None, False)])
1153
+ if data["currency"] is None:
1154
+ data["currency"] = "USD"
1155
+ return budget_service.create_budget(
1156
+ project_id, data["name"], data["currency"]
1157
+ )
1158
+
1159
+
1160
+ class ProductionBudgetResource(Resource, ArgsMixin):
1161
+ """
1162
+ Resource to retrieve a budget for given production.
1163
+ """
1164
+
1165
+ @jwt_required()
1166
+ def get(self, project_id, budget_id):
1167
+ """
1168
+ Retrieve a budget for given production
1169
+ ---
1170
+ tags:
1171
+ - Projects
1172
+ parameters:
1173
+ - in: path
1174
+ name: project_id
1175
+ required: true
1176
+ type: string
1177
+ format: UUID
1178
+ x-example: a24a6ea4-ce75-4665-a070-57453082c25
1179
+ - in: path
1180
+ name: budget_id
1181
+ required: true
1182
+ type: string
1183
+ format: UUID
1184
+ x-example: a24a6ea4-ce75-4665-a070-57453082c25
1185
+ responses:
1186
+ 200:
1187
+ description: Budget retrieved
1188
+ """
1189
+ self.check_id_parameter(project_id)
1190
+ self.check_id_parameter(budget_id)
1191
+ user_service.check_manager_project_access(project_id)
1192
+ return budget_service.get_budget(budget_id)
1193
+
1194
+ @jwt_required()
1195
+ def put(self, project_id, budget_id):
1196
+ """
1197
+ Update a budget name for given production
1198
+ ---
1199
+ tags:
1200
+ - Projects
1201
+ parameters:
1202
+ - in: path
1203
+ name: project_id
1204
+ required: true
1205
+ type: string
1206
+ format: UUID
1207
+ x-example: a24a6ea4-ce75-4665-a070-57453082c25
1208
+ - in: path
1209
+ name: budget_id
1210
+ required: true
1211
+ type: string
1212
+ format: UUID
1213
+ x-example: a24a6ea4-ce75-4665-a070-57453082c25
1214
+ - in: formData
1215
+ name: name
1216
+ required: false
1217
+ type: string
1218
+ x-example: "New Budget"
1219
+ - in: formData
1220
+ name: currency
1221
+ required: false
1222
+ type: string
1223
+ x-example: "USD"
1224
+ responses:
1225
+ 200:
1226
+ description: Budget updated
1227
+ """
1228
+ self.check_id_parameter(project_id)
1229
+ self.check_id_parameter(budget_id)
1230
+ user_service.check_manager_project_access(project_id)
1231
+ data = self.get_args(
1232
+ [("name", None, False), ("currency", None, False)]
1233
+ )
1234
+ return budget_service.update_budget(
1235
+ budget_id, name=data["name"], currency=data["currency"]
1236
+ )
1237
+
1238
+ @jwt_required()
1239
+ def delete(self, project_id, budget_id):
1240
+ """
1241
+ Delete a budget for given production
1242
+ ---
1243
+ tags:
1244
+ - Projects
1245
+ parameters:
1246
+ - in: path
1247
+ name: project_id
1248
+ required: true
1249
+ type: string
1250
+ format: UUID
1251
+ x-example: a24a6ea4-ce75-4665-a070-57453082c25
1252
+ - in: path
1253
+ name: budget_id
1254
+ required: true
1255
+ type: string
1256
+ format: UUID
1257
+ x-example: a24a6ea4-ce75-4665-a070-57453082c25
1258
+ responses:
1259
+ 204:
1260
+ description: Empty response
1261
+ """
1262
+ self.check_id_parameter(project_id)
1263
+ self.check_id_parameter(budget_id)
1264
+ user_service.check_manager_project_access(project_id)
1265
+ budget_service.delete_budget(budget_id)
1266
+ return "", 204
1267
+
1268
+
1269
+ class ProductionBudgetEntriesResource(Resource, ArgsMixin):
1270
+
1271
+ @jwt_required()
1272
+ def get(self, project_id, budget_id):
1273
+ """
1274
+ Retrieve budget entries for given production
1275
+ ---
1276
+ tags:
1277
+ - Projects
1278
+ parameters:
1279
+ - in: path
1280
+ name: project_id
1281
+ required: true
1282
+ type: string
1283
+ format: UUID
1284
+ x-example: a24a6ea4-ce75-4665-a070-57453082c25
1285
+ - in: path
1286
+ name: budget_id
1287
+ required: true
1288
+ type: string
1289
+ format: UUID
1290
+ x-example: a24a6ea4-ce75-4665-a070-57453082c25
1291
+ responses:
1292
+ 200:
1293
+ description: All budget entries of given production and budget
1294
+ """
1295
+ self.check_id_parameter(project_id)
1296
+ self.check_id_parameter(budget_id)
1297
+ user_service.check_manager_project_access(project_id)
1298
+ return budget_service.get_budget_entries(budget_id)
1299
+
1300
+ @jwt_required()
1301
+ def post(self, project_id, budget_id):
1302
+ """
1303
+ Create a budget entry for given production and budget
1304
+ """
1305
+ self.check_id_parameter(project_id)
1306
+ self.check_id_parameter(budget_id)
1307
+ user_service.check_manager_project_access(project_id)
1308
+ data = self.get_args(
1309
+ [
1310
+ ("department_id", None, True),
1311
+ ("person_id", None, False),
1312
+ ("start_date", None, False),
1313
+ ("months_duration", None, False),
1314
+ ("daily_salary", None, False),
1315
+ ("position", None, False),
1316
+ ("seniority", None, False),
1317
+ ]
1318
+ )
1319
+ return budget_service.create_budget_entry(
1320
+ budget_id,
1321
+ data["department_id"],
1322
+ data["start_date"],
1323
+ data["months_duration"],
1324
+ data["daily_salary"],
1325
+ data["position"],
1326
+ data["seniority"],
1327
+ person_id=data["person_id"],
1328
+ )
1329
+
1330
+
1331
+ class ProductionBudgetEntryResource(Resource, ArgsMixin):
1332
+
1333
+ @jwt_required()
1334
+ def get(self, project_id, budget_id, entry_id):
1335
+ """
1336
+ Retrieve a budget entry for given production and budget
1337
+ ---
1338
+ tags:
1339
+ - Projects
1340
+ parameters:
1341
+ - in: path
1342
+ name: project_id
1343
+ required: true
1344
+ type: string
1345
+ format: UUID
1346
+ x-example: a24a6ea4-ce75-4665-a070-57453082c25
1347
+ - in: path
1348
+ name: budget_id
1349
+ required: true
1350
+ type: string
1351
+ format: UUID
1352
+ x-example: a24a6ea4-ce75-4665-a070-57453082c25
1353
+ - in: path
1354
+ name: entry_id
1355
+ required: true
1356
+ type: string
1357
+ format: UUID
1358
+ x-example: a24a6ea4-ce75-4665-a070-57453082c25
1359
+ responses:
1360
+ 200:
1361
+ description: Budget entry retrieved
1362
+ """
1363
+ user_service.check_manager_project_access(project_id)
1364
+ self.check_id_parameter(project_id)
1365
+ self.check_id_parameter(budget_id)
1366
+ self.check_id_parameter(entry_id)
1367
+ return budget_service.get_budget_entry(entry_id)
1368
+
1369
+ @jwt_required()
1370
+ def put(self, project_id, budget_id, entry_id):
1371
+ """
1372
+ Update a budget entry for given production and budget
1373
+ ---
1374
+ tags:
1375
+ - Projects
1376
+ parameters:
1377
+ - in: path
1378
+ name: project_id
1379
+ required: true
1380
+ type: string
1381
+ format: UUID
1382
+ x-example: a24a6ea4-ce75-4665-a070-57453082c25
1383
+ - in: path
1384
+ name: budget_id
1385
+ required: true
1386
+ type: string
1387
+ format: UUID
1388
+ x-example: a24a6ea4-ce75-4665-a070-57453082c25
1389
+ - in: path
1390
+ name: entry_id
1391
+ required: true
1392
+ type: string
1393
+ format: UUID
1394
+ x-example: a24a6ea4-ce75-4665-a070-57453082c25
1395
+ - in: formData
1396
+ name: department_id
1397
+ required: false
1398
+ type: string
1399
+ format: UUID
1400
+ x-example: a24a6ea4-ce75-4665-a070-57453082c25
1401
+ - in: formData
1402
+ name: person_id
1403
+ required: false
1404
+ type: string
1405
+ format: UUID
1406
+ x-example: a24a6ea4-ce75-4665-a070-57453082c25
1407
+ - in: formData
1408
+ name: start_date
1409
+ required: false
1410
+ type: string
1411
+ format: date
1412
+ x-example: 2025-01-01
1413
+ - in: formData
1414
+ name: months_duration
1415
+ required: false
1416
+ type: integer
1417
+ x-example: 12
1418
+ - in: formData
1419
+ name: daily_salary
1420
+ required: false
1421
+ type: float
1422
+ x-example: 100.00
1423
+ - in: formData
1424
+ name: position
1425
+ required: false
1426
+ type: string
1427
+ x-example: "Artist"
1428
+ - in: formData
1429
+ name: seniority
1430
+ required: false
1431
+ type: string
1432
+ x-example: "Mid"
1433
+ responses:
1434
+ 200:
1435
+ description: Budget entry updated
1436
+ """
1437
+ user_service.check_manager_project_access(project_id)
1438
+ self.check_id_parameter(project_id)
1439
+ self.check_id_parameter(budget_id)
1440
+ self.check_id_parameter(entry_id)
1441
+ data = self.get_args(
1442
+ [
1443
+ ("department_id", None, False),
1444
+ ("person_id", None, False),
1445
+ ("start_date", None, False),
1446
+ ("months_duration", None, False),
1447
+ ("daily_salary", None, False),
1448
+ ("position", None, False),
1449
+ ("seniority", None, False),
1450
+ ]
1451
+ )
1452
+ return budget_service.update_budget_entry(entry_id, data)
1453
+
1454
+ @jwt_required()
1455
+ def delete(self, project_id, budget_id, entry_id):
1456
+ """
1457
+ Delete a budget entry for given production and budget.
1458
+ ---
1459
+ tags:
1460
+ - Projects
1461
+ parameters:
1462
+ - in: path
1463
+ name: project_id
1464
+ required: true
1465
+ type: string
1466
+ format: UUID
1467
+ x-example: a24a6ea4-ce75-4665-a070-57453082c25
1468
+ - in: path
1469
+ name: budget_id
1470
+ required: true
1471
+ type: string
1472
+ format: UUID
1473
+ x-example: a24a6ea4-ce75-4665-a070-57453082c25
1474
+ - in: path
1475
+ name: entry_id
1476
+ required: true
1477
+ type: string
1478
+ format: UUID
1479
+ x-example: a24a6ea4-ce75-4665-a070-57453082c25
1480
+ responses:
1481
+ 204:
1482
+ description: empty response
1483
+ """
1484
+ self.check_id_parameter(project_id)
1485
+ self.check_id_parameter(budget_id)
1486
+ self.check_id_parameter(entry_id)
1487
+ user_service.check_manager_project_access(project_id)
1488
+ budget_service.delete_budget_entry(entry_id)
1489
+ return "", 204
@@ -565,6 +565,7 @@ class SequenceTaskTypesResource(Resource):
565
565
 
566
566
 
567
567
  class ShotsAndTasksResource(Resource):
568
+
568
569
  @jwt_required()
569
570
  def get(self):
570
571
  """
zou/app/mixin.py CHANGED
@@ -1,7 +1,7 @@
1
1
  from flask_restful import reqparse
2
2
  from flask import request
3
3
 
4
- from zou.app.utils import date_helpers
4
+ from zou.app.utils import date_helpers, fields
5
5
  from zou.app.services.exception import WrongParameterException
6
6
 
7
7
 
@@ -11,6 +11,9 @@ class ArgsMixin(object):
11
11
  """
12
12
 
13
13
  def get_args(self, descriptors, location=None):
14
+ """
15
+ Retrieve arguments from GET or POST queries.
16
+ """
14
17
  parser = reqparse.RequestParser()
15
18
  if location is None:
16
19
  location = ["values", "json"] if request.is_json else ["values"]
@@ -157,3 +160,11 @@ class ArgsMixin(object):
157
160
  "Expected format: 2020-01-05T13:23:10 or 2020-01-05"
158
161
  )
159
162
  return date
163
+
164
+ def check_id_parameter(self, uuid):
165
+ """
166
+ Check if the given UUID is valid.
167
+ """
168
+ if not fields.is_valid_id(uuid):
169
+ raise WrongParameterException("Wrong UUID format.")
170
+ return True
@@ -0,0 +1,39 @@
1
+ from sqlalchemy_utils import UUIDType
2
+
3
+ from zou.app import db
4
+ from zou.app.models.serializer import SerializerMixin
5
+ from zou.app.models.base import BaseMixin
6
+ from zou.app.utils import fields
7
+
8
+
9
+ class Budget(db.Model, BaseMixin, SerializerMixin):
10
+ """
11
+ Budget quote for a project. It's a base object where budget entries
12
+ are linked to.
13
+ """
14
+
15
+ project_id = db.Column(
16
+ UUIDType(binary=False), db.ForeignKey("project.id"), index=True
17
+ )
18
+ revision = db.Column(db.Integer, nullable=False, default=1)
19
+ name = db.Column(db.String(255), nullable=False)
20
+ currency = db.Column(db.String(3))
21
+
22
+ def __repr__(self):
23
+ return "<Budget of %s - %d %s %s>" % (
24
+ self.project_id,
25
+ self.revision,
26
+ self.name,
27
+ self.id,
28
+ )
29
+
30
+ def present(self):
31
+ return fields.serialize_dict(
32
+ {
33
+ "id": self.id,
34
+ "project_id": self.project_id,
35
+ "revision": self.revision,
36
+ "name": self.name,
37
+ "currency": self.currency,
38
+ }
39
+ )
@@ -0,0 +1,65 @@
1
+ from sqlalchemy_utils import (
2
+ UUIDType,
3
+ ChoiceType,
4
+ )
5
+
6
+ from zou.app import db
7
+ from zou.app.models.serializer import SerializerMixin
8
+ from zou.app.models.base import BaseMixin
9
+ from zou.app.utils import fields
10
+
11
+ from zou.app.models.person import POSITION_TYPES, SENIORITY_TYPES
12
+
13
+
14
+ class BudgetEntry(db.Model, BaseMixin, SerializerMixin):
15
+ """
16
+ Budget entry for a budget. It stores the information about a person
17
+ (present or not) salary for a given department.
18
+ """
19
+
20
+ budget_id = db.Column(
21
+ UUIDType(binary=False),
22
+ db.ForeignKey("budget.id"),
23
+ index=True,
24
+ nullable=False,
25
+ )
26
+ department_id = db.Column(
27
+ UUIDType(binary=False),
28
+ db.ForeignKey("department.id"),
29
+ index=True,
30
+ nullable=False,
31
+ )
32
+ person_id = db.Column(
33
+ UUIDType(binary=False),
34
+ db.ForeignKey("person.id"),
35
+ index=True,
36
+ nullable=True,
37
+ )
38
+ start_date = db.Column(db.Date, nullable=False)
39
+ months_duration = db.Column(db.Integer, nullable=False)
40
+ daily_salary = db.Column(db.Float, nullable=False)
41
+ position = db.Column(ChoiceType(POSITION_TYPES), default="artist")
42
+ seniority = db.Column(ChoiceType(SENIORITY_TYPES), default="mid")
43
+
44
+ def __repr__(self):
45
+ return "<BudgetEntry of %s - %d %s %s>" % (
46
+ self.budget_id,
47
+ self.department_id,
48
+ self.person_id,
49
+ self.start_date,
50
+ )
51
+
52
+ def present(self):
53
+ return fields.serialize_dict(
54
+ {
55
+ "id": self.id,
56
+ "budget_id": self.budget_id,
57
+ "department_id": self.department_id,
58
+ "person_id": self.person_id,
59
+ "start_date": self.start_date,
60
+ "months_duration": self.months_duration,
61
+ "daily_salary": self.daily_salary,
62
+ "position": self.position,
63
+ "seniority": self.seniority,
64
+ }
65
+ )
zou/app/models/person.py CHANGED
@@ -13,8 +13,8 @@ from pytz import timezone as pytz_timezone
13
13
  from babel import Locale
14
14
 
15
15
  from zou.app.models.serializer import SerializerMixin
16
- from zou.app.models.base import BaseMixin
17
16
  from zou.app.models.department import Department
17
+ from zou.app.models.base import BaseMixin
18
18
  from zou.app import config, db
19
19
 
20
20
 
@@ -42,6 +42,18 @@ ROLE_TYPES = [
42
42
  ("vendor", "Vendor"),
43
43
  ]
44
44
 
45
+ POSITION_TYPES = [
46
+ ("supervisor", "Supervisor"),
47
+ ("lead", "Lead"),
48
+ ("artist", "Artist"),
49
+ ]
50
+
51
+ SENIORITY_TYPES = [
52
+ ("senior", "Senior"),
53
+ ("mid", "Mid"),
54
+ ("junior", "Junior"),
55
+ ]
56
+
45
57
 
46
58
  class DepartmentLink(db.Model):
47
59
  __tablename__ = "department_link"
@@ -107,6 +119,10 @@ class Person(db.Model, BaseMixin, SerializerMixin):
107
119
  locale = db.Column(LocaleType, default=Locale(config.DEFAULT_LOCALE))
108
120
  data = db.Column(JSONB)
109
121
  role = db.Column(ChoiceType(ROLE_TYPES), default="user", nullable=False)
122
+ position = db.Column(ChoiceType(POSITION_TYPES), default="artist")
123
+ seniority = db.Column(ChoiceType(SENIORITY_TYPES), default="mid")
124
+ daily_salary = db.Column(db.Integer, default=0)
125
+
110
126
  has_avatar = db.Column(db.Boolean(), default=False)
111
127
 
112
128
  notifications_enabled = db.Column(db.Boolean(), default=False)
@@ -0,0 +1,21 @@
1
+ from zou.app import db
2
+ from zou.app.models.serializer import SerializerMixin
3
+ from zou.app.models.base import BaseMixin
4
+ from sqlalchemy_utils import EmailType, URLType
5
+
6
+
7
+ class Plugin(db.Model, BaseMixin, SerializerMixin):
8
+ """
9
+ Describe a plugin.
10
+ """
11
+
12
+ plugin_id = db.Column(
13
+ db.String(80), unique=True, nullable=False, index=True
14
+ )
15
+ name = db.Column(db.String(80), nullable=False, index=True)
16
+ description = db.Column(db.Text())
17
+ version = db.Column(db.String(50), nullable=False)
18
+ maintainer_name = db.Column(db.String(200), nullable=False)
19
+ maintainer_email = db.Column(EmailType)
20
+ website = db.Column(URLType)
21
+ license = db.Column(db.String(80), nullable=False)
@@ -0,0 +1,28 @@
1
+ from sqlalchemy_utils import UUIDType
2
+ from sqlalchemy_utils import ChoiceType
3
+
4
+ from zou.app.models.person import POSITION_TYPES, SENIORITY_TYPES
5
+
6
+ from zou.app import db
7
+ from zou.app.models.serializer import SerializerMixin
8
+ from zou.app.models.base import BaseMixin
9
+
10
+
11
+ class SalaryScale(db.Model, BaseMixin, SerializerMixin):
12
+ """
13
+ Model to represent a salary scale tied to a department.
14
+ """
15
+
16
+ department_id = db.Column(
17
+ UUIDType(binary=False),
18
+ db.ForeignKey("department.id"),
19
+ index=True,
20
+ nullable=False,
21
+ )
22
+
23
+ position = db.Column(ChoiceType(POSITION_TYPES), default="artist")
24
+ seniority = db.Column(ChoiceType(SENIORITY_TYPES), default="mid")
25
+ salary = db.Column(db.Integer, nullable=False, default=0)
26
+
27
+ def present(self):
28
+ return self.serialize()