zou 0.20.61__py3-none-any.whl → 0.20.62__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.
- zou/__init__.py +1 -1
- zou/app/api.py +2 -0
- zou/app/blueprints/crud/__init__.py +25 -1
- zou/app/blueprints/crud/hardware_item.py +12 -0
- zou/app/blueprints/crud/notification.py +0 -4
- zou/app/blueprints/crud/production_schedule_version.py +114 -0
- zou/app/blueprints/departments/__init__.py +35 -0
- zou/app/blueprints/departments/resources.py +262 -0
- zou/app/blueprints/index/resources.py +2 -9
- zou/app/blueprints/persons/resources.py +1 -3
- zou/app/blueprints/projects/__init__.py +20 -0
- zou/app/blueprints/projects/resources.py +200 -0
- zou/app/blueprints/tasks/resources.py +5 -2
- zou/app/blueprints/user/resources.py +1 -3
- zou/app/models/base.py +15 -4
- zou/app/models/department.py +62 -0
- zou/app/models/entity.py +3 -3
- zou/app/models/hardware_item.py +15 -0
- zou/app/models/person.py +1 -1
- zou/app/models/production_schedule_version.py +81 -0
- zou/app/models/project.py +17 -6
- zou/app/models/software.py +5 -1
- zou/app/models/task.py +7 -10
- zou/app/services/assets_service.py +5 -6
- zou/app/services/concepts_service.py +3 -4
- zou/app/services/deletion_service.py +10 -18
- zou/app/services/departments_service.py +153 -0
- zou/app/services/edits_service.py +3 -4
- zou/app/services/entities_service.py +5 -6
- zou/app/services/exception.py +8 -0
- zou/app/services/file_tree_service.py +2 -2
- zou/app/services/preview_files_service.py +6 -2
- zou/app/services/schedule_service.py +243 -1
- zou/app/services/shots_service.py +3 -4
- zou/app/services/tasks_service.py +5 -1
- zou/app/services/user_service.py +57 -23
- zou/migrations/alembic.ini +1 -1
- zou/migrations/versions/0bd1e89f2a6f_add_productionscheduleversiontasklink_uc.py +58 -0
- zou/migrations/versions/26f96f65cfa3_add_productionversionschedule_uc.py +40 -0
- zou/migrations/versions/3d8e68dffeee_fix_task_person_link.py +56 -0
- zou/migrations/versions/4368137b44e1_productionscheduleversion_add_on_delete_.py +188 -0
- zou/migrations/versions/4bd9bfb73f11_add_fields_to_the_software_table.py +49 -0
- zou/migrations/versions/5f715f2b6348_add_new_table_productionscheduleversion.py +128 -0
- zou/migrations/versions/7a16258f2fab_add_currency_field_to_budgets.py +2 -4
- zou/migrations/versions/9683bd840dee_add_archived_field_to_software.py +33 -0
- zou/migrations/versions/9af2df17a9d5_add_hardware_table.py +48 -0
- zou/migrations/versions/ce7f46f445dc_add_column_estimation_for_.py +37 -0
- zou/migrations/versions/d5665dca188b_add_version_field_to_software.py +35 -0
- zou/migrations/versions/d97f2730bf7b_add_.py +101 -0
- zou/migrations/versions/dde6be40f54f_add_departement_links_tables_for_.py +151 -0
- zou/migrations/versions/e4b48ca33539_add_project_production_schedule_version_.py +56 -0
- zou/migrations/versions/e8bc24998b34_remove_on_delete_cascade_for_.py +59 -0
- {zou-0.20.61.dist-info → zou-0.20.62.dist-info}/METADATA +1 -1
- {zou-0.20.61.dist-info → zou-0.20.62.dist-info}/RECORD +58 -37
- {zou-0.20.61.dist-info → zou-0.20.62.dist-info}/WHEEL +0 -0
- {zou-0.20.61.dist-info → zou-0.20.62.dist-info}/entry_points.txt +0 -0
- {zou-0.20.61.dist-info → zou-0.20.62.dist-info}/licenses/LICENSE +0 -0
- {zou-0.20.61.dist-info → zou-0.20.62.dist-info}/top_level.txt +0 -0
|
@@ -1526,3 +1526,203 @@ class ProductionMonthTimeSpentsResource(Resource, ArgsMixin):
|
|
|
1526
1526
|
return time_spents_service.get_project_month_time_spents(
|
|
1527
1527
|
project_id, user["timezone"]
|
|
1528
1528
|
)
|
|
1529
|
+
|
|
1530
|
+
|
|
1531
|
+
class ProductionScheduleVersionTaskLinksResource(Resource, ArgsMixin):
|
|
1532
|
+
|
|
1533
|
+
@jwt_required()
|
|
1534
|
+
def get(self, production_schedule_version_id):
|
|
1535
|
+
"""
|
|
1536
|
+
Get task links for given production schedule version.
|
|
1537
|
+
---
|
|
1538
|
+
tags:
|
|
1539
|
+
- Projects
|
|
1540
|
+
parameters:
|
|
1541
|
+
- in: path
|
|
1542
|
+
name: production_schedule_version_id
|
|
1543
|
+
required: True
|
|
1544
|
+
type: string
|
|
1545
|
+
format: UUID
|
|
1546
|
+
x-example: a24a6ea4-ce75-4665-a070-57453082c25
|
|
1547
|
+
- in: query
|
|
1548
|
+
name: task_type_id
|
|
1549
|
+
required: false
|
|
1550
|
+
type: string
|
|
1551
|
+
format: UUID
|
|
1552
|
+
x-example: a24a6ea4-ce75-4665-a070-57453082c25
|
|
1553
|
+
responses:
|
|
1554
|
+
200:
|
|
1555
|
+
description: Task links for given production schedule version.
|
|
1556
|
+
400:
|
|
1557
|
+
description: Wrong ID format
|
|
1558
|
+
"""
|
|
1559
|
+
production_schedule_version = (
|
|
1560
|
+
schedule_service.get_production_schedule_version(
|
|
1561
|
+
production_schedule_version_id
|
|
1562
|
+
)
|
|
1563
|
+
)
|
|
1564
|
+
if (
|
|
1565
|
+
permissions.has_vendor_permissions()
|
|
1566
|
+
or permissions.has_client_permissions()
|
|
1567
|
+
):
|
|
1568
|
+
raise permissions.PermissionDenied
|
|
1569
|
+
user_service.check_project_access(
|
|
1570
|
+
production_schedule_version["project_id"]
|
|
1571
|
+
)
|
|
1572
|
+
|
|
1573
|
+
args = self.get_args(
|
|
1574
|
+
[
|
|
1575
|
+
("task_type_id", None, False),
|
|
1576
|
+
]
|
|
1577
|
+
)
|
|
1578
|
+
|
|
1579
|
+
relations = self.get_relations()
|
|
1580
|
+
|
|
1581
|
+
return schedule_service.get_production_schedule_version_task_links(
|
|
1582
|
+
production_schedule_version_id,
|
|
1583
|
+
task_type_id=args["task_type_id"],
|
|
1584
|
+
relations=relations,
|
|
1585
|
+
)
|
|
1586
|
+
|
|
1587
|
+
|
|
1588
|
+
class ProductionScheduleVersionSetTaskLinksFromTasksResource(
|
|
1589
|
+
Resource, ArgsMixin
|
|
1590
|
+
):
|
|
1591
|
+
|
|
1592
|
+
@jwt_required()
|
|
1593
|
+
def post(self, production_schedule_version_id):
|
|
1594
|
+
"""
|
|
1595
|
+
Set task links for given production schedule version from tasks.
|
|
1596
|
+
---
|
|
1597
|
+
tags:
|
|
1598
|
+
- Projects
|
|
1599
|
+
parameters:
|
|
1600
|
+
- in: path
|
|
1601
|
+
name: production_schedule_version_id
|
|
1602
|
+
required: True
|
|
1603
|
+
type: string
|
|
1604
|
+
format: UUID
|
|
1605
|
+
x-example: a24a6ea4-ce75-4665-a070-57453082c25
|
|
1606
|
+
responses:
|
|
1607
|
+
200:
|
|
1608
|
+
description: Task links created.
|
|
1609
|
+
400:
|
|
1610
|
+
description: Wrong ID format
|
|
1611
|
+
"""
|
|
1612
|
+
production_schedule_version = (
|
|
1613
|
+
schedule_service.get_production_schedule_version(
|
|
1614
|
+
production_schedule_version_id
|
|
1615
|
+
)
|
|
1616
|
+
)
|
|
1617
|
+
user_service.check_manager_project_access(
|
|
1618
|
+
production_schedule_version["project_id"]
|
|
1619
|
+
)
|
|
1620
|
+
|
|
1621
|
+
return schedule_service.set_production_schedule_version_task_links_from_production(
|
|
1622
|
+
production_schedule_version_id
|
|
1623
|
+
)
|
|
1624
|
+
|
|
1625
|
+
|
|
1626
|
+
class ProductionScheduleVersionApplyToProductionResource(Resource, ArgsMixin):
|
|
1627
|
+
|
|
1628
|
+
@jwt_required()
|
|
1629
|
+
def post(self, production_schedule_version_id):
|
|
1630
|
+
"""
|
|
1631
|
+
Apply production schedule version to production.
|
|
1632
|
+
---
|
|
1633
|
+
tags:
|
|
1634
|
+
- Projects
|
|
1635
|
+
parameters:
|
|
1636
|
+
- in: path
|
|
1637
|
+
name: production_schedule_version_id
|
|
1638
|
+
required: True
|
|
1639
|
+
type: string
|
|
1640
|
+
format: UUID
|
|
1641
|
+
x-example: a24a6ea4-ce75-4665-a070-57453082c25
|
|
1642
|
+
responses:
|
|
1643
|
+
200:
|
|
1644
|
+
description: Task links created.
|
|
1645
|
+
400:
|
|
1646
|
+
description: Wrong ID format
|
|
1647
|
+
"""
|
|
1648
|
+
production_schedule_version = (
|
|
1649
|
+
schedule_service.get_production_schedule_version(
|
|
1650
|
+
production_schedule_version_id
|
|
1651
|
+
)
|
|
1652
|
+
)
|
|
1653
|
+
user_service.check_manager_project_access(
|
|
1654
|
+
production_schedule_version["project_id"]
|
|
1655
|
+
)
|
|
1656
|
+
|
|
1657
|
+
return (
|
|
1658
|
+
schedule_service.apply_production_schedule_version_to_production(
|
|
1659
|
+
production_schedule_version_id,
|
|
1660
|
+
)
|
|
1661
|
+
)
|
|
1662
|
+
|
|
1663
|
+
|
|
1664
|
+
class ProductionScheduleVersionSetTaskLinksFromProductionScheduleVersionResource(
|
|
1665
|
+
Resource, ArgsMixin
|
|
1666
|
+
):
|
|
1667
|
+
|
|
1668
|
+
@jwt_required()
|
|
1669
|
+
def post(self, production_schedule_version_id):
|
|
1670
|
+
"""
|
|
1671
|
+
Set task links for given production schedule version from another production schedule version.
|
|
1672
|
+
---
|
|
1673
|
+
tags:
|
|
1674
|
+
- Projects
|
|
1675
|
+
parameters:
|
|
1676
|
+
- in: path
|
|
1677
|
+
name: production_schedule_version_id
|
|
1678
|
+
required: True
|
|
1679
|
+
type: string
|
|
1680
|
+
format: UUID
|
|
1681
|
+
x-example: a24a6ea4-ce75-4665-a070-57453082c25
|
|
1682
|
+
- in: formData
|
|
1683
|
+
name: production_schedule_version_id
|
|
1684
|
+
required: True
|
|
1685
|
+
type: string
|
|
1686
|
+
format: UUID
|
|
1687
|
+
x-example: a24a6ea4-ce75-4665-a070-57453082c25
|
|
1688
|
+
responses:
|
|
1689
|
+
200:
|
|
1690
|
+
description: Task links created.
|
|
1691
|
+
400:
|
|
1692
|
+
description: Wrong ID format
|
|
1693
|
+
"""
|
|
1694
|
+
production_schedule_version = (
|
|
1695
|
+
schedule_service.get_production_schedule_version(
|
|
1696
|
+
production_schedule_version_id
|
|
1697
|
+
)
|
|
1698
|
+
)
|
|
1699
|
+
user_service.check_manager_project_access(
|
|
1700
|
+
production_schedule_version["project_id"]
|
|
1701
|
+
)
|
|
1702
|
+
|
|
1703
|
+
args = self.get_args(
|
|
1704
|
+
[
|
|
1705
|
+
("production_schedule_version_id", None, True),
|
|
1706
|
+
]
|
|
1707
|
+
)
|
|
1708
|
+
|
|
1709
|
+
other_production_schedule_version = (
|
|
1710
|
+
schedule_service.get_production_schedule_version(
|
|
1711
|
+
args["production_schedule_version_id"]
|
|
1712
|
+
)
|
|
1713
|
+
)
|
|
1714
|
+
|
|
1715
|
+
if (
|
|
1716
|
+
production_schedule_version["project_id"]
|
|
1717
|
+
!= other_production_schedule_version["project_id"]
|
|
1718
|
+
):
|
|
1719
|
+
raise WrongParameterException(
|
|
1720
|
+
"Production schedule versions must belong to the same project."
|
|
1721
|
+
)
|
|
1722
|
+
|
|
1723
|
+
return schedule_service.set_production_schedule_version_task_links_from_production_schedule_version(
|
|
1724
|
+
production_schedule_version_id,
|
|
1725
|
+
other_production_schedule_version_id=other_production_schedule_version[
|
|
1726
|
+
"id"
|
|
1727
|
+
],
|
|
1728
|
+
)
|
|
@@ -1603,7 +1603,7 @@ class SetTaskMainPreviewResource(Resource):
|
|
|
1603
1603
|
return entity
|
|
1604
1604
|
|
|
1605
1605
|
|
|
1606
|
-
class PersonsTasksDatesResource(Resource):
|
|
1606
|
+
class PersonsTasksDatesResource(Resource, ArgsMixin):
|
|
1607
1607
|
@jwt_required()
|
|
1608
1608
|
@permissions.require_admin
|
|
1609
1609
|
def get(self):
|
|
@@ -1625,7 +1625,10 @@ class PersonsTasksDatesResource(Resource):
|
|
|
1625
1625
|
description: For each person, the first start date of all tasks of assigned to this person and the last end date.
|
|
1626
1626
|
"""
|
|
1627
1627
|
permissions.check_admin_permissions()
|
|
1628
|
-
|
|
1628
|
+
args = self.get_args([("project_id", None, True, str)])
|
|
1629
|
+
return tasks_service.get_persons_tasks_dates(
|
|
1630
|
+
project_id=args["project_id"]
|
|
1631
|
+
)
|
|
1629
1632
|
|
|
1630
1633
|
|
|
1631
1634
|
class OpenTasksResource(Resource, ArgsMixin):
|
|
@@ -1229,9 +1229,7 @@ class TimeSpentsResource(Resource):
|
|
|
1229
1229
|
except WrongDateFormatException:
|
|
1230
1230
|
abort(
|
|
1231
1231
|
400,
|
|
1232
|
-
"Wrong date format for {} and/or {}"
|
|
1233
|
-
start_date, end_date
|
|
1234
|
-
),
|
|
1232
|
+
f"Wrong date format for {start_date} and/or {end_date}",
|
|
1235
1233
|
)
|
|
1236
1234
|
|
|
1237
1235
|
|
zou/app/models/base.py
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
from sqlalchemy_utils import UUIDType
|
|
2
|
-
from sqlalchemy import func
|
|
3
|
-
from sqlalchemy import orm
|
|
2
|
+
from sqlalchemy import func, orm
|
|
4
3
|
from zou.app import db
|
|
5
|
-
from zou.app.utils import
|
|
4
|
+
from zou.app.utils import date_helpers, fields
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
class BaseMixin(object):
|
|
9
8
|
id = db.Column(
|
|
10
|
-
UUIDType(binary=False),
|
|
9
|
+
UUIDType(binary=False),
|
|
10
|
+
primary_key=True,
|
|
11
|
+
default=fields.gen_uuid,
|
|
11
12
|
)
|
|
12
13
|
|
|
13
14
|
# Audit fields
|
|
@@ -78,6 +79,16 @@ class BaseMixin(object):
|
|
|
78
79
|
"""
|
|
79
80
|
return cls.query.filter_by(**kw).all()
|
|
80
81
|
|
|
82
|
+
@classmethod
|
|
83
|
+
def get_or_create(cls, **kw):
|
|
84
|
+
"""
|
|
85
|
+
Shorthand to retrieve data by using filters.
|
|
86
|
+
"""
|
|
87
|
+
instance = cls.get_by(**kw)
|
|
88
|
+
if instance is None:
|
|
89
|
+
instance = cls.create(**kw)
|
|
90
|
+
return instance
|
|
91
|
+
|
|
81
92
|
@classmethod
|
|
82
93
|
def create(cls, **kw):
|
|
83
94
|
"""
|
zou/app/models/department.py
CHANGED
|
@@ -2,6 +2,68 @@ from zou.app import db
|
|
|
2
2
|
from zou.app.models.serializer import SerializerMixin
|
|
3
3
|
from zou.app.models.base import BaseMixin
|
|
4
4
|
|
|
5
|
+
from sqlalchemy_utils import UUIDType
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class HardwareItemDepartmentLink(db.Model, BaseMixin, SerializerMixin):
|
|
9
|
+
"""
|
|
10
|
+
Uses a many-to-many relationship to link hardware items with departments.
|
|
11
|
+
It can be used to track which hardware items are used by which departments in
|
|
12
|
+
order to set budget forecasting.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
__tablename__ = "hardware_item_department_link"
|
|
16
|
+
department_id = db.Column(
|
|
17
|
+
UUIDType(binary=False),
|
|
18
|
+
db.ForeignKey("department.id"),
|
|
19
|
+
primary_key=True,
|
|
20
|
+
index=True,
|
|
21
|
+
)
|
|
22
|
+
hardware_item_id = db.Column(
|
|
23
|
+
UUIDType(binary=False),
|
|
24
|
+
db.ForeignKey("hardware_item.id"),
|
|
25
|
+
primary_key=True,
|
|
26
|
+
index=True,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
__table_args__ = (
|
|
30
|
+
db.UniqueConstraint(
|
|
31
|
+
"hardware_item_id",
|
|
32
|
+
"department_id",
|
|
33
|
+
name="hardware_item_department_link_uc",
|
|
34
|
+
),
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class SoftwareDepartmentLink(db.Model, BaseMixin, SerializerMixin):
|
|
39
|
+
"""
|
|
40
|
+
Uses a many-to-many relationship to link software with departments.
|
|
41
|
+
It can be used to track which software is used by which departments in
|
|
42
|
+
order to set budget forecasting.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
__tablename__ = "software_department_link"
|
|
46
|
+
department_id = db.Column(
|
|
47
|
+
UUIDType(binary=False),
|
|
48
|
+
db.ForeignKey("department.id"),
|
|
49
|
+
primary_key=True,
|
|
50
|
+
index=True,
|
|
51
|
+
)
|
|
52
|
+
software_id = db.Column(
|
|
53
|
+
UUIDType(binary=False),
|
|
54
|
+
db.ForeignKey("software.id"),
|
|
55
|
+
primary_key=True,
|
|
56
|
+
index=True,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
__table_args__ = (
|
|
60
|
+
db.UniqueConstraint(
|
|
61
|
+
"department_id",
|
|
62
|
+
"software_id",
|
|
63
|
+
name="software_department_link_uc",
|
|
64
|
+
),
|
|
65
|
+
)
|
|
66
|
+
|
|
5
67
|
|
|
6
68
|
class Department(db.Model, BaseMixin, SerializerMixin):
|
|
7
69
|
"""
|
zou/app/models/entity.py
CHANGED
|
@@ -149,7 +149,7 @@ class Entity(db.Model, BaseMixin, SerializerMixin):
|
|
|
149
149
|
|
|
150
150
|
entities_out = db.relationship(
|
|
151
151
|
"Entity",
|
|
152
|
-
secondary=
|
|
152
|
+
secondary=EntityLink.__table__,
|
|
153
153
|
primaryjoin=(id == EntityLink.entity_in_id),
|
|
154
154
|
secondaryjoin=(id == EntityLink.entity_out_id),
|
|
155
155
|
backref="entities_in",
|
|
@@ -157,14 +157,14 @@ class Entity(db.Model, BaseMixin, SerializerMixin):
|
|
|
157
157
|
|
|
158
158
|
entity_concept_links = db.relationship(
|
|
159
159
|
"Entity",
|
|
160
|
-
secondary=
|
|
160
|
+
secondary=EntityConceptLink.__table__,
|
|
161
161
|
primaryjoin=(id == EntityConceptLink.entity_in_id),
|
|
162
162
|
secondaryjoin=(id == EntityConceptLink.entity_out_id),
|
|
163
163
|
lazy="joined",
|
|
164
164
|
)
|
|
165
165
|
|
|
166
166
|
instance_casting = db.relationship(
|
|
167
|
-
"AssetInstance", secondary=
|
|
167
|
+
"AssetInstance", secondary=AssetInstanceLink.__table__, backref="shots"
|
|
168
168
|
)
|
|
169
169
|
|
|
170
170
|
__table_args__ = (
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from zou.app import db
|
|
2
|
+
from zou.app.models.serializer import SerializerMixin
|
|
3
|
+
from zou.app.models.base import BaseMixin
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class HardwareItem(db.Model, BaseMixin, SerializerMixin):
|
|
7
|
+
"""
|
|
8
|
+
Describes hardware items available in the studio.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
name = db.Column(db.String(40), unique=True, nullable=False)
|
|
12
|
+
short_name = db.Column(db.String(20), nullable=False)
|
|
13
|
+
archived = db.Column(db.Boolean, default=False)
|
|
14
|
+
monthly_cost = db.Column(db.Integer, default=0)
|
|
15
|
+
inventory_amount = db.Column(db.Integer, default=0)
|
zou/app/models/person.py
CHANGED
|
@@ -138,7 +138,7 @@ class Person(db.Model, BaseMixin, SerializerMixin):
|
|
|
138
138
|
expiration_date = db.Column(db.Date(), nullable=True)
|
|
139
139
|
|
|
140
140
|
departments = db.relationship(
|
|
141
|
-
"Department", secondary=
|
|
141
|
+
"Department", secondary=DepartmentLink.__table__, lazy="joined"
|
|
142
142
|
)
|
|
143
143
|
studio_id = db.Column(
|
|
144
144
|
UUIDType(binary=False), db.ForeignKey("studio.id"), index=True
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
from zou.app import db
|
|
2
|
+
from zou.app.models.serializer import SerializerMixin
|
|
3
|
+
from zou.app.models.base import BaseMixin
|
|
4
|
+
|
|
5
|
+
from sqlalchemy_utils import UUIDType
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ProductionScheduleVersion(db.Model, BaseMixin, SerializerMixin):
|
|
9
|
+
"""
|
|
10
|
+
Describe a production schedule.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
name = db.Column(db.String(80), nullable=False)
|
|
14
|
+
project_id = db.Column(
|
|
15
|
+
UUIDType(binary=False),
|
|
16
|
+
db.ForeignKey("project.id", ondelete="CASCADE"),
|
|
17
|
+
index=True,
|
|
18
|
+
nullable=False,
|
|
19
|
+
)
|
|
20
|
+
production_schedule_from = db.Column(
|
|
21
|
+
UUIDType(binary=False),
|
|
22
|
+
db.ForeignKey("production_schedule_version.id"),
|
|
23
|
+
index=True,
|
|
24
|
+
nullable=True,
|
|
25
|
+
)
|
|
26
|
+
locked = db.Column(db.Boolean(), default=False)
|
|
27
|
+
canceled = db.Column(db.Boolean(), default=False)
|
|
28
|
+
__table_args__ = (
|
|
29
|
+
db.UniqueConstraint(
|
|
30
|
+
"name", "project_id", name="production_schedule_version_uc"
|
|
31
|
+
),
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class ProductionScheduleVersionTaskLinkPersonLink(db.Model):
|
|
36
|
+
__tablename__ = "production_schedule_version_task_link_person_link"
|
|
37
|
+
production_schedule_version_task_link_id = db.Column(
|
|
38
|
+
UUIDType(binary=False),
|
|
39
|
+
db.ForeignKey(
|
|
40
|
+
"production_schedule_version_task_link.id", ondelete="CASCADE"
|
|
41
|
+
),
|
|
42
|
+
primary_key=True,
|
|
43
|
+
)
|
|
44
|
+
person_id = db.Column(
|
|
45
|
+
UUIDType(binary=False),
|
|
46
|
+
db.ForeignKey("person.id", ondelete="CASCADE"),
|
|
47
|
+
primary_key=True,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class ProductionScheduleVersionTaskLink(db.Model, BaseMixin, SerializerMixin):
|
|
52
|
+
"""
|
|
53
|
+
Link a task to a production schedule version.
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
production_schedule_version_id = db.Column(
|
|
57
|
+
UUIDType(binary=False),
|
|
58
|
+
db.ForeignKey("production_schedule_version.id", ondelete="CASCADE"),
|
|
59
|
+
index=True,
|
|
60
|
+
nullable=False,
|
|
61
|
+
)
|
|
62
|
+
task_id = db.Column(
|
|
63
|
+
UUIDType(binary=False),
|
|
64
|
+
db.ForeignKey("task.id", ondelete="CASCADE"),
|
|
65
|
+
index=True,
|
|
66
|
+
nullable=False,
|
|
67
|
+
)
|
|
68
|
+
start_date = db.Column(db.DateTime)
|
|
69
|
+
due_date = db.Column(db.DateTime)
|
|
70
|
+
estimation = db.Column(db.Float, default=0)
|
|
71
|
+
assignees = db.relationship(
|
|
72
|
+
"Person",
|
|
73
|
+
secondary=ProductionScheduleVersionTaskLinkPersonLink.__table__,
|
|
74
|
+
)
|
|
75
|
+
__table_args__ = (
|
|
76
|
+
db.UniqueConstraint(
|
|
77
|
+
"production_schedule_version_id",
|
|
78
|
+
"task_id",
|
|
79
|
+
name="production_schedule_version_task_link_uc",
|
|
80
|
+
),
|
|
81
|
+
)
|
zou/app/models/project.py
CHANGED
|
@@ -178,22 +178,33 @@ class Project(db.Model, BaseMixin, SerializerMixin):
|
|
|
178
178
|
index=True,
|
|
179
179
|
)
|
|
180
180
|
|
|
181
|
-
|
|
181
|
+
from_schedule_version_id = db.Column(
|
|
182
|
+
UUIDType(binary=False),
|
|
183
|
+
db.ForeignKey(
|
|
184
|
+
"production_schedule_version.id",
|
|
185
|
+
name="project_from_schedule_version_id_fkey",
|
|
186
|
+
use_alter=True,
|
|
187
|
+
),
|
|
188
|
+
index=True,
|
|
189
|
+
nullable=True,
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
team = db.relationship("Person", secondary=ProjectPersonLink.__table__)
|
|
182
193
|
asset_types = db.relationship(
|
|
183
|
-
"EntityType", secondary=
|
|
194
|
+
"EntityType", secondary=ProjectAssetTypeLink.__table__
|
|
184
195
|
)
|
|
185
196
|
task_statuses = db.relationship(
|
|
186
|
-
"TaskStatus", secondary=
|
|
197
|
+
"TaskStatus", secondary=ProjectTaskStatusLink.__table__
|
|
187
198
|
)
|
|
188
199
|
task_types = db.relationship(
|
|
189
|
-
"TaskType", secondary=
|
|
200
|
+
"TaskType", secondary=ProjectTaskTypeLink.__table__
|
|
190
201
|
)
|
|
191
202
|
status_automations = db.relationship(
|
|
192
|
-
"StatusAutomation", secondary=
|
|
203
|
+
"StatusAutomation", secondary=ProjectStatusAutomationLink.__table__
|
|
193
204
|
)
|
|
194
205
|
preview_background_files = db.relationship(
|
|
195
206
|
"PreviewBackgroundFile",
|
|
196
|
-
secondary=
|
|
207
|
+
secondary=ProjectPreviewBackgroundFileLink.__table__,
|
|
197
208
|
)
|
|
198
209
|
|
|
199
210
|
def set_team(self, person_ids):
|
zou/app/models/software.py
CHANGED
|
@@ -7,10 +7,14 @@ from sqlalchemy.dialects.postgresql import JSONB
|
|
|
7
7
|
|
|
8
8
|
class Software(db.Model, BaseMixin, SerializerMixin):
|
|
9
9
|
"""
|
|
10
|
-
Describes software used
|
|
10
|
+
Describes software used in the studio.
|
|
11
11
|
"""
|
|
12
12
|
|
|
13
13
|
name = db.Column(db.String(40), unique=True, nullable=False)
|
|
14
14
|
short_name = db.Column(db.String(20), nullable=False)
|
|
15
|
+
archived = db.Column(db.Boolean, default=False)
|
|
16
|
+
version = db.Column(db.String(20), nullable=True)
|
|
15
17
|
file_extension = db.Column(db.String(20), nullable=False)
|
|
16
18
|
secondary_extensions = db.Column(JSONB)
|
|
19
|
+
monthly_cost = db.Column(db.Integer, default=0)
|
|
20
|
+
inventory_amount = db.Column(db.Integer, default=0)
|
zou/app/models/task.py
CHANGED
|
@@ -5,21 +5,18 @@ from zou.app.models.serializer import SerializerMixin
|
|
|
5
5
|
from zou.app.models.base import BaseMixin
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
"
|
|
10
|
-
db.Column(
|
|
11
|
-
"task",
|
|
8
|
+
class TaskPersonLink(db.Model):
|
|
9
|
+
__tablename__ = "task_person_link"
|
|
10
|
+
task_id = db.Column(
|
|
12
11
|
UUIDType(binary=False),
|
|
13
12
|
db.ForeignKey("task.id"),
|
|
14
13
|
primary_key=True,
|
|
15
|
-
)
|
|
16
|
-
db.Column(
|
|
17
|
-
"person",
|
|
14
|
+
)
|
|
15
|
+
person_id = db.Column(
|
|
18
16
|
UUIDType(binary=False),
|
|
19
17
|
db.ForeignKey("person.id"),
|
|
20
18
|
primary_key=True,
|
|
21
|
-
)
|
|
22
|
-
)
|
|
19
|
+
)
|
|
23
20
|
|
|
24
21
|
|
|
25
22
|
class Task(db.Model, BaseMixin, SerializerMixin):
|
|
@@ -67,7 +64,7 @@ class Task(db.Model, BaseMixin, SerializerMixin):
|
|
|
67
64
|
assigner_id = db.Column(
|
|
68
65
|
UUIDType(binary=False), db.ForeignKey("person.id"), index=True
|
|
69
66
|
)
|
|
70
|
-
assignees = db.relationship("Person", secondary=
|
|
67
|
+
assignees = db.relationship("Person", secondary=TaskPersonLink.__table__)
|
|
71
68
|
|
|
72
69
|
__table_args__ = (
|
|
73
70
|
db.UniqueConstraint(
|
|
@@ -14,9 +14,8 @@ from zou.app.models.entity import (
|
|
|
14
14
|
from zou.app.models.entity_type import EntityType
|
|
15
15
|
from zou.app.models.subscription import Subscription
|
|
16
16
|
from zou.app.models.project import Project
|
|
17
|
-
from zou.app.models.task import Task
|
|
17
|
+
from zou.app.models.task import Task, TaskPersonLink
|
|
18
18
|
from zou.app.models.asset_instance import AssetInstance
|
|
19
|
-
from zou.app.models.task import assignees_table
|
|
20
19
|
|
|
21
20
|
from zou.app.services import (
|
|
22
21
|
base_service,
|
|
@@ -184,7 +183,7 @@ def get_assets_and_tasks(criterions={}, with_episode_ids=False):
|
|
|
184
183
|
Entity.query.filter(build_asset_type_filter())
|
|
185
184
|
.join(EntityType, Entity.entity_type_id == EntityType.id)
|
|
186
185
|
.outerjoin(Task)
|
|
187
|
-
.outerjoin(
|
|
186
|
+
.outerjoin(TaskPersonLink)
|
|
188
187
|
)
|
|
189
188
|
|
|
190
189
|
tasks_query = query.add_columns(
|
|
@@ -204,7 +203,7 @@ def get_assets_and_tasks(criterions={}, with_episode_ids=False):
|
|
|
204
203
|
Task.last_comment_date,
|
|
205
204
|
Task.last_preview_file_id,
|
|
206
205
|
Task.difficulty,
|
|
207
|
-
|
|
206
|
+
TaskPersonLink.person_id,
|
|
208
207
|
).order_by(EntityType.name, Entity.name)
|
|
209
208
|
|
|
210
209
|
if "id" in criterions:
|
|
@@ -656,8 +655,6 @@ def remove_asset(asset_id, force=False):
|
|
|
656
655
|
for task in tasks:
|
|
657
656
|
deletion_service.remove_task(task.id, force=True)
|
|
658
657
|
tasks_service.clear_task_cache(str(task.id))
|
|
659
|
-
asset.delete()
|
|
660
|
-
clear_asset_cache(str(asset_id))
|
|
661
658
|
index_service.remove_asset_index(str(asset_id))
|
|
662
659
|
events.emit(
|
|
663
660
|
"asset:delete",
|
|
@@ -670,6 +667,8 @@ def remove_asset(asset_id, force=False):
|
|
|
670
667
|
EntityLink.delete_all_by(entity_out_id=asset_id)
|
|
671
668
|
EntityConceptLink.delete_all_by(entity_in_id=asset_id)
|
|
672
669
|
EntityConceptLink.delete_all_by(entity_out_id=asset_id)
|
|
670
|
+
asset.delete()
|
|
671
|
+
clear_asset_cache(str(asset_id))
|
|
673
672
|
deleted_asset = asset.serialize(obj_type="Asset")
|
|
674
673
|
return deleted_asset
|
|
675
674
|
|
|
@@ -15,8 +15,7 @@ from zou.app.models.entity import (
|
|
|
15
15
|
)
|
|
16
16
|
from zou.app.models.project import Project
|
|
17
17
|
from zou.app.models.subscription import Subscription
|
|
18
|
-
from zou.app.models.task import Task
|
|
19
|
-
from zou.app.models.task import assignees_table
|
|
18
|
+
from zou.app.models.task import Task, TaskPersonLink
|
|
20
19
|
|
|
21
20
|
from zou.app.services import (
|
|
22
21
|
deletion_service,
|
|
@@ -177,7 +176,7 @@ def get_concepts_and_tasks(criterions={}):
|
|
|
177
176
|
query = (
|
|
178
177
|
Entity.query.join(Project, Project.id == Entity.project_id)
|
|
179
178
|
.outerjoin(Task, Task.entity_id == Entity.id)
|
|
180
|
-
.outerjoin(
|
|
179
|
+
.outerjoin(TaskPersonLink)
|
|
181
180
|
.add_columns(
|
|
182
181
|
Task.id,
|
|
183
182
|
Task.task_type_id,
|
|
@@ -192,7 +191,7 @@ def get_concepts_and_tasks(criterions={}):
|
|
|
192
191
|
Task.due_date,
|
|
193
192
|
Task.last_comment_date,
|
|
194
193
|
Task.nb_assets_ready,
|
|
195
|
-
|
|
194
|
+
TaskPersonLink.person_id,
|
|
196
195
|
Project.id,
|
|
197
196
|
Project.name,
|
|
198
197
|
)
|
|
@@ -342,20 +342,13 @@ def remove_project(project_id):
|
|
|
342
342
|
for task in tasks:
|
|
343
343
|
remove_task(task.id, force=True)
|
|
344
344
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
query = EntityVersion.query.join(
|
|
353
|
-
Entity, EntityVersion.entity_id == Entity.id
|
|
354
|
-
).filter(Entity.project_id == project_id)
|
|
355
|
-
for version in query:
|
|
356
|
-
version.delete_no_commit()
|
|
357
|
-
EntityLink.commit()
|
|
358
|
-
|
|
345
|
+
EntityLink.query.filter(
|
|
346
|
+
EntityLink.entity_in_id == Entity.id,
|
|
347
|
+
Entity.project_id == project_id,
|
|
348
|
+
).delete()
|
|
349
|
+
EntityVersion.query.filter(
|
|
350
|
+
EntityVersion.entity_id == Entity.id, Entity.project_id == project_id
|
|
351
|
+
).delete()
|
|
359
352
|
playlists = Playlist.query.filter_by(project_id=project_id)
|
|
360
353
|
for playlist in playlists:
|
|
361
354
|
playlists_service.remove_playlist(playlist.id)
|
|
@@ -372,10 +365,9 @@ def remove_project(project_id):
|
|
|
372
365
|
ScheduleItem.delete_all_by(project_id=project_id)
|
|
373
366
|
SearchFilterGroup.delete_all_by(project_id=project_id)
|
|
374
367
|
SearchFilter.delete_all_by(project_id=project_id)
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
News.commit()
|
|
368
|
+
News.query.filter(
|
|
369
|
+
News.task_id == Task.id, Task.project_id == project_id
|
|
370
|
+
).delete()
|
|
379
371
|
project = Project.get(project_id)
|
|
380
372
|
project.delete()
|
|
381
373
|
events.emit("project:delete", {"project_id": project.id})
|