class OutputFile(db.Model, BaseMixin, SerializerMixin): """ Describe a file generated from a CG artist scene. It's the result of a publication. It is linked to a working file, an entity and a task type. """ shotgun_id = db.Column(db.Integer()) name = db.Column(db.String(250), nullable=False) extension = db.Column(db.String(10)) revision = db.Column(db.Integer(), nullable=False) representation = db.Column(db.String(20), index=True) nb_elements = db.Column(db.Integer(), default=1) path = db.Column(db.String(400)) description = db.Column(db.Text()) comment = db.Column(db.Text()) size = db.Column(db.Integer()) checksum = db.Column(db.String(32)) source = db.Column(db.String(40)) canceled = db.Column(db.Boolean(), default=False, nullable=False) file_status_id = db.Column(UUIDType(binary=False), db.ForeignKey("file_status.id"), nullable=False) entity_id = db.Column(UUIDType(binary=False), db.ForeignKey("entity.id")) asset_instance_id = db.Column(UUIDType(binary=False), db.ForeignKey("asset_instance.id"), index=True) output_type_id = db.Column(UUIDType(binary=False), db.ForeignKey("output_type.id"), index=True) task_type_id = db.Column(UUIDType(binary=False), db.ForeignKey("task_type.id"), index=True) person_id = db.Column(UUIDType(binary=False), db.ForeignKey("person.id")) source_file_id = db.Column( UUIDType(binary=False), db.ForeignKey("working_file.id"), ) source_file = relationship("WorkingFile", back_populates="outputs") temporal_entity_id = db.Column(UUIDType(binary=False), db.ForeignKey("entity.id"), default=None, nullable=True) __table_args__ = (db.UniqueConstraint("name", "entity_id", "asset_instance_id", "output_type_id", "task_type_id", "temporal_entity_id", "representation", "revision", name="output_file_uc"), ) def __repr__(self): return "<OutputFile %s>" % self.id
class Comment(db.Model, BaseMixin, SerializerMixin): """ Comment can occurs on any object but they are mainly used on tasks. In the case of comment tasks, they are linked to a task status and eventually on a preview file. The status means that comment leads to task status change. The preview file means that the comment relates to this preview in the context of the task. """ shotgun_id = db.Column(db.Integer) object_id = db.Column(UUIDType(binary=False), nullable=False, index=True) object_type = db.Column(db.String(80), nullable=False, index=True) text = db.Column(db.Text()) data = db.Column(JSONB) checklist = db.Column(JSONB) pinned = db.Column(db.Boolean) task_status_id = db.Column(UUIDType(binary=False), db.ForeignKey("task_status.id")) person_id = db.Column(UUIDType(binary=False), db.ForeignKey("person.id"), nullable=False) preview_file_id = db.Column(UUIDType(binary=False), db.ForeignKey("preview_file.id")) previews = db.relationship("PreviewFile", secondary=preview_link_table, backref="comments") mentions = db.relationship("Person", secondary=mentions_table) def __repr__(self): return "<Comment of %s>" % self.object_id
class WorkingFile(db.Model, BaseMixin, SerializerMixin): """ Describes the file related to the work done on a given task. It is used as source of output files published for a given entity. """ shotgun_id = db.Column(db.Integer(), index=True) name = db.Column(db.String(250)) description = db.Column(db.String(200)) comment = db.Column(db.Text()) revision = db.Column(db.Integer()) size = db.Column(db.Integer()) checksum = db.Column(db.Integer()) path = db.Column(db.String(400)) task_id = db.Column(UUIDType(binary=False), db.ForeignKey("task.id"), index=True) entity_id = db.Column(UUIDType(binary=False), db.ForeignKey("entity.id"), index=True) person_id = \ db.Column(UUIDType(binary=False), db.ForeignKey("person.id")) software_id = \ db.Column(UUIDType(binary=False), db.ForeignKey("software.id")) outputs = relationship("OutputFile", back_populates="source_file") __table_args__ = (db.UniqueConstraint("name", "task_id", "entity_id", "revision", name="working_file_uc"), ) def __repr__(self): return "<WorkingFile %s>" % self.id
class PreviewFile(db.Model, BaseMixin, SerializerMixin): """ Describes a file which is aimed at being reviewed. It is not a publication neither a working file. """ name = db.Column(db.String(250)) revision = db.Column(db.Integer(), default=1) description = db.Column(db.Text()) path = db.Column(db.String(400)) source = db.Column(db.String(40)) shotgun_id = db.Column(db.Integer, unique=True) is_movie = db.Column(db.Boolean, default=False) url = db.Column(db.String(600)) uploaded_movie_url = db.Column(db.String(600)) uploaded_movie_name = db.Column(db.String(150)) task_id = db.Column(UUIDType(binary=False), db.ForeignKey("task.id"), index=True) person_id = db.Column(UUIDType(binary=False), db.ForeignKey("person.id")) source_file_id = db.Column(UUIDType(binary=False), db.ForeignKey("output_file.id")) __table_args__ = (db.UniqueConstraint("name", "task_id", "revision", name="preview_uc"), ) def __repr__(self): return "<PreviewFile %s>" % self.id
class WorkingFile(db.Model, BaseMixin, SerializerMixin): shotgun_id = db.Column(db.Integer()) name = db.Column(db.String(250)) description = db.Column(db.String(200)) comment = db.Column(db.Text()) revision = db.Column(db.Integer()) size = db.Column(db.Integer()) checksum = db.Column(db.Integer()) task_id = db.Column(UUIDType(binary=False), db.ForeignKey("task.id")) entity_id = db.Column(UUIDType(binary=False), db.ForeignKey("entity.id")) person_id = \ db.Column(UUIDType(binary=False), db.ForeignKey("person.id")) __table_args__ = ( db.UniqueConstraint( "name", "task_id", "entity_id", "revision", name="working_file_uc" ), ) def __repr__(self): return "<WorkingFile %s>" % self.id
class PreviewFile(db.Model, BaseMixin, SerializerMixin): """ Describes a file which is aimed at being reviewed. It is not a publication neither a working file. """ name = db.Column(db.String(250)) original_name = db.Column(db.String(250)) revision = db.Column(db.Integer(), default=1) position = db.Column(db.Integer(), default=1) extension = db.Column(db.String(6)) description = db.Column(db.Text()) path = db.Column(db.String(400)) source = db.Column(db.String(40)) file_size = db.Column(db.Integer(), default=0) status = db.Column(ChoiceType(STATUSES), default="processing") validation_status = db.Column( ChoiceType(VALIDATION_STATUSES), default="neutral" ) annotations = db.Column(JSONB) task_id = db.Column( UUIDType(binary=False), db.ForeignKey("task.id"), index=True ) person_id = db.Column(UUIDType(binary=False), db.ForeignKey("person.id")) source_file_id = db.Column( UUIDType(binary=False), db.ForeignKey("output_file.id") ) __table_args__ = ( db.UniqueConstraint("name", "task_id", "revision", name="preview_uc"), ) shotgun_id = db.Column(db.Integer, unique=True) is_movie = db.Column(db.Boolean, default=False) # deprecated url = db.Column(db.String(600)) # deprecated uploaded_movie_url = db.Column(db.String(600)) # deprecated uploaded_movie_name = db.Column(db.String(150)) # deprecated def __repr__(self): return "<PreviewFile %s>" % self.id @classmethod def create_from_import(cls, data): del data["type"] if "comments" in data: del data["comments"] previous_data = cls.get(data["id"]) if "status" not in data or data["status"] == None: data["status"] = "ready" if previous_data is None: return (cls.create(**data), False) else: previous_data.update(data) return (previous_data, True)
class OutputFile(db.Model, BaseMixin, SerializerMixin): shotgun_id = db.Column(db.Integer()) name = db.Column(db.String(250)) description = db.Column(db.Text()) comment = db.Column(db.Text()) revision = db.Column(db.Integer()) size = db.Column(db.Integer()) checksum = db.Column(db.Integer()) source = db.Column(db.String(40)) uploaded_movie_url = db.Column(db.String(600)) uploaded_movie_name = db.Column(db.String(150)) file_status_id = \ db.Column( UUIDType(binary=False), db.ForeignKey("file_status.id"), nullable=False ) task_id = db.Column(UUIDType(binary=False), db.ForeignKey("task.id")) entity_id = db.Column(UUIDType(binary=False), db.ForeignKey("entity.id")) person_id = db.Column(UUIDType(binary=False), db.ForeignKey("person.id")) source_file_id = \ db.Column( UUIDType(binary=False), db.ForeignKey("working_file.id") ) __table_args__ = (db.UniqueConstraint("name", "task_id", "entity_id", "revision", name="output_file_uc"), ) def __repr__(self): return "<OutputFile %s>" % self.id
class Comment(db.Model, BaseMixin, SerializerMixin): shotgun_id = db.Column(db.Integer) object_id = db.Column(UUIDType(binary=False), nullable=False) object_type = db.Column(db.String(80), nullable=False) text = db.Column(db.Text()) data = db.Column(JSONB) person_id = db.Column(UUIDType(binary=False), db.ForeignKey("person.id"), nullable=False) def __repr__(self): return "<Comment of %s>" % self.object_id
class DayWorked(db.Model, BaseMixin, SerializerMixin): """ Describes the day worked by a person. """ date = db.Column(db.Date, nullable=False) person_id = db.Column(UUIDType(binary=False), db.ForeignKey("person.id"), index=True) work_duration = db.Column(db.Float, default=1) variable_time = db.Column(db.Integer, default=0) justification = db.Column(db.Text()) __table_args__ = (db.UniqueConstraint("person_id", "date", name="day_worked_uc"), )
class PreviewFile(db.Model, BaseMixin, SerializerMixin): name = db.Column(db.String(250)) description = db.Column(db.Text()) source = db.Column(db.String(40)) shotgun_id = db.Column(db.Integer, unique=True) uploaded_movie_url = db.Column(db.String(600)) uploaded_movie_name = db.Column(db.String(150)) task_id = db.Column(UUIDType(binary=False), db.ForeignKey("task.id")) person_id = db.Column(UUIDType(binary=False), db.ForeignKey("person.id")) entity_id = db.Column(UUIDType(binary=False), db.ForeignKey("entity.id")) source_file_id = db.Column(UUIDType(binary=False), db.ForeignKey("output_file.id")) __table_args__ = (db.UniqueConstraint("name", "task_id", "source_file_id", name="preview_uc"), ) def __repr__(self): return "<PreviewFile %s>" % self.id
class TimeSpent(db.Model, BaseMixin, SerializerMixin): """ Describes the time spent by someone on a task. """ duration = db.Column(db.Integer, nullable=False) date = db.Column(db.Date, nullable=False) task_id = db.Column(UUIDType(binary=False), db.ForeignKey("task.id"), index=True) person_id = db.Column(UUIDType(binary=False), db.ForeignKey("person.id"), index=True) description = db.Column(db.Text()) validation_status_id = db.Column(UUIDType(binary=False), db.ForeignKey("time_spent_status.id"), nullable=False) __table_args__ = (db.UniqueConstraint("person_id", "task_id", "date", name="time_spent_uc"), )
class Comment(db.Model, BaseMixin, SerializerMixin): """ Comment can occurs on any object but they are mainly used on tasks. In the case of comment tasks, they are linked to a task status and eventually on a preview file. The status means that comment leads to task status change. The preview file means that the comment relates to this preview in the context of the task. """ shotgun_id = db.Column(db.Integer) object_id = db.Column(UUIDType(binary=False), nullable=False, index=True) object_type = db.Column(db.String(80), nullable=False, index=True) text = db.Column(db.Text()) data = db.Column(JSONB) checklist = db.Column(JSONB) pinned = db.Column(db.Boolean) task_status_id = db.Column(UUIDType(binary=False), db.ForeignKey("task_status.id")) person_id = db.Column(UUIDType(binary=False), db.ForeignKey("person.id"), nullable=False) preview_file_id = db.Column(UUIDType(binary=False), db.ForeignKey("preview_file.id")) previews = db.relationship("PreviewFile", secondary=preview_link_table, backref="comments") mentions = db.relationship("Person", secondary=mentions_table) acknowledgements = db.relationship("Person", secondary=acknowledgements_table) attachment_files = db.relationship("AttachmentFile", backref="comment") def __repr__(self): return "<Comment of %s>" % self.object_id def set_preview_files(self, preview_file_ids): from zou.app.models.preview_file import PreviewFile self.preview_files = [] for preview_file_id in preview_file_ids: preview_file = PreviewFile.get(preview_file_id) if preview_file is not None: self.previews.append(preview_file) self.save() def set_mentions(self, person_ids): from zou.app.models.person import Person self.mentions = [] for person_id in person_ids: person = Person.get(person_id) if person is not None: self.mentions.append(person) self.save() @classmethod def create_from_import(cls, data): previous_comment = cls.get(data["id"]) preview_file_ids = data.get("previews", None) mention_ids = data.get("mentions", None) del data["previews"] del data["mentions"] del data["type"] if previous_comment is None: previous_comment = cls.create(**data) previous_comment.save() else: previous_comment.update(data) previous_comment.save() if preview_file_ids is not None: previous_comment.set_preview_files(preview_file_ids) if mention_ids is not None: previous_comment.set_mentions(mention_ids) return previous_comment
class Project(db.Model, BaseMixin, SerializerMixin): """ Describes a CG production the studio works on. """ name = db.Column(db.String(80), nullable=False, unique=True, index=True) code = db.Column(db.String(80)) description = db.Column(db.Text()) shotgun_id = db.Column(db.Integer) file_tree = db.Column(JSONB) data = db.Column(JSONB) has_avatar = db.Column(db.Boolean(), default=False) fps = db.Column(db.String(10)) ratio = db.Column(db.String(10)) resolution = db.Column(db.String(12)) production_type = db.Column(db.String(20), default="short") start_date = db.Column(db.Date()) end_date = db.Column(db.Date()) man_days = db.Column(db.Integer) nb_episodes = db.Column(db.Integer, default=0) episode_span = db.Column(db.Integer, default=0) project_status_id = db.Column( UUIDType(binary=False), db.ForeignKey("project_status.id"), index=True ) team = db.relationship("Person", secondary="project_person_link") asset_types = db.relationship( "EntityType", secondary="project_asset_type_link" ) task_statuses = db.relationship( "TaskStatus", secondary="project_task_status_link" ) task_types = db.relationship( "TaskType", secondary="project_task_type_link" ) def set_team(self, person_ids): for person_id in person_ids: link = ProjectPersonLink.query.filter_by( project_id=self.id, person_id=person_id ).first() if link is None: link = ProjectPersonLink( project_id=self.id, person_id=person_id ) db.session.add(link) db.session.commit() def set_task_types(self, task_type_ids): return self.set_links( task_type_ids, ProjectTaskTypeLink, "project_id", "task_type_id" ) def set_task_statuses(self, task_status_ids): return self.set_links( task_status_ids, ProjectTaskStatusLink, "project_id", "task_status_id", ) def set_asset_types(self, asset_type_ids): return self.set_links( asset_type_ids, ProjectAssetTypeLink, "project_id", "asset_type_id" ) @classmethod def create_from_import(cls, data): is_update = False previous_project = cls.get(data["id"]) data.pop("team", None) data.pop("type", None) data.pop("project_status_name", None) person_ids = data.pop("team", None) task_type_ids = data.pop("task_types", None) task_status_ids = data.pop("task_statuses", None) asset_type_ids = data.pop("asset_types", None) if previous_project is None: previous_project = cls.create(**data) previous_project.save() else: is_update = True previous_project.update(data) previous_project.save() if person_ids is not None: previous_project.set_team(person_ids) if task_type_ids is not None: previous_project.set_task_types(task_type_ids) if task_status_ids is not None: previous_project.set_task_statuses(task_status_ids) if asset_type_ids is not None: previous_project.set_asset_types(asset_type_ids) return (previous_project, is_update)
class OutputFile(db.Model, BaseMixin, OutputFileSerializer): """ Describe a file generated from a CG artist scene. It's the result of a publication. It is linked to a working/ children/ dependent file, an entity and a task type. """ __tablename__ = "output_file" shotgun_id = db.Column(db.String(50)) name = db.Column(db.String(250), nullable=False) canceled = db.Column(db.Boolean(), default=False, nullable=False) # surement une forme d'"omit" size = db.Column(db.Integer()) checksum = db.Column(db.String(32)) description = db.Column(db.Text()) comment = db.Column(db.Text()) extension = db.Column(db.String(10)) revision = db.Column(db.Integer(), nullable=False) # version representation = db.Column(db.String(20), index=True) # une manière de regrouper (ex: par extension) nb_elements = db.Column(db.Integer(), default=1) # à refaire, pas de start-end source = db.Column(db.String(40)) # permet de dire d'où ça vient (ex: muster) path = db.Column(db.String(400)) data = db.Column(JSONB) file_status_id = db.Column( UUIDType(binary=False), db.ForeignKey("file_status.id"), nullable=False ) entity_id = db.Column(UUIDType(binary=False), db.ForeignKey("entity.id")) asset_instance_id = db.Column( UUIDType(binary=False), db.ForeignKey("asset_instance.id"), index=True ) output_type_id = db.Column( UUIDType(binary=False), db.ForeignKey("output_type.id"), index=True ) task_type_id = db.Column( UUIDType(binary=False), db.ForeignKey("task_type.id"), index=True ) person_id = db.Column(UUIDType(binary=False), db.ForeignKey("person.id")) render_info = db.Column(db.String(200)) source_file_id = db.Column( UUIDType(binary=False), db.ForeignKey("working_file.id") ) render_info = db.Column(db.String(200)) source_file = relationship( "WorkingFile", lazy="joined", back_populates="outputs" ) children_files = relationship( "ChildrenFile", lazy="joined", backref=backref("parent_file", cascade="all, delete") ) # TODO: by default not serialize it dependent_files = relationship( "DependentFile", secondary=dependent_table, back_populates="used_by" ) temporal_entity_id = db.Column( UUIDType(binary=False), db.ForeignKey("entity.id"), default=None, nullable=True, ) __table_args__ = ( db.UniqueConstraint( "name", "entity_id", "asset_instance_id", "output_type_id", "task_type_id", "temporal_entity_id", "representation", "revision", name="output_file_uc", ), ) def __repr__(self): return "<OutputFile %s>" % self.id