@open-mercato/core 0.10.1-develop.7717.1.2befe9c634 → 0.10.1-develop.7721.1.b5c4a00a68

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 (384) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/dist/generated/entities/staff_support_routing_rule/index.js +21 -0
  3. package/dist/generated/entities/staff_support_routing_rule/index.js.map +7 -0
  4. package/dist/generated/entities/staff_support_ticket/index.js +37 -0
  5. package/dist/generated/entities/staff_support_ticket/index.js.map +7 -0
  6. package/dist/generated/entities/staff_time_project/index.js +2 -0
  7. package/dist/generated/entities/staff_time_project/index.js.map +2 -2
  8. package/dist/generated/entities/staff_time_project_member/index.js +2 -0
  9. package/dist/generated/entities/staff_time_project_member/index.js.map +2 -2
  10. package/dist/generated/entities/staff_time_task/index.js +4 -0
  11. package/dist/generated/entities/staff_time_task/index.js.map +2 -2
  12. package/dist/generated/entities/staff_time_task_comment/index.js +9 -1
  13. package/dist/generated/entities/staff_time_task_comment/index.js.map +2 -2
  14. package/dist/generated/entities.ids.generated.js +2 -0
  15. package/dist/generated/entities.ids.generated.js.map +2 -2
  16. package/dist/generated/entity-fields-registry.js +38 -0
  17. package/dist/generated/entity-fields-registry.js.map +2 -2
  18. package/dist/helpers/integration/auth.js +1 -0
  19. package/dist/helpers/integration/auth.js.map +2 -2
  20. package/dist/helpers/integration/communicationChannelsFixtures.js +20 -0
  21. package/dist/helpers/integration/communicationChannelsFixtures.js.map +2 -2
  22. package/dist/modules/catalog/api/bulk-delete/route.js +12 -2
  23. package/dist/modules/catalog/api/bulk-delete/route.js.map +2 -2
  24. package/dist/modules/communication_channels/api/post/test-seed/route.js +17 -3
  25. package/dist/modules/communication_channels/api/post/test-seed/route.js.map +2 -2
  26. package/dist/modules/communication_channels/lib/test-seed.js +38 -5
  27. package/dist/modules/communication_channels/lib/test-seed.js.map +2 -2
  28. package/dist/modules/messages/commands/messages.js +2 -3
  29. package/dist/modules/messages/commands/messages.js.map +2 -2
  30. package/dist/modules/portal/frontend/[orgSlug]/portal/dashboard/page.js +2 -2
  31. package/dist/modules/portal/frontend/[orgSlug]/portal/dashboard/page.js.map +2 -2
  32. package/dist/modules/staff/api/portal/support-tickets/[id]/attachments/route.js +299 -0
  33. package/dist/modules/staff/api/portal/support-tickets/[id]/attachments/route.js.map +7 -0
  34. package/dist/modules/staff/api/portal/support-tickets/[id]/messages/route.js +91 -0
  35. package/dist/modules/staff/api/portal/support-tickets/[id]/messages/route.js.map +7 -0
  36. package/dist/modules/staff/api/portal/support-tickets/[id]/route.js +146 -0
  37. package/dist/modules/staff/api/portal/support-tickets/[id]/route.js.map +7 -0
  38. package/dist/modules/staff/api/portal/support-tickets/options/route.js +60 -0
  39. package/dist/modules/staff/api/portal/support-tickets/options/route.js.map +7 -0
  40. package/dist/modules/staff/api/portal/support-tickets/route.js +220 -0
  41. package/dist/modules/staff/api/portal/support-tickets/route.js.map +7 -0
  42. package/dist/modules/staff/api/timesheets/settings/route.js +7 -1
  43. package/dist/modules/staff/api/timesheets/settings/route.js.map +2 -2
  44. package/dist/modules/staff/api/timesheets/support-routing-rules/fallback-project/route.js +122 -0
  45. package/dist/modules/staff/api/timesheets/support-routing-rules/fallback-project/route.js.map +7 -0
  46. package/dist/modules/staff/api/timesheets/support-routing-rules/preview/route.js +180 -0
  47. package/dist/modules/staff/api/timesheets/support-routing-rules/preview/route.js.map +7 -0
  48. package/dist/modules/staff/api/timesheets/support-routing-rules/route.js +147 -0
  49. package/dist/modules/staff/api/timesheets/support-routing-rules/route.js.map +7 -0
  50. package/dist/modules/staff/api/timesheets/support-tickets/options/route.js +133 -0
  51. package/dist/modules/staff/api/timesheets/support-tickets/options/route.js.map +7 -0
  52. package/dist/modules/staff/api/timesheets/tasks/[id]/claim/route.js +33 -0
  53. package/dist/modules/staff/api/timesheets/tasks/[id]/claim/route.js.map +7 -0
  54. package/dist/modules/staff/api/timesheets/tasks/[id]/comments/route.js +25 -7
  55. package/dist/modules/staff/api/timesheets/tasks/[id]/comments/route.js.map +2 -2
  56. package/dist/modules/staff/api/timesheets/tasks/[id]/release/route.js +32 -0
  57. package/dist/modules/staff/api/timesheets/tasks/[id]/release/route.js.map +7 -0
  58. package/dist/modules/staff/api/timesheets/tasks/route.js +94 -47
  59. package/dist/modules/staff/api/timesheets/tasks/route.js.map +2 -2
  60. package/dist/modules/staff/api/timesheets/time-projects/[id]/employees/route.js +3 -0
  61. package/dist/modules/staff/api/timesheets/time-projects/[id]/employees/route.js.map +2 -2
  62. package/dist/modules/staff/api/timesheets/time-projects/route.js +3 -0
  63. package/dist/modules/staff/api/timesheets/time-projects/route.js.map +2 -2
  64. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.js +1 -0
  65. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.js.map +2 -2
  66. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/page.js +54 -4
  67. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/page.js.map +2 -2
  68. package/dist/modules/staff/backend/staff/time-tracking/projects/projectFormConfig.js +21 -5
  69. package/dist/modules/staff/backend/staff/time-tracking/projects/projectFormConfig.js.map +2 -2
  70. package/dist/modules/staff/backend/staff/time-tracking/settings/page.js +319 -254
  71. package/dist/modules/staff/backend/staff/time-tracking/settings/page.js.map +2 -2
  72. package/dist/modules/staff/backend/staff/time-tracking/support/page.js +363 -0
  73. package/dist/modules/staff/backend/staff/time-tracking/support/page.js.map +7 -0
  74. package/dist/modules/staff/backend/staff/time-tracking/support/page.meta.js +18 -0
  75. package/dist/modules/staff/backend/staff/time-tracking/support/page.meta.js.map +7 -0
  76. package/dist/modules/staff/cli.js +27 -0
  77. package/dist/modules/staff/cli.js.map +2 -2
  78. package/dist/modules/staff/commands/index.js +3 -0
  79. package/dist/modules/staff/commands/index.js.map +2 -2
  80. package/dist/modules/staff/commands/shared.js +10 -1
  81. package/dist/modules/staff/commands/shared.js.map +2 -2
  82. package/dist/modules/staff/commands/support-routing-rules.js +505 -0
  83. package/dist/modules/staff/commands/support-routing-rules.js.map +7 -0
  84. package/dist/modules/staff/commands/support-tickets.js +513 -0
  85. package/dist/modules/staff/commands/support-tickets.js.map +7 -0
  86. package/dist/modules/staff/commands/timesheets-projects.js +72 -14
  87. package/dist/modules/staff/commands/timesheets-projects.js.map +2 -2
  88. package/dist/modules/staff/commands/timesheets-task-assignment.js +270 -0
  89. package/dist/modules/staff/commands/timesheets-task-assignment.js.map +7 -0
  90. package/dist/modules/staff/commands/timesheets-task-comments.js +58 -12
  91. package/dist/modules/staff/commands/timesheets-task-comments.js.map +2 -2
  92. package/dist/modules/staff/commands/timesheets-tasks.js +91 -9
  93. package/dist/modules/staff/commands/timesheets-tasks.js.map +3 -3
  94. package/dist/modules/staff/data/enrichers.js +141 -0
  95. package/dist/modules/staff/data/enrichers.js.map +2 -2
  96. package/dist/modules/staff/data/entities.js +143 -2
  97. package/dist/modules/staff/data/entities.js.map +2 -2
  98. package/dist/modules/staff/data/extensions.js +8 -0
  99. package/dist/modules/staff/data/extensions.js.map +2 -2
  100. package/dist/modules/staff/data/validators.js +34 -5
  101. package/dist/modules/staff/data/validators.js.map +2 -2
  102. package/dist/modules/staff/encryption.js +6 -0
  103. package/dist/modules/staff/encryption.js.map +2 -2
  104. package/dist/modules/staff/events.js +25 -0
  105. package/dist/modules/staff/events.js.map +2 -2
  106. package/dist/modules/staff/events.payloads.js +54 -0
  107. package/dist/modules/staff/events.payloads.js.map +2 -2
  108. package/dist/modules/staff/extension-points.js +1 -0
  109. package/dist/modules/staff/extension-points.js.map +2 -2
  110. package/dist/modules/staff/frontend/[orgSlug]/portal/support/[id]/page.js +468 -0
  111. package/dist/modules/staff/frontend/[orgSlug]/portal/support/[id]/page.js.map +7 -0
  112. package/dist/modules/staff/frontend/[orgSlug]/portal/support/[id]/page.meta.js +12 -0
  113. package/dist/modules/staff/frontend/[orgSlug]/portal/support/[id]/page.meta.js.map +7 -0
  114. package/dist/modules/staff/frontend/[orgSlug]/portal/support/new/page.js +316 -0
  115. package/dist/modules/staff/frontend/[orgSlug]/portal/support/new/page.js.map +7 -0
  116. package/dist/modules/staff/frontend/[orgSlug]/portal/support/new/page.meta.js +12 -0
  117. package/dist/modules/staff/frontend/[orgSlug]/portal/support/new/page.meta.js.map +7 -0
  118. package/dist/modules/staff/frontend/[orgSlug]/portal/support/page.js +190 -0
  119. package/dist/modules/staff/frontend/[orgSlug]/portal/support/page.js.map +7 -0
  120. package/dist/modules/staff/frontend/[orgSlug]/portal/support/page.meta.js +19 -0
  121. package/dist/modules/staff/frontend/[orgSlug]/portal/support/page.meta.js.map +7 -0
  122. package/dist/modules/staff/index.js +1 -1
  123. package/dist/modules/staff/index.js.map +2 -2
  124. package/dist/modules/staff/lib/crud.js +2 -0
  125. package/dist/modules/staff/lib/crud.js.map +2 -2
  126. package/dist/modules/staff/lib/support/attachments.js +36 -0
  127. package/dist/modules/staff/lib/support/attachments.js.map +7 -0
  128. package/dist/modules/staff/lib/support/dictionaries.js +87 -0
  129. package/dist/modules/staff/lib/support/dictionaries.js.map +7 -0
  130. package/dist/modules/staff/lib/support/notifications.js +111 -0
  131. package/dist/modules/staff/lib/support/notifications.js.map +7 -0
  132. package/dist/modules/staff/lib/support/portalAttachments.js +100 -0
  133. package/dist/modules/staff/lib/support/portalAttachments.js.map +7 -0
  134. package/dist/modules/staff/lib/support/portalBroadcast.js +117 -0
  135. package/dist/modules/staff/lib/support/portalBroadcast.js.map +7 -0
  136. package/dist/modules/staff/lib/support/portalRoute.js +99 -0
  137. package/dist/modules/staff/lib/support/portalRoute.js.map +7 -0
  138. package/dist/modules/staff/lib/support/portalStatus.js +12 -0
  139. package/dist/modules/staff/lib/support/portalStatus.js.map +7 -0
  140. package/dist/modules/staff/lib/support/portalTickets.js +148 -0
  141. package/dist/modules/staff/lib/support/portalTickets.js.map +7 -0
  142. package/dist/modules/staff/lib/support/routing.js +81 -0
  143. package/dist/modules/staff/lib/support/routing.js.map +7 -0
  144. package/dist/modules/staff/lib/support/routingRuleDraft.js +25 -0
  145. package/dist/modules/staff/lib/support/routingRuleDraft.js.map +7 -0
  146. package/dist/modules/staff/lib/support/seedDefaults.js +114 -0
  147. package/dist/modules/staff/lib/support/seedDefaults.js.map +7 -0
  148. package/dist/modules/staff/lib/support/supportActivity.js +26 -0
  149. package/dist/modules/staff/lib/support/supportActivity.js.map +7 -0
  150. package/dist/modules/staff/lib/support-ui/PortalSupportNotLinked.js +23 -0
  151. package/dist/modules/staff/lib/support-ui/PortalSupportNotLinked.js.map +7 -0
  152. package/dist/modules/staff/lib/support-ui/portalAttachmentValidation.js +112 -0
  153. package/dist/modules/staff/lib/support-ui/portalAttachmentValidation.js.map +7 -0
  154. package/dist/modules/staff/lib/support-ui/portalPendingUploads.js +45 -0
  155. package/dist/modules/staff/lib/support-ui/portalPendingUploads.js.map +7 -0
  156. package/dist/modules/staff/lib/support-ui/portalSupport.js +51 -0
  157. package/dist/modules/staff/lib/support-ui/portalSupport.js.map +7 -0
  158. package/dist/modules/staff/lib/time-tracking/access.js +3 -39
  159. package/dist/modules/staff/lib/time-tracking/access.js.map +2 -2
  160. package/dist/modules/staff/lib/time-tracking/listProjectAccess.js +54 -0
  161. package/dist/modules/staff/lib/time-tracking/listProjectAccess.js.map +7 -0
  162. package/dist/modules/staff/lib/time-tracking/portalRecipients.js +92 -2
  163. package/dist/modules/staff/lib/time-tracking/portalRecipients.js.map +2 -2
  164. package/dist/modules/staff/lib/time-tracking/projectAssignment.js +112 -0
  165. package/dist/modules/staff/lib/time-tracking/projectAssignment.js.map +7 -0
  166. package/dist/modules/staff/lib/time-tracking/settingKeys.js +14 -0
  167. package/dist/modules/staff/lib/time-tracking/settingKeys.js.map +2 -2
  168. package/dist/modules/staff/lib/time-tracking/settings.js +28 -1
  169. package/dist/modules/staff/lib/time-tracking/settings.js.map +2 -2
  170. package/dist/modules/staff/lib/time-tracking/taskAssignmentRoute.js +143 -0
  171. package/dist/modules/staff/lib/time-tracking/taskAssignmentRoute.js.map +7 -0
  172. package/dist/modules/staff/lib/time-tracking/workRecipients.js +92 -0
  173. package/dist/modules/staff/lib/time-tracking/workRecipients.js.map +7 -0
  174. package/dist/modules/staff/lib/time-tracking-ui/BoardFilterChips.js +32 -3
  175. package/dist/modules/staff/lib/time-tracking-ui/BoardFilterChips.js.map +2 -2
  176. package/dist/modules/staff/lib/time-tracking-ui/KanbanBoard.js +29 -0
  177. package/dist/modules/staff/lib/time-tracking-ui/KanbanBoard.js.map +2 -2
  178. package/dist/modules/staff/lib/time-tracking-ui/KanbanCard.js +4 -0
  179. package/dist/modules/staff/lib/time-tracking-ui/KanbanCard.js.map +2 -2
  180. package/dist/modules/staff/lib/time-tracking-ui/ProjectFormSections.js +141 -1
  181. package/dist/modules/staff/lib/time-tracking-ui/ProjectFormSections.js.map +2 -2
  182. package/dist/modules/staff/lib/time-tracking-ui/SupportAttachmentsSection.js +153 -0
  183. package/dist/modules/staff/lib/time-tracking-ui/SupportAttachmentsSection.js.map +7 -0
  184. package/dist/modules/staff/lib/time-tracking-ui/SupportRequestPanel.js +67 -0
  185. package/dist/modules/staff/lib/time-tracking-ui/SupportRequestPanel.js.map +7 -0
  186. package/dist/modules/staff/lib/time-tracking-ui/TaskBoardScreen.js +3 -1
  187. package/dist/modules/staff/lib/time-tracking-ui/TaskBoardScreen.js.map +2 -2
  188. package/dist/modules/staff/lib/time-tracking-ui/TaskCommentThread.js +80 -17
  189. package/dist/modules/staff/lib/time-tracking-ui/TaskCommentThread.js.map +2 -2
  190. package/dist/modules/staff/lib/time-tracking-ui/TaskDrawer.js +230 -41
  191. package/dist/modules/staff/lib/time-tracking-ui/TaskDrawer.js.map +2 -2
  192. package/dist/modules/staff/lib/time-tracking-ui/boardDirectory.js +21 -1
  193. package/dist/modules/staff/lib/time-tracking-ui/boardDirectory.js.map +2 -2
  194. package/dist/modules/staff/lib/time-tracking-ui/boardFilters.js +16 -4
  195. package/dist/modules/staff/lib/time-tracking-ui/boardFilters.js.map +2 -2
  196. package/dist/modules/staff/lib/time-tracking-ui/kanbanBoardData.js +3 -1
  197. package/dist/modules/staff/lib/time-tracking-ui/kanbanBoardData.js.map +2 -2
  198. package/dist/modules/staff/lib/time-tracking-ui/projectDefaultAssignee.js +68 -0
  199. package/dist/modules/staff/lib/time-tracking-ui/projectDefaultAssignee.js.map +7 -0
  200. package/dist/modules/staff/lib/time-tracking-ui/settingsTabs.js +7 -0
  201. package/dist/modules/staff/lib/time-tracking-ui/settingsTabs.js.map +7 -0
  202. package/dist/modules/staff/lib/time-tracking-ui/supportTicketData.js +50 -0
  203. package/dist/modules/staff/lib/time-tracking-ui/supportTicketData.js.map +7 -0
  204. package/dist/modules/staff/lib/time-tracking-ui/taskDrawerData.js +13 -1
  205. package/dist/modules/staff/lib/time-tracking-ui/taskDrawerData.js.map +2 -2
  206. package/dist/modules/staff/lib/time-tracking-ui/timeTrackingSettingsForm.js +36 -2
  207. package/dist/modules/staff/lib/time-tracking-ui/timeTrackingSettingsForm.js.map +2 -2
  208. package/dist/modules/staff/migrations/Migration20261009180543_staff.js +42 -0
  209. package/dist/modules/staff/migrations/Migration20261009180543_staff.js.map +7 -0
  210. package/dist/modules/staff/notifications.js +92 -0
  211. package/dist/modules/staff/notifications.js.map +2 -2
  212. package/dist/modules/staff/setup.js +6 -2
  213. package/dist/modules/staff/setup.js.map +2 -2
  214. package/dist/modules/staff/subscribers/support-portal-comment-created.js +26 -0
  215. package/dist/modules/staff/subscribers/support-portal-comment-created.js.map +7 -0
  216. package/dist/modules/staff/subscribers/support-portal-comment-deleted.js +26 -0
  217. package/dist/modules/staff/subscribers/support-portal-comment-deleted.js.map +7 -0
  218. package/dist/modules/staff/subscribers/support-portal-comment-updated.js +26 -0
  219. package/dist/modules/staff/subscribers/support-portal-comment-updated.js.map +7 -0
  220. package/dist/modules/staff/subscribers/support-portal-status-column-updated.js +24 -0
  221. package/dist/modules/staff/subscribers/support-portal-status-column-updated.js.map +7 -0
  222. package/dist/modules/staff/subscribers/support-portal-task-status-changed.js +25 -0
  223. package/dist/modules/staff/subscribers/support-portal-task-status-changed.js.map +7 -0
  224. package/dist/modules/staff/subscribers/support-portal-task-updated.js +25 -0
  225. package/dist/modules/staff/subscribers/support-portal-task-updated.js.map +7 -0
  226. package/dist/modules/staff/subscribers/support-ticket-created-notification.js +25 -0
  227. package/dist/modules/staff/subscribers/support-ticket-created-notification.js.map +7 -0
  228. package/dist/modules/staff/subscribers/support-ticket-customer-replied-notification.js +25 -0
  229. package/dist/modules/staff/subscribers/support-ticket-customer-replied-notification.js.map +7 -0
  230. package/dist/modules/staff/subscribers/support-ticket-unnotified-clear.js +26 -0
  231. package/dist/modules/staff/subscribers/support-ticket-unnotified-clear.js.map +7 -0
  232. package/dist/modules/staff/subscribers/time-task-assignee-notification.js +83 -0
  233. package/dist/modules/staff/subscribers/time-task-assignee-notification.js.map +7 -0
  234. package/dist/modules/staff/widgets/injection/portal-support-tickets/widget.client.js +112 -0
  235. package/dist/modules/staff/widgets/injection/portal-support-tickets/widget.client.js.map +7 -0
  236. package/dist/modules/staff/widgets/injection/portal-support-tickets/widget.js +17 -0
  237. package/dist/modules/staff/widgets/injection/portal-support-tickets/widget.js.map +7 -0
  238. package/dist/modules/staff/widgets/injection/time-tracking-settings-support/widget.client.js +870 -0
  239. package/dist/modules/staff/widgets/injection/time-tracking-settings-support/widget.client.js.map +7 -0
  240. package/dist/modules/staff/widgets/injection/time-tracking-settings-support/widget.js +17 -0
  241. package/dist/modules/staff/widgets/injection/time-tracking-settings-support/widget.js.map +7 -0
  242. package/dist/modules/staff/widgets/injection-table.js +16 -1
  243. package/dist/modules/staff/widgets/injection-table.js.map +2 -2
  244. package/dist/modules/wms/components/backend/WmsLocationDetailPage.js +4 -18
  245. package/dist/modules/wms/components/backend/WmsLocationDetailPage.js.map +2 -2
  246. package/dist/modules/wms/components/backend/WmsLotDetailPage.js +4 -18
  247. package/dist/modules/wms/components/backend/WmsLotDetailPage.js.map +2 -2
  248. package/dist/modules/wms/components/backend/WmsSkuDetailPage.js +4 -18
  249. package/dist/modules/wms/components/backend/WmsSkuDetailPage.js.map +2 -2
  250. package/dist/modules/wms/lib/inventoryCsvExport.js +19 -0
  251. package/dist/modules/wms/lib/inventoryCsvExport.js.map +7 -0
  252. package/generated/entities/staff_support_routing_rule/index.ts +9 -0
  253. package/generated/entities/staff_support_ticket/index.ts +17 -0
  254. package/generated/entities/staff_time_project/index.ts +1 -0
  255. package/generated/entities/staff_time_project_member/index.ts +1 -0
  256. package/generated/entities/staff_time_task/index.ts +2 -0
  257. package/generated/entities/staff_time_task_comment/index.ts +4 -0
  258. package/generated/entities.ids.generated.ts +2 -0
  259. package/generated/entity-fields-registry.ts +38 -0
  260. package/package.json +8 -8
  261. package/src/helpers/integration/auth.ts +1 -1
  262. package/src/helpers/integration/communicationChannelsFixtures.ts +60 -2
  263. package/src/modules/catalog/api/bulk-delete/route.ts +12 -2
  264. package/src/modules/communication_channels/api/post/test-seed/route.ts +29 -12
  265. package/src/modules/communication_channels/lib/test-seed.ts +49 -10
  266. package/src/modules/messages/commands/messages.ts +8 -10
  267. package/src/modules/portal/frontend/[orgSlug]/portal/dashboard/page.tsx +2 -2
  268. package/src/modules/staff/AGENTS.md +22 -6
  269. package/src/modules/staff/api/portal/support-tickets/[id]/attachments/route.ts +327 -0
  270. package/src/modules/staff/api/portal/support-tickets/[id]/messages/route.ts +94 -0
  271. package/src/modules/staff/api/portal/support-tickets/[id]/route.ts +160 -0
  272. package/src/modules/staff/api/portal/support-tickets/options/route.ts +60 -0
  273. package/src/modules/staff/api/portal/support-tickets/route.ts +253 -0
  274. package/src/modules/staff/api/timesheets/settings/route.ts +7 -1
  275. package/src/modules/staff/api/timesheets/support-routing-rules/fallback-project/route.ts +131 -0
  276. package/src/modules/staff/api/timesheets/support-routing-rules/preview/route.ts +248 -0
  277. package/src/modules/staff/api/timesheets/support-routing-rules/route.ts +150 -0
  278. package/src/modules/staff/api/timesheets/support-tickets/options/route.ts +181 -0
  279. package/src/modules/staff/api/timesheets/tasks/[id]/claim/route.ts +31 -0
  280. package/src/modules/staff/api/timesheets/tasks/[id]/comments/route.ts +25 -7
  281. package/src/modules/staff/api/timesheets/tasks/[id]/release/route.ts +30 -0
  282. package/src/modules/staff/api/timesheets/tasks/route.ts +119 -67
  283. package/src/modules/staff/api/timesheets/time-projects/[id]/employees/route.ts +3 -0
  284. package/src/modules/staff/api/timesheets/time-projects/route.ts +3 -0
  285. package/src/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.tsx +1 -0
  286. package/src/modules/staff/backend/staff/time-tracking/projects/[id]/page.tsx +67 -2
  287. package/src/modules/staff/backend/staff/time-tracking/projects/projectFormConfig.ts +22 -3
  288. package/src/modules/staff/backend/staff/time-tracking/settings/page.tsx +405 -308
  289. package/src/modules/staff/backend/staff/time-tracking/support/page.meta.ts +14 -0
  290. package/src/modules/staff/backend/staff/time-tracking/support/page.tsx +428 -0
  291. package/src/modules/staff/cli.ts +28 -0
  292. package/src/modules/staff/commands/index.ts +3 -0
  293. package/src/modules/staff/commands/shared.ts +22 -1
  294. package/src/modules/staff/commands/support-routing-rules.ts +595 -0
  295. package/src/modules/staff/commands/support-tickets.ts +580 -0
  296. package/src/modules/staff/commands/timesheets-projects.ts +84 -13
  297. package/src/modules/staff/commands/timesheets-task-assignment.ts +319 -0
  298. package/src/modules/staff/commands/timesheets-task-comments.ts +70 -15
  299. package/src/modules/staff/commands/timesheets-tasks.ts +106 -15
  300. package/src/modules/staff/data/enrichers.ts +203 -0
  301. package/src/modules/staff/data/entities.ts +133 -2
  302. package/src/modules/staff/data/extensions.ts +9 -1
  303. package/src/modules/staff/data/validators.ts +36 -0
  304. package/src/modules/staff/encryption.ts +6 -0
  305. package/src/modules/staff/events.payloads.ts +87 -1
  306. package/src/modules/staff/events.ts +26 -0
  307. package/src/modules/staff/extension-points.ts +1 -0
  308. package/src/modules/staff/frontend/[orgSlug]/portal/support/[id]/page.meta.ts +10 -0
  309. package/src/modules/staff/frontend/[orgSlug]/portal/support/[id]/page.tsx +553 -0
  310. package/src/modules/staff/frontend/[orgSlug]/portal/support/new/page.meta.ts +10 -0
  311. package/src/modules/staff/frontend/[orgSlug]/portal/support/new/page.tsx +346 -0
  312. package/src/modules/staff/frontend/[orgSlug]/portal/support/page.meta.ts +17 -0
  313. package/src/modules/staff/frontend/[orgSlug]/portal/support/page.tsx +253 -0
  314. package/src/modules/staff/i18n/de.json +291 -0
  315. package/src/modules/staff/i18n/en.json +291 -0
  316. package/src/modules/staff/i18n/es.json +291 -0
  317. package/src/modules/staff/i18n/ko.json +291 -0
  318. package/src/modules/staff/i18n/pl.json +291 -0
  319. package/src/modules/staff/index.ts +1 -1
  320. package/src/modules/staff/lib/crud.ts +2 -1
  321. package/src/modules/staff/lib/support/attachments.ts +43 -0
  322. package/src/modules/staff/lib/support/dictionaries.ts +120 -0
  323. package/src/modules/staff/lib/support/notifications.ts +138 -0
  324. package/src/modules/staff/lib/support/portalAttachments.ts +140 -0
  325. package/src/modules/staff/lib/support/portalBroadcast.ts +161 -0
  326. package/src/modules/staff/lib/support/portalRoute.ts +108 -0
  327. package/src/modules/staff/lib/support/portalStatus.ts +15 -0
  328. package/src/modules/staff/lib/support/portalTickets.ts +233 -0
  329. package/src/modules/staff/lib/support/routing.ts +117 -0
  330. package/src/modules/staff/lib/support/routingRuleDraft.ts +45 -0
  331. package/src/modules/staff/lib/support/seedDefaults.ts +151 -0
  332. package/src/modules/staff/lib/support/supportActivity.ts +39 -0
  333. package/src/modules/staff/lib/support-ui/PortalSupportNotLinked.tsx +20 -0
  334. package/src/modules/staff/lib/support-ui/portalAttachmentValidation.ts +125 -0
  335. package/src/modules/staff/lib/support-ui/portalPendingUploads.ts +49 -0
  336. package/src/modules/staff/lib/support-ui/portalSupport.ts +116 -0
  337. package/src/modules/staff/lib/time-tracking/access.ts +2 -62
  338. package/src/modules/staff/lib/time-tracking/listProjectAccess.ts +78 -0
  339. package/src/modules/staff/lib/time-tracking/portalRecipients.ts +173 -5
  340. package/src/modules/staff/lib/time-tracking/projectAssignment.ts +172 -0
  341. package/src/modules/staff/lib/time-tracking/settingKeys.ts +11 -0
  342. package/src/modules/staff/lib/time-tracking/settings.ts +46 -1
  343. package/src/modules/staff/lib/time-tracking/taskAssignmentRoute.ts +165 -0
  344. package/src/modules/staff/lib/time-tracking/workRecipients.ts +183 -0
  345. package/src/modules/staff/lib/time-tracking-ui/BoardFilterChips.tsx +36 -1
  346. package/src/modules/staff/lib/time-tracking-ui/KanbanBoard.tsx +30 -0
  347. package/src/modules/staff/lib/time-tracking-ui/KanbanCard.tsx +9 -0
  348. package/src/modules/staff/lib/time-tracking-ui/ProjectFormSections.tsx +185 -6
  349. package/src/modules/staff/lib/time-tracking-ui/SupportAttachmentsSection.tsx +188 -0
  350. package/src/modules/staff/lib/time-tracking-ui/SupportRequestPanel.tsx +102 -0
  351. package/src/modules/staff/lib/time-tracking-ui/TaskBoardScreen.tsx +2 -0
  352. package/src/modules/staff/lib/time-tracking-ui/TaskCommentThread.tsx +105 -22
  353. package/src/modules/staff/lib/time-tracking-ui/TaskDrawer.tsx +278 -43
  354. package/src/modules/staff/lib/time-tracking-ui/boardDirectory.ts +21 -0
  355. package/src/modules/staff/lib/time-tracking-ui/boardFilters.ts +16 -2
  356. package/src/modules/staff/lib/time-tracking-ui/kanbanBoardData.ts +4 -0
  357. package/src/modules/staff/lib/time-tracking-ui/projectDefaultAssignee.ts +117 -0
  358. package/src/modules/staff/lib/time-tracking-ui/settingsTabs.ts +17 -0
  359. package/src/modules/staff/lib/time-tracking-ui/supportTicketData.ts +71 -0
  360. package/src/modules/staff/lib/time-tracking-ui/taskDrawerData.ts +15 -0
  361. package/src/modules/staff/lib/time-tracking-ui/timeTrackingSettingsForm.ts +48 -1
  362. package/src/modules/staff/migrations/.snapshot-open-mercato.json +714 -0
  363. package/src/modules/staff/migrations/Migration20261009180543_staff.ts +50 -0
  364. package/src/modules/staff/notifications.ts +92 -0
  365. package/src/modules/staff/setup.ts +6 -2
  366. package/src/modules/staff/subscribers/support-portal-comment-created.ts +35 -0
  367. package/src/modules/staff/subscribers/support-portal-comment-deleted.ts +35 -0
  368. package/src/modules/staff/subscribers/support-portal-comment-updated.ts +35 -0
  369. package/src/modules/staff/subscribers/support-portal-status-column-updated.ts +36 -0
  370. package/src/modules/staff/subscribers/support-portal-task-status-changed.ts +34 -0
  371. package/src/modules/staff/subscribers/support-portal-task-updated.ts +34 -0
  372. package/src/modules/staff/subscribers/support-ticket-created-notification.ts +27 -0
  373. package/src/modules/staff/subscribers/support-ticket-customer-replied-notification.ts +27 -0
  374. package/src/modules/staff/subscribers/support-ticket-unnotified-clear.ts +29 -0
  375. package/src/modules/staff/subscribers/time-task-assignee-notification.ts +102 -0
  376. package/src/modules/staff/widgets/injection/portal-support-tickets/widget.client.tsx +151 -0
  377. package/src/modules/staff/widgets/injection/portal-support-tickets/widget.ts +16 -0
  378. package/src/modules/staff/widgets/injection/time-tracking-settings-support/widget.client.tsx +1058 -0
  379. package/src/modules/staff/widgets/injection/time-tracking-settings-support/widget.ts +17 -0
  380. package/src/modules/staff/widgets/injection-table.ts +15 -0
  381. package/src/modules/wms/components/backend/WmsLocationDetailPage.tsx +4 -20
  382. package/src/modules/wms/components/backend/WmsLotDetailPage.tsx +4 -20
  383. package/src/modules/wms/components/backend/WmsSkuDetailPage.tsx +4 -19
  384. package/src/modules/wms/lib/inventoryCsvExport.ts +18 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/staff/commands/timesheets-projects.ts"],
4
- "sourcesContent": ["import { z } from 'zod'\nimport type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { UniqueConstraintViolationException } from '@mikro-orm/core'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { buildChanges, emitCrudSideEffects, emitCrudUndoSideEffects, setCustomFieldsIfAny } from '@open-mercato/shared/lib/commands/helpers'\nimport { extractCustomFieldValuesFromPayload } from '@open-mercato/shared/lib/crud/custom-fields'\nimport { E } from '#generated/entities.ids.generated'\nimport { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'\nimport { makeCreateRedo } from '@open-mercato/shared/lib/commands/redo'\nimport type { CrudEventsConfig, CrudIndexerConfig } from '@open-mercato/shared/lib/crud/types'\nimport { CustomerEntity } from '@open-mercato/core/modules/customers/data/entities'\nimport {\n StaffTeamMember,\n StaffTimeEntry,\n StaffTimeProject,\n StaffTimeProjectMember,\n StaffTimeReport,\n type StaffTimeProjectStatus,\n type StaffTimeProjectBudgetKind,\n type StaffTimeProjectMemberStatus,\n} from '../data/entities'\n\nconst timeProjectCrudIndexer: CrudIndexerConfig<StaffTimeProject> = {\n entityType: 'staff:staff_time_project',\n}\nconst timeProjectMemberCrudIndexer: CrudIndexerConfig<StaffTimeProjectMember> = {\n entityType: 'staff:staff_time_project_member',\n}\nimport {\n staffTimeProjectCreateSchema,\n staffTimeProjectUpdateSchema,\n staffTimeProjectChangeCurrencySchema,\n staffTimeProjectMemberAssignSchema,\n staffTimeProjectMemberUpdateSchema,\n type StaffTimeProjectCreateInput,\n type StaffTimeProjectUpdateInput,\n type StaffTimeProjectMemberAssignInput,\n type StaffTimeProjectMemberUpdateInput,\n} from '../data/validators'\nimport { staffTimeProjectCrudEvents, staffTimeProjectMemberCrudEvents } from '../lib/crud'\nimport { DEFAULT_BUDGET_WARN_AT_PERCENT } from '../lib/timesheets-projects/budgetBurn'\nimport { seedProjectTaskStatuses } from '../lib/timesheets-tasks/seedProjectStatuses'\nimport {\n applyScopeToWhere,\n commandActorScope,\n commandInputScope,\n ensureOrganizationScope,\n ensureTenantScope,\n extractUndoPayload,\n scopeForDecryption,\n scopedStaffSnapshotWhere,\n staffSnapshotDecryptionScope,\n staffSnapshotScopeFromContext,\n staffSnapshotScopeFromSnapshot,\n type StaffSnapshotScope,\n} from './shared'\n\nfunction isUniqueViolation(error: unknown): boolean {\n if (error instanceof UniqueConstraintViolationException) return true\n if (!error || typeof error !== 'object') return false\n const code = (error as { code?: string }).code\n if (code === '23505') return true\n const message = (error as { message?: string }).message\n return typeof message === 'string' && message.toLowerCase().includes('duplicate key')\n}\n\nfunction readSnapshotText(value: unknown): string | null {\n if (typeof value !== 'string') return null\n const trimmed = value.trim()\n return trimmed.length > 0 ? trimmed : null\n}\n\n/**\n * D-9 keeps a project's customer as an FK id plus a denormalized snapshot, and\n * denormalizing belongs to the module that owns the write: a caller that sends\n * `customerId` alone \u2014 the CRUD route, an import, an integration \u2014 must still\n * produce a project the portfolio grid can name, instead of one that has a\n * customer in the database and advertises none in the UI. A snapshot the caller\n * supplied still wins verbatim; the project form already carries the picked\n * customer and must not be second-guessed.\n *\n * The lookup is a scoped read by id \u2014 never an ORM relation to the customers\n * module \u2014 and a customers module that is absent, or a customer that is gone,\n * degrades to `null` rather than failing the write.\n */\nasync function resolveCustomerSnapshot(\n em: EntityManager,\n scope: { tenantId: string; organizationId: string },\n customerId: string | null | undefined,\n): Promise<Record<string, unknown> | null> {\n if (!customerId) return null\n let customer: CustomerEntity | null = null\n try {\n customer = await findOneWithDecryption(\n em,\n CustomerEntity,\n {\n id: customerId,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n },\n undefined,\n { tenantId: scope.tenantId, organizationId: scope.organizationId },\n )\n } catch {\n return null\n }\n if (!customer) return null\n const email = readSnapshotText(customer.primaryEmail)\n const name = readSnapshotText(customer.displayName) ?? email\n if (!name) return null\n const snapshot: Record<string, unknown> = { name }\n const kind = readSnapshotText(customer.kind)\n if (kind) snapshot.kind = kind\n if (email) snapshot.email = email\n return snapshot\n}\n\ntype TimeProjectSnapshot = {\n id: string\n tenantId: string\n organizationId: string\n name: string\n customerId: string | null\n customerSnapshot: Record<string, unknown> | null\n code: string\n description: string | null\n projectType: string | null\n color: string | null\n status: string\n ownerUserId: string | null\n costCenter: string | null\n startDate: string | null\n hourlyRate: string | null\n currencyCode: string | null\n billableByDefault: boolean\n budgetKind: string\n budgetValue: string | null\n budgetWarnAtPercent: number\n deletedAt: string | null\n}\n\ntype TimeProjectUndoPayload = {\n before?: TimeProjectSnapshot | null\n after?: TimeProjectSnapshot | null\n}\n\ntype TimeProjectMemberSnapshot = {\n id: string\n tenantId: string\n organizationId: string\n timeProjectId: string\n staffMemberId: string\n role: string | null\n status: string\n showInGrid: boolean\n assignedStartDate: string\n assignedEndDate: string | null\n deletedAt: string | null\n}\n\ntype TimeProjectMemberUndoPayload = {\n before?: TimeProjectMemberSnapshot | null\n after?: TimeProjectMemberSnapshot | null\n}\n\nasync function loadTimeProjectSnapshot(em: EntityManager, id: string, scope?: StaffSnapshotScope | null): Promise<TimeProjectSnapshot | null> {\n const project = await findOneWithDecryption(\n em,\n StaffTimeProject,\n scopedStaffSnapshotWhere(id, scope),\n undefined,\n staffSnapshotDecryptionScope(scope),\n )\n if (!project) return null\n return {\n id: project.id,\n tenantId: project.tenantId,\n organizationId: project.organizationId,\n name: project.name,\n customerId: project.customerId ?? null,\n customerSnapshot: project.customerSnapshot ?? null,\n code: project.code,\n description: project.description ?? null,\n projectType: project.projectType ?? null,\n color: project.color ?? null,\n status: project.status,\n ownerUserId: project.ownerUserId ?? null,\n costCenter: project.costCenter ?? null,\n startDate: project.startDate instanceof Date ? project.startDate.toISOString().split('T')[0] : (project.startDate ?? null),\n hourlyRate: project.hourlyRate ?? null,\n currencyCode: project.currencyCode ?? null,\n billableByDefault: project.billableByDefault ?? true,\n budgetKind: project.budgetKind ?? 'none',\n budgetValue: project.budgetValue ?? null,\n budgetWarnAtPercent: project.budgetWarnAtPercent ?? DEFAULT_BUDGET_WARN_AT_PERCENT,\n deletedAt: project.deletedAt ? project.deletedAt.toISOString() : null,\n }\n}\n\nasync function loadTimeProjectMemberSnapshot(em: EntityManager, id: string, scope?: StaffSnapshotScope | null): Promise<TimeProjectMemberSnapshot | null> {\n const member = await findOneWithDecryption(\n em,\n StaffTimeProjectMember,\n scopedStaffSnapshotWhere(id, scope),\n undefined,\n staffSnapshotDecryptionScope(scope),\n )\n if (!member) return null\n return {\n id: member.id,\n tenantId: member.tenantId,\n organizationId: member.organizationId,\n timeProjectId: member.timeProjectId,\n staffMemberId: member.staffMemberId,\n role: member.role ?? null,\n status: member.status,\n showInGrid: member.showInGrid ?? false,\n assignedStartDate: member.assignedStartDate instanceof Date ? member.assignedStartDate.toISOString().split('T')[0] : String(member.assignedStartDate),\n assignedEndDate: member.assignedEndDate instanceof Date ? member.assignedEndDate.toISOString().split('T')[0] : (member.assignedEndDate ?? null),\n deletedAt: member.deletedAt ? member.deletedAt.toISOString() : null,\n }\n}\n\nfunction timeProjectSeedFromSnapshot(snapshot: TimeProjectSnapshot): Record<string, unknown> {\n return {\n id: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n name: snapshot.name,\n customerId: snapshot.customerId ?? null,\n customerSnapshot: snapshot.customerSnapshot ?? null,\n code: snapshot.code,\n description: snapshot.description ?? null,\n projectType: snapshot.projectType ?? null,\n color: snapshot.color ?? null,\n status: (snapshot.status ?? 'active') as StaffTimeProjectStatus,\n ownerUserId: snapshot.ownerUserId ?? null,\n costCenter: snapshot.costCenter ?? null,\n startDate: snapshot.startDate ? new Date(snapshot.startDate) : null,\n hourlyRate: snapshot.hourlyRate ?? null,\n currencyCode: snapshot.currencyCode ?? null,\n billableByDefault: snapshot.billableByDefault ?? true,\n budgetKind: (snapshot.budgetKind ?? 'none') as StaffTimeProjectBudgetKind,\n budgetValue: snapshot.budgetValue ?? null,\n budgetWarnAtPercent: snapshot.budgetWarnAtPercent ?? DEFAULT_BUDGET_WARN_AT_PERCENT,\n createdAt: new Date(),\n updatedAt: new Date(),\n deletedAt: null,\n }\n}\n\nfunction timeProjectMemberSeedFromSnapshot(snapshot: TimeProjectMemberSnapshot): Record<string, unknown> {\n return {\n id: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n timeProjectId: snapshot.timeProjectId,\n staffMemberId: snapshot.staffMemberId,\n role: snapshot.role ?? null,\n status: (snapshot.status ?? 'active') as StaffTimeProjectMemberStatus,\n showInGrid: snapshot.showInGrid ?? false,\n assignedStartDate: new Date(snapshot.assignedStartDate),\n assignedEndDate: snapshot.assignedEndDate ? new Date(snapshot.assignedEndDate) : null,\n createdAt: new Date(),\n updatedAt: new Date(),\n deletedAt: null,\n }\n}\n\nconst createTimeProjectCommand: CommandHandler<StaffTimeProjectCreateInput, { timeProjectId: string }> = {\n id: 'staff.timesheets.time_projects.create',\n async execute(rawInput, ctx) {\n const parsed = staffTimeProjectCreateSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n commandInputScope(ctx, parsed.tenantId, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const customerSnapshot =\n parsed.customerSnapshot\n ?? (await resolveCustomerSnapshot(\n em,\n { tenantId: parsed.tenantId, organizationId: parsed.organizationId },\n parsed.customerId,\n ))\n const now = new Date()\n const project = em.create(StaffTimeProject, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n name: parsed.name,\n customerId: parsed.customerId,\n customerSnapshot,\n code: parsed.code,\n description: parsed.description ?? null,\n projectType: parsed.projectType ?? null,\n color: parsed.color ?? null,\n status: parsed.status ?? 'active',\n ownerUserId: parsed.ownerUserId ?? null,\n costCenter: parsed.costCenter ?? null,\n startDate: parsed.startDate ?? null,\n hourlyRate: parsed.hourlyRate ?? null,\n // D-3: creation is the one moment the currency may be chosen freely.\n currencyCode: parsed.currencyCode ?? null,\n billableByDefault: parsed.billableByDefault ?? true,\n budgetKind: parsed.budgetKind ?? 'none',\n budgetValue: parsed.budgetValue ?? null,\n budgetWarnAtPercent: parsed.budgetWarnAtPercent ?? DEFAULT_BUDGET_WARN_AT_PERCENT,\n createdAt: now,\n updatedAt: now,\n deletedAt: null,\n })\n const { translate } = await resolveTranslations()\n try {\n // D-1: the project and its Kanban columns are one transaction. The template\n // can only be seeded once the insert has handed back the project's id, so\n // the two writes are separate phases \u2014 but a rollback takes both, and a\n // project therefore never exists with an empty board.\n await withAtomicFlush(\n em,\n [\n () => {\n em.persist(project)\n },\n () => {\n seedProjectTaskStatuses(\n em,\n { tenantId: project.tenantId, organizationId: project.organizationId, timeProjectId: project.id },\n translate,\n )\n },\n ],\n { transaction: true, label: 'staff.timesheets.time_projects.create' },\n )\n } catch (err) {\n if (isUniqueViolation(err)) {\n throw new CrudHttpError(409, {\n error: translate('staff.timesheets.errors.projectCodeDuplicate', 'A project with this code already exists.'),\n fieldErrors: { code: translate('staff.timesheets.errors.projectCodeDuplicate', 'A project with this code already exists.') },\n })\n }\n throw err\n }\n\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.staff.staff_time_project,\n recordId: project.id,\n tenantId: project.tenantId,\n organizationId: project.organizationId,\n values: extractCustomFieldValuesFromPayload(\n (rawInput && typeof rawInput === 'object' ? rawInput : {}) as Record<string, unknown>,\n ),\n })\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'created',\n entity: project,\n identifiers: {\n id: project.id,\n organizationId: project.organizationId,\n tenantId: project.tenantId,\n },\n events: staffTimeProjectCrudEvents,\n indexer: timeProjectCrudIndexer,\n })\n\n return { timeProjectId: project.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTimeProjectSnapshot(em, result.timeProjectId, staffSnapshotScopeFromContext(ctx))\n if (!snapshot) return null\n return { snapshot }\n },\n buildLog: async ({ result, ctx }) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTimeProjectSnapshot(em, result.timeProjectId, staffSnapshotScopeFromContext(ctx))\n if (!snapshot) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_projects.create', 'Create time project'),\n resourceKind: 'staff.timesheets.time_project',\n resourceId: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n snapshotAfter: snapshot,\n payload: {\n undo: {\n after: snapshot,\n } satisfies TimeProjectUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeProjectUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const project = await em.findOne(StaffTimeProject, scopedStaffSnapshotWhere(after.id, staffSnapshotScopeFromSnapshot(after)))\n if (project) {\n project.deletedAt = new Date()\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'deleted',\n entity: project,\n identifiers: {\n id: project.id,\n organizationId: project.organizationId,\n tenantId: project.tenantId,\n },\n events: staffTimeProjectCrudEvents,\n indexer: timeProjectCrudIndexer,\n })\n }\n },\n redo: makeCreateRedo<StaffTimeProject, TimeProjectSnapshot, StaffTimeProjectCreateInput, { timeProjectId: string }>({\n entityClass: StaffTimeProject,\n getSnapshotId: (snapshot) => snapshot.id,\n seedFromSnapshot: timeProjectSeedFromSnapshot,\n buildResult: (entity) => ({ timeProjectId: entity.id }),\n events: staffTimeProjectCrudEvents,\n indexer: timeProjectCrudIndexer,\n }),\n}\n\nconst updateTimeProjectCommand: CommandHandler<StaffTimeProjectUpdateInput, { timeProjectId: string }> = {\n id: 'staff.timesheets.time_projects.update',\n async prepare(rawInput, ctx) {\n const parsed = staffTimeProjectUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadTimeProjectSnapshot(em, parsed.id, staffSnapshotScopeFromContext(ctx))\n if (!snapshot) return {}\n return { before: snapshot }\n },\n async execute(rawInput, ctx) {\n const parsed = staffTimeProjectUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n const project = await findOneWithDecryption(\n em,\n StaffTimeProject,\n applyScopeToWhere<StaffTimeProject>({ id: parsed.id, deletedAt: null }, scope),\n undefined,\n scopeForDecryption(scope),\n )\n if (!project) throw new CrudHttpError(404, { error: 'Time project not found.' })\n ensureTenantScope(ctx, project.tenantId)\n ensureOrganizationScope(ctx, project.organizationId)\n\n // The FK and its snapshot move together. A payload that re-points the\n // customer without carrying a snapshot \u2014 or that clears a stale one while\n // keeping the customer \u2014 has the snapshot re-derived here, so the grid never\n // reads a project with a customer as unassigned. The read runs before every\n // scalar mutation below, so it cannot reset the unit of work.\n const customerTouched = parsed.customerId !== undefined || parsed.customerSnapshot !== undefined\n const nextCustomerId = parsed.customerId !== undefined ? parsed.customerId ?? null : project.customerId ?? null\n const customerUnchanged = nextCustomerId === (project.customerId ?? null)\n let nextCustomerSnapshot: Record<string, unknown> | null | undefined\n if (customerTouched) {\n nextCustomerSnapshot =\n parsed.customerSnapshot\n ?? (await resolveCustomerSnapshot(\n em,\n { tenantId: project.tenantId, organizationId: project.organizationId },\n nextCustomerId,\n ))\n // A customer that stays put keeps the snapshot it already had when the\n // lookup comes back empty (customer removed, customers module absent);\n // only a re-pointed or cleared customer drops it, because holding the\n // previous customer's details on a different FK would misattribute them.\n ?? (customerUnchanged && nextCustomerId ? project.customerSnapshot ?? null : null)\n }\n\n if (parsed.name !== undefined) project.name = parsed.name\n if (parsed.customerId !== undefined) project.customerId = parsed.customerId ?? null\n if (nextCustomerSnapshot !== undefined) project.customerSnapshot = nextCustomerSnapshot\n if (parsed.code !== undefined) project.code = parsed.code\n if (parsed.description !== undefined) project.description = parsed.description ?? null\n if (parsed.projectType !== undefined) project.projectType = parsed.projectType ?? null\n if (parsed.color !== undefined) project.color = parsed.color ?? null\n if (parsed.status !== undefined) project.status = parsed.status\n if (parsed.ownerUserId !== undefined) project.ownerUserId = parsed.ownerUserId ?? null\n if (parsed.costCenter !== undefined) project.costCenter = parsed.costCenter ?? null\n if (parsed.startDate !== undefined) project.startDate = parsed.startDate ?? null\n if (parsed.hourlyRate !== undefined) project.hourlyRate = parsed.hourlyRate ?? null\n if (parsed.billableByDefault !== undefined) project.billableByDefault = parsed.billableByDefault\n if (parsed.budgetKind !== undefined) project.budgetKind = parsed.budgetKind\n if (parsed.budgetValue !== undefined) project.budgetValue = parsed.budgetValue ?? null\n if (parsed.budgetWarnAtPercent !== undefined) project.budgetWarnAtPercent = parsed.budgetWarnAtPercent\n // `currency_code` is intentionally absent here and from the update schema:\n // D-3 gives that column to `staff.timesheets.time_projects.change_currency`,\n // which owns the acknowledgement and the locked-entry refusal. A caller that\n // smuggles `currencyCode` into a PUT has it stripped by the schema, so there\n // is no key to assign from.\n project.updatedAt = new Date()\n try {\n await em.flush()\n } catch (err) {\n if (isUniqueViolation(err)) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(409, {\n error: translate('staff.timesheets.errors.projectCodeDuplicate', 'A project with this code already exists.'),\n fieldErrors: { code: translate('staff.timesheets.errors.projectCodeDuplicate', 'A project with this code already exists.') },\n })\n }\n throw err\n }\n\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.staff.staff_time_project,\n recordId: project.id,\n tenantId: project.tenantId,\n organizationId: project.organizationId,\n values: extractCustomFieldValuesFromPayload(\n (rawInput && typeof rawInput === 'object' ? rawInput : {}) as Record<string, unknown>,\n ),\n })\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'updated',\n entity: project,\n identifiers: {\n id: project.id,\n organizationId: project.organizationId,\n tenantId: project.tenantId,\n },\n events: staffTimeProjectCrudEvents,\n indexer: timeProjectCrudIndexer,\n })\n\n return { timeProjectId: project.id }\n },\n buildLog: async ({ snapshots, ctx }) => {\n const before = snapshots.before as TimeProjectSnapshot | undefined\n if (!before) return null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const after = await loadTimeProjectSnapshot(em, before.id, staffSnapshotScopeFromSnapshot(before))\n if (!after) return null\n const changes = buildChanges(before as unknown as Record<string, unknown>, after as unknown as Record<string, unknown>, [\n 'name',\n 'customerId',\n 'code',\n 'description',\n 'projectType',\n 'color',\n 'status',\n 'ownerUserId',\n 'costCenter',\n 'startDate',\n 'hourlyRate',\n 'billableByDefault',\n 'budgetKind',\n 'budgetValue',\n 'budgetWarnAtPercent',\n 'deletedAt',\n ])\n // `buildChanges` compares by identity, and the two snapshots are loaded through\n // separate forks, so the denormalized customer snapshot needs a value compare\n // or every edit would report it as changed.\n if (JSON.stringify(before.customerSnapshot ?? null) !== JSON.stringify(after.customerSnapshot ?? null)) {\n changes.customerSnapshot = { from: before.customerSnapshot ?? null, to: after.customerSnapshot ?? null }\n }\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_projects.update', 'Update time project'),\n resourceKind: 'staff.timesheets.time_project',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes,\n payload: {\n undo: {\n before,\n after,\n } satisfies TimeProjectUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeProjectUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const project = await em.findOne(StaffTimeProject, scopedStaffSnapshotWhere(before.id, staffSnapshotScopeFromSnapshot(before)))\n if (!project) return\n project.name = before.name\n project.customerId = before.customerId ?? null\n project.customerSnapshot = before.customerSnapshot ?? null\n project.code = before.code\n project.description = before.description ?? null\n project.projectType = before.projectType ?? null\n project.color = before.color ?? null\n project.status = (before.status ?? 'active') as StaffTimeProjectStatus\n project.ownerUserId = before.ownerUserId ?? null\n project.costCenter = before.costCenter ?? null\n project.startDate = before.startDate ? new Date(before.startDate) : null\n project.hourlyRate = before.hourlyRate ?? null\n project.billableByDefault = before.billableByDefault ?? true\n project.budgetKind = (before.budgetKind ?? 'none') as StaffTimeProjectBudgetKind\n project.budgetValue = before.budgetValue ?? null\n project.budgetWarnAtPercent = before.budgetWarnAtPercent ?? DEFAULT_BUDGET_WARN_AT_PERCENT\n // Undo of a plain update restores what a plain update could change; the currency\n // stays where change_currency left it (D-3).\n project.deletedAt = before.deletedAt ? new Date(before.deletedAt) : null\n project.updatedAt = new Date()\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'updated',\n entity: project,\n identifiers: {\n id: project.id,\n organizationId: project.organizationId,\n tenantId: project.tenantId,\n },\n events: staffTimeProjectCrudEvents,\n indexer: timeProjectCrudIndexer,\n })\n },\n}\n\nconst deleteTimeProjectCommand: CommandHandler<{ id?: string }, { timeProjectId: string }> = {\n id: 'staff.timesheets.time_projects.delete',\n async prepare(input, ctx) {\n const id = input?.id\n if (!id) throw new CrudHttpError(400, { error: 'Time project id is required.' })\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadTimeProjectSnapshot(em, id, staffSnapshotScopeFromContext(ctx))\n if (!snapshot) return {}\n return { before: snapshot }\n },\n async execute(input, ctx) {\n const id = input?.id\n if (!id) throw new CrudHttpError(400, { error: 'Time project id is required.' })\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n const project = await findOneWithDecryption(\n em,\n StaffTimeProject,\n applyScopeToWhere<StaffTimeProject>({ id, deletedAt: null }, scope),\n undefined,\n scopeForDecryption(scope),\n )\n if (!project) throw new CrudHttpError(404, { error: 'Time project not found.' })\n ensureTenantScope(ctx, project.tenantId)\n ensureOrganizationScope(ctx, project.organizationId)\n\n project.deletedAt = new Date()\n project.updatedAt = new Date()\n await em.flush()\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'deleted',\n entity: project,\n identifiers: {\n id: project.id,\n organizationId: project.organizationId,\n tenantId: project.tenantId,\n },\n events: staffTimeProjectCrudEvents,\n indexer: timeProjectCrudIndexer,\n })\n return { timeProjectId: project.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as TimeProjectSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_projects.delete', 'Delete time project'),\n resourceKind: 'staff.timesheets.time_project',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: {\n before,\n } satisfies TimeProjectUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeProjectUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let project = await em.findOne(StaffTimeProject, scopedStaffSnapshotWhere(before.id, staffSnapshotScopeFromSnapshot(before)))\n if (!project) {\n project = em.create(StaffTimeProject, {\n id: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n name: before.name,\n customerId: before.customerId ?? null,\n customerSnapshot: before.customerSnapshot ?? null,\n code: before.code,\n description: before.description ?? null,\n projectType: before.projectType ?? null,\n status: (before.status ?? 'active') as StaffTimeProjectStatus,\n ownerUserId: before.ownerUserId ?? null,\n costCenter: before.costCenter ?? null,\n startDate: before.startDate ? new Date(before.startDate) : null,\n hourlyRate: before.hourlyRate ?? null,\n currencyCode: before.currencyCode ?? null,\n billableByDefault: before.billableByDefault ?? true,\n budgetKind: (before.budgetKind ?? 'none') as StaffTimeProjectBudgetKind,\n budgetValue: before.budgetValue ?? null,\n budgetWarnAtPercent: before.budgetWarnAtPercent ?? DEFAULT_BUDGET_WARN_AT_PERCENT,\n deletedAt: null,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(project)\n } else {\n project.name = before.name\n project.customerId = before.customerId ?? null\n project.customerSnapshot = before.customerSnapshot ?? null\n project.code = before.code\n project.description = before.description ?? null\n project.projectType = before.projectType ?? null\n project.status = (before.status ?? 'active') as StaffTimeProjectStatus\n project.ownerUserId = before.ownerUserId ?? null\n project.costCenter = before.costCenter ?? null\n project.startDate = before.startDate ? new Date(before.startDate) : null\n project.hourlyRate = before.hourlyRate ?? null\n project.currencyCode = before.currencyCode ?? null\n project.billableByDefault = before.billableByDefault ?? true\n project.budgetKind = (before.budgetKind ?? 'none') as StaffTimeProjectBudgetKind\n project.budgetValue = before.budgetValue ?? null\n project.budgetWarnAtPercent = before.budgetWarnAtPercent ?? DEFAULT_BUDGET_WARN_AT_PERCENT\n project.deletedAt = null\n project.updatedAt = new Date()\n }\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'created',\n entity: project,\n identifiers: {\n id: project.id,\n organizationId: project.organizationId,\n tenantId: project.tenantId,\n },\n events: staffTimeProjectCrudEvents,\n indexer: timeProjectCrudIndexer,\n })\n },\n}\n\n/**\n * D-3: a project's currency is read-only once hours have been logged against it,\n * and the deliberate change action below relabels the project WITHOUT converting\n * any historical amount. It never touches an entry's `rate_currency_code` or its\n * stored cost, so a closed report keeps billing what it billed. That is also why\n * the change is refused outright while any entry of the project sits frozen in a\n * closed report: relabelling then would make the project disagree with the\n * `frozen_currency_code` those report lines were issued under.\n */\nexport const staffTimeProjectChangeCurrencyCommandId = 'staff.timesheets.time_projects.change_currency'\n\nexport const PROJECT_HAS_LOCKED_ENTRIES_CODE = 'project_has_locked_entries'\n\nconst changeTimeProjectCurrencyCommandSchema = staffTimeProjectChangeCurrencySchema.extend({\n id: z.string().uuid(),\n})\n\nexport type StaffTimeProjectChangeCurrencyCommandInput = z.infer<typeof changeTimeProjectCurrencyCommandSchema>\n\nexport type StaffTimeProjectChangeCurrencyResult = {\n timeProjectId: string\n currencyCode: string\n previousCurrencyCode: string | null\n}\n\ntype BlockingLockedReport = {\n id: string\n reference: string | null\n title: string | null\n}\n\ntype LockedEntryBlock = {\n lockedEntryCount: number\n reports: BlockingLockedReport[]\n}\n\nasync function findLockedEntryBlock(\n em: EntityManager,\n project: StaffTimeProject,\n): Promise<LockedEntryBlock> {\n const scope = { tenantId: project.tenantId, organizationId: project.organizationId }\n const lockedEntries = await em.find(\n StaffTimeEntry,\n { ...scope, timeProjectId: project.id, lockedReportId: { $ne: null }, deletedAt: null },\n { fields: ['id', 'lockedReportId'] },\n )\n if (lockedEntries.length === 0) return { lockedEntryCount: 0, reports: [] }\n\n const reportIds = Array.from(\n new Set(lockedEntries.map((entry) => entry.lockedReportId).filter((value): value is string => typeof value === 'string')),\n )\n const reports = reportIds.length\n ? await em.find(\n StaffTimeReport,\n { ...scope, id: { $in: reportIds } },\n { fields: ['id', 'reference', 'title'] },\n )\n : []\n const known = new Map(reports.map((report) => [report.id, report]))\n\n return {\n lockedEntryCount: lockedEntries.length,\n reports: reportIds.map((id) => ({\n id,\n reference: known.get(id)?.reference ?? null,\n title: known.get(id)?.title ?? null,\n })),\n }\n}\n\nasync function assertNoLockedEntries(em: EntityManager, project: StaffTimeProject): Promise<void> {\n const block = await findLockedEntryBlock(em, project)\n if (block.lockedEntryCount === 0) return\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(409, {\n code: PROJECT_HAS_LOCKED_ENTRIES_CODE,\n error: translate(\n 'staff.timesheets.errors.projectCurrencyLocked',\n 'This project has time entries frozen in a closed report. Unlock those reports before changing the currency.',\n ),\n lockedEntryCount: block.lockedEntryCount,\n lockedReports: block.reports,\n })\n}\n\n/**\n * Same `staff.timesheets.time_project.updated` event id every project write emits,\n * with the currency transition carried in the payload so a subscriber can tell a\n * relabel apart from an ordinary field edit without re-reading the project.\n */\nfunction timeProjectCurrencyChangeEvents(\n previousCurrencyCode: string | null,\n currencyCode: string,\n): CrudEventsConfig<StaffTimeProject> {\n return {\n ...staffTimeProjectCrudEvents,\n buildPayload: (emitCtx) => ({\n id: emitCtx.identifiers.id,\n organizationId: emitCtx.identifiers.organizationId,\n tenantId: emitCtx.identifiers.tenantId,\n changedField: 'currencyCode',\n previousCurrencyCode,\n currencyCode,\n converted: false,\n }),\n }\n}\n\nconst changeTimeProjectCurrencyCommand: CommandHandler<\n StaffTimeProjectChangeCurrencyCommandInput,\n StaffTimeProjectChangeCurrencyResult\n> = {\n id: staffTimeProjectChangeCurrencyCommandId,\n async prepare(rawInput, ctx) {\n const parsed = changeTimeProjectCurrencyCommandSchema.parse(rawInput)\n const em = ctx.container.resolve('em') as EntityManager\n const snapshot = await loadTimeProjectSnapshot(em, parsed.id, staffSnapshotScopeFromContext(ctx))\n if (!snapshot) return {}\n return { before: snapshot }\n },\n async execute(rawInput, ctx) {\n const parsed = changeTimeProjectCurrencyCommandSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n const project = await findOneWithDecryption(\n em,\n StaffTimeProject,\n applyScopeToWhere<StaffTimeProject>({ id: parsed.id, deletedAt: null }, scope),\n undefined,\n scopeForDecryption(scope),\n )\n if (!project) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(404, {\n error: translate('staff.timesheets.errors.projectNotFound', 'Time project not found or not accessible.'),\n })\n }\n ensureTenantScope(ctx, project.tenantId)\n ensureOrganizationScope(ctx, project.organizationId)\n\n const previousCurrencyCode = project.currencyCode ?? null\n\n // The lock probe and the relabel are separate phases of one transaction: the\n // probe queries `staff_time_entries` and must therefore never share a phase\n // with the scalar mutation, and the shared transaction keeps a report closing\n // concurrently from slipping between the check and the write.\n await withAtomicFlush(\n em,\n [\n () => assertNoLockedEntries(em, project),\n () => {\n project.currencyCode = parsed.currencyCode\n project.updatedAt = new Date()\n },\n ],\n { transaction: true, label: staffTimeProjectChangeCurrencyCommandId },\n )\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'updated',\n entity: project,\n identifiers: {\n id: project.id,\n organizationId: project.organizationId,\n tenantId: project.tenantId,\n },\n events: timeProjectCurrencyChangeEvents(previousCurrencyCode, parsed.currencyCode),\n indexer: timeProjectCrudIndexer,\n })\n\n return {\n timeProjectId: project.id,\n currencyCode: parsed.currencyCode,\n previousCurrencyCode,\n }\n },\n buildLog: async ({ snapshots, ctx }) => {\n const before = snapshots.before as TimeProjectSnapshot | undefined\n if (!before) return null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const after = await loadTimeProjectSnapshot(em, before.id, staffSnapshotScopeFromSnapshot(before))\n if (!after) return null\n const changes = buildChanges(\n before as unknown as Record<string, unknown>,\n after as unknown as Record<string, unknown>,\n ['currencyCode'],\n )\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_projects.change_currency', 'Change time project currency'),\n resourceKind: 'staff.timesheets.time_project',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes,\n payload: {\n undo: {\n before,\n after,\n } satisfies TimeProjectUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeProjectUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const project = await em.findOne(StaffTimeProject, scopedStaffSnapshotWhere(before.id, staffSnapshotScopeFromSnapshot(before)))\n if (!project) return\n\n // Undo relabels back, so it has to honour the same invariant: entries may have\n // been frozen into a closed report since the change was made.\n await withAtomicFlush(\n em,\n [\n () => assertNoLockedEntries(em, project),\n () => {\n project.currencyCode = before.currencyCode ?? null\n project.updatedAt = new Date()\n },\n ],\n { transaction: true, label: `${staffTimeProjectChangeCurrencyCommandId}.undo` },\n )\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'updated',\n entity: project,\n identifiers: {\n id: project.id,\n organizationId: project.organizationId,\n tenantId: project.tenantId,\n },\n events: staffTimeProjectCrudEvents,\n indexer: timeProjectCrudIndexer,\n })\n },\n}\n\nconst assignTimeProjectMemberCommand: CommandHandler<StaffTimeProjectMemberAssignInput, { timeProjectMemberId: string }> = {\n id: 'staff.timesheets.time_project_members.assign',\n async execute(rawInput, ctx) {\n const parsed = staffTimeProjectMemberAssignSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n const scope = commandInputScope(ctx, parsed.tenantId, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n\n // Validate referenced project and staff member are in-scope before persisting.\n // Without this check a foreign or stale UUID would produce a dangling reference.\n const projectExists = await em.findOne(\n StaffTimeProject,\n applyScopeToWhere<StaffTimeProject>({ id: parsed.timeProjectId, deletedAt: null }, scope),\n { fields: ['id'] },\n )\n if (!projectExists) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(422, {\n error: translate('staff.timesheets.errors.projectNotFound', 'Time project not found or not accessible.'),\n fieldErrors: {\n timeProjectId: translate('staff.timesheets.errors.projectNotFound', 'Time project not found or not accessible.'),\n },\n })\n }\n const memberExists = await em.findOne(\n StaffTeamMember,\n applyScopeToWhere<StaffTeamMember>({ id: parsed.staffMemberId, deletedAt: null }, scope),\n { fields: ['id'] },\n )\n if (!memberExists) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(422, {\n error: translate('staff.timesheets.errors.staffMemberNotFound', 'Staff member not found or not accessible.'),\n fieldErrors: {\n staffMemberId: translate('staff.timesheets.errors.staffMemberNotFound', 'Staff member not found or not accessible.'),\n },\n })\n }\n\n const now = new Date()\n const member = em.create(StaffTimeProjectMember, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n timeProjectId: parsed.timeProjectId,\n staffMemberId: parsed.staffMemberId,\n role: parsed.role ?? null,\n status: parsed.status ?? 'active',\n showInGrid: false,\n assignedStartDate: parsed.assignedStartDate,\n assignedEndDate: parsed.assignedEndDate ?? null,\n createdAt: now,\n updatedAt: now,\n deletedAt: null,\n })\n em.persist(member)\n await em.flush()\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'created',\n entity: member,\n identifiers: { id: member.id, organizationId: member.organizationId, tenantId: member.tenantId },\n events: staffTimeProjectMemberCrudEvents,\n indexer: timeProjectMemberCrudIndexer,\n })\n\n return { timeProjectMemberId: member.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTimeProjectMemberSnapshot(em, result.timeProjectMemberId, staffSnapshotScopeFromContext(ctx))\n if (!snapshot) return null\n return { snapshot }\n },\n buildLog: async ({ result, ctx }) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTimeProjectMemberSnapshot(em, result.timeProjectMemberId, staffSnapshotScopeFromContext(ctx))\n if (!snapshot) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_project_members.assign', 'Assign time project member'),\n resourceKind: 'staff.timesheets.time_project_member',\n resourceId: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n snapshotAfter: snapshot,\n payload: {\n undo: {\n after: snapshot,\n } satisfies TimeProjectMemberUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeProjectMemberUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await em.findOne(StaffTimeProjectMember, scopedStaffSnapshotWhere(after.id, staffSnapshotScopeFromSnapshot(after)))\n if (member) {\n member.deletedAt = new Date()\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'deleted',\n entity: member,\n identifiers: { id: member.id, organizationId: member.organizationId, tenantId: member.tenantId },\n events: staffTimeProjectMemberCrudEvents,\n indexer: timeProjectMemberCrudIndexer,\n })\n }\n },\n redo: makeCreateRedo<StaffTimeProjectMember, TimeProjectMemberSnapshot, StaffTimeProjectMemberAssignInput, { timeProjectMemberId: string }>({\n entityClass: StaffTimeProjectMember,\n getSnapshotId: (snapshot) => snapshot.id,\n seedFromSnapshot: timeProjectMemberSeedFromSnapshot,\n buildResult: (entity) => ({ timeProjectMemberId: entity.id }),\n events: staffTimeProjectMemberCrudEvents,\n indexer: timeProjectMemberCrudIndexer,\n }),\n}\n\n/**\n * D-12 turned `assigned_end_date` into a field a Team Leader edits, so a\n * membership row needs an update path of its own. Without one the project team\n * drawer had to express a re-dating as \"assign a replacement row, drop the old\n * one\", and the audit trail then read as an unassign plus an assign \u2014 a history\n * that misstates what happened on the record an invoice is defended with.\n *\n * `timeProjectId` is optional in the schema but always supplied by the route\n * from the URL segment: the membership must belong to the project being edited,\n * so a body carrying a foreign membership id cannot reach another project's row.\n */\nconst updateTimeProjectMemberCommandSchema = staffTimeProjectMemberUpdateSchema.extend({\n timeProjectId: z.string().uuid().optional(),\n})\n\nexport type StaffTimeProjectMemberUpdateCommandInput = StaffTimeProjectMemberUpdateInput & {\n timeProjectId?: string\n}\n\nconst updateTimeProjectMemberCommand: CommandHandler<StaffTimeProjectMemberUpdateCommandInput, { timeProjectMemberId: string }> = {\n id: 'staff.timesheets.time_project_members.update',\n async prepare(rawInput, ctx) {\n const parsed = updateTimeProjectMemberCommandSchema.parse(rawInput)\n const em = ctx.container.resolve('em') as EntityManager\n const snapshot = await loadTimeProjectMemberSnapshot(em, parsed.id, staffSnapshotScopeFromContext(ctx))\n if (!snapshot) return {}\n return { before: snapshot }\n },\n async execute(rawInput, ctx) {\n const parsed = updateTimeProjectMemberCommandSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n const member = await findOneWithDecryption(\n em,\n StaffTimeProjectMember,\n applyScopeToWhere<StaffTimeProjectMember>(\n {\n id: parsed.id,\n deletedAt: null,\n ...(parsed.timeProjectId ? { timeProjectId: parsed.timeProjectId } : {}),\n },\n scope,\n ),\n undefined,\n scopeForDecryption(scope),\n )\n if (!member) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(404, {\n error: translate('staff.timesheets.errors.memberNotFound', 'Time project member not found or not accessible.'),\n })\n }\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n\n if (parsed.role !== undefined) member.role = parsed.role ?? null\n if (parsed.status !== undefined) member.status = parsed.status\n if (parsed.assignedEndDate !== undefined) member.assignedEndDate = parsed.assignedEndDate ?? null\n member.updatedAt = new Date()\n await em.flush()\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'updated',\n entity: member,\n identifiers: { id: member.id, organizationId: member.organizationId, tenantId: member.tenantId },\n events: staffTimeProjectMemberCrudEvents,\n indexer: timeProjectMemberCrudIndexer,\n })\n\n return { timeProjectMemberId: member.id }\n },\n buildLog: async ({ snapshots, ctx }) => {\n const before = snapshots.before as TimeProjectMemberSnapshot | undefined\n if (!before) return null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const after = await loadTimeProjectMemberSnapshot(em, before.id, staffSnapshotScopeFromSnapshot(before))\n if (!after) return null\n const changes = buildChanges(before as unknown as Record<string, unknown>, after as unknown as Record<string, unknown>, [\n 'role',\n 'status',\n 'assignedEndDate',\n ])\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_project_members.update', 'Update time project member'),\n resourceKind: 'staff.timesheets.time_project_member',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes,\n payload: {\n undo: {\n before,\n after,\n } satisfies TimeProjectMemberUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeProjectMemberUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await em.findOne(StaffTimeProjectMember, scopedStaffSnapshotWhere(before.id, staffSnapshotScopeFromSnapshot(before)))\n if (!member) return\n // Restores exactly what this command can change; the assignment window's\n // start and the row's identity belong to assign/unassign.\n member.role = before.role ?? null\n member.status = (before.status ?? 'active') as StaffTimeProjectMemberStatus\n member.assignedEndDate = before.assignedEndDate ? new Date(before.assignedEndDate) : null\n member.updatedAt = new Date()\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'updated',\n entity: member,\n identifiers: { id: member.id, organizationId: member.organizationId, tenantId: member.tenantId },\n events: staffTimeProjectMemberCrudEvents,\n indexer: timeProjectMemberCrudIndexer,\n })\n },\n}\n\nconst unassignTimeProjectMemberCommand: CommandHandler<{ id?: string }, { timeProjectMemberId: string }> = {\n id: 'staff.timesheets.time_project_members.unassign',\n async prepare(input, ctx) {\n const id = input?.id\n if (!id) throw new CrudHttpError(400, { error: 'Time project member id is required.' })\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadTimeProjectMemberSnapshot(em, id, staffSnapshotScopeFromContext(ctx))\n if (!snapshot) return {}\n return { before: snapshot }\n },\n async execute(input, ctx) {\n const id = input?.id\n if (!id) throw new CrudHttpError(400, { error: 'Time project member id is required.' })\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n const member = await findOneWithDecryption(\n em,\n StaffTimeProjectMember,\n applyScopeToWhere<StaffTimeProjectMember>({ id, deletedAt: null }, scope),\n undefined,\n scopeForDecryption(scope),\n )\n if (!member) throw new CrudHttpError(404, { error: 'Time project member not found.' })\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n\n member.deletedAt = new Date()\n member.updatedAt = new Date()\n await em.flush()\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'deleted',\n entity: member,\n identifiers: { id: member.id, organizationId: member.organizationId, tenantId: member.tenantId },\n events: staffTimeProjectMemberCrudEvents,\n indexer: timeProjectMemberCrudIndexer,\n })\n\n return { timeProjectMemberId: member.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as TimeProjectMemberSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_project_members.unassign', 'Unassign time project member'),\n resourceKind: 'staff.timesheets.time_project_member',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: {\n before,\n } satisfies TimeProjectMemberUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeProjectMemberUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let member = await em.findOne(StaffTimeProjectMember, scopedStaffSnapshotWhere(before.id, staffSnapshotScopeFromSnapshot(before)))\n if (!member) {\n member = em.create(StaffTimeProjectMember, {\n id: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n timeProjectId: before.timeProjectId,\n staffMemberId: before.staffMemberId,\n role: before.role ?? null,\n status: (before.status ?? 'active') as StaffTimeProjectMemberStatus,\n showInGrid: before.showInGrid ?? false,\n assignedStartDate: new Date(before.assignedStartDate),\n assignedEndDate: before.assignedEndDate ? new Date(before.assignedEndDate) : null,\n deletedAt: null,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(member)\n } else {\n member.timeProjectId = before.timeProjectId\n member.staffMemberId = before.staffMemberId\n member.role = before.role ?? null\n member.status = (before.status ?? 'active') as StaffTimeProjectMemberStatus\n member.assignedStartDate = new Date(before.assignedStartDate)\n member.assignedEndDate = before.assignedEndDate ? new Date(before.assignedEndDate) : null\n member.deletedAt = null\n member.updatedAt = new Date()\n }\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'created',\n entity: member,\n identifiers: { id: member.id, organizationId: member.organizationId, tenantId: member.tenantId },\n events: staffTimeProjectMemberCrudEvents,\n indexer: timeProjectMemberCrudIndexer,\n })\n },\n}\n\nregisterCommand(createTimeProjectCommand)\nregisterCommand(updateTimeProjectCommand)\nregisterCommand(deleteTimeProjectCommand)\nregisterCommand(changeTimeProjectCurrencyCommand)\nregisterCommand(assignTimeProjectMemberCommand)\nregisterCommand(updateTimeProjectMemberCommand)\nregisterCommand(unassignTimeProjectMemberCommand)\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { z } from 'zod'\nimport type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { UniqueConstraintViolationException } from '@mikro-orm/core'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { buildChanges, emitCrudSideEffects, emitCrudUndoSideEffects, setCustomFieldsIfAny } from '@open-mercato/shared/lib/commands/helpers'\nimport { extractCustomFieldValuesFromPayload } from '@open-mercato/shared/lib/crud/custom-fields'\nimport { E } from '#generated/entities.ids.generated'\nimport { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'\nimport { makeCreateRedo } from '@open-mercato/shared/lib/commands/redo'\nimport type { CrudEventsConfig, CrudIndexerConfig } from '@open-mercato/shared/lib/crud/types'\nimport { CustomerEntity } from '@open-mercato/core/modules/customers/data/entities'\nimport {\n StaffTeamMember,\n StaffTimeEntry,\n StaffTimeProject,\n StaffTimeProjectMember,\n StaffTimeReport,\n type StaffTimeProjectStatus,\n type StaffTimeProjectBudgetKind,\n type StaffTimeProjectMemberStatus,\n} from '../data/entities'\n\nconst timeProjectMemberCrudIndexer: CrudIndexerConfig<StaffTimeProjectMember> = {\n entityType: 'staff:staff_time_project_member',\n}\nimport {\n staffTimeProjectCreateSchema,\n staffTimeProjectUpdateSchema,\n staffTimeProjectChangeCurrencySchema,\n staffTimeProjectMemberAssignSchema,\n staffTimeProjectMemberUpdateSchema,\n type StaffTimeProjectCreateInput,\n type StaffTimeProjectUpdateInput,\n type StaffTimeProjectMemberAssignInput,\n type StaffTimeProjectMemberUpdateInput,\n} from '../data/validators'\nimport { staffTimeProjectCrudEvents, staffTimeProjectCrudIndexer, staffTimeProjectMemberCrudEvents } from '../lib/crud'\nimport { DEFAULT_BUDGET_WARN_AT_PERCENT } from '../lib/timesheets-projects/budgetBurn'\nimport { seedProjectTaskStatuses } from '../lib/timesheets-tasks/seedProjectStatuses'\nimport {\n applyScopeToWhere,\n commandActorScope,\n commandInputScope,\n ensureOrganizationScope,\n ensureTenantScope,\n extractUndoPayload,\n scopeForDecryption,\n scopedStaffSnapshotWhere,\n staffSnapshotDecryptionScope,\n staffSnapshotScopeFromContext,\n staffSnapshotScopeFromSnapshot,\n type StaffSnapshotScope,\n} from './shared'\n\nfunction isUniqueViolation(error: unknown): boolean {\n if (error instanceof UniqueConstraintViolationException) return true\n if (!error || typeof error !== 'object') return false\n const code = (error as { code?: string }).code\n if (code === '23505') return true\n const message = (error as { message?: string }).message\n return typeof message === 'string' && message.toLowerCase().includes('duplicate key')\n}\n\nfunction readSnapshotText(value: unknown): string | null {\n if (typeof value !== 'string') return null\n const trimmed = value.trim()\n return trimmed.length > 0 ? trimmed : null\n}\n\n/**\n * D-9 keeps a project's customer as an FK id plus a denormalized snapshot, and\n * denormalizing belongs to the module that owns the write: a caller that sends\n * `customerId` alone \u2014 the CRUD route, an import, an integration \u2014 must still\n * produce a project the portfolio grid can name, instead of one that has a\n * customer in the database and advertises none in the UI. A snapshot the caller\n * supplied still wins verbatim; the project form already carries the picked\n * customer and must not be second-guessed.\n *\n * The lookup is a scoped read by id \u2014 never an ORM relation to the customers\n * module \u2014 and a customers module that is absent, or a customer that is gone,\n * degrades to `null` rather than failing the write.\n */\nasync function resolveCustomerSnapshot(\n em: EntityManager,\n scope: { tenantId: string; organizationId: string },\n customerId: string | null | undefined,\n): Promise<Record<string, unknown> | null> {\n if (!customerId) return null\n let customer: CustomerEntity | null = null\n try {\n customer = await findOneWithDecryption(\n em,\n CustomerEntity,\n {\n id: customerId,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n },\n undefined,\n { tenantId: scope.tenantId, organizationId: scope.organizationId },\n )\n } catch {\n return null\n }\n if (!customer) return null\n const email = readSnapshotText(customer.primaryEmail)\n const name = readSnapshotText(customer.displayName) ?? email\n if (!name) return null\n const snapshot: Record<string, unknown> = { name }\n const kind = readSnapshotText(customer.kind)\n if (kind) snapshot.kind = kind\n if (email) snapshot.email = email\n return snapshot\n}\n\ntype TimeProjectSnapshot = {\n id: string\n tenantId: string\n organizationId: string\n name: string\n customerId: string | null\n customerSnapshot: Record<string, unknown> | null\n code: string\n description: string | null\n projectType: string | null\n color: string | null\n status: string\n ownerUserId: string | null\n costCenter: string | null\n startDate: string | null\n hourlyRate: string | null\n currencyCode: string | null\n billableByDefault: boolean\n budgetKind: string\n budgetValue: string | null\n budgetWarnAtPercent: number\n defaultAssigneeStaffMemberId: string | null\n deletedAt: string | null\n}\n\ntype TimeProjectUndoPayload = {\n before?: TimeProjectSnapshot | null\n after?: TimeProjectSnapshot | null\n}\n\ntype TimeProjectMemberSnapshot = {\n id: string\n tenantId: string\n organizationId: string\n timeProjectId: string\n staffMemberId: string\n role: string | null\n status: string\n showInGrid: boolean\n isAssigner: boolean\n assignedStartDate: string\n assignedEndDate: string | null\n deletedAt: string | null\n}\n\ntype TimeProjectMemberUndoPayload = {\n before?: TimeProjectMemberSnapshot | null\n after?: TimeProjectMemberSnapshot | null\n}\n\nasync function loadTimeProjectSnapshot(em: EntityManager, id: string, scope?: StaffSnapshotScope | null): Promise<TimeProjectSnapshot | null> {\n const project = await findOneWithDecryption(\n em,\n StaffTimeProject,\n scopedStaffSnapshotWhere(id, scope),\n undefined,\n staffSnapshotDecryptionScope(scope),\n )\n if (!project) return null\n return {\n id: project.id,\n tenantId: project.tenantId,\n organizationId: project.organizationId,\n name: project.name,\n customerId: project.customerId ?? null,\n customerSnapshot: project.customerSnapshot ?? null,\n code: project.code,\n description: project.description ?? null,\n projectType: project.projectType ?? null,\n color: project.color ?? null,\n status: project.status,\n ownerUserId: project.ownerUserId ?? null,\n costCenter: project.costCenter ?? null,\n startDate: project.startDate instanceof Date ? project.startDate.toISOString().split('T')[0] : (project.startDate ?? null),\n hourlyRate: project.hourlyRate ?? null,\n currencyCode: project.currencyCode ?? null,\n billableByDefault: project.billableByDefault ?? true,\n budgetKind: project.budgetKind ?? 'none',\n budgetValue: project.budgetValue ?? null,\n budgetWarnAtPercent: project.budgetWarnAtPercent ?? DEFAULT_BUDGET_WARN_AT_PERCENT,\n defaultAssigneeStaffMemberId: project.defaultAssigneeStaffMemberId ?? null,\n deletedAt: project.deletedAt ? project.deletedAt.toISOString() : null,\n }\n}\n\nasync function loadTimeProjectMemberSnapshot(em: EntityManager, id: string, scope?: StaffSnapshotScope | null): Promise<TimeProjectMemberSnapshot | null> {\n const member = await findOneWithDecryption(\n em,\n StaffTimeProjectMember,\n scopedStaffSnapshotWhere(id, scope),\n undefined,\n staffSnapshotDecryptionScope(scope),\n )\n if (!member) return null\n return {\n id: member.id,\n tenantId: member.tenantId,\n organizationId: member.organizationId,\n timeProjectId: member.timeProjectId,\n staffMemberId: member.staffMemberId,\n role: member.role ?? null,\n status: member.status,\n showInGrid: member.showInGrid ?? false,\n isAssigner: member.isAssigner === true,\n assignedStartDate: member.assignedStartDate instanceof Date ? member.assignedStartDate.toISOString().split('T')[0] : String(member.assignedStartDate),\n assignedEndDate: member.assignedEndDate instanceof Date ? member.assignedEndDate.toISOString().split('T')[0] : (member.assignedEndDate ?? null),\n deletedAt: member.deletedAt ? member.deletedAt.toISOString() : null,\n }\n}\n\nfunction timeProjectSeedFromSnapshot(snapshot: TimeProjectSnapshot): Record<string, unknown> {\n return {\n id: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n name: snapshot.name,\n customerId: snapshot.customerId ?? null,\n customerSnapshot: snapshot.customerSnapshot ?? null,\n code: snapshot.code,\n description: snapshot.description ?? null,\n projectType: snapshot.projectType ?? null,\n color: snapshot.color ?? null,\n status: (snapshot.status ?? 'active') as StaffTimeProjectStatus,\n ownerUserId: snapshot.ownerUserId ?? null,\n costCenter: snapshot.costCenter ?? null,\n startDate: snapshot.startDate ? new Date(snapshot.startDate) : null,\n hourlyRate: snapshot.hourlyRate ?? null,\n currencyCode: snapshot.currencyCode ?? null,\n billableByDefault: snapshot.billableByDefault ?? true,\n budgetKind: (snapshot.budgetKind ?? 'none') as StaffTimeProjectBudgetKind,\n budgetValue: snapshot.budgetValue ?? null,\n budgetWarnAtPercent: snapshot.budgetWarnAtPercent ?? DEFAULT_BUDGET_WARN_AT_PERCENT,\n defaultAssigneeStaffMemberId: snapshot.defaultAssigneeStaffMemberId ?? null,\n createdAt: new Date(),\n updatedAt: new Date(),\n deletedAt: null,\n }\n}\n\nfunction timeProjectMemberSeedFromSnapshot(snapshot: TimeProjectMemberSnapshot): Record<string, unknown> {\n return {\n id: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n timeProjectId: snapshot.timeProjectId,\n staffMemberId: snapshot.staffMemberId,\n role: snapshot.role ?? null,\n status: (snapshot.status ?? 'active') as StaffTimeProjectMemberStatus,\n showInGrid: snapshot.showInGrid ?? false,\n isAssigner: snapshot.isAssigner === true,\n assignedStartDate: new Date(snapshot.assignedStartDate),\n assignedEndDate: snapshot.assignedEndDate ? new Date(snapshot.assignedEndDate) : null,\n createdAt: new Date(),\n updatedAt: new Date(),\n deletedAt: null,\n }\n}\n\nconst createTimeProjectCommand: CommandHandler<StaffTimeProjectCreateInput, { timeProjectId: string }> = {\n id: 'staff.timesheets.time_projects.create',\n async execute(rawInput, ctx) {\n const parsed = staffTimeProjectCreateSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n commandInputScope(ctx, parsed.tenantId, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const customerSnapshot =\n parsed.customerSnapshot\n ?? (await resolveCustomerSnapshot(\n em,\n { tenantId: parsed.tenantId, organizationId: parsed.organizationId },\n parsed.customerId,\n ))\n const now = new Date()\n const project = em.create(StaffTimeProject, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n name: parsed.name,\n customerId: parsed.customerId,\n customerSnapshot,\n code: parsed.code,\n description: parsed.description ?? null,\n projectType: parsed.projectType ?? null,\n color: parsed.color ?? null,\n status: parsed.status ?? 'active',\n ownerUserId: parsed.ownerUserId ?? null,\n costCenter: parsed.costCenter ?? null,\n startDate: parsed.startDate ?? null,\n hourlyRate: parsed.hourlyRate ?? null,\n // D-3: creation is the one moment the currency may be chosen freely.\n currencyCode: parsed.currencyCode ?? null,\n billableByDefault: parsed.billableByDefault ?? true,\n budgetKind: parsed.budgetKind ?? 'none',\n budgetValue: parsed.budgetValue ?? null,\n budgetWarnAtPercent: parsed.budgetWarnAtPercent ?? DEFAULT_BUDGET_WARN_AT_PERCENT,\n createdAt: now,\n updatedAt: now,\n deletedAt: null,\n })\n const { translate } = await resolveTranslations()\n try {\n // D-1: the project and its Kanban columns are one transaction. The template\n // can only be seeded once the insert has handed back the project's id, so\n // the two writes are separate phases \u2014 but a rollback takes both, and a\n // project therefore never exists with an empty board.\n await withAtomicFlush(\n em,\n [\n () => {\n em.persist(project)\n },\n () => {\n seedProjectTaskStatuses(\n em,\n { tenantId: project.tenantId, organizationId: project.organizationId, timeProjectId: project.id },\n translate,\n )\n },\n ],\n { transaction: true, label: 'staff.timesheets.time_projects.create' },\n )\n } catch (err) {\n if (isUniqueViolation(err)) {\n throw new CrudHttpError(409, {\n error: translate('staff.timesheets.errors.projectCodeDuplicate', 'A project with this code already exists.'),\n fieldErrors: { code: translate('staff.timesheets.errors.projectCodeDuplicate', 'A project with this code already exists.') },\n })\n }\n throw err\n }\n\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.staff.staff_time_project,\n recordId: project.id,\n tenantId: project.tenantId,\n organizationId: project.organizationId,\n values: extractCustomFieldValuesFromPayload(\n (rawInput && typeof rawInput === 'object' ? rawInput : {}) as Record<string, unknown>,\n ),\n })\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'created',\n entity: project,\n identifiers: {\n id: project.id,\n organizationId: project.organizationId,\n tenantId: project.tenantId,\n },\n events: staffTimeProjectCrudEvents,\n indexer: staffTimeProjectCrudIndexer,\n })\n\n return { timeProjectId: project.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTimeProjectSnapshot(em, result.timeProjectId, staffSnapshotScopeFromContext(ctx))\n if (!snapshot) return null\n return { snapshot }\n },\n buildLog: async ({ result, ctx }) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTimeProjectSnapshot(em, result.timeProjectId, staffSnapshotScopeFromContext(ctx))\n if (!snapshot) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_projects.create', 'Create time project'),\n resourceKind: 'staff.timesheets.time_project',\n resourceId: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n snapshotAfter: snapshot,\n payload: {\n undo: {\n after: snapshot,\n } satisfies TimeProjectUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeProjectUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const project = await em.findOne(StaffTimeProject, scopedStaffSnapshotWhere(after.id, staffSnapshotScopeFromSnapshot(after)))\n if (project) {\n project.deletedAt = new Date()\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'deleted',\n entity: project,\n identifiers: {\n id: project.id,\n organizationId: project.organizationId,\n tenantId: project.tenantId,\n },\n events: staffTimeProjectCrudEvents,\n indexer: staffTimeProjectCrudIndexer,\n })\n }\n },\n redo: makeCreateRedo<StaffTimeProject, TimeProjectSnapshot, StaffTimeProjectCreateInput, { timeProjectId: string }>({\n entityClass: StaffTimeProject,\n getSnapshotId: (snapshot) => snapshot.id,\n seedFromSnapshot: timeProjectSeedFromSnapshot,\n buildResult: (entity) => ({ timeProjectId: entity.id }),\n events: staffTimeProjectCrudEvents,\n indexer: staffTimeProjectCrudIndexer,\n }),\n}\n\nasync function requireAssignerUserAccount(\n em: EntityManager,\n member: { staffMemberId: string; tenantId: string; organizationId: string },\n): Promise<void> {\n const teamMember = await findOneWithDecryption(\n em,\n StaffTeamMember,\n { id: member.staffMemberId, tenantId: member.tenantId, organizationId: member.organizationId, deletedAt: null },\n undefined,\n { tenantId: member.tenantId, organizationId: member.organizationId },\n )\n if (teamMember?.userId) return\n const { translate } = await resolveTranslations()\n const message = translate(\n 'staff.timesheets.errors.assignerNeedsUser',\n 'Only team members with a user account can be assigners, because they must log in and receive notifications.',\n )\n throw new CrudHttpError(422, { code: 'assigner_needs_user', error: message, fieldErrors: { isAssigner: message } })\n}\n\nasync function requireDefaultAssigneeMember(\n em: EntityManager,\n project: { id: string; tenantId: string; organizationId: string },\n staffMemberId: string,\n): Promise<void> {\n const membership = await em.findOne(\n StaffTimeProjectMember,\n {\n timeProjectId: project.id,\n staffMemberId,\n tenantId: project.tenantId,\n organizationId: project.organizationId,\n status: 'active',\n deletedAt: null,\n },\n { fields: ['id'] },\n )\n if (membership) return\n const { translate } = await resolveTranslations()\n const message = translate(\n 'staff.timesheets.errors.defaultAssigneeNotMember',\n 'The default assignee must be an active member of this project.',\n )\n throw new CrudHttpError(422, {\n code: 'default_assignee_not_member',\n error: message,\n fieldErrors: { defaultAssigneeStaffMemberId: message },\n })\n}\n\nconst updateTimeProjectCommand: CommandHandler<StaffTimeProjectUpdateInput, { timeProjectId: string }> = {\n id: 'staff.timesheets.time_projects.update',\n async prepare(rawInput, ctx) {\n const parsed = staffTimeProjectUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadTimeProjectSnapshot(em, parsed.id, staffSnapshotScopeFromContext(ctx))\n if (!snapshot) return {}\n return { before: snapshot }\n },\n async execute(rawInput, ctx) {\n const parsed = staffTimeProjectUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n const project = await findOneWithDecryption(\n em,\n StaffTimeProject,\n applyScopeToWhere<StaffTimeProject>({ id: parsed.id, deletedAt: null }, scope),\n undefined,\n scopeForDecryption(scope),\n )\n if (!project) throw new CrudHttpError(404, { error: 'Time project not found.' })\n ensureTenantScope(ctx, project.tenantId)\n ensureOrganizationScope(ctx, project.organizationId)\n\n // The FK and its snapshot move together. A payload that re-points the\n // customer without carrying a snapshot \u2014 or that clears a stale one while\n // keeping the customer \u2014 has the snapshot re-derived here, so the grid never\n // reads a project with a customer as unassigned. The read runs before every\n // scalar mutation below, so it cannot reset the unit of work.\n const customerTouched = parsed.customerId !== undefined || parsed.customerSnapshot !== undefined\n const nextCustomerId = parsed.customerId !== undefined ? parsed.customerId ?? null : project.customerId ?? null\n const customerUnchanged = nextCustomerId === (project.customerId ?? null)\n let nextCustomerSnapshot: Record<string, unknown> | null | undefined\n if (customerTouched) {\n nextCustomerSnapshot =\n parsed.customerSnapshot\n ?? (await resolveCustomerSnapshot(\n em,\n { tenantId: project.tenantId, organizationId: project.organizationId },\n nextCustomerId,\n ))\n // A customer that stays put keeps the snapshot it already had when the\n // lookup comes back empty (customer removed, customers module absent);\n // only a re-pointed or cleared customer drops it, because holding the\n // previous customer's details on a different FK would misattribute them.\n ?? (customerUnchanged && nextCustomerId ? project.customerSnapshot ?? null : null)\n }\n\n if (parsed.defaultAssigneeStaffMemberId) {\n await requireDefaultAssigneeMember(em, project, parsed.defaultAssigneeStaffMemberId)\n }\n\n if (parsed.name !== undefined) project.name = parsed.name\n if (parsed.customerId !== undefined) project.customerId = parsed.customerId ?? null\n if (nextCustomerSnapshot !== undefined) project.customerSnapshot = nextCustomerSnapshot\n if (parsed.code !== undefined) project.code = parsed.code\n if (parsed.description !== undefined) project.description = parsed.description ?? null\n if (parsed.projectType !== undefined) project.projectType = parsed.projectType ?? null\n if (parsed.color !== undefined) project.color = parsed.color ?? null\n if (parsed.status !== undefined) project.status = parsed.status\n if (parsed.ownerUserId !== undefined) project.ownerUserId = parsed.ownerUserId ?? null\n if (parsed.costCenter !== undefined) project.costCenter = parsed.costCenter ?? null\n if (parsed.startDate !== undefined) project.startDate = parsed.startDate ?? null\n if (parsed.hourlyRate !== undefined) project.hourlyRate = parsed.hourlyRate ?? null\n if (parsed.billableByDefault !== undefined) project.billableByDefault = parsed.billableByDefault\n if (parsed.budgetKind !== undefined) project.budgetKind = parsed.budgetKind\n if (parsed.budgetValue !== undefined) project.budgetValue = parsed.budgetValue ?? null\n if (parsed.budgetWarnAtPercent !== undefined) project.budgetWarnAtPercent = parsed.budgetWarnAtPercent\n if (parsed.defaultAssigneeStaffMemberId !== undefined) project.defaultAssigneeStaffMemberId = parsed.defaultAssigneeStaffMemberId ?? null\n // `currency_code` is intentionally absent here and from the update schema:\n // D-3 gives that column to `staff.timesheets.time_projects.change_currency`,\n // which owns the acknowledgement and the locked-entry refusal. A caller that\n // smuggles `currencyCode` into a PUT has it stripped by the schema, so there\n // is no key to assign from.\n project.updatedAt = new Date()\n try {\n await em.flush()\n } catch (err) {\n if (isUniqueViolation(err)) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(409, {\n error: translate('staff.timesheets.errors.projectCodeDuplicate', 'A project with this code already exists.'),\n fieldErrors: { code: translate('staff.timesheets.errors.projectCodeDuplicate', 'A project with this code already exists.') },\n })\n }\n throw err\n }\n\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.staff.staff_time_project,\n recordId: project.id,\n tenantId: project.tenantId,\n organizationId: project.organizationId,\n values: extractCustomFieldValuesFromPayload(\n (rawInput && typeof rawInput === 'object' ? rawInput : {}) as Record<string, unknown>,\n ),\n })\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'updated',\n entity: project,\n identifiers: {\n id: project.id,\n organizationId: project.organizationId,\n tenantId: project.tenantId,\n },\n events: staffTimeProjectCrudEvents,\n indexer: staffTimeProjectCrudIndexer,\n })\n\n return { timeProjectId: project.id }\n },\n buildLog: async ({ snapshots, ctx }) => {\n const before = snapshots.before as TimeProjectSnapshot | undefined\n if (!before) return null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const after = await loadTimeProjectSnapshot(em, before.id, staffSnapshotScopeFromSnapshot(before))\n if (!after) return null\n const changes = buildChanges(before as unknown as Record<string, unknown>, after as unknown as Record<string, unknown>, [\n 'name',\n 'customerId',\n 'code',\n 'description',\n 'projectType',\n 'color',\n 'status',\n 'ownerUserId',\n 'costCenter',\n 'startDate',\n 'hourlyRate',\n 'billableByDefault',\n 'budgetKind',\n 'budgetValue',\n 'budgetWarnAtPercent',\n 'defaultAssigneeStaffMemberId',\n 'deletedAt',\n ])\n // `buildChanges` compares by identity, and the two snapshots are loaded through\n // separate forks, so the denormalized customer snapshot needs a value compare\n // or every edit would report it as changed.\n if (JSON.stringify(before.customerSnapshot ?? null) !== JSON.stringify(after.customerSnapshot ?? null)) {\n changes.customerSnapshot = { from: before.customerSnapshot ?? null, to: after.customerSnapshot ?? null }\n }\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_projects.update', 'Update time project'),\n resourceKind: 'staff.timesheets.time_project',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes,\n payload: {\n undo: {\n before,\n after,\n } satisfies TimeProjectUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeProjectUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const project = await em.findOne(StaffTimeProject, scopedStaffSnapshotWhere(before.id, staffSnapshotScopeFromSnapshot(before)))\n if (!project) return\n project.name = before.name\n project.customerId = before.customerId ?? null\n project.customerSnapshot = before.customerSnapshot ?? null\n project.code = before.code\n project.description = before.description ?? null\n project.projectType = before.projectType ?? null\n project.color = before.color ?? null\n project.status = (before.status ?? 'active') as StaffTimeProjectStatus\n project.ownerUserId = before.ownerUserId ?? null\n project.costCenter = before.costCenter ?? null\n project.startDate = before.startDate ? new Date(before.startDate) : null\n project.hourlyRate = before.hourlyRate ?? null\n project.billableByDefault = before.billableByDefault ?? true\n project.budgetKind = (before.budgetKind ?? 'none') as StaffTimeProjectBudgetKind\n project.budgetValue = before.budgetValue ?? null\n project.budgetWarnAtPercent = before.budgetWarnAtPercent ?? DEFAULT_BUDGET_WARN_AT_PERCENT\n project.defaultAssigneeStaffMemberId = before.defaultAssigneeStaffMemberId ?? null\n // Undo of a plain update restores what a plain update could change; the currency\n // stays where change_currency left it (D-3).\n project.deletedAt = before.deletedAt ? new Date(before.deletedAt) : null\n project.updatedAt = new Date()\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'updated',\n entity: project,\n identifiers: {\n id: project.id,\n organizationId: project.organizationId,\n tenantId: project.tenantId,\n },\n events: staffTimeProjectCrudEvents,\n indexer: staffTimeProjectCrudIndexer,\n })\n },\n}\n\nconst deleteTimeProjectCommand: CommandHandler<{ id?: string }, { timeProjectId: string }> = {\n id: 'staff.timesheets.time_projects.delete',\n async prepare(input, ctx) {\n const id = input?.id\n if (!id) throw new CrudHttpError(400, { error: 'Time project id is required.' })\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadTimeProjectSnapshot(em, id, staffSnapshotScopeFromContext(ctx))\n if (!snapshot) return {}\n return { before: snapshot }\n },\n async execute(input, ctx) {\n const id = input?.id\n if (!id) throw new CrudHttpError(400, { error: 'Time project id is required.' })\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n const project = await findOneWithDecryption(\n em,\n StaffTimeProject,\n applyScopeToWhere<StaffTimeProject>({ id, deletedAt: null }, scope),\n undefined,\n scopeForDecryption(scope),\n )\n if (!project) throw new CrudHttpError(404, { error: 'Time project not found.' })\n ensureTenantScope(ctx, project.tenantId)\n ensureOrganizationScope(ctx, project.organizationId)\n\n project.deletedAt = new Date()\n project.updatedAt = new Date()\n await em.flush()\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'deleted',\n entity: project,\n identifiers: {\n id: project.id,\n organizationId: project.organizationId,\n tenantId: project.tenantId,\n },\n events: staffTimeProjectCrudEvents,\n indexer: staffTimeProjectCrudIndexer,\n })\n return { timeProjectId: project.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as TimeProjectSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_projects.delete', 'Delete time project'),\n resourceKind: 'staff.timesheets.time_project',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: {\n before,\n } satisfies TimeProjectUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeProjectUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let project = await em.findOne(StaffTimeProject, scopedStaffSnapshotWhere(before.id, staffSnapshotScopeFromSnapshot(before)))\n if (!project) {\n project = em.create(StaffTimeProject, {\n id: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n name: before.name,\n customerId: before.customerId ?? null,\n customerSnapshot: before.customerSnapshot ?? null,\n code: before.code,\n description: before.description ?? null,\n projectType: before.projectType ?? null,\n status: (before.status ?? 'active') as StaffTimeProjectStatus,\n ownerUserId: before.ownerUserId ?? null,\n costCenter: before.costCenter ?? null,\n startDate: before.startDate ? new Date(before.startDate) : null,\n hourlyRate: before.hourlyRate ?? null,\n currencyCode: before.currencyCode ?? null,\n billableByDefault: before.billableByDefault ?? true,\n budgetKind: (before.budgetKind ?? 'none') as StaffTimeProjectBudgetKind,\n budgetValue: before.budgetValue ?? null,\n budgetWarnAtPercent: before.budgetWarnAtPercent ?? DEFAULT_BUDGET_WARN_AT_PERCENT,\n deletedAt: null,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(project)\n } else {\n project.name = before.name\n project.customerId = before.customerId ?? null\n project.customerSnapshot = before.customerSnapshot ?? null\n project.code = before.code\n project.description = before.description ?? null\n project.projectType = before.projectType ?? null\n project.status = (before.status ?? 'active') as StaffTimeProjectStatus\n project.ownerUserId = before.ownerUserId ?? null\n project.costCenter = before.costCenter ?? null\n project.startDate = before.startDate ? new Date(before.startDate) : null\n project.hourlyRate = before.hourlyRate ?? null\n project.currencyCode = before.currencyCode ?? null\n project.billableByDefault = before.billableByDefault ?? true\n project.budgetKind = (before.budgetKind ?? 'none') as StaffTimeProjectBudgetKind\n project.budgetValue = before.budgetValue ?? null\n project.budgetWarnAtPercent = before.budgetWarnAtPercent ?? DEFAULT_BUDGET_WARN_AT_PERCENT\n project.deletedAt = null\n project.updatedAt = new Date()\n }\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'created',\n entity: project,\n identifiers: {\n id: project.id,\n organizationId: project.organizationId,\n tenantId: project.tenantId,\n },\n events: staffTimeProjectCrudEvents,\n indexer: staffTimeProjectCrudIndexer,\n })\n },\n}\n\n/**\n * D-3: a project's currency is read-only once hours have been logged against it,\n * and the deliberate change action below relabels the project WITHOUT converting\n * any historical amount. It never touches an entry's `rate_currency_code` or its\n * stored cost, so a closed report keeps billing what it billed. That is also why\n * the change is refused outright while any entry of the project sits frozen in a\n * closed report: relabelling then would make the project disagree with the\n * `frozen_currency_code` those report lines were issued under.\n */\nexport const staffTimeProjectChangeCurrencyCommandId = 'staff.timesheets.time_projects.change_currency'\n\nexport const PROJECT_HAS_LOCKED_ENTRIES_CODE = 'project_has_locked_entries'\n\nconst changeTimeProjectCurrencyCommandSchema = staffTimeProjectChangeCurrencySchema.extend({\n id: z.string().uuid(),\n})\n\nexport type StaffTimeProjectChangeCurrencyCommandInput = z.infer<typeof changeTimeProjectCurrencyCommandSchema>\n\nexport type StaffTimeProjectChangeCurrencyResult = {\n timeProjectId: string\n currencyCode: string\n previousCurrencyCode: string | null\n}\n\ntype BlockingLockedReport = {\n id: string\n reference: string | null\n title: string | null\n}\n\ntype LockedEntryBlock = {\n lockedEntryCount: number\n reports: BlockingLockedReport[]\n}\n\nasync function findLockedEntryBlock(\n em: EntityManager,\n project: StaffTimeProject,\n): Promise<LockedEntryBlock> {\n const scope = { tenantId: project.tenantId, organizationId: project.organizationId }\n const lockedEntries = await em.find(\n StaffTimeEntry,\n { ...scope, timeProjectId: project.id, lockedReportId: { $ne: null }, deletedAt: null },\n { fields: ['id', 'lockedReportId'] },\n )\n if (lockedEntries.length === 0) return { lockedEntryCount: 0, reports: [] }\n\n const reportIds = Array.from(\n new Set(lockedEntries.map((entry) => entry.lockedReportId).filter((value): value is string => typeof value === 'string')),\n )\n const reports = reportIds.length\n ? await em.find(\n StaffTimeReport,\n { ...scope, id: { $in: reportIds } },\n { fields: ['id', 'reference', 'title'] },\n )\n : []\n const known = new Map(reports.map((report) => [report.id, report]))\n\n return {\n lockedEntryCount: lockedEntries.length,\n reports: reportIds.map((id) => ({\n id,\n reference: known.get(id)?.reference ?? null,\n title: known.get(id)?.title ?? null,\n })),\n }\n}\n\nasync function assertNoLockedEntries(em: EntityManager, project: StaffTimeProject): Promise<void> {\n const block = await findLockedEntryBlock(em, project)\n if (block.lockedEntryCount === 0) return\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(409, {\n code: PROJECT_HAS_LOCKED_ENTRIES_CODE,\n error: translate(\n 'staff.timesheets.errors.projectCurrencyLocked',\n 'This project has time entries frozen in a closed report. Unlock those reports before changing the currency.',\n ),\n lockedEntryCount: block.lockedEntryCount,\n lockedReports: block.reports,\n })\n}\n\n/**\n * Same `staff.timesheets.time_project.updated` event id every project write emits,\n * with the currency transition carried in the payload so a subscriber can tell a\n * relabel apart from an ordinary field edit without re-reading the project.\n */\nfunction timeProjectCurrencyChangeEvents(\n previousCurrencyCode: string | null,\n currencyCode: string,\n): CrudEventsConfig<StaffTimeProject> {\n return {\n ...staffTimeProjectCrudEvents,\n buildPayload: (emitCtx) => ({\n id: emitCtx.identifiers.id,\n organizationId: emitCtx.identifiers.organizationId,\n tenantId: emitCtx.identifiers.tenantId,\n changedField: 'currencyCode',\n previousCurrencyCode,\n currencyCode,\n converted: false,\n }),\n }\n}\n\nconst changeTimeProjectCurrencyCommand: CommandHandler<\n StaffTimeProjectChangeCurrencyCommandInput,\n StaffTimeProjectChangeCurrencyResult\n> = {\n id: staffTimeProjectChangeCurrencyCommandId,\n async prepare(rawInput, ctx) {\n const parsed = changeTimeProjectCurrencyCommandSchema.parse(rawInput)\n const em = ctx.container.resolve('em') as EntityManager\n const snapshot = await loadTimeProjectSnapshot(em, parsed.id, staffSnapshotScopeFromContext(ctx))\n if (!snapshot) return {}\n return { before: snapshot }\n },\n async execute(rawInput, ctx) {\n const parsed = changeTimeProjectCurrencyCommandSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n const project = await findOneWithDecryption(\n em,\n StaffTimeProject,\n applyScopeToWhere<StaffTimeProject>({ id: parsed.id, deletedAt: null }, scope),\n undefined,\n scopeForDecryption(scope),\n )\n if (!project) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(404, {\n error: translate('staff.timesheets.errors.projectNotFound', 'Time project not found or not accessible.'),\n })\n }\n ensureTenantScope(ctx, project.tenantId)\n ensureOrganizationScope(ctx, project.organizationId)\n\n const previousCurrencyCode = project.currencyCode ?? null\n\n // The lock probe and the relabel are separate phases of one transaction: the\n // probe queries `staff_time_entries` and must therefore never share a phase\n // with the scalar mutation, and the shared transaction keeps a report closing\n // concurrently from slipping between the check and the write.\n await withAtomicFlush(\n em,\n [\n () => assertNoLockedEntries(em, project),\n () => {\n project.currencyCode = parsed.currencyCode\n project.updatedAt = new Date()\n },\n ],\n { transaction: true, label: staffTimeProjectChangeCurrencyCommandId },\n )\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'updated',\n entity: project,\n identifiers: {\n id: project.id,\n organizationId: project.organizationId,\n tenantId: project.tenantId,\n },\n events: timeProjectCurrencyChangeEvents(previousCurrencyCode, parsed.currencyCode),\n indexer: staffTimeProjectCrudIndexer,\n })\n\n return {\n timeProjectId: project.id,\n currencyCode: parsed.currencyCode,\n previousCurrencyCode,\n }\n },\n buildLog: async ({ snapshots, ctx }) => {\n const before = snapshots.before as TimeProjectSnapshot | undefined\n if (!before) return null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const after = await loadTimeProjectSnapshot(em, before.id, staffSnapshotScopeFromSnapshot(before))\n if (!after) return null\n const changes = buildChanges(\n before as unknown as Record<string, unknown>,\n after as unknown as Record<string, unknown>,\n ['currencyCode'],\n )\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_projects.change_currency', 'Change time project currency'),\n resourceKind: 'staff.timesheets.time_project',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes,\n payload: {\n undo: {\n before,\n after,\n } satisfies TimeProjectUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeProjectUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const project = await em.findOne(StaffTimeProject, scopedStaffSnapshotWhere(before.id, staffSnapshotScopeFromSnapshot(before)))\n if (!project) return\n\n // Undo relabels back, so it has to honour the same invariant: entries may have\n // been frozen into a closed report since the change was made.\n await withAtomicFlush(\n em,\n [\n () => assertNoLockedEntries(em, project),\n () => {\n project.currencyCode = before.currencyCode ?? null\n project.updatedAt = new Date()\n },\n ],\n { transaction: true, label: `${staffTimeProjectChangeCurrencyCommandId}.undo` },\n )\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'updated',\n entity: project,\n identifiers: {\n id: project.id,\n organizationId: project.organizationId,\n tenantId: project.tenantId,\n },\n events: staffTimeProjectCrudEvents,\n indexer: staffTimeProjectCrudIndexer,\n })\n },\n}\n\nconst assignTimeProjectMemberCommand: CommandHandler<StaffTimeProjectMemberAssignInput, { timeProjectMemberId: string }> = {\n id: 'staff.timesheets.time_project_members.assign',\n async execute(rawInput, ctx) {\n const parsed = staffTimeProjectMemberAssignSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n const scope = commandInputScope(ctx, parsed.tenantId, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n\n // Validate referenced project and staff member are in-scope before persisting.\n // Without this check a foreign or stale UUID would produce a dangling reference.\n const projectExists = await em.findOne(\n StaffTimeProject,\n applyScopeToWhere<StaffTimeProject>({ id: parsed.timeProjectId, deletedAt: null }, scope),\n { fields: ['id'] },\n )\n if (!projectExists) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(422, {\n error: translate('staff.timesheets.errors.projectNotFound', 'Time project not found or not accessible.'),\n fieldErrors: {\n timeProjectId: translate('staff.timesheets.errors.projectNotFound', 'Time project not found or not accessible.'),\n },\n })\n }\n const memberExists = await em.findOne(\n StaffTeamMember,\n applyScopeToWhere<StaffTeamMember>({ id: parsed.staffMemberId, deletedAt: null }, scope),\n { fields: ['id'] },\n )\n if (!memberExists) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(422, {\n error: translate('staff.timesheets.errors.staffMemberNotFound', 'Staff member not found or not accessible.'),\n fieldErrors: {\n staffMemberId: translate('staff.timesheets.errors.staffMemberNotFound', 'Staff member not found or not accessible.'),\n },\n })\n }\n\n if (parsed.isAssigner === true) {\n await requireAssignerUserAccount(em, { staffMemberId: parsed.staffMemberId, tenantId: parsed.tenantId, organizationId: parsed.organizationId })\n }\n\n const now = new Date()\n const member = em.create(StaffTimeProjectMember, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n timeProjectId: parsed.timeProjectId,\n staffMemberId: parsed.staffMemberId,\n role: parsed.role ?? null,\n status: parsed.status ?? 'active',\n showInGrid: false,\n isAssigner: parsed.isAssigner === true,\n assignedStartDate: parsed.assignedStartDate,\n assignedEndDate: parsed.assignedEndDate ?? null,\n createdAt: now,\n updatedAt: now,\n deletedAt: null,\n })\n em.persist(member)\n await em.flush()\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'created',\n entity: member,\n identifiers: { id: member.id, organizationId: member.organizationId, tenantId: member.tenantId },\n events: staffTimeProjectMemberCrudEvents,\n indexer: timeProjectMemberCrudIndexer,\n })\n\n return { timeProjectMemberId: member.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTimeProjectMemberSnapshot(em, result.timeProjectMemberId, staffSnapshotScopeFromContext(ctx))\n if (!snapshot) return null\n return { snapshot }\n },\n buildLog: async ({ result, ctx }) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTimeProjectMemberSnapshot(em, result.timeProjectMemberId, staffSnapshotScopeFromContext(ctx))\n if (!snapshot) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_project_members.assign', 'Assign time project member'),\n resourceKind: 'staff.timesheets.time_project_member',\n resourceId: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n snapshotAfter: snapshot,\n payload: {\n undo: {\n after: snapshot,\n } satisfies TimeProjectMemberUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeProjectMemberUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await em.findOne(StaffTimeProjectMember, scopedStaffSnapshotWhere(after.id, staffSnapshotScopeFromSnapshot(after)))\n if (member) {\n member.deletedAt = new Date()\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'deleted',\n entity: member,\n identifiers: { id: member.id, organizationId: member.organizationId, tenantId: member.tenantId },\n events: staffTimeProjectMemberCrudEvents,\n indexer: timeProjectMemberCrudIndexer,\n })\n }\n },\n redo: makeCreateRedo<StaffTimeProjectMember, TimeProjectMemberSnapshot, StaffTimeProjectMemberAssignInput, { timeProjectMemberId: string }>({\n entityClass: StaffTimeProjectMember,\n getSnapshotId: (snapshot) => snapshot.id,\n seedFromSnapshot: timeProjectMemberSeedFromSnapshot,\n buildResult: (entity) => ({ timeProjectMemberId: entity.id }),\n events: staffTimeProjectMemberCrudEvents,\n indexer: timeProjectMemberCrudIndexer,\n }),\n}\n\n/**\n * D-12 turned `assigned_end_date` into a field a Team Leader edits, so a\n * membership row needs an update path of its own. Without one the project team\n * drawer had to express a re-dating as \"assign a replacement row, drop the old\n * one\", and the audit trail then read as an unassign plus an assign \u2014 a history\n * that misstates what happened on the record an invoice is defended with.\n *\n * `timeProjectId` is optional in the schema but always supplied by the route\n * from the URL segment: the membership must belong to the project being edited,\n * so a body carrying a foreign membership id cannot reach another project's row.\n */\nconst updateTimeProjectMemberCommandSchema = staffTimeProjectMemberUpdateSchema.extend({\n timeProjectId: z.string().uuid().optional(),\n})\n\nexport type StaffTimeProjectMemberUpdateCommandInput = StaffTimeProjectMemberUpdateInput & {\n timeProjectId?: string\n}\n\nconst updateTimeProjectMemberCommand: CommandHandler<StaffTimeProjectMemberUpdateCommandInput, { timeProjectMemberId: string }> = {\n id: 'staff.timesheets.time_project_members.update',\n async prepare(rawInput, ctx) {\n const parsed = updateTimeProjectMemberCommandSchema.parse(rawInput)\n const em = ctx.container.resolve('em') as EntityManager\n const snapshot = await loadTimeProjectMemberSnapshot(em, parsed.id, staffSnapshotScopeFromContext(ctx))\n if (!snapshot) return {}\n return { before: snapshot }\n },\n async execute(rawInput, ctx) {\n const parsed = updateTimeProjectMemberCommandSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n const member = await findOneWithDecryption(\n em,\n StaffTimeProjectMember,\n applyScopeToWhere<StaffTimeProjectMember>(\n {\n id: parsed.id,\n deletedAt: null,\n ...(parsed.timeProjectId ? { timeProjectId: parsed.timeProjectId } : {}),\n },\n scope,\n ),\n undefined,\n scopeForDecryption(scope),\n )\n if (!member) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(404, {\n error: translate('staff.timesheets.errors.memberNotFound', 'Time project member not found or not accessible.'),\n })\n }\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n\n if (parsed.isAssigner === true && member.isAssigner !== true) {\n await requireAssignerUserAccount(em, member)\n }\n if (parsed.role !== undefined) member.role = parsed.role ?? null\n if (parsed.status !== undefined) member.status = parsed.status\n if (parsed.assignedEndDate !== undefined) member.assignedEndDate = parsed.assignedEndDate ?? null\n if (parsed.isAssigner !== undefined) member.isAssigner = parsed.isAssigner\n member.updatedAt = new Date()\n await em.flush()\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'updated',\n entity: member,\n identifiers: { id: member.id, organizationId: member.organizationId, tenantId: member.tenantId },\n events: staffTimeProjectMemberCrudEvents,\n indexer: timeProjectMemberCrudIndexer,\n })\n\n return { timeProjectMemberId: member.id }\n },\n buildLog: async ({ snapshots, ctx }) => {\n const before = snapshots.before as TimeProjectMemberSnapshot | undefined\n if (!before) return null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const after = await loadTimeProjectMemberSnapshot(em, before.id, staffSnapshotScopeFromSnapshot(before))\n if (!after) return null\n const changes = buildChanges(before as unknown as Record<string, unknown>, after as unknown as Record<string, unknown>, [\n 'role',\n 'status',\n 'assignedEndDate',\n 'isAssigner',\n ])\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_project_members.update', 'Update time project member'),\n resourceKind: 'staff.timesheets.time_project_member',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes,\n payload: {\n undo: {\n before,\n after,\n } satisfies TimeProjectMemberUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeProjectMemberUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await em.findOne(StaffTimeProjectMember, scopedStaffSnapshotWhere(before.id, staffSnapshotScopeFromSnapshot(before)))\n if (!member) return\n // Restores exactly what this command can change; the assignment window's\n // start and the row's identity belong to assign/unassign.\n member.role = before.role ?? null\n member.status = (before.status ?? 'active') as StaffTimeProjectMemberStatus\n member.assignedEndDate = before.assignedEndDate ? new Date(before.assignedEndDate) : null\n member.isAssigner = before.isAssigner === true\n member.updatedAt = new Date()\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'updated',\n entity: member,\n identifiers: { id: member.id, organizationId: member.organizationId, tenantId: member.tenantId },\n events: staffTimeProjectMemberCrudEvents,\n indexer: timeProjectMemberCrudIndexer,\n })\n },\n}\n\nconst unassignTimeProjectMemberCommand: CommandHandler<{ id?: string }, { timeProjectMemberId: string }> = {\n id: 'staff.timesheets.time_project_members.unassign',\n async prepare(input, ctx) {\n const id = input?.id\n if (!id) throw new CrudHttpError(400, { error: 'Time project member id is required.' })\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadTimeProjectMemberSnapshot(em, id, staffSnapshotScopeFromContext(ctx))\n if (!snapshot) return {}\n return { before: snapshot }\n },\n async execute(input, ctx) {\n const id = input?.id\n if (!id) throw new CrudHttpError(400, { error: 'Time project member id is required.' })\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n const member = await findOneWithDecryption(\n em,\n StaffTimeProjectMember,\n applyScopeToWhere<StaffTimeProjectMember>({ id, deletedAt: null }, scope),\n undefined,\n scopeForDecryption(scope),\n )\n if (!member) throw new CrudHttpError(404, { error: 'Time project member not found.' })\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n\n member.deletedAt = new Date()\n member.updatedAt = new Date()\n await em.flush()\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'deleted',\n entity: member,\n identifiers: { id: member.id, organizationId: member.organizationId, tenantId: member.tenantId },\n events: staffTimeProjectMemberCrudEvents,\n indexer: timeProjectMemberCrudIndexer,\n })\n\n return { timeProjectMemberId: member.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as TimeProjectMemberSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_project_members.unassign', 'Unassign time project member'),\n resourceKind: 'staff.timesheets.time_project_member',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: {\n before,\n } satisfies TimeProjectMemberUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeProjectMemberUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let member = await em.findOne(StaffTimeProjectMember, scopedStaffSnapshotWhere(before.id, staffSnapshotScopeFromSnapshot(before)))\n if (!member) {\n member = em.create(StaffTimeProjectMember, {\n id: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n timeProjectId: before.timeProjectId,\n staffMemberId: before.staffMemberId,\n role: before.role ?? null,\n status: (before.status ?? 'active') as StaffTimeProjectMemberStatus,\n showInGrid: before.showInGrid ?? false,\n assignedStartDate: new Date(before.assignedStartDate),\n assignedEndDate: before.assignedEndDate ? new Date(before.assignedEndDate) : null,\n deletedAt: null,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(member)\n } else {\n member.timeProjectId = before.timeProjectId\n member.staffMemberId = before.staffMemberId\n member.role = before.role ?? null\n member.status = (before.status ?? 'active') as StaffTimeProjectMemberStatus\n member.assignedStartDate = new Date(before.assignedStartDate)\n member.assignedEndDate = before.assignedEndDate ? new Date(before.assignedEndDate) : null\n member.deletedAt = null\n member.updatedAt = new Date()\n }\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'created',\n entity: member,\n identifiers: { id: member.id, organizationId: member.organizationId, tenantId: member.tenantId },\n events: staffTimeProjectMemberCrudEvents,\n indexer: timeProjectMemberCrudIndexer,\n })\n },\n}\n\nregisterCommand(createTimeProjectCommand)\nregisterCommand(updateTimeProjectCommand)\nregisterCommand(deleteTimeProjectCommand)\nregisterCommand(changeTimeProjectCurrencyCommand)\nregisterCommand(assignTimeProjectMemberCommand)\nregisterCommand(updateTimeProjectMemberCommand)\nregisterCommand(unassignTimeProjectMemberCommand)\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }