zou 0.19.51__py3-none-any.whl → 0.19.53__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/__init__.py +1 -1
- zou/app/blueprints/assets/__init__.py +22 -0
- zou/app/blueprints/assets/resources.py +240 -3
- zou/app/blueprints/auth/resources.py +26 -22
- zou/app/blueprints/chats/resources.py +2 -2
- zou/app/blueprints/crud/base.py +10 -6
- zou/app/blueprints/crud/day_off.py +3 -3
- zou/app/blueprints/crud/entity.py +3 -3
- zou/app/blueprints/crud/entity_type.py +15 -0
- zou/app/blueprints/crud/metadata_descriptor.py +16 -3
- zou/app/blueprints/crud/person.py +13 -15
- zou/app/blueprints/crud/preview_background_file.py +3 -3
- zou/app/blueprints/crud/project.py +5 -5
- zou/app/blueprints/crud/schedule_item.py +2 -2
- zou/app/blueprints/crud/task_type.py +3 -3
- zou/app/blueprints/persons/resources.py +2 -2
- zou/app/blueprints/previews/resources.py +31 -6
- zou/app/blueprints/projects/resources.py +1 -1
- zou/app/blueprints/shots/resources.py +2 -2
- zou/app/models/base.py +6 -1
- zou/app/models/entity.py +3 -5
- zou/app/services/assets_service.py +74 -1
- zou/app/services/breakdown_service.py +33 -3
- zou/app/services/deletion_service.py +5 -0
- zou/app/services/exception.py +1 -5
- zou/app/services/preview_files_service.py +2 -2
- zou/app/services/tasks_service.py +1 -1
- zou/app/services/time_spents_service.py +4 -4
- zou/app/swagger.py +15 -20
- zou/app/utils/query.py +53 -5
- zou/event_stream.py +1 -0
- zou/migrations/versions/59a7445a966c_add_entity_is_shared.py +41 -0
- {zou-0.19.51.dist-info → zou-0.19.53.dist-info}/METADATA +6 -6
- {zou-0.19.51.dist-info → zou-0.19.53.dist-info}/RECORD +39 -38
- {zou-0.19.51.dist-info → zou-0.19.53.dist-info}/WHEEL +1 -1
- {zou-0.19.51.dist-info → zou-0.19.53.dist-info}/LICENSE +0 -0
- {zou-0.19.51.dist-info → zou-0.19.53.dist-info}/entry_points.txt +0 -0
- {zou-0.19.51.dist-info → zou-0.19.53.dist-info}/top_level.txt +0 -0
|
@@ -20,7 +20,7 @@ from zou.app.blueprints.crud.base import BaseModelsResource, BaseModelResource
|
|
|
20
20
|
from zou.app.mixin import ArgsMixin
|
|
21
21
|
|
|
22
22
|
from zou.app.services.exception import (
|
|
23
|
-
|
|
23
|
+
WrongParameterException,
|
|
24
24
|
PersonInProtectedAccounts,
|
|
25
25
|
)
|
|
26
26
|
|
|
@@ -61,11 +61,9 @@ class PersonsResource(BaseModelsResource):
|
|
|
61
61
|
and data.get("active", True)
|
|
62
62
|
and persons_service.is_user_limit_reached()
|
|
63
63
|
):
|
|
64
|
-
raise
|
|
64
|
+
raise WrongParameterException(
|
|
65
65
|
"User limit reached.",
|
|
66
66
|
{
|
|
67
|
-
"error": True,
|
|
68
|
-
"message": "User limit reached.",
|
|
69
67
|
"limit": config.USER_LIMIT,
|
|
70
68
|
},
|
|
71
69
|
)
|
|
@@ -75,18 +73,18 @@ class PersonsResource(BaseModelsResource):
|
|
|
75
73
|
if "role" in data and data["role"] not in [
|
|
76
74
|
role for role, _ in ROLE_TYPES
|
|
77
75
|
]:
|
|
78
|
-
raise
|
|
76
|
+
raise WrongParameterException("Invalid role")
|
|
79
77
|
if "contract_type" in data and data["contract_type"] not in [
|
|
80
78
|
contract_type for contract_type, _ in CONTRACT_TYPES
|
|
81
79
|
]:
|
|
82
|
-
raise
|
|
80
|
+
raise WrongParameterException("Invalid contract_type")
|
|
83
81
|
if "two_factor_authentication" in data and data[
|
|
84
82
|
"two_factor_authentication"
|
|
85
83
|
] not in [
|
|
86
84
|
two_factor_authentication
|
|
87
85
|
for two_factor_authentication, _ in TWO_FACTOR_AUTHENTICATION_TYPES
|
|
88
86
|
]:
|
|
89
|
-
raise
|
|
87
|
+
raise WrongParameterException("Invalid two_factor_authentication")
|
|
90
88
|
|
|
91
89
|
if "expiration_date" in data and data["expiration_date"] is not None:
|
|
92
90
|
try:
|
|
@@ -96,11 +94,11 @@ class PersonsResource(BaseModelsResource):
|
|
|
96
94
|
).date()
|
|
97
95
|
< datetime.date.today()
|
|
98
96
|
):
|
|
99
|
-
raise
|
|
97
|
+
raise WrongParameterException(
|
|
100
98
|
"Expiration date can't be in the past."
|
|
101
99
|
)
|
|
102
100
|
except:
|
|
103
|
-
raise
|
|
101
|
+
raise WrongParameterException("Expiration date is not valid.")
|
|
104
102
|
return data
|
|
105
103
|
|
|
106
104
|
def update_data(self, data):
|
|
@@ -156,18 +154,18 @@ class PersonResource(BaseModelResource, ArgsMixin):
|
|
|
156
154
|
if "role" in data and data["role"] not in [
|
|
157
155
|
role for role, _ in ROLE_TYPES
|
|
158
156
|
]:
|
|
159
|
-
raise
|
|
157
|
+
raise WrongParameterException("Invalid role")
|
|
160
158
|
if "contract_type" in data and data["contract_type"] not in [
|
|
161
159
|
contract_type for contract_type, _ in CONTRACT_TYPES
|
|
162
160
|
]:
|
|
163
|
-
raise
|
|
161
|
+
raise WrongParameterException("Invalid contract_type")
|
|
164
162
|
if "two_factor_authentication" in data and data[
|
|
165
163
|
"two_factor_authentication"
|
|
166
164
|
] not in [
|
|
167
165
|
two_factor_authentication
|
|
168
166
|
for two_factor_authentication, _ in TWO_FACTOR_AUTHENTICATION_TYPES
|
|
169
167
|
]:
|
|
170
|
-
raise
|
|
168
|
+
raise WrongParameterException("Invalid two_factor_authentication")
|
|
171
169
|
|
|
172
170
|
if "expiration_date" in data and data["expiration_date"] is not None:
|
|
173
171
|
try:
|
|
@@ -177,11 +175,11 @@ class PersonResource(BaseModelResource, ArgsMixin):
|
|
|
177
175
|
).date()
|
|
178
176
|
< datetime.date.today()
|
|
179
177
|
):
|
|
180
|
-
raise
|
|
178
|
+
raise WrongParameterException(
|
|
181
179
|
"Expiration date can't be in the past."
|
|
182
180
|
)
|
|
183
181
|
except:
|
|
184
|
-
raise
|
|
182
|
+
raise WrongParameterException("Expiration date is not valid.")
|
|
185
183
|
return data
|
|
186
184
|
|
|
187
185
|
def check_delete_permissions(self, instance_dict):
|
|
@@ -204,7 +202,7 @@ class PersonResource(BaseModelResource, ArgsMixin):
|
|
|
204
202
|
and not data.get("is_bot", False)
|
|
205
203
|
and persons_service.is_user_limit_reached()
|
|
206
204
|
):
|
|
207
|
-
raise
|
|
205
|
+
raise WrongParameterException("User limit reached.")
|
|
208
206
|
if instance_dict["email"] in config.PROTECTED_ACCOUNTS:
|
|
209
207
|
message = None
|
|
210
208
|
if data.get("active") is False:
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from zou.app.models.preview_background_file import PreviewBackgroundFile
|
|
2
|
-
from zou.app.services.exception import
|
|
2
|
+
from zou.app.services.exception import WrongParameterException
|
|
3
3
|
from zou.app.services import files_service, deletion_service
|
|
4
4
|
|
|
5
5
|
from zou.app.blueprints.crud.base import BaseModelResource, BaseModelsResource
|
|
@@ -17,7 +17,7 @@ class PreviewBackgroundFilesResource(BaseModelsResource):
|
|
|
17
17
|
name = data.get("name", None)
|
|
18
18
|
preview_background_file = PreviewBackgroundFile.get_by(name=name)
|
|
19
19
|
if preview_background_file is not None:
|
|
20
|
-
raise
|
|
20
|
+
raise WrongParameterException(
|
|
21
21
|
"A preview background file with similar name already exists"
|
|
22
22
|
)
|
|
23
23
|
return data
|
|
@@ -44,7 +44,7 @@ class PreviewBackgroundFileResource(BaseModelResource):
|
|
|
44
44
|
if preview_background_file is not None and instance_id != str(
|
|
45
45
|
preview_background_file.id
|
|
46
46
|
):
|
|
47
|
-
raise
|
|
47
|
+
raise WrongParameterException(
|
|
48
48
|
"A preview background file with similar name already exists"
|
|
49
49
|
)
|
|
50
50
|
return data
|
|
@@ -18,7 +18,7 @@ from zou.app.utils import events, permissions, fields
|
|
|
18
18
|
|
|
19
19
|
from zou.app.blueprints.crud.base import BaseModelResource, BaseModelsResource
|
|
20
20
|
|
|
21
|
-
from zou.app.services.exception import
|
|
21
|
+
from zou.app.services.exception import WrongParameterException
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
class ProjectsResource(BaseModelsResource):
|
|
@@ -44,7 +44,7 @@ class ProjectsResource(BaseModelsResource):
|
|
|
44
44
|
if data["production_style"] not in [
|
|
45
45
|
type_name for type_name, _ in PROJECT_STYLES
|
|
46
46
|
]:
|
|
47
|
-
raise
|
|
47
|
+
raise WrongParameterException("Invalid production_style")
|
|
48
48
|
return True
|
|
49
49
|
|
|
50
50
|
def update_data(self, data):
|
|
@@ -71,7 +71,7 @@ class ProjectsResource(BaseModelsResource):
|
|
|
71
71
|
or data["preview_background_file_id"]
|
|
72
72
|
not in data["preview_background_files_ids"]
|
|
73
73
|
):
|
|
74
|
-
raise
|
|
74
|
+
raise WrongParameterException("Invalid preview_background_file_id")
|
|
75
75
|
return data
|
|
76
76
|
|
|
77
77
|
def post_creation(self, project):
|
|
@@ -131,7 +131,7 @@ class ProjectResource(BaseModelResource, ArgsMixin):
|
|
|
131
131
|
data["preview_background_file_id"]
|
|
132
132
|
not in preview_background_files_ids
|
|
133
133
|
):
|
|
134
|
-
raise
|
|
134
|
+
raise WrongParameterException("Invalid preview_background_file_id")
|
|
135
135
|
|
|
136
136
|
return data
|
|
137
137
|
|
|
@@ -167,7 +167,7 @@ class ProjectResource(BaseModelResource, ArgsMixin):
|
|
|
167
167
|
if data["production_style"] not in [
|
|
168
168
|
type_name for type_name, _ in PROJECT_STYLES
|
|
169
169
|
]:
|
|
170
|
-
raise
|
|
170
|
+
raise WrongParameterException("Invalid production_style")
|
|
171
171
|
return data
|
|
172
172
|
|
|
173
173
|
@jwt_required()
|
|
@@ -3,7 +3,7 @@ from zou.app.models.schedule_item import ScheduleItem
|
|
|
3
3
|
from zou.app.blueprints.crud.base import BaseModelResource, BaseModelsResource
|
|
4
4
|
|
|
5
5
|
from zou.app.services import user_service
|
|
6
|
-
from zou.app.services.exception import
|
|
6
|
+
from zou.app.services.exception import WrongParameterException
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class ScheduleItemsResource(BaseModelsResource):
|
|
@@ -17,7 +17,7 @@ class ScheduleItemsResource(BaseModelsResource):
|
|
|
17
17
|
object_id=data.get("object_id", None),
|
|
18
18
|
)
|
|
19
19
|
if schedule_item is not None:
|
|
20
|
-
raise
|
|
20
|
+
raise WrongParameterException("A similar schedule item already exists")
|
|
21
21
|
return schedule_item
|
|
22
22
|
|
|
23
23
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from zou.app.models.task_type import TaskType
|
|
2
|
-
from zou.app.services.exception import
|
|
2
|
+
from zou.app.services.exception import WrongParameterException
|
|
3
3
|
from zou.app.services import tasks_service
|
|
4
4
|
|
|
5
5
|
from zou.app.blueprints.crud.base import BaseModelResource, BaseModelsResource
|
|
@@ -17,7 +17,7 @@ class TaskTypesResource(BaseModelsResource):
|
|
|
17
17
|
name = data.get("name", None)
|
|
18
18
|
task_type = TaskType.get_by(name=name)
|
|
19
19
|
if task_type is not None:
|
|
20
|
-
raise
|
|
20
|
+
raise WrongParameterException(
|
|
21
21
|
"A task type with similar name already exists"
|
|
22
22
|
)
|
|
23
23
|
return data
|
|
@@ -40,7 +40,7 @@ class TaskTypeResource(BaseModelResource):
|
|
|
40
40
|
if name is not None:
|
|
41
41
|
task_type = TaskType.get_by(name=name)
|
|
42
42
|
if task_type is not None and instance_id != str(task_type.id):
|
|
43
|
-
raise
|
|
43
|
+
raise WrongParameterException(
|
|
44
44
|
"A task type with similar name already exists"
|
|
45
45
|
)
|
|
46
46
|
return data
|
|
@@ -30,7 +30,7 @@ from zou.app.services.exception import (
|
|
|
30
30
|
UnactiveUserException,
|
|
31
31
|
TwoFactorAuthenticationNotEnabledException,
|
|
32
32
|
PersonInProtectedAccounts,
|
|
33
|
-
|
|
33
|
+
WrongParameterException,
|
|
34
34
|
)
|
|
35
35
|
from zou.app.services.auth_service import (
|
|
36
36
|
disable_two_factor_authentication_for_person,
|
|
@@ -779,7 +779,7 @@ class TimeSpentDurationResource(Resource, ArgsMixin):
|
|
|
779
779
|
)["departments"]
|
|
780
780
|
if department_id is not None:
|
|
781
781
|
if department_id not in persons_departments:
|
|
782
|
-
raise
|
|
782
|
+
raise WrongParameterException(
|
|
783
783
|
"Supervisor not allowed to access this department"
|
|
784
784
|
)
|
|
785
785
|
else:
|
|
@@ -35,7 +35,7 @@ from zou.app.utils import (
|
|
|
35
35
|
date_helpers,
|
|
36
36
|
)
|
|
37
37
|
from zou.app.services.exception import (
|
|
38
|
-
|
|
38
|
+
WrongParameterException,
|
|
39
39
|
PreviewBackgroundFileNotFoundException,
|
|
40
40
|
PreviewFileReuploadNotAllowedException,
|
|
41
41
|
)
|
|
@@ -813,7 +813,29 @@ class BasePreviewPictureResource(BasePreviewFileResource):
|
|
|
813
813
|
abort(404)
|
|
814
814
|
|
|
815
815
|
|
|
816
|
-
class
|
|
816
|
+
class BasePreviewFileThumbnailResource(BasePreviewPictureResource):
|
|
817
|
+
"""
|
|
818
|
+
Base class to download a thumbnail for a preview file.
|
|
819
|
+
"""
|
|
820
|
+
|
|
821
|
+
def is_allowed(self, preview_file_id):
|
|
822
|
+
self.preview_file = files_service.get_preview_file(preview_file_id)
|
|
823
|
+
task = tasks_service.get_task(self.preview_file["task_id"])
|
|
824
|
+
entity = entities_service.get_entity(task["entity_id"])
|
|
825
|
+
if (
|
|
826
|
+
entity["preview_file_id"] != preview_file_id
|
|
827
|
+
or not entity["is_shared"]
|
|
828
|
+
or permissions.has_vendor_permissions()
|
|
829
|
+
):
|
|
830
|
+
user_service.check_project_access(task["project_id"])
|
|
831
|
+
user_service.check_entity_access(task["entity_id"])
|
|
832
|
+
self.last_modified = date_helpers.get_datetime_from_string(
|
|
833
|
+
self.preview_file["updated_at"]
|
|
834
|
+
)
|
|
835
|
+
|
|
836
|
+
|
|
837
|
+
class PreviewFileThumbnailResource(BasePreviewFileThumbnailResource):
|
|
838
|
+
|
|
817
839
|
def __init__(self):
|
|
818
840
|
BasePreviewPictureResource.__init__(self, "thumbnails")
|
|
819
841
|
|
|
@@ -832,12 +854,12 @@ class PreviewFilePreviewResource(BasePreviewPictureResource):
|
|
|
832
854
|
BasePreviewPictureResource.__init__(self, "previews")
|
|
833
855
|
|
|
834
856
|
|
|
835
|
-
class PreviewFileThumbnailSquareResource(
|
|
857
|
+
class PreviewFileThumbnailSquareResource(BasePreviewFileThumbnailResource):
|
|
836
858
|
def __init__(self):
|
|
837
859
|
BasePreviewPictureResource.__init__(self, "thumbnails-square")
|
|
838
860
|
|
|
839
861
|
|
|
840
|
-
class PreviewFileOriginalResource(
|
|
862
|
+
class PreviewFileOriginalResource(BasePreviewFileThumbnailResource):
|
|
841
863
|
def __init__(self):
|
|
842
864
|
BasePreviewPictureResource.__init__(self, "original")
|
|
843
865
|
|
|
@@ -981,6 +1003,7 @@ class BaseThumbnailResource(Resource):
|
|
|
981
1003
|
|
|
982
1004
|
|
|
983
1005
|
class PersonThumbnailResource(BaseThumbnailResource):
|
|
1006
|
+
|
|
984
1007
|
def __init__(self):
|
|
985
1008
|
BaseThumbnailResource.__init__(
|
|
986
1009
|
self,
|
|
@@ -1028,11 +1051,13 @@ class ProjectThumbnailResource(BaseThumbnailResource):
|
|
|
1028
1051
|
"projects",
|
|
1029
1052
|
projects_service.get_project,
|
|
1030
1053
|
projects_service.update_project,
|
|
1054
|
+
thumbnail_utils.BIG_SQUARE_SIZE,
|
|
1031
1055
|
)
|
|
1032
1056
|
|
|
1033
1057
|
def check_allowed_to_get(self, instance_id):
|
|
1034
1058
|
super().check_allowed_to_get(instance_id)
|
|
1035
|
-
|
|
1059
|
+
if not permissions.has_manager_permissions():
|
|
1060
|
+
user_service.check_project_access(instance_id)
|
|
1036
1061
|
|
|
1037
1062
|
|
|
1038
1063
|
class CreateProjectThumbnailResource(ProjectThumbnailResource):
|
|
@@ -1072,7 +1097,7 @@ class SetMainPreviewResource(Resource, ArgsMixin):
|
|
|
1072
1097
|
user_service.check_entity_access(task["entity_id"])
|
|
1073
1098
|
if frame_number is not None:
|
|
1074
1099
|
if preview_file["extension"] != "mp4":
|
|
1075
|
-
raise
|
|
1100
|
+
raise WrongParameterException(
|
|
1076
1101
|
"Can't use a given frame on non movie preview"
|
|
1077
1102
|
)
|
|
1078
1103
|
preview_files_service.replace_extracted_frame_for_preview_file(
|
|
@@ -659,7 +659,7 @@ class ProductionMetadataDescriptorsResource(Resource, ArgsMixin):
|
|
|
659
659
|
200:
|
|
660
660
|
description: All metadata descriptors
|
|
661
661
|
"""
|
|
662
|
-
user_service.
|
|
662
|
+
user_service.check_project_access(project_id)
|
|
663
663
|
for_client = permissions.has_client_permissions()
|
|
664
664
|
return projects_service.get_metadata_descriptors(
|
|
665
665
|
project_id, for_client
|
|
@@ -20,7 +20,7 @@ from zou.app.mixin import ArgsMixin
|
|
|
20
20
|
from zou.app.utils import fields, query, permissions
|
|
21
21
|
from zou.app.services.exception import (
|
|
22
22
|
WrongParameterException,
|
|
23
|
-
|
|
23
|
+
WrongParameterException,
|
|
24
24
|
)
|
|
25
25
|
|
|
26
26
|
|
|
@@ -77,7 +77,7 @@ class ShotResource(Resource, ArgsMixin):
|
|
|
77
77
|
user_service.check_manager_project_access(shot["project_id"])
|
|
78
78
|
data = request.json
|
|
79
79
|
if data is None:
|
|
80
|
-
raise
|
|
80
|
+
raise WrongParameterException(
|
|
81
81
|
"Data are empty. Please verify that you sent JSON data and"
|
|
82
82
|
" that you set the right headers."
|
|
83
83
|
)
|
zou/app/models/base.py
CHANGED
|
@@ -184,7 +184,12 @@ class BaseMixin(object):
|
|
|
184
184
|
|
|
185
185
|
@classmethod
|
|
186
186
|
def commit(cls):
|
|
187
|
-
|
|
187
|
+
try:
|
|
188
|
+
db.session.commit()
|
|
189
|
+
except BaseException:
|
|
190
|
+
db.session.rollback()
|
|
191
|
+
db.session.remove()
|
|
192
|
+
raise
|
|
188
193
|
|
|
189
194
|
def save(self):
|
|
190
195
|
"""
|
zou/app/models/entity.py
CHANGED
|
@@ -3,7 +3,6 @@ from sqlalchemy_utils import UUIDType, ChoiceType
|
|
|
3
3
|
from zou.app import db
|
|
4
4
|
from zou.app.models.serializer import SerializerMixin
|
|
5
5
|
from zou.app.models.base import BaseMixin
|
|
6
|
-
from zou.app.utils import fields
|
|
7
6
|
|
|
8
7
|
from sqlalchemy.dialects.postgresql import JSONB
|
|
9
8
|
|
|
@@ -90,10 +89,7 @@ class Entity(db.Model, BaseMixin, SerializerMixin):
|
|
|
90
89
|
tasks and files.
|
|
91
90
|
"""
|
|
92
91
|
|
|
93
|
-
id =
|
|
94
|
-
UUIDType(binary=False), primary_key=True, default=fields.gen_uuid
|
|
95
|
-
)
|
|
96
|
-
|
|
92
|
+
id = BaseMixin.id
|
|
97
93
|
name = db.Column(db.String(160), nullable=False)
|
|
98
94
|
code = db.Column(db.String(160)) # To store sanitized version of name
|
|
99
95
|
description = db.Column(db.Text())
|
|
@@ -104,6 +100,8 @@ class Entity(db.Model, BaseMixin, SerializerMixin):
|
|
|
104
100
|
nb_entities_out = db.Column(db.Integer, default=0)
|
|
105
101
|
is_casting_standby = db.Column(db.Boolean, default=False)
|
|
106
102
|
|
|
103
|
+
is_shared = db.Column(db.Boolean, default=False, nullable=False)
|
|
104
|
+
|
|
107
105
|
status = db.Column(
|
|
108
106
|
ChoiceType(ENTITY_STATUSES), default="running", nullable=False
|
|
109
107
|
)
|
|
@@ -84,7 +84,7 @@ def build_entity_type_asset_type_filter():
|
|
|
84
84
|
return ~EntityType.id.in_(ids_to_exclude)
|
|
85
85
|
|
|
86
86
|
|
|
87
|
-
def get_assets(criterions={}):
|
|
87
|
+
def get_assets(criterions={}, is_admin=False):
|
|
88
88
|
"""
|
|
89
89
|
Get all assets for given criterions.
|
|
90
90
|
"""
|
|
@@ -102,6 +102,12 @@ def get_assets(criterions={}):
|
|
|
102
102
|
query = query.outerjoin(Task)
|
|
103
103
|
query = query.filter(user_service.build_assignee_filter())
|
|
104
104
|
|
|
105
|
+
if "is_shared" in criterions:
|
|
106
|
+
if not is_admin:
|
|
107
|
+
query = (
|
|
108
|
+
query.join(Project).filter(user_service.build_team_filter())
|
|
109
|
+
)
|
|
110
|
+
|
|
105
111
|
if episode_id is not None:
|
|
106
112
|
# Filter based on main episode.
|
|
107
113
|
query = query.filter(Entity.source_id == episode_id)
|
|
@@ -306,6 +312,7 @@ def get_assets_and_tasks(criterions={}, page=1, with_episode_ids=False):
|
|
|
306
312
|
"episode_id": source_id,
|
|
307
313
|
"casting_episode_ids": cast_in_episode_ids.get(asset_id, []),
|
|
308
314
|
"is_casting_standby": asset.is_casting_standby,
|
|
315
|
+
"is_shared": asset.is_shared,
|
|
309
316
|
"data": data,
|
|
310
317
|
"tasks": [],
|
|
311
318
|
}
|
|
@@ -571,6 +578,7 @@ def create_asset(
|
|
|
571
578
|
name,
|
|
572
579
|
description,
|
|
573
580
|
data,
|
|
581
|
+
is_shared=False,
|
|
574
582
|
source_id=None,
|
|
575
583
|
created_by=None,
|
|
576
584
|
):
|
|
@@ -587,6 +595,7 @@ def create_asset(
|
|
|
587
595
|
name=name,
|
|
588
596
|
description=description,
|
|
589
597
|
data=data,
|
|
598
|
+
is_shared=is_shared,
|
|
590
599
|
source_id=source_id,
|
|
591
600
|
created_by=created_by,
|
|
592
601
|
)
|
|
@@ -706,3 +715,67 @@ def cancel_asset(asset_id, force=True):
|
|
|
706
715
|
project_id=str(asset.project_id),
|
|
707
716
|
)
|
|
708
717
|
return asset_dict
|
|
718
|
+
|
|
719
|
+
|
|
720
|
+
def set_shared_assets(
|
|
721
|
+
is_shared=True,
|
|
722
|
+
project_id=None,
|
|
723
|
+
asset_type_id=None,
|
|
724
|
+
asset_ids=None,
|
|
725
|
+
):
|
|
726
|
+
"""
|
|
727
|
+
Set all assets of a project to is_shared=True or False.
|
|
728
|
+
"""
|
|
729
|
+
|
|
730
|
+
query = Entity.query.filter(build_asset_type_filter()).filter()
|
|
731
|
+
|
|
732
|
+
if project_id is not None:
|
|
733
|
+
query = query.filter(Entity.project_id == project_id)
|
|
734
|
+
|
|
735
|
+
if asset_type_id is not None:
|
|
736
|
+
query = query.filter(Entity.entity_type_id == asset_type_id)
|
|
737
|
+
|
|
738
|
+
if asset_ids is not None:
|
|
739
|
+
query = query.filter(Entity.id.in_(asset_ids))
|
|
740
|
+
|
|
741
|
+
assets = query.all()
|
|
742
|
+
|
|
743
|
+
for asset in assets:
|
|
744
|
+
asset.update_no_commit({"is_shared": is_shared})
|
|
745
|
+
|
|
746
|
+
Entity.commit()
|
|
747
|
+
|
|
748
|
+
for asset in assets:
|
|
749
|
+
asset_id = str(asset.id)
|
|
750
|
+
clear_asset_cache(asset_id)
|
|
751
|
+
events.emit(
|
|
752
|
+
"asset:update",
|
|
753
|
+
{"asset_id": asset_id},
|
|
754
|
+
project_id=project_id,
|
|
755
|
+
)
|
|
756
|
+
|
|
757
|
+
return Entity.serialize_list(assets, obj_type="Asset")
|
|
758
|
+
|
|
759
|
+
|
|
760
|
+
def get_shared_assets_used_in_project(project_id, episode_id=None):
|
|
761
|
+
"""
|
|
762
|
+
Get all shared assets used in a project.
|
|
763
|
+
"""
|
|
764
|
+
Shot = aliased(Entity, name="shot")
|
|
765
|
+
Sequence = aliased(Entity, name="sequence")
|
|
766
|
+
|
|
767
|
+
assets = (
|
|
768
|
+
Entity.query.filter(build_asset_type_filter())
|
|
769
|
+
.filter(Entity.is_shared == True)
|
|
770
|
+
.join(EntityLink, EntityLink.entity_out_id == Entity.id)
|
|
771
|
+
.join(Shot, EntityLink.entity_in_id == Shot.id)
|
|
772
|
+
.join(Sequence, Shot.parent_id == Sequence.id)
|
|
773
|
+
.filter(Shot.project_id == project_id)
|
|
774
|
+
.filter(Entity.canceled != True)
|
|
775
|
+
.filter(Entity.project_id != project_id)
|
|
776
|
+
)
|
|
777
|
+
|
|
778
|
+
if episode_id is not None and episode_id not in ["main", "all"]:
|
|
779
|
+
assets = assets.filter(Sequence.parent_id == episode_id)
|
|
780
|
+
|
|
781
|
+
return Entity.serialize_list(assets.all(), obj_type="Asset")
|
|
@@ -50,6 +50,8 @@ def get_casting(shot_id):
|
|
|
50
50
|
Entity.preview_file_id,
|
|
51
51
|
Entity.source_id,
|
|
52
52
|
Entity.ready_for,
|
|
53
|
+
Entity.is_shared,
|
|
54
|
+
Entity.project_id,
|
|
53
55
|
)
|
|
54
56
|
.order_by(EntityType.name, Entity.name)
|
|
55
57
|
)
|
|
@@ -61,6 +63,8 @@ def get_casting(shot_id):
|
|
|
61
63
|
entity_preview_file_id,
|
|
62
64
|
episode_id,
|
|
63
65
|
entity_ready_for,
|
|
66
|
+
entity_is_shared,
|
|
67
|
+
entity_project_id,
|
|
64
68
|
) in links:
|
|
65
69
|
casting.append(
|
|
66
70
|
{
|
|
@@ -74,6 +78,8 @@ def get_casting(shot_id):
|
|
|
74
78
|
),
|
|
75
79
|
"nb_occurences": link.nb_occurences,
|
|
76
80
|
"label": link.label,
|
|
81
|
+
"is_shared": entity_is_shared,
|
|
82
|
+
"project_id": entity_project_id,
|
|
77
83
|
}
|
|
78
84
|
)
|
|
79
85
|
return casting
|
|
@@ -93,11 +99,27 @@ def get_production_episodes_casting(project_id):
|
|
|
93
99
|
.join(EntityType, Entity.entity_type_id == EntityType.id)
|
|
94
100
|
.filter(Episode.project_id == project_id)
|
|
95
101
|
.filter(Entity.canceled != True)
|
|
96
|
-
.add_columns(
|
|
97
|
-
|
|
102
|
+
.add_columns(
|
|
103
|
+
Entity.name,
|
|
104
|
+
EntityType.name,
|
|
105
|
+
Entity.preview_file_id,
|
|
106
|
+
Entity.is_shared,
|
|
107
|
+
Entity.project_id,
|
|
108
|
+
)
|
|
109
|
+
.order_by(
|
|
110
|
+
EntityType.name,
|
|
111
|
+
Entity.name,
|
|
112
|
+
)
|
|
98
113
|
)
|
|
99
114
|
|
|
100
|
-
for
|
|
115
|
+
for (
|
|
116
|
+
link,
|
|
117
|
+
entity_name,
|
|
118
|
+
entity_type_name,
|
|
119
|
+
entity_preview_file_id,
|
|
120
|
+
entity_is_shared,
|
|
121
|
+
entity_project_id,
|
|
122
|
+
) in links:
|
|
101
123
|
episode_id = str(link.entity_in_id)
|
|
102
124
|
if episode_id not in castings:
|
|
103
125
|
castings[episode_id] = []
|
|
@@ -112,6 +134,8 @@ def get_production_episodes_casting(project_id):
|
|
|
112
134
|
),
|
|
113
135
|
"nb_occurences": link.nb_occurences,
|
|
114
136
|
"label": link.label,
|
|
137
|
+
"is_shared": entity_is_shared,
|
|
138
|
+
"project_id": entity_project_id,
|
|
115
139
|
}
|
|
116
140
|
)
|
|
117
141
|
return castings
|
|
@@ -139,6 +163,8 @@ def get_sequence_casting(sequence_id, project_id=None, episode_id=None):
|
|
|
139
163
|
Entity.name,
|
|
140
164
|
EntityType.name,
|
|
141
165
|
Entity.preview_file_id,
|
|
166
|
+
Entity.is_shared,
|
|
167
|
+
Entity.project_id,
|
|
142
168
|
Sequence.name,
|
|
143
169
|
)
|
|
144
170
|
)
|
|
@@ -163,6 +189,8 @@ def get_sequence_casting(sequence_id, project_id=None, episode_id=None):
|
|
|
163
189
|
entity_name,
|
|
164
190
|
entity_type_name,
|
|
165
191
|
entity_preview_file_id,
|
|
192
|
+
entity_is_shared,
|
|
193
|
+
entity_project_id,
|
|
166
194
|
sequence_name,
|
|
167
195
|
) in links:
|
|
168
196
|
shot_id = str(link.entity_in_id)
|
|
@@ -180,6 +208,8 @@ def get_sequence_casting(sequence_id, project_id=None, episode_id=None):
|
|
|
180
208
|
),
|
|
181
209
|
"nb_occurences": link.nb_occurences,
|
|
182
210
|
"label": link.label,
|
|
211
|
+
"is_shared": entity_is_shared,
|
|
212
|
+
"project_id": entity_project_id,
|
|
183
213
|
}
|
|
184
214
|
)
|
|
185
215
|
return castings
|
|
@@ -362,6 +362,11 @@ def remove_project(project_id):
|
|
|
362
362
|
|
|
363
363
|
ApiEvent.delete_all_by(project_id=project_id)
|
|
364
364
|
Entity.delete_all_by(project_id=project_id)
|
|
365
|
+
|
|
366
|
+
descriptors = MetadataDescriptor.query.filter_by(project_id=project_id)
|
|
367
|
+
for descriptor in descriptors:
|
|
368
|
+
descriptor.departments = []
|
|
369
|
+
descriptor.save()
|
|
365
370
|
MetadataDescriptor.delete_all_by(project_id=project_id)
|
|
366
371
|
Milestone.delete_all_by(project_id=project_id)
|
|
367
372
|
ScheduleItem.delete_all_by(project_id=project_id)
|
zou/app/services/exception.py
CHANGED
|
@@ -251,7 +251,7 @@ class EntryAlreadyExistsException(Exception):
|
|
|
251
251
|
pass
|
|
252
252
|
|
|
253
253
|
|
|
254
|
-
class
|
|
254
|
+
class WrongParameterException(Exception):
|
|
255
255
|
def __init__(self, message, dict=None):
|
|
256
256
|
super().__init__(message)
|
|
257
257
|
self.dict = dict
|
|
@@ -261,10 +261,6 @@ class WrongIdFormatException(Exception):
|
|
|
261
261
|
pass
|
|
262
262
|
|
|
263
263
|
|
|
264
|
-
class WrongParameterException(Exception):
|
|
265
|
-
pass
|
|
266
|
-
|
|
267
|
-
|
|
268
264
|
class ModelWithRelationsDeletionException(Exception):
|
|
269
265
|
pass
|
|
270
266
|
|
|
@@ -34,7 +34,7 @@ from zou.app.utils import (
|
|
|
34
34
|
thumbnail as thumbnail_utils,
|
|
35
35
|
)
|
|
36
36
|
from zou.app.services.exception import (
|
|
37
|
-
|
|
37
|
+
WrongParameterException,
|
|
38
38
|
PreviewFileNotFoundException,
|
|
39
39
|
ProjectNotFoundException,
|
|
40
40
|
EpisodeNotFoundException,
|
|
@@ -650,7 +650,7 @@ def extract_tile_from_preview_file(preview_file):
|
|
|
650
650
|
extracted_tile_path = movie.generate_tile(preview_file_path)
|
|
651
651
|
return extracted_tile_path
|
|
652
652
|
else:
|
|
653
|
-
return
|
|
653
|
+
return WrongParameterException("Preview file is not a movie")
|
|
654
654
|
|
|
655
655
|
|
|
656
656
|
def reset_movie_files_metadata():
|
|
@@ -1082,7 +1082,7 @@ def get_person_tasks_to_check(project_ids=None, department_ids=None):
|
|
|
1082
1082
|
else:
|
|
1083
1083
|
query = query.filter(user_service.build_open_project_filter())
|
|
1084
1084
|
|
|
1085
|
-
if department_ids
|
|
1085
|
+
if department_ids:
|
|
1086
1086
|
query = query.filter(TaskType.department_id.in_(department_ids))
|
|
1087
1087
|
tasks = []
|
|
1088
1088
|
for (
|