zou 0.20.78__tar.gz → 0.20.80__tar.gz

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 (492) hide show
  1. {zou-0.20.78/zou.egg-info → zou-0.20.80}/PKG-INFO +1 -1
  2. zou-0.20.80/zou/__init__.py +1 -0
  3. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/auth/resources.py +8 -15
  4. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/comments/resources.py +5 -5
  5. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/files/resources.py +1 -1
  6. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/persons/resources.py +13 -10
  7. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/playlists/resources.py +46 -44
  8. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/user/resources.py +0 -2
  9. {zou-0.20.78 → zou-0.20.80}/zou/app/services/auth_service.py +4 -8
  10. {zou-0.20.78 → zou-0.20.80}/zou/app/services/comments_service.py +6 -7
  11. {zou-0.20.78 → zou-0.20.80}/zou/app/services/deletion_service.py +7 -0
  12. {zou-0.20.78 → zou-0.20.80}/zou/app/services/emails_service.py +40 -19
  13. {zou-0.20.78 → zou-0.20.80}/zou/app/services/entities_service.py +1 -1
  14. {zou-0.20.78 → zou-0.20.80}/zou/app/services/notifications_service.py +10 -2
  15. {zou-0.20.78 → zou-0.20.80}/zou/app/services/persons_service.py +10 -17
  16. {zou-0.20.78 → zou-0.20.80}/zou/app/services/playlists_service.py +7 -8
  17. zou-0.20.78/zou/app/services/template_services.py → zou-0.20.80/zou/app/services/templates_service.py +9 -6
  18. {zou-0.20.78 → zou-0.20.80}/zou/app/services/user_service.py +8 -3
  19. zou-0.20.80/zou/migrations/versions/0c05b22194f3_add_performance_indexes.py +44 -0
  20. zou-0.20.80/zou/migrations/versions/1b0ab951adca_add_reply_id_to_attachments.py +52 -0
  21. zou-0.20.80/zou/migrations/versions/5f1620d191af_add_playlist_id_field_to_notification.py +72 -0
  22. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/71d546ace0ee_add_performance_indexes.py +9 -6
  23. {zou-0.20.78 → zou-0.20.80/zou.egg-info}/PKG-INFO +1 -1
  24. {zou-0.20.78 → zou-0.20.80}/zou.egg-info/SOURCES.txt +1 -1
  25. zou-0.20.78/zou/__init__.py +0 -1
  26. zou-0.20.78/zou/migrations/versions/0c05b22194f3_add_performance_indexes.py +0 -35
  27. zou-0.20.78/zou/migrations/versions/1b0ab951adca_add_reply_id_to_attachments.py +0 -44
  28. zou-0.20.78/zou/migrations/versions/5f1620d191af_add_playlist_id_field_to_notification.py +0 -46
  29. {zou-0.20.78 → zou-0.20.80}/LICENSE +0 -0
  30. {zou-0.20.78 → zou-0.20.80}/README.rst +0 -0
  31. {zou-0.20.78 → zou-0.20.80}/pyproject.toml +0 -0
  32. {zou-0.20.78 → zou-0.20.80}/setup.cfg +0 -0
  33. {zou-0.20.78 → zou-0.20.80}/setup.py +0 -0
  34. {zou-0.20.78 → zou-0.20.80}/zou/app/__init__.py +0 -0
  35. {zou-0.20.78 → zou-0.20.80}/zou/app/api.py +0 -0
  36. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/__init__.py +0 -0
  37. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/assets/__init__.py +0 -0
  38. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/assets/resources.py +0 -0
  39. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/auth/__init__.py +0 -0
  40. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/breakdown/__init__.py +0 -0
  41. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/breakdown/resources.py +0 -0
  42. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/chats/__init__.py +0 -0
  43. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/chats/resources.py +0 -0
  44. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/comments/__init__.py +0 -0
  45. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/concepts/__init__.py +0 -0
  46. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/concepts/resources.py +0 -0
  47. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/__init__.py +0 -0
  48. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/asset_instance.py +0 -0
  49. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/attachment_file.py +0 -0
  50. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/base.py +0 -0
  51. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/budget.py +0 -0
  52. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/budget_entry.py +0 -0
  53. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/chat.py +0 -0
  54. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/chat_message.py +0 -0
  55. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/comments.py +0 -0
  56. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/custom_action.py +0 -0
  57. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/day_off.py +0 -0
  58. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/department.py +0 -0
  59. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/entity.py +0 -0
  60. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/entity_link.py +0 -0
  61. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/entity_type.py +0 -0
  62. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/event.py +0 -0
  63. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/file_status.py +0 -0
  64. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/hardware_item.py +0 -0
  65. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/metadata_descriptor.py +0 -0
  66. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/milestone.py +0 -0
  67. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/news.py +0 -0
  68. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/notification.py +0 -0
  69. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/organisation.py +0 -0
  70. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/output_file.py +0 -0
  71. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/output_type.py +0 -0
  72. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/person.py +0 -0
  73. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/playlist.py +0 -0
  74. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/plugin.py +0 -0
  75. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/preview_background_file.py +0 -0
  76. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/preview_file.py +0 -0
  77. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/production_schedule_version.py +0 -0
  78. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/project.py +0 -0
  79. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/project_status.py +0 -0
  80. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/salary_scale.py +0 -0
  81. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/schedule_item.py +0 -0
  82. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/search_filter.py +0 -0
  83. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/search_filter_group.py +0 -0
  84. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/software.py +0 -0
  85. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/status_automation.py +0 -0
  86. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/studio.py +0 -0
  87. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/subscription.py +0 -0
  88. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/task.py +0 -0
  89. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/task_status.py +0 -0
  90. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/task_type.py +0 -0
  91. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/time_spent.py +0 -0
  92. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/crud/working_file.py +0 -0
  93. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/departments/__init__.py +0 -0
  94. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/departments/resources.py +0 -0
  95. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/edits/__init__.py +0 -0
  96. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/edits/resources.py +0 -0
  97. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/entities/__init__.py +0 -0
  98. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/entities/resources.py +0 -0
  99. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/events/__init__.py +0 -0
  100. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/events/resources.py +0 -0
  101. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/export/__init__.py +0 -0
  102. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/export/csv/__init__.py +0 -0
  103. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/export/csv/assets.py +0 -0
  104. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/export/csv/base.py +0 -0
  105. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/export/csv/casting.py +0 -0
  106. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/export/csv/edits.py +0 -0
  107. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/export/csv/persons.py +0 -0
  108. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/export/csv/playlists.py +0 -0
  109. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/export/csv/projects.py +0 -0
  110. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/export/csv/shots.py +0 -0
  111. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/export/csv/task_types.py +0 -0
  112. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/export/csv/tasks.py +0 -0
  113. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/export/csv/time_spents.py +0 -0
  114. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/files/__init__.py +0 -0
  115. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/index/__init__.py +0 -0
  116. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/index/resources.py +0 -0
  117. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/news/__init__.py +0 -0
  118. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/news/resources.py +0 -0
  119. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/persons/__init__.py +0 -0
  120. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/playlists/__init__.py +0 -0
  121. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/previews/__init__.py +0 -0
  122. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/previews/resources.py +0 -0
  123. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/projects/__init__.py +0 -0
  124. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/projects/resources.py +0 -0
  125. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/search/__init__.py +0 -0
  126. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/search/resources.py +0 -0
  127. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/shots/__init__.py +0 -0
  128. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/shots/resources.py +0 -0
  129. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/source/__init__.py +0 -0
  130. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/source/csv/__init__.py +0 -0
  131. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/source/csv/assets.py +0 -0
  132. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/source/csv/base.py +0 -0
  133. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/source/csv/casting.py +0 -0
  134. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/source/csv/edits.py +0 -0
  135. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/source/csv/persons.py +0 -0
  136. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/source/csv/shots.py +0 -0
  137. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/source/csv/task_type_estimations.py +0 -0
  138. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/source/kitsu.py +0 -0
  139. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/source/otio.py +0 -0
  140. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/source/shotgun/__init__.py +0 -0
  141. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/source/shotgun/assets.py +0 -0
  142. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/source/shotgun/base.py +0 -0
  143. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/source/shotgun/episode.py +0 -0
  144. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/source/shotgun/exception.py +0 -0
  145. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/source/shotgun/import_errors.py +0 -0
  146. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/source/shotgun/notes.py +0 -0
  147. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/source/shotgun/person.py +0 -0
  148. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/source/shotgun/project.py +0 -0
  149. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/source/shotgun/scene.py +0 -0
  150. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/source/shotgun/sequence.py +0 -0
  151. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/source/shotgun/shot.py +0 -0
  152. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/source/shotgun/status.py +0 -0
  153. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/source/shotgun/steps.py +0 -0
  154. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/source/shotgun/tasks.py +0 -0
  155. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/source/shotgun/team.py +0 -0
  156. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/source/shotgun/versions.py +0 -0
  157. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/tasks/__init__.py +0 -0
  158. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/tasks/resources.py +0 -0
  159. {zou-0.20.78 → zou-0.20.80}/zou/app/blueprints/user/__init__.py +0 -0
  160. {zou-0.20.78 → zou-0.20.80}/zou/app/config.py +0 -0
  161. {zou-0.20.78 → zou-0.20.80}/zou/app/file_trees/default.json +0 -0
  162. {zou-0.20.78 → zou-0.20.80}/zou/app/file_trees/simple.json +0 -0
  163. {zou-0.20.78 → zou-0.20.80}/zou/app/indexer/__init__.py +0 -0
  164. {zou-0.20.78 → zou-0.20.80}/zou/app/indexer/indexing.py +0 -0
  165. {zou-0.20.78 → zou-0.20.80}/zou/app/mixin.py +0 -0
  166. {zou-0.20.78 → zou-0.20.80}/zou/app/models/__init__.py +0 -0
  167. {zou-0.20.78 → zou-0.20.80}/zou/app/models/asset_instance.py +0 -0
  168. {zou-0.20.78 → zou-0.20.80}/zou/app/models/attachment_file.py +0 -0
  169. {zou-0.20.78 → zou-0.20.80}/zou/app/models/base.py +0 -0
  170. {zou-0.20.78 → zou-0.20.80}/zou/app/models/budget.py +0 -0
  171. {zou-0.20.78 → zou-0.20.80}/zou/app/models/budget_entry.py +0 -0
  172. {zou-0.20.78 → zou-0.20.80}/zou/app/models/build_job.py +0 -0
  173. {zou-0.20.78 → zou-0.20.80}/zou/app/models/chat.py +0 -0
  174. {zou-0.20.78 → zou-0.20.80}/zou/app/models/chat_message.py +0 -0
  175. {zou-0.20.78 → zou-0.20.80}/zou/app/models/comment.py +0 -0
  176. {zou-0.20.78 → zou-0.20.80}/zou/app/models/custom_action.py +0 -0
  177. {zou-0.20.78 → zou-0.20.80}/zou/app/models/data_import_error.py +0 -0
  178. {zou-0.20.78 → zou-0.20.80}/zou/app/models/day_off.py +0 -0
  179. {zou-0.20.78 → zou-0.20.80}/zou/app/models/department.py +0 -0
  180. {zou-0.20.78 → zou-0.20.80}/zou/app/models/desktop_login_log.py +0 -0
  181. {zou-0.20.78 → zou-0.20.80}/zou/app/models/entity.py +0 -0
  182. {zou-0.20.78 → zou-0.20.80}/zou/app/models/entity_type.py +0 -0
  183. {zou-0.20.78 → zou-0.20.80}/zou/app/models/event.py +0 -0
  184. {zou-0.20.78 → zou-0.20.80}/zou/app/models/file_status.py +0 -0
  185. {zou-0.20.78 → zou-0.20.80}/zou/app/models/hardware_item.py +0 -0
  186. {zou-0.20.78 → zou-0.20.80}/zou/app/models/login_log.py +0 -0
  187. {zou-0.20.78 → zou-0.20.80}/zou/app/models/metadata_descriptor.py +0 -0
  188. {zou-0.20.78 → zou-0.20.80}/zou/app/models/milestone.py +0 -0
  189. {zou-0.20.78 → zou-0.20.80}/zou/app/models/news.py +0 -0
  190. {zou-0.20.78 → zou-0.20.80}/zou/app/models/notification.py +0 -0
  191. {zou-0.20.78 → zou-0.20.80}/zou/app/models/organisation.py +0 -0
  192. {zou-0.20.78 → zou-0.20.80}/zou/app/models/output_file.py +0 -0
  193. {zou-0.20.78 → zou-0.20.80}/zou/app/models/output_type.py +0 -0
  194. {zou-0.20.78 → zou-0.20.80}/zou/app/models/person.py +0 -0
  195. {zou-0.20.78 → zou-0.20.80}/zou/app/models/playlist.py +0 -0
  196. {zou-0.20.78 → zou-0.20.80}/zou/app/models/plugin.py +0 -0
  197. {zou-0.20.78 → zou-0.20.80}/zou/app/models/preview_background_file.py +0 -0
  198. {zou-0.20.78 → zou-0.20.80}/zou/app/models/preview_file.py +0 -0
  199. {zou-0.20.78 → zou-0.20.80}/zou/app/models/production_schedule_version.py +0 -0
  200. {zou-0.20.78 → zou-0.20.80}/zou/app/models/project.py +0 -0
  201. {zou-0.20.78 → zou-0.20.80}/zou/app/models/project_status.py +0 -0
  202. {zou-0.20.78 → zou-0.20.80}/zou/app/models/salary_scale.py +0 -0
  203. {zou-0.20.78 → zou-0.20.80}/zou/app/models/schedule_item.py +0 -0
  204. {zou-0.20.78 → zou-0.20.80}/zou/app/models/search_filter.py +0 -0
  205. {zou-0.20.78 → zou-0.20.80}/zou/app/models/search_filter_group.py +0 -0
  206. {zou-0.20.78 → zou-0.20.80}/zou/app/models/serializer.py +0 -0
  207. {zou-0.20.78 → zou-0.20.80}/zou/app/models/software.py +0 -0
  208. {zou-0.20.78 → zou-0.20.80}/zou/app/models/status_automation.py +0 -0
  209. {zou-0.20.78 → zou-0.20.80}/zou/app/models/studio.py +0 -0
  210. {zou-0.20.78 → zou-0.20.80}/zou/app/models/subscription.py +0 -0
  211. {zou-0.20.78 → zou-0.20.80}/zou/app/models/task.py +0 -0
  212. {zou-0.20.78 → zou-0.20.80}/zou/app/models/task_status.py +0 -0
  213. {zou-0.20.78 → zou-0.20.80}/zou/app/models/task_type.py +0 -0
  214. {zou-0.20.78 → zou-0.20.80}/zou/app/models/time_spent.py +0 -0
  215. {zou-0.20.78 → zou-0.20.80}/zou/app/models/working_file.py +0 -0
  216. {zou-0.20.78 → zou-0.20.80}/zou/app/services/__init__.py +0 -0
  217. {zou-0.20.78 → zou-0.20.80}/zou/app/services/assets_service.py +0 -0
  218. {zou-0.20.78 → zou-0.20.80}/zou/app/services/backup_service.py +0 -0
  219. {zou-0.20.78 → zou-0.20.80}/zou/app/services/base_service.py +0 -0
  220. {zou-0.20.78 → zou-0.20.80}/zou/app/services/breakdown_service.py +0 -0
  221. {zou-0.20.78 → zou-0.20.80}/zou/app/services/budget_service.py +0 -0
  222. {zou-0.20.78 → zou-0.20.80}/zou/app/services/chats_service.py +0 -0
  223. {zou-0.20.78 → zou-0.20.80}/zou/app/services/concepts_service.py +0 -0
  224. {zou-0.20.78 → zou-0.20.80}/zou/app/services/custom_actions_service.py +0 -0
  225. {zou-0.20.78 → zou-0.20.80}/zou/app/services/departments_service.py +0 -0
  226. {zou-0.20.78 → zou-0.20.80}/zou/app/services/edits_service.py +0 -0
  227. {zou-0.20.78 → zou-0.20.80}/zou/app/services/events_service.py +0 -0
  228. {zou-0.20.78 → zou-0.20.80}/zou/app/services/exception.py +0 -0
  229. {zou-0.20.78 → zou-0.20.80}/zou/app/services/file_tree_service.py +0 -0
  230. {zou-0.20.78 → zou-0.20.80}/zou/app/services/files_service.py +0 -0
  231. {zou-0.20.78 → zou-0.20.80}/zou/app/services/index_service.py +0 -0
  232. {zou-0.20.78 → zou-0.20.80}/zou/app/services/names_service.py +0 -0
  233. {zou-0.20.78 → zou-0.20.80}/zou/app/services/news_service.py +0 -0
  234. {zou-0.20.78 → zou-0.20.80}/zou/app/services/plugins_service.py +0 -0
  235. {zou-0.20.78 → zou-0.20.80}/zou/app/services/preview_files_service.py +0 -0
  236. {zou-0.20.78 → zou-0.20.80}/zou/app/services/projects_service.py +0 -0
  237. {zou-0.20.78 → zou-0.20.80}/zou/app/services/scenes_service.py +0 -0
  238. {zou-0.20.78 → zou-0.20.80}/zou/app/services/schedule_service.py +0 -0
  239. {zou-0.20.78 → zou-0.20.80}/zou/app/services/shots_service.py +0 -0
  240. {zou-0.20.78 → zou-0.20.80}/zou/app/services/stats_service.py +0 -0
  241. {zou-0.20.78 → zou-0.20.80}/zou/app/services/status_automations_service.py +0 -0
  242. {zou-0.20.78 → zou-0.20.80}/zou/app/services/sync_service.py +0 -0
  243. {zou-0.20.78 → zou-0.20.80}/zou/app/services/tasks_service.py +0 -0
  244. {zou-0.20.78 → zou-0.20.80}/zou/app/services/telemetry_services.py +0 -0
  245. {zou-0.20.78 → zou-0.20.80}/zou/app/services/time_spents_service.py +0 -0
  246. {zou-0.20.78 → zou-0.20.80}/zou/app/stores/__init__.py +0 -0
  247. {zou-0.20.78 → zou-0.20.80}/zou/app/stores/auth_tokens_store.py +0 -0
  248. {zou-0.20.78 → zou-0.20.80}/zou/app/stores/file_store.py +0 -0
  249. {zou-0.20.78 → zou-0.20.80}/zou/app/stores/publisher_store.py +0 -0
  250. {zou-0.20.78 → zou-0.20.80}/zou/app/stores/queue_store.py +0 -0
  251. {zou-0.20.78 → zou-0.20.80}/zou/app/swagger.py +0 -0
  252. {zou-0.20.78 → zou-0.20.80}/zou/app/utils/__init__.py +0 -0
  253. {zou-0.20.78 → zou-0.20.80}/zou/app/utils/api.py +0 -0
  254. {zou-0.20.78 → zou-0.20.80}/zou/app/utils/auth.py +0 -0
  255. {zou-0.20.78 → zou-0.20.80}/zou/app/utils/cache.py +0 -0
  256. {zou-0.20.78 → zou-0.20.80}/zou/app/utils/chats.py +0 -0
  257. {zou-0.20.78 → zou-0.20.80}/zou/app/utils/colors.py +0 -0
  258. {zou-0.20.78 → zou-0.20.80}/zou/app/utils/commands.py +0 -0
  259. {zou-0.20.78 → zou-0.20.80}/zou/app/utils/csv_utils.py +0 -0
  260. {zou-0.20.78 → zou-0.20.80}/zou/app/utils/date_helpers.py +0 -0
  261. {zou-0.20.78 → zou-0.20.80}/zou/app/utils/dbhelpers.py +0 -0
  262. {zou-0.20.78 → zou-0.20.80}/zou/app/utils/emails.py +0 -0
  263. {zou-0.20.78 → zou-0.20.80}/zou/app/utils/env.py +0 -0
  264. {zou-0.20.78 → zou-0.20.80}/zou/app/utils/events.py +0 -0
  265. {zou-0.20.78 → zou-0.20.80}/zou/app/utils/fido.py +0 -0
  266. {zou-0.20.78 → zou-0.20.80}/zou/app/utils/fields.py +0 -0
  267. {zou-0.20.78 → zou-0.20.80}/zou/app/utils/flask.py +0 -0
  268. {zou-0.20.78 → zou-0.20.80}/zou/app/utils/fs.py +0 -0
  269. {zou-0.20.78 → zou-0.20.80}/zou/app/utils/git.py +0 -0
  270. {zou-0.20.78 → zou-0.20.80}/zou/app/utils/logs.py +0 -0
  271. {zou-0.20.78 → zou-0.20.80}/zou/app/utils/monitoring.py +0 -0
  272. {zou-0.20.78 → zou-0.20.80}/zou/app/utils/permissions.py +0 -0
  273. {zou-0.20.78 → zou-0.20.80}/zou/app/utils/plugins.py +0 -0
  274. {zou-0.20.78 → zou-0.20.80}/zou/app/utils/query.py +0 -0
  275. {zou-0.20.78 → zou-0.20.80}/zou/app/utils/redis.py +0 -0
  276. {zou-0.20.78 → zou-0.20.80}/zou/app/utils/remote_job.py +0 -0
  277. {zou-0.20.78 → zou-0.20.80}/zou/app/utils/saml.py +0 -0
  278. {zou-0.20.78 → zou-0.20.80}/zou/app/utils/shell.py +0 -0
  279. {zou-0.20.78 → zou-0.20.80}/zou/app/utils/string.py +0 -0
  280. {zou-0.20.78 → zou-0.20.80}/zou/app/utils/thumbnail.py +0 -0
  281. {zou-0.20.78 → zou-0.20.80}/zou/cli.py +0 -0
  282. {zou-0.20.78 → zou-0.20.80}/zou/debug.py +0 -0
  283. {zou-0.20.78 → zou-0.20.80}/zou/event_stream.py +0 -0
  284. {zou-0.20.78 → zou-0.20.80}/zou/job_settings.py +0 -0
  285. {zou-0.20.78 → zou-0.20.80}/zou/migrations/README +0 -0
  286. {zou-0.20.78 → zou-0.20.80}/zou/migrations/__init__.py +0 -0
  287. {zou-0.20.78 → zou-0.20.80}/zou/migrations/alembic.ini +0 -0
  288. {zou-0.20.78 → zou-0.20.80}/zou/migrations/env.py +0 -0
  289. {zou-0.20.78 → zou-0.20.80}/zou/migrations/script.py.mako +0 -0
  290. {zou-0.20.78 → zou-0.20.80}/zou/migrations/utils/__init__.py +0 -0
  291. {zou-0.20.78 → zou-0.20.80}/zou/migrations/utils/base.py +0 -0
  292. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/003be8a91001_add_start_and_end_dates_to_projects.py +0 -0
  293. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/0596674df51d_add_department_mentions_to_comments.py +0 -0
  294. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/05ac7e8caa21_remove_unique_constraint_for_taskstatus_.py +0 -0
  295. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/05b7dc79a416_add_archived_fields_to_main_tables.py +0 -0
  296. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/06552e22f9e7_add_comment_updated_by.py +0 -0
  297. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/0bd1e89f2a6f_add_productionscheduleversiontasklink_uc.py +0 -0
  298. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/0cf5e0e035fa_drop_column_tasktype_for_shots.py +0 -0
  299. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/0ec3762a745d_add_attachment_table.py +0 -0
  300. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/0ef6416a507b_.py +0 -0
  301. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/10cf267d95c9_fix_schedule_item.py +0 -0
  302. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/16328eae4b5f_add_new_constraint_for_timespent.py +0 -0
  303. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/16df47d76c64_add_some_indexes.py +0 -0
  304. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/17ef8f7be758_disallow_null_choicetype.py +0 -0
  305. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/1bb55759146f_add_table_studio.py +0 -0
  306. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/1cb44194db49_add_file_size_field_to_preview_file.py +0 -0
  307. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/1e150c2cea4d_add_nb_entities_out.py +0 -0
  308. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/1e2d77a2f0c4_add_hd_by_default_column.py +0 -0
  309. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/1fab8c420678_add_attachments_to_message_chats.py +0 -0
  310. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/20a8ad264659_tasktypeassettypelink_.py +0 -0
  311. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/20dfeb36142b_add_projecttaskstatuslink_roles_for_.py +0 -0
  312. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/23122f290ca2_add_entity_chat_models.py +0 -0
  313. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/269d41bfb73f_add_entity_entity_links.py +0 -0
  314. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/26f96f65cfa3_add_productionversionschedule_uc.py +0 -0
  315. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/2762a797f1f9_add_people_salary_information.py +0 -0
  316. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/29df910f04a4_create_unique_constraint_project_id_.py +0 -0
  317. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/29fe01a6c9eb_add_status_automation_field.py +0 -0
  318. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/2adc020885fa_.py +0 -0
  319. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/2baede80b111_add_entity_status_field.py +0 -0
  320. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/306266361f4f_.py +0 -0
  321. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/307edd8c639d_change_comment_updated_by_in_comment_.py +0 -0
  322. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/328fd44c6347_add_entity_created_by.py +0 -0
  323. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/32f134ff1201_add_is_shared_flag_to_filters.py +0 -0
  324. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/346250b5304c_add_position_to_preview_files.py +0 -0
  325. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/3476e147e632_add_acks_to_comments.py +0 -0
  326. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/389cfb9de776_.py +0 -0
  327. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/38baa9a23b3d_.py +0 -0
  328. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/398150912a3f_validation_status_preview.py +0 -0
  329. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/3b0d1321079e_.py +0 -0
  330. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/3d5c93bafb9d_.py +0 -0
  331. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/3d8e68dffeee_fix_task_person_link.py +0 -0
  332. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/3e0538ddf80f_.py +0 -0
  333. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/3fee3bd10f9d_.py +0 -0
  334. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/4095103c7d01_add_is_clients_isolated_flag_to_projects.py +0 -0
  335. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/40dea9555940_.py +0 -0
  336. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/42ec83db6a01_change_person_preferred_two_factor_.py +0 -0
  337. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/4368137b44e1_productionscheduleversion_add_on_delete_.py +0 -0
  338. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/43d0cf0ed5e7_.py +0 -0
  339. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/443d1e78a932_.py +0 -0
  340. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/45c2de366e66_.py +0 -0
  341. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/45dafbb3f4e1_for_person_contract_type_disallow_null.py +0 -0
  342. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/45f739ef962a_add_people_salary_scale_table.py +0 -0
  343. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/4715c2586036_add_last_preview_file_fields.py +0 -0
  344. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/4aab1f84ad72_introduce_plugin_table.py +0 -0
  345. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/4bd9bfb73f11_add_fields_to_the_software_table.py +0 -0
  346. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/4d585b6956f2_add_taskstatus_is_wip.py +0 -0
  347. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/4e3738cdc34c_.py +0 -0
  348. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/4f2398ebcd49_.py +0 -0
  349. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/523ee9647bee_.py +0 -0
  350. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/539a3a00c417_for_departmentlink_index_person_id_.py +0 -0
  351. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/54ee0d1d60ba_add_build_job_model.py +0 -0
  352. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/556526e47daa_.py +0 -0
  353. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/57222395f2be_add_statusautomation_import_last_revision.py +0 -0
  354. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/5798d2c9020b_change_person_role_to_choicetype.py +0 -0
  355. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/590aa1ffe731_add_notifications_enabled_flag.py +0 -0
  356. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/59a7445a966c_add_entity_is_shared.py +0 -0
  357. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/5a291251823c_add_max_retake_parameter.py +0 -0
  358. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/5ab9d7a75887_.py +0 -0
  359. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/5b0fcbb94f24_.py +0 -0
  360. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/5b7fa3e51701_add_is_client_allowed_flag_to_task_.py +0 -0
  361. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/5b980f0dc365_add_comment_links.py +0 -0
  362. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/5b9fd9ddfe43_add_homepage_and_contract_fields.py +0 -0
  363. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/5c0498e264bc_add_slack_fields.py +0 -0
  364. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/5e2ce62632a6_add_workflow_to_project.py +0 -0
  365. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/5f715f2b6348_add_new_table_productionscheduleversion.py +0 -0
  366. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/680c64565f9d_for_searchfiltergroup_is_shared.py +0 -0
  367. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/693cc511d28d_add_taskstatus_priority.py +0 -0
  368. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/6aa446ee4072_add_is_for_all_flage_to_playlists.py +0 -0
  369. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/6bd3b102d61b_.py +0 -0
  370. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/6c597e842afa_add_task_type_field_to_playlists.py +0 -0
  371. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/6d1b2c60f58b_add_milestone_model.py +0 -0
  372. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/6d7fa5a8e9a5_add_timesheets_locked_field_to_org.py +0 -0
  373. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/6eeaff945706_add_data_field_on_entity_links.py +0 -0
  374. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/6f6049877105_.py +0 -0
  375. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/7417c8eb70d8_add_for_entity_field_to_playlists.py +0 -0
  376. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/772a5e43f05b_.py +0 -0
  377. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/7748d3d22925_add_columns_to_searchfilter_table_to_.py +0 -0
  378. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/77d6820f494f_add_reply_to_notif.py +0 -0
  379. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/7a16258f2fab_add_currency_field_to_budgets.py +0 -0
  380. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/7b1f765677d8_.py +0 -0
  381. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/7bc746997e8d_add_slack_token_field_to_organisation.py +0 -0
  382. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/7dc79d4ed7cd_.py +0 -0
  383. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/818f7bda2528_.py +0 -0
  384. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/82e7f7a95e84_add_project_id_to_events.py +0 -0
  385. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/82ee682204ab_add_is_generated_from_ldap_column_to_.py +0 -0
  386. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/83e2f33a9b14_add_project_bugdet_table.py +0 -0
  387. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/8588f254d6b8_add_archived_fields.py +0 -0
  388. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/8739ae9fa28b_add_for_client_field.py +0 -0
  389. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/87efceb6745b_add_ready_for_to_entity.py +0 -0
  390. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/892b264937ec_.py +0 -0
  391. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/8a1b4a1b7f4a_add_totp_columns_for_person.py +0 -0
  392. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/8ab98c178903_add_budget_entry_table.py +0 -0
  393. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/8e4f39e321f4_add_day_off_table.py +0 -0
  394. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/8e67c183bed7_add_preference_fields.py +0 -0
  395. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/8fbd40afbe5f_allow_to_set_float_values_for_.py +0 -0
  396. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/9010a64e5a2d_add_indices.py +0 -0
  397. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/9060dd4f6116_notification_uc.py +0 -0
  398. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/925771029620_.py +0 -0
  399. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/92b40d79ad3f_allow_message_attachments.py +0 -0
  400. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/92bdfe07e5f5_discord_integration.py +0 -0
  401. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/956659992419_add_columns_for_person_to_store_fido_.py +0 -0
  402. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/9683bd840dee_add_archived_field_to_software.py +0 -0
  403. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/96c79d31e648_add_mail_otp_columns_for_person.py +0 -0
  404. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/96f58a4a2a58_person_partial_index_for_email_only_.py +0 -0
  405. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/971dbf5a0faf_add_short_name_for_asset_type_entity_.py +0 -0
  406. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/98c90621cf58_add_for_client_flag_to_playlist.py +0 -0
  407. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/99825b9cc778_.py +0 -0
  408. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/9a09467f9b2c_.py +0 -0
  409. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/9af2df17a9d5_add_hardware_table.py +0 -0
  410. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/9b85c14fa8a7_add_day_off_new_columns.py +0 -0
  411. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/9bd17364fc18_.py +0 -0
  412. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/9d3bb33c6fc6_add_department_keys_to_filter_models.py +0 -0
  413. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/9e5b3a9b0cee_add_new_column_metadatadescriptor_data_type_.py +0 -0
  414. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/9f8445f9b42c_add_man_days_fields.py +0 -0
  415. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/a23682ccc1f1_.py +0 -0
  416. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/a252a094e977_add_descriptions_for_entities_tasks_and_.py +0 -0
  417. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/a519c710877c_.py +0 -0
  418. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/a65bdadbae2f_.py +0 -0
  419. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/a66508788c53_add_nb_assets_ready.py +0 -0
  420. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/a6c25eed3ea1_add_login_failed_attemps_and_last_login_.py +0 -0
  421. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/a7c43f3fbc76_add_duration_column_to_the_preview_file.py +0 -0
  422. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/aa0a60033106_feedback_request.py +0 -0
  423. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/addbad59c706_allow_to_manage_drawings_instead_of_.py +0 -0
  424. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/addbbefa7028_add_departments_link_to_metadata_.py +0 -0
  425. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/ae0127f2fc56_add_previewfile_width_and_previewfile_.py +0 -0
  426. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/af1790868e2c_.py +0 -0
  427. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/b45cb782bb9c_.py +0 -0
  428. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/b4dd0add5f79_.py +0 -0
  429. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/b8c0a0f9d054_drop_task_status_is_reviewable.py +0 -0
  430. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/b8ed0fb263f8_add_person_jti_and_jti_expiration_date.py +0 -0
  431. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/b97a71306fc8_add_is_casting_standby_column_to_entity.py +0 -0
  432. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/be56dc0fb760_for_is_shared_disallow_nullable.py +0 -0
  433. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/bf1347acdee2_.py +0 -0
  434. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/c49e41f1298b_add_previewbackground.py +0 -0
  435. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/c68c2a62cfac_add_mimetype_column_to_attachment.py +0 -0
  436. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/c726b98be194_.py +0 -0
  437. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/c81f3e83bdb5_.py +0 -0
  438. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/ca28796a2a62_add_is_done_field_to_the_task_model.py +0 -0
  439. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/ce7f46f445dc_add_column_estimation_for_.py +0 -0
  440. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/cf3d365de164_add_entity_version_model.py +0 -0
  441. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/cf6cec6d6bf5_add_status_field_to_preview_file.py +0 -0
  442. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/d25118cddcaa_modify_salary_scale_model.py +0 -0
  443. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/d5665dca188b_add_version_field_to_software.py +0 -0
  444. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/d80267806131_task_status_new_column_is_default.py +0 -0
  445. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/d80f02824047_add_plugin_revision.py +0 -0
  446. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/d8dcd5196d57_add_casting_label.py +0 -0
  447. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/d97f2730bf7b_add_.py +0 -0
  448. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/dde6be40f54f_add_departement_links_tables_for_.py +0 -0
  449. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/de8a3de227ef_.py +0 -0
  450. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/deeacd38d373_for_projecttaskstatuslink_set_default_.py +0 -0
  451. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/df1834485f57_.py +0 -0
  452. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/df9f8a147e80_change_file_size_to_big_integer.py +0 -0
  453. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/e1ef93f40d3d_.py +0 -0
  454. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/e29638428dfd_add_schedule_item_table.py +0 -0
  455. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/e3f6db74cc1e_.py +0 -0
  456. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/e4b48ca33539_add_project_production_schedule_version_.py +0 -0
  457. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/e7e633bd6fa2_add_exceptions_to_budget_entries.py +0 -0
  458. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/e839d6603c09_add_person_id_to_shot_history.py +0 -0
  459. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/e8bc24998b34_remove_on_delete_cascade_for_.py +0 -0
  460. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/ee2373fbe3a4_.py +0 -0
  461. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/f0567e8d0c62_.py +0 -0
  462. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/f0c6cbb61869_add_production_style_field.py +0 -0
  463. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/f344b867a911_for_description_of_entity_task_working_.py +0 -0
  464. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/f4ff5a73d283_add_person_ldap_uid.py +0 -0
  465. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/f5b113876a49_add_preferred_two_factor_authentication_.py +0 -0
  466. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/f5bdca075cdc_add_preview_download_flag_to_projects.py +0 -0
  467. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/f874ad5e898a_add_link_entity_type_task_type.py +0 -0
  468. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/f995b28fb749_.py +0 -0
  469. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/fb6b6f188497_.py +0 -0
  470. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/fb87feaaa094_add_missing_unique_constraints.py +0 -0
  471. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/fba149993140_add_missing_index.py +0 -0
  472. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/fc322f908695_.py +0 -0
  473. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/fee7c696166e_.py +0 -0
  474. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/feffd3c5b806_introduce_concepts.py +0 -0
  475. {zou-0.20.78 → zou-0.20.80}/zou/migrations/versions/ffeed4956ab1_add_more_details_to_projects.py +0 -0
  476. {zou-0.20.78 → zou-0.20.80}/zou/plugin_template/__init__.py +0 -0
  477. {zou-0.20.78 → zou-0.20.80}/zou/plugin_template/migrations/alembic.ini +0 -0
  478. {zou-0.20.78 → zou-0.20.80}/zou/plugin_template/migrations/env.py +0 -0
  479. {zou-0.20.78 → zou-0.20.80}/zou/plugin_template/migrations/script.py.mako +0 -0
  480. {zou-0.20.78 → zou-0.20.80}/zou/plugin_template/models.py +0 -0
  481. {zou-0.20.78 → zou-0.20.80}/zou/plugin_template/routes.py +0 -0
  482. {zou-0.20.78 → zou-0.20.80}/zou/remote/__init__.py +0 -0
  483. {zou-0.20.78 → zou-0.20.80}/zou/remote/config_payload.py +0 -0
  484. {zou-0.20.78 → zou-0.20.80}/zou/remote/normalize_movie.py +0 -0
  485. {zou-0.20.78 → zou-0.20.80}/zou/remote/playlist.py +0 -0
  486. {zou-0.20.78 → zou-0.20.80}/zou/utils/__init__.py +0 -0
  487. {zou-0.20.78 → zou-0.20.80}/zou/utils/movie.py +0 -0
  488. {zou-0.20.78 → zou-0.20.80}/zou.egg-info/dependency_links.txt +0 -0
  489. {zou-0.20.78 → zou-0.20.80}/zou.egg-info/entry_points.txt +0 -0
  490. {zou-0.20.78 → zou-0.20.80}/zou.egg-info/not-zip-safe +0 -0
  491. {zou-0.20.78 → zou-0.20.80}/zou.egg-info/requires.txt +0 -0
  492. {zou-0.20.78 → zou-0.20.80}/zou.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: zou
3
- Version: 0.20.78
3
+ Version: 0.20.80
4
4
  Summary: API to store and manage the data of your animation production
5
5
  Home-page: https://zou.cg-wire.com
6
6
  Author: CG Wire
@@ -0,0 +1 @@
1
+ __version__ = "0.20.80"
@@ -572,19 +572,16 @@ class ChangePasswordResource(Resource, ArgsMixin):
572
572
  html = f"""<p>Hello {user["first_name"]},</p>
573
573
 
574
574
  <p>
575
- You have successfully changed your password at this date : {time_string}.
576
-
577
- Your IP when you have changed your password is : {person_IP}.
578
- </p>
579
-
580
- Thank you and see you soon on Kitsu,
575
+ You have successfully changed your password at this date: {time_string}.
581
576
  </p>
582
577
  <p>
583
- {organisation["name"]} Team
578
+ Your IP when you have changed your password is: {person_IP}.
584
579
  </p>
585
580
  """
586
581
  subject = f"{organisation['name']} - Kitsu: password changed"
587
- emails.send_email(subject, html, user["email"])
582
+ title = "Password Changed"
583
+ email_html_body = templates_service.generate_html_body(title, html)
584
+ emails.send_email(subject, email_html_body, user["email"])
588
585
  return {"success": True}
589
586
 
590
587
  except auth.PasswordsNoMatchException:
@@ -778,15 +775,11 @@ This link will expire after 2 hours. After, you have to do a new request to rese
778
775
  This email was sent at this date: {time_string}.
779
776
  The IP of the person who requested this is: {person_IP}.
780
777
  </p>
781
-
782
- Thank you and see you soon on Kitsu,
783
- </p>
784
- <p>
785
- {organisation["name"]} Team
786
- </p>
787
778
  """
788
779
  subject = f"{organisation['name']} - Kitsu: password recovery"
789
- emails.send_email(subject, html, args["email"])
780
+ title = "Password Recovery"
781
+ email_html_body = templates_service.generate_html_body(title, html)
782
+ emails.send_email(subject, email_html_body, args["email"])
790
783
  return {"success": "Reset token sent"}
791
784
 
792
785
 
@@ -498,8 +498,10 @@ class ReplyCommentResource(Resource, ArgsMixin):
498
498
  if comment["person_id"] != current_user["id"]:
499
499
  if permissions.has_client_permissions():
500
500
  author = persons_service.get_person(comment["person_id"])
501
- if current_user["studio_id"] != author["studio_id"] and \
502
- author["role"] == "client":
501
+ if (
502
+ current_user["studio_id"] != author["studio_id"]
503
+ and author["role"] == "client"
504
+ ):
503
505
  raise permissions.PermissionDenied()
504
506
  user_service.check_task_action_access(task_id)
505
507
 
@@ -510,9 +512,7 @@ class ReplyCommentResource(Resource, ArgsMixin):
510
512
  )
511
513
  files = request.files
512
514
  return comments_service.reply_comment(
513
- comment_id,
514
- args["text"],
515
- files=files
515
+ comment_id, args["text"], files=files
516
516
  )
517
517
 
518
518
 
@@ -2575,4 +2575,4 @@ class GuessFromPathResource(Resource, ArgsMixin):
2575
2575
  },
2576
2576
  ["sep", "/"],
2577
2577
  ]
2578
- )
2578
+ )
@@ -14,6 +14,7 @@ from zou.app.services import (
14
14
  time_spents_service,
15
15
  shots_service,
16
16
  user_service,
17
+ templates_service,
17
18
  )
18
19
  from zou.app.utils import (
19
20
  permissions,
@@ -1398,17 +1399,18 @@ class ChangePasswordForPersonResource(Resource, ArgsMixin):
1398
1399
  html = f"""<p>Hello {person["first_name"]},</p>
1399
1400
  <p>
1400
1401
  Your password was changed at this date: {time_string}.
1401
- The IP of the user who changed your password is: {person_IP}.
1402
- If you don't know the person who changed the password, please contact our support team.
1403
1402
  </p>
1404
- Thank you and see you soon on Kitsu,
1403
+ <p>
1404
+ The IP of the user who changed your password is: {person_IP}.
1405
1405
  </p>
1406
1406
  <p>
1407
- {organisation["name"]} Team
1407
+ If you don't know the person who changed the password, please contact our support team.
1408
1408
  </p>
1409
1409
  """
1410
1410
  subject = f"{organisation['name']} - Kitsu: password changed"
1411
- emails.send_email(subject, html, person["email"])
1411
+ title = "Password Changed"
1412
+ email_html_body = templates_service.generate_html_body(title, html)
1413
+ emails.send_email(subject, email_html_body, person["email"])
1412
1414
  return {"success": True}
1413
1415
 
1414
1416
  except auth.PasswordsNoMatchException:
@@ -1497,17 +1499,18 @@ class DisableTwoFactorAuthenticationPersonResource(Resource, ArgsMixin):
1497
1499
  html = f"""<p>Hello {person["first_name"]},</p>
1498
1500
  <p>
1499
1501
  Your two factor authentication was disabled at this date: {time_string}.
1500
- The IP of the user who disabled your two factor authentication is: {person_IP}.
1501
- If you don't know the person who disabled the two factor authentication, please contact our support team.
1502
1502
  </p>
1503
- Thank you and see you soon on Kitsu,
1503
+ <p>
1504
+ The IP of the user who disabled your two factor authentication is: {person_IP}.
1504
1505
  </p>
1505
1506
  <p>
1506
- {organisation["name"]} Team
1507
+ If you don't know the person who disabled the two factor authentication, please contact our support team.
1507
1508
  </p>
1508
1509
  """
1509
1510
  subject = f"{organisation['name']} - Kitsu: two factor authentication disabled"
1510
- emails.send_email(subject, html, person["email"])
1511
+ title = "Two Factor Authentication Disabled"
1512
+ email_html_body = templates_service.generate_html_body(title, html)
1513
+ emails.send_email(subject, email_html_body, person["email"])
1511
1514
  return {"success": True}
1512
1515
 
1513
1516
  except UnactiveUserException:
@@ -727,48 +727,50 @@ class TempPlaylistResource(Resource, ArgsMixin):
727
727
 
728
728
  class NotifyClientsResource(Resource, ArgsMixin):
729
729
 
730
- @jwt_required()
731
- def post(self, playlist_id):
732
- """
733
- Notify clients that given playlist is ready.
734
-
735
- ---
736
- tags:
737
- - Playlists
738
- parameters:
739
- - in: path
740
- name: playlist_id
741
- required: true
742
- schema:
743
- type: string
744
- format: uuid
745
- example: a24a6ea4-ce75-4665-a070-57453082c25
746
- requestBody:
747
- required: true
748
- content:
749
- application/json:
750
- schema:
751
- type: object
752
- properties:
753
- studio_id:
754
- type: string
755
- format: uuid
756
- example: a24a6ea4-ce75-4665-a070-57453082c25
757
- responses:
758
- '200':
759
- description: Clients notified
760
- content:
761
- application/json:
730
+ @jwt_required()
731
+ def post(self, playlist_id):
732
+ """
733
+ Notify clients that given playlist is ready.
734
+
735
+ ---
736
+ tags:
737
+ - Playlists
738
+ parameters:
739
+ - in: path
740
+ name: playlist_id
741
+ required: true
762
742
  schema:
763
- type: object
764
- properties:
765
- status:
766
- type: string
767
- example: success
768
- """
769
- studio_id = request.json.get("studio_id", None)
770
- playlist = playlists_service.get_playlist(playlist_id)
771
- project_id = playlist["project_id"]
772
- user_service.check_manager_project_access(project_id)
773
- notifications_service.notify_clients_playlist_ready(playlist, studio_id)
774
- return {"status": "success"}
743
+ type: string
744
+ format: uuid
745
+ example: a24a6ea4-ce75-4665-a070-57453082c25
746
+ requestBody:
747
+ required: true
748
+ content:
749
+ application/json:
750
+ schema:
751
+ type: object
752
+ properties:
753
+ studio_id:
754
+ type: string
755
+ format: uuid
756
+ example: a24a6ea4-ce75-4665-a070-57453082c25
757
+ responses:
758
+ '200':
759
+ description: Clients notified
760
+ content:
761
+ application/json:
762
+ schema:
763
+ type: object
764
+ properties:
765
+ status:
766
+ type: string
767
+ example: success
768
+ """
769
+ studio_id = request.json.get("studio_id", None)
770
+ playlist = playlists_service.get_playlist(playlist_id)
771
+ project_id = playlist["project_id"]
772
+ user_service.check_manager_project_access(project_id)
773
+ notifications_service.notify_clients_playlist_ready(
774
+ playlist, studio_id
775
+ )
776
+ return {"status": "success"}
@@ -594,7 +594,6 @@ class DoneResource(Resource):
594
594
 
595
595
  class FiltersResource(Resource, ArgsMixin):
596
596
 
597
-
598
597
  def get(self):
599
598
  """
600
599
  Get filters
@@ -701,7 +700,6 @@ class FiltersResource(Resource, ArgsMixin):
701
700
 
702
701
  class FilterResource(Resource, ArgsMixin):
703
702
 
704
-
705
703
  def put(self, filter_id):
706
704
  """
707
705
  Update filter
@@ -14,7 +14,7 @@ from ldap3.core.exceptions import (
14
14
  LDAPInvalidCredentialsResult,
15
15
  )
16
16
 
17
- from zou.app.services import persons_service
17
+ from zou.app.services import persons_service, templates_service
18
18
  from zou.app.models.person import Person
19
19
  from zou.app.services.exception import (
20
20
  EmailOTPAlreadyEnabledException,
@@ -493,17 +493,13 @@ This one time password will expire after 5 minutes. After, you will have to requ
493
493
  This email was sent at this date : {time_string}.
494
494
  The IP of the person who requested this is: {person_IP}.
495
495
  </p>
496
-
497
- Thank you and see you soon on Kitsu,
498
- </p>
499
- <p>
500
- {organisation["name"]} Team
501
- </p>
502
496
  """
503
497
  subject = (
504
498
  f"{organisation['name']} - Kitsu : your verification code is {otp}"
505
499
  )
506
- emails.send_email(subject, html, person["email"])
500
+ title = "Your verification code"
501
+ email_html_body = templates_service.generate_html_body(title, html)
502
+ emails.send_email(subject, email_html_body, person["email"])
507
503
  return True
508
504
 
509
505
 
@@ -79,7 +79,7 @@ def create_comment(
79
79
  files={},
80
80
  created_at="",
81
81
  links=[],
82
- with_hashtags=True
82
+ with_hashtags=True,
83
83
  ):
84
84
  """
85
85
  Create a new comment and related: news, notifications and events.
@@ -136,12 +136,11 @@ def _handle_hashtags(person, task_type, task, text):
136
136
  task_id=_task["id"],
137
137
  text=text + f"\n\n____\nFrom {task_type['name']} task",
138
138
  task_status_id=task_status["id"],
139
- with_hashtags=False
139
+ with_hashtags=False,
140
140
  )
141
141
  return hashtags
142
142
 
143
143
 
144
-
145
144
  def _check_retake_capping(task_status, task):
146
145
  if task_status["is_retake"]:
147
146
  project = projects_service.get_project(task["project_id"])
@@ -629,7 +628,7 @@ def get_comment_department_mention_ids(project_id, text):
629
628
 
630
629
  def get_comment_hashtags(text):
631
630
  """
632
- Check for task type mentions (#full name) in text and returns matching
631
+ Check for task type mentions (#full name) in text and returns matching
633
632
  tags. If all is present, return only all because it includes everything
634
633
  else.
635
634
  """
@@ -650,13 +649,13 @@ def filter_tasks_by_hashtags(tasks, hashtags, original_task_type):
650
649
  return [
651
650
  task
652
651
  for task in tasks
653
- if task["task_type_name"].lower() != \
654
- original_task_type["name"].lower()
652
+ if task["task_type_name"].lower()
653
+ != original_task_type["name"].lower()
655
654
  ]
656
655
  else:
657
656
  hashtag_map = {
658
657
  hashtag: True
659
- for hashtag in hashtags
658
+ for hashtag in hashtags
660
659
  if hashtag != original_task_type["name"].lower()
661
660
  }
662
661
  return [
@@ -3,6 +3,8 @@ from sqlalchemy.exc import IntegrityError
3
3
 
4
4
 
5
5
  from zou.app.models.attachment_file import AttachmentFile
6
+ from zou.app.models.budget import Budget
7
+ from zou.app.models.budget_entry import BudgetEntry
6
8
  from zou.app.models.comment import Comment
7
9
  from zou.app.models.desktop_login_log import DesktopLoginLog
8
10
  from zou.app.models.entity import (
@@ -346,6 +348,11 @@ def remove_project(project_id):
346
348
  for task in tasks:
347
349
  remove_task(task.id, force=True)
348
350
 
351
+ budgets = Budget.get_all_by(project_id=project_id)
352
+ for budget in budgets:
353
+ BudgetEntry.delete_all_by(budget_id=budget.id)
354
+ budget.delete()
355
+
349
356
  EntityLink.query.filter(
350
357
  EntityLink.entity_in_id == Entity.id,
351
358
  Entity.project_id == project_id,
@@ -10,10 +10,12 @@ from zou.app.services import (
10
10
  tasks_service,
11
11
  )
12
12
  from zou.app.stores import queue_store
13
- from zou.app.services.template_services import generate_html_body
13
+ from zou.app.services.templates_service import generate_html_body
14
14
 
15
15
 
16
- def send_notification(person_id, subject, messages, title=""):
16
+ def send_notification(
17
+ person_id, subject, messages, title="", force_email=False
18
+ ):
17
19
  """
18
20
  Send email notification to given person. Use the job queue if it is
19
21
  activated.
@@ -25,7 +27,7 @@ def send_notification(person_id, subject, messages, title=""):
25
27
  discord_message = messages["discord_message"]
26
28
  email_html_body = generate_html_body(title, email_message)
27
29
 
28
- if person["notifications_enabled"]:
30
+ if person["notifications_enabled"] or force_email:
29
31
  if config.ENABLE_JOB_QUEUE:
30
32
  queue_store.job_queue.enqueue(
31
33
  emails.send_email,
@@ -79,7 +81,7 @@ def send_notification(person_id, subject, messages, title=""):
79
81
 
80
82
  def send_comment_notification(person_id, author_id, comment, task):
81
83
  """
82
- Send a notification emali telling that a new comment was posted to person
84
+ Send a notification email telling that a new comment was posted to person
83
85
  matching given person id.
84
86
  """
85
87
  person = persons_service.get_person(person_id)
@@ -155,6 +157,7 @@ _%s_
155
157
  task_status_name,
156
158
  )
157
159
 
160
+ title = "New Comment"
158
161
  messages = {
159
162
  "email_message": email_message,
160
163
  "slack_message": slack_message,
@@ -164,7 +167,7 @@ _%s_
164
167
  },
165
168
  "discord_message": discord_message,
166
169
  }
167
- send_notification(person_id, subject, messages)
170
+ send_notification(person_id, subject, messages, title)
168
171
 
169
172
  return True
170
173
 
@@ -215,7 +218,7 @@ _%s_
215
218
  task_url,
216
219
  comment["text"],
217
220
  )
218
-
221
+ title = "New Mention"
219
222
  messages = {
220
223
  "email_message": email_message,
221
224
  "slack_message": slack_message,
@@ -225,7 +228,7 @@ _%s_
225
228
  },
226
229
  "discord_message": discord_message,
227
230
  }
228
- return send_notification(person_id, subject, messages)
231
+ return send_notification(person_id, subject, messages, title)
229
232
  else:
230
233
  return True
231
234
 
@@ -273,7 +276,7 @@ def send_assignation_notification(person_id, author_id, task):
273
276
  },
274
277
  "discord_message": discord_message,
275
278
  }
276
- return send_notification(person_id, subject, messages)
279
+ return send_notification(person_id, subject, messages, title)
277
280
  return True
278
281
 
279
282
 
@@ -372,7 +375,7 @@ _%s_
372
375
  },
373
376
  "discord_message": discord_message,
374
377
  }
375
- send_notification(person_id, subject, messages)
378
+ send_notification(person_id, subject, messages, title)
376
379
  return True
377
380
 
378
381
 
@@ -397,25 +400,41 @@ def send_playlist_ready_notification(person_id, author_id, playlist):
397
400
  or person["notifications_mattermost_enabled"]
398
401
  or person["notifications_discord_enabled"]
399
402
  ):
403
+
404
+ playlist_url = f"{config.DOMAIN_PROTOCOL}://{config.DOMAIN_NAME}/productions/{playlist['project_id']}/"
405
+
400
406
  if episode is not None:
401
- playlist_url = f"{config.DOMAIN_PROTOCOL}://{config.DOMAIN_NAME}/productions/{playlist['project_id']}/episodes/{episode['id']}/playlists/{playlist['id']}"
407
+ playlist_url += (
408
+ f"episodes/{episode['id']}/playlists/{playlist['id']}"
409
+ )
410
+ elif (
411
+ project["production_type"] == "tvshow"
412
+ and playlist["for_entity"] == "asset"
413
+ ):
414
+ if playlist["is_for_all"] == True:
415
+ playlist_url += f"episodes/all/playlists/{playlist['id']}"
416
+ else:
417
+ playlist_url += f"episodes/main/playlists/{playlist['id']}"
402
418
  else:
403
- playlist_url = f"{config.DOMAIN_PROTOCOL}://{config.DOMAIN_NAME}/productions/{playlist['project_id']}/playlists/{playlist['id']}"
419
+ playlist_url += f"playlists/{playlist['id']}"
404
420
 
405
- title = "Playlist Ready"
421
+ title = "New Playlist Ready"
406
422
  episode_segment = ""
407
423
  if episode is not None:
408
- episode_segment = f"the episode {episode['name']} of"
409
- subject = "[Kitsu] A new playlist is ready"
424
+ episode_segment = f"the episode {episode['name']} of "
425
+ subject = f'[Kitsu] The playlist {playlist["name"]} in project {project["name"]} is ready for review'
410
426
 
411
- email_message = f"""<p><strong>{author["full_name"]}</strong> notifies you that playlist <a href="{playlist_url}">{playlist["name"]}</a> is ready for a review under {episode_segment} the project {project["name"]}.</p>
427
+ email_message = f"""<p><strong>{author["full_name"]}</strong> notifies you that playlist <a href="{playlist_url}">{playlist["name"]}</a> is ready for a review under {episode_segment}the project {project["name"]}.</p>
428
+ """
412
429
 
413
- {len(playlist["shots"])} elements are listed in the playlist.
430
+ if len(playlist["shots"]) > 1:
431
+ email_message += f"""
432
+ <p>{len(playlist["shots"])} elements are listed in the playlist.</p>
414
433
  """
415
434
 
416
- slack_message = f"*{author['full_name']}* notifies you that a playlist <{playlist_url}|{playlist['name']}> is ready for a review under {episode_segment} the project {project['name']}."
435
+ slack_message = f"*{author['full_name']}* notifies you that a playlist <{playlist_url}|{playlist['name']}> is ready for a review under {episode_segment}the project {project['name']}."
417
436
 
418
- discord_message = f"*{author['full_name']}* notifies you that a playlist [{playlist['name']}]({playlist_url}) is ready for a review under {episode_segment} the project {project['name']}."
437
+ discord_message = f"*{author['full_name']}* notifies you that a playlist [{playlist['name']}]({playlist_url}) is ready for a review under {episode_segment}the project {project['name']}."
419
438
  messages = {
420
439
  "email_message": email_message,
421
440
  "slack_message": slack_message,
@@ -425,4 +444,6 @@ def send_playlist_ready_notification(person_id, author_id, playlist):
425
444
  },
426
445
  "discord_message": discord_message,
427
446
  }
428
- send_notification(person_id, subject, messages, title)
447
+ send_notification(
448
+ person_id, subject, messages, title, force_email=True
449
+ )
@@ -376,7 +376,7 @@ def get_entity_tasks(entity):
376
376
  get_tasks = getattr(
377
377
  tasks_service, "get_tasks_for_" + entity_type_name.lower()
378
378
  )
379
- return get_tasks(entity["id"])
379
+ return get_tasks(entity["id"])
380
380
 
381
381
 
382
382
  def remove_entity_link(link_id):
@@ -505,8 +505,7 @@ def notify_clients_playlist_ready(playlist, studio_id=None):
505
505
  author = persons_service.get_current_user()
506
506
  project_id = playlist["project_id"]
507
507
  query = (
508
- Person.query
509
- .join(ProjectPersonLink)
508
+ Person.query.join(ProjectPersonLink)
510
509
  .filter(Person.is_bot == False)
511
510
  .filter(Person.role == "client")
512
511
  .filter(ProjectPersonLink.project_id == project_id)
@@ -529,3 +528,12 @@ def notify_clients_playlist_ready(playlist, studio_id=None):
529
528
  emails_service.send_playlist_ready_notification(
530
529
  recipient_id, author_id, playlist
531
530
  )
531
+ events.emit(
532
+ "notification:new",
533
+ {
534
+ "notification_id": notification["id"],
535
+ "person_id": recipient_id,
536
+ },
537
+ project_id=playlist["project_id"],
538
+ persist=False,
539
+ )
@@ -18,7 +18,7 @@ from zou.app.models.time_spent import TimeSpent
18
18
 
19
19
  from zou.app import config, file_store
20
20
  from zou.app.utils import fields, events, cache, emails, date_helpers
21
- from zou.app.services import index_service, auth_service
21
+ from zou.app.services import index_service, auth_service, templates_service
22
22
  from zou.app.stores import auth_tokens_store
23
23
  from zou.app.services.exception import (
24
24
  PersonNotFoundException,
@@ -441,9 +441,8 @@ def invite_person(person_id):
441
441
  auth_tokens_store.add(
442
442
  "reset-token-%s" % person["email"], token, ttl=3600 * 24 * 7
443
443
  )
444
- subject = (
445
- "You are invited by %s to join their Kitsu production tracker"
446
- % (organisation["name"])
444
+ subject = "You are invited by %s to join their Kitsu platform" % (
445
+ organisation["name"]
447
446
  )
448
447
  params = {"email": person["email"], "token": token}
449
448
  query = urllib.parse.urlencode(params)
@@ -461,27 +460,21 @@ def invite_person(person_id):
461
460
 
462
461
  html = f"""<p>Hello {person["first_name"]},</p>
463
462
  <p>
464
- You are invited by {organisation["name"]} to collaborate on their Kitsu production tracker.
463
+ You are invited by {organisation["name"]} to join their team on Kitsu.
465
464
  </p>
466
465
  <p>
467
466
  Your login is: <strong>{person["email"]}</strong>
468
467
  </p>
469
468
  <p>
470
- You are invited to set your password by following this link: <a href="{reset_url}">{reset_url}</a>
469
+ Set your password to continue:
471
470
  </p>
472
- <p>
473
- This link will expire after one week. After, you have to request to reset your password.
474
- The invitation was sent at this date: {time_string}.
475
- </p>
476
- <p>
477
- Thank you and see you soon on Kitsu,
478
- </p>
479
- <p>
480
- {organisation["name"]} Team
471
+ <p class="cta">
472
+ <a class="button" href="{reset_url}">Set your password</a>
481
473
  </p>
482
474
  """
483
-
484
- emails.send_email(subject, html, person["email"])
475
+ title = "Welcome to Kitsu"
476
+ email_html_body = templates_service.generate_html_body(title, html)
477
+ emails.send_email(subject, email_html_body, person["email"])
485
478
 
486
479
 
487
480
  @cache.memoize_function(120)
@@ -38,6 +38,7 @@ from zou.app.services import (
38
38
  tasks_service,
39
39
  names_service,
40
40
  persons_service,
41
+ templates_service,
41
42
  )
42
43
 
43
44
  from zou.app.services.exception import (
@@ -694,19 +695,17 @@ def build_playlist_job(playlist, job, shots, params, email, full, remote):
694
695
  job["id"],
695
696
  )
696
697
  html = f"""<p>Hello {person.first_name},</p>
697
- <p>Your playlist {playlist["name"]} is available at:
698
- <a href="{playlist_url}">{playlist_url}</a>
698
+ <p>Your playlist {playlist["name"]} build is available:
699
699
  </p>
700
- <p>
701
- Thank you and see you soon on Kitsu,
702
- </p>
703
- <p>
704
- {organisation["name"]} Team
700
+ <p class="cta">
701
+ <a href="{playlist_url}">Download Playlist Build (.mp4)</a>
705
702
  </p>
706
703
  """
707
704
 
708
705
  subject = f"{organisation['name']} - Kitsu: playlist download"
709
- emails.send_email(subject, html, email)
706
+ title = "Playlist Download"
707
+ email_html_body = templates_service.generate_html_body(title, html)
708
+ emails.send_email(subject, email_html_body, email)
710
709
 
711
710
 
712
711
  def get_playlist_file_name(playlist):
@@ -107,7 +107,6 @@ notification_template_end_title = """
107
107
  """
108
108
 
109
109
 
110
-
111
110
  def get_signature():
112
111
  """
113
112
  Build signature for Zou emails.
@@ -115,7 +114,7 @@ def get_signature():
115
114
  organisation = persons_service.get_organisation()
116
115
  return (
117
116
  """
118
- <p>Best,</p>
117
+ <p>Best regards,</p>
119
118
 
120
119
  <p>%s Team</p>"""
121
120
  % organisation["name"]
@@ -123,7 +122,11 @@ def get_signature():
123
122
 
124
123
 
125
124
  def generate_html_body(title, message):
126
- return notification_template_begin + \
127
- title + notification_template_end_title + \
128
- message + get_signature () + \
129
- notification_template_end
125
+ return (
126
+ notification_template_begin
127
+ + title
128
+ + notification_template_end_title
129
+ + message
130
+ + get_signature()
131
+ + notification_template_end
132
+ )