@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
@@ -0,0 +1,42 @@
1
+ import { Migration } from "@mikro-orm/migrations";
2
+ import { buildEncryptionMapBackfillSql } from "@open-mercato/shared/lib/encryption/migration-backfill";
3
+ class Migration20261009180543_staff extends Migration {
4
+ constructor() {
5
+ super(...arguments);
6
+ this.name = "Migration20261009180543";
7
+ }
8
+ up() {
9
+ this.addSql(`create table "staff_support_routing_rules" ("id" uuid not null default gen_random_uuid(), "tenant_id" uuid not null, "organization_id" uuid not null, "category_value" text null, "time_project_id" uuid not null, "is_active" boolean not null default true, "created_at" timestamptz not null, "updated_at" timestamptz not null, "deleted_at" timestamptz null, primary key ("id"));`);
10
+ this.addSql(`create index "staff_support_routing_rules_tenant_org_idx" on "staff_support_routing_rules" ("tenant_id", "organization_id");`);
11
+ this.addSql(`create unique index "staff_support_routing_rules_category_unique_idx" on "staff_support_routing_rules" ("tenant_id", "organization_id", coalesce("category_value", '')) where "deleted_at" is null;`);
12
+ this.addSql(`create table "staff_support_tickets" ("id" uuid not null default gen_random_uuid(), "tenant_id" uuid not null, "organization_id" uuid not null, "task_id" uuid not null, "customer_snapshot" jsonb null, "reported_by_customer_user_id" uuid null, "support_reference" text not null, "support_sequence_number" int not null, "category_value" text not null, "category_snapshot" jsonb not null, "routed_via" text not null, "customer_request_snapshot" jsonb not null, "unnotified_at" timestamptz null, "portal_status_published" text null, "created_at" timestamptz not null, "updated_at" timestamptz not null, "deleted_at" timestamptz null, primary key ("id"));`);
13
+ this.addSql(`create unique index "staff_support_tickets_reference_unique_idx" on "staff_support_tickets" ("tenant_id", "organization_id", "support_reference") where "deleted_at" is null;`);
14
+ this.addSql(`create index "staff_support_tickets_sequence_idx" on "staff_support_tickets" ("tenant_id", "organization_id", "support_sequence_number");`);
15
+ this.addSql(`create unique index "staff_support_tickets_task_unique_idx" on "staff_support_tickets" ("tenant_id", "organization_id", "task_id") where "deleted_at" is null;`);
16
+ this.addSql(`create index "staff_support_tickets_tenant_org_idx" on "staff_support_tickets" ("tenant_id", "organization_id");`);
17
+ this.addSql(`alter table "staff_time_projects" add "default_assignee_staff_member_id" uuid null;`);
18
+ this.addSql(`alter table "staff_time_project_members" add "is_assigner" boolean not null default false;`);
19
+ this.addSql(`create index "staff_time_project_members_assigner_idx" on "staff_time_project_members" ("tenant_id", "organization_id", "time_project_id") where "is_assigner" = true and "status" = 'active' and "deleted_at" is null;`);
20
+ this.addSql(`alter table "staff_time_tasks" add "source" text not null default 'internal', add "customer_id" uuid null;`);
21
+ this.addSql(`create index "staff_time_tasks_portal_customer_idx" on "staff_time_tasks" ("tenant_id", "organization_id", "customer_id", "updated_at") where "source" = 'portal' and "deleted_at" is null;`);
22
+ this.addSql(`alter table "staff_time_task_comments" add "visibility" text not null default 'internal', add "author_kind" text not null default 'staff', add "author_customer_user_id" uuid null, add "author_display_snapshot" jsonb null;`);
23
+ this.addSql(buildEncryptionMapBackfillSql({
24
+ entityId: "staff:staff_support_ticket",
25
+ fields: [{ field: "customer_request_snapshot" }]
26
+ }));
27
+ }
28
+ down() {
29
+ this.addSql(`drop table if exists "staff_support_tickets";`);
30
+ this.addSql(`drop table if exists "staff_support_routing_rules";`);
31
+ this.addSql(`drop index "staff_time_project_members_assigner_idx";`);
32
+ this.addSql(`alter table "staff_time_project_members" drop column "is_assigner";`);
33
+ this.addSql(`alter table "staff_time_projects" drop column "default_assignee_staff_member_id";`);
34
+ this.addSql(`alter table "staff_time_task_comments" drop column "visibility", drop column "author_kind", drop column "author_customer_user_id", drop column "author_display_snapshot";`);
35
+ this.addSql(`drop index "staff_time_tasks_portal_customer_idx";`);
36
+ this.addSql(`alter table "staff_time_tasks" drop column "source", drop column "customer_id";`);
37
+ }
38
+ }
39
+ export {
40
+ Migration20261009180543_staff
41
+ };
42
+ //# sourceMappingURL=Migration20261009180543_staff.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/staff/migrations/Migration20261009180543_staff.ts"],
4
+ "sourcesContent": ["import { Migration } from '@mikro-orm/migrations';\nimport { buildEncryptionMapBackfillSql } from '@open-mercato/shared/lib/encryption/migration-backfill';\n\nexport class Migration20261009180543_staff extends Migration {\n\n override name = 'Migration20261009180543';\n\n override up(): void | Promise<void> {\n this.addSql(`create table \"staff_support_routing_rules\" (\"id\" uuid not null default gen_random_uuid(), \"tenant_id\" uuid not null, \"organization_id\" uuid not null, \"category_value\" text null, \"time_project_id\" uuid not null, \"is_active\" boolean not null default true, \"created_at\" timestamptz not null, \"updated_at\" timestamptz not null, \"deleted_at\" timestamptz null, primary key (\"id\"));`);\n this.addSql(`create index \"staff_support_routing_rules_tenant_org_idx\" on \"staff_support_routing_rules\" (\"tenant_id\", \"organization_id\");`);\n this.addSql(`create unique index \"staff_support_routing_rules_category_unique_idx\" on \"staff_support_routing_rules\" (\"tenant_id\", \"organization_id\", coalesce(\"category_value\", '')) where \"deleted_at\" is null;`);\n\n this.addSql(`create table \"staff_support_tickets\" (\"id\" uuid not null default gen_random_uuid(), \"tenant_id\" uuid not null, \"organization_id\" uuid not null, \"task_id\" uuid not null, \"customer_snapshot\" jsonb null, \"reported_by_customer_user_id\" uuid null, \"support_reference\" text not null, \"support_sequence_number\" int not null, \"category_value\" text not null, \"category_snapshot\" jsonb not null, \"routed_via\" text not null, \"customer_request_snapshot\" jsonb not null, \"unnotified_at\" timestamptz null, \"portal_status_published\" text null, \"created_at\" timestamptz not null, \"updated_at\" timestamptz not null, \"deleted_at\" timestamptz null, primary key (\"id\"));`);\n this.addSql(`create unique index \"staff_support_tickets_reference_unique_idx\" on \"staff_support_tickets\" (\"tenant_id\", \"organization_id\", \"support_reference\") where \"deleted_at\" is null;`);\n this.addSql(`create index \"staff_support_tickets_sequence_idx\" on \"staff_support_tickets\" (\"tenant_id\", \"organization_id\", \"support_sequence_number\");`);\n this.addSql(`create unique index \"staff_support_tickets_task_unique_idx\" on \"staff_support_tickets\" (\"tenant_id\", \"organization_id\", \"task_id\") where \"deleted_at\" is null;`);\n this.addSql(`create index \"staff_support_tickets_tenant_org_idx\" on \"staff_support_tickets\" (\"tenant_id\", \"organization_id\");`);\n\n this.addSql(`alter table \"staff_time_projects\" add \"default_assignee_staff_member_id\" uuid null;`);\n\n this.addSql(`alter table \"staff_time_project_members\" add \"is_assigner\" boolean not null default false;`);\n this.addSql(`create index \"staff_time_project_members_assigner_idx\" on \"staff_time_project_members\" (\"tenant_id\", \"organization_id\", \"time_project_id\") where \"is_assigner\" = true and \"status\" = 'active' and \"deleted_at\" is null;`);\n\n this.addSql(`alter table \"staff_time_tasks\" add \"source\" text not null default 'internal', add \"customer_id\" uuid null;`);\n this.addSql(`create index \"staff_time_tasks_portal_customer_idx\" on \"staff_time_tasks\" (\"tenant_id\", \"organization_id\", \"customer_id\", \"updated_at\") where \"source\" = 'portal' and \"deleted_at\" is null;`);\n\n this.addSql(`alter table \"staff_time_task_comments\" add \"visibility\" text not null default 'internal', add \"author_kind\" text not null default 'staff', add \"author_customer_user_id\" uuid null, add \"author_display_snapshot\" jsonb null;`);\n\n this.addSql(buildEncryptionMapBackfillSql({\n entityId: 'staff:staff_support_ticket',\n fields: [{ field: 'customer_request_snapshot' }],\n }));\n }\n\n override down(): void | Promise<void> {\n this.addSql(`drop table if exists \"staff_support_tickets\";`);\n this.addSql(`drop table if exists \"staff_support_routing_rules\";`);\n\n this.addSql(`drop index \"staff_time_project_members_assigner_idx\";`);\n this.addSql(`alter table \"staff_time_project_members\" drop column \"is_assigner\";`);\n\n this.addSql(`alter table \"staff_time_projects\" drop column \"default_assignee_staff_member_id\";`);\n\n this.addSql(`alter table \"staff_time_task_comments\" drop column \"visibility\", drop column \"author_kind\", drop column \"author_customer_user_id\", drop column \"author_display_snapshot\";`);\n\n this.addSql(`drop index \"staff_time_tasks_portal_customer_idx\";`);\n this.addSql(`alter table \"staff_time_tasks\" drop column \"source\", drop column \"customer_id\";`);\n }\n\n}\n"],
5
+ "mappings": "AAAA,SAAS,iBAAiB;AAC1B,SAAS,qCAAqC;AAEvC,MAAM,sCAAsC,UAAU;AAAA,EAAtD;AAAA;AAEL,SAAS,OAAO;AAAA;AAAA,EAEP,KAA2B;AAClC,SAAK,OAAO,yXAAyX;AACrY,SAAK,OAAO,8HAA8H;AAC1I,SAAK,OAAO,qMAAqM;AAEjN,SAAK,OAAO,4oBAA4oB;AACxpB,SAAK,OAAO,+KAA+K;AAC3L,SAAK,OAAO,2IAA2I;AACvJ,SAAK,OAAO,gKAAgK;AAC5K,SAAK,OAAO,kHAAkH;AAE9H,SAAK,OAAO,qFAAqF;AAEjG,SAAK,OAAO,4FAA4F;AACxG,SAAK,OAAO,yNAAyN;AAErO,SAAK,OAAO,4GAA4G;AACxH,SAAK,OAAO,6LAA6L;AAEzM,SAAK,OAAO,+NAA+N;AAE3O,SAAK,OAAO,8BAA8B;AAAA,MACxC,UAAU;AAAA,MACV,QAAQ,CAAC,EAAE,OAAO,4BAA4B,CAAC;AAAA,IACjD,CAAC,CAAC;AAAA,EACJ;AAAA,EAES,OAA6B;AACpC,SAAK,OAAO,+CAA+C;AAC3D,SAAK,OAAO,qDAAqD;AAEjE,SAAK,OAAO,uDAAuD;AACnE,SAAK,OAAO,qEAAqE;AAEjF,SAAK,OAAO,mFAAmF;AAE/F,SAAK,OAAO,2KAA2K;AAEvL,SAAK,OAAO,oDAAoD;AAChE,SAAK,OAAO,iFAAiF;AAAA,EAC/F;AAEF;",
6
+ "names": []
7
+ }
@@ -239,6 +239,98 @@ const notificationTypes = [
239
239
  linkHref: "/backend/staff/time-tracking/timesheet",
240
240
  expiresAfterHours: 168
241
241
  // 7 days
242
+ },
243
+ {
244
+ // Customer support tickets: raised for every portal ticket. The audience is the
245
+ // assignee (when the project default applied) plus the project's active
246
+ // assigners, falling back through owner and organization project managers.
247
+ type: "staff.support_ticket.created",
248
+ channels: ["in_app", "email"],
249
+ module: "staff",
250
+ titleKey: "staff.notifications.supportTicket.created.title",
251
+ bodyKey: "staff.notifications.supportTicket.created.body",
252
+ icon: "life-buoy",
253
+ severity: "info",
254
+ actions: [
255
+ {
256
+ id: "open-ticket",
257
+ labelKey: "staff.notifications.supportTicket.actions.open",
258
+ variant: "default",
259
+ icon: "external-link",
260
+ href: "/backend/staff/time-tracking/support?task={sourceEntityId}"
261
+ }
262
+ ],
263
+ primaryActionId: "open-ticket",
264
+ linkHref: "/backend/staff/time-tracking/support?task={sourceEntityId}",
265
+ expiresAfterHours: 336
266
+ },
267
+ {
268
+ type: "staff.support_ticket.customer_replied",
269
+ channels: ["in_app", "email"],
270
+ module: "staff",
271
+ titleKey: "staff.notifications.supportTicket.customerReplied.title",
272
+ bodyKey: "staff.notifications.supportTicket.customerReplied.body",
273
+ icon: "message-square",
274
+ severity: "info",
275
+ actions: [
276
+ {
277
+ id: "open-ticket",
278
+ labelKey: "staff.notifications.supportTicket.actions.open",
279
+ variant: "default",
280
+ icon: "external-link",
281
+ href: "/backend/staff/time-tracking/support?task={sourceEntityId}"
282
+ }
283
+ ],
284
+ primaryActionId: "open-ticket",
285
+ linkHref: "/backend/staff/time-tracking/support?task={sourceEntityId}",
286
+ expiresAfterHours: 336
287
+ },
288
+ {
289
+ // A task in the project became unassigned (released or cleared): tells the
290
+ // project's assigners there is claimable work.
291
+ type: "staff.timesheets.time_task.released",
292
+ channels: ["in_app"],
293
+ module: "staff",
294
+ titleKey: "staff.notifications.timeTask.released.title",
295
+ bodyKey: "staff.notifications.timeTask.released.body",
296
+ icon: "hand",
297
+ severity: "info",
298
+ actions: [
299
+ {
300
+ id: "open-task",
301
+ labelKey: "staff.notifications.timeTask.actions.open",
302
+ variant: "default",
303
+ icon: "external-link",
304
+ href: "/backend/staff/time-tracking/board?task={sourceEntityId}"
305
+ }
306
+ ],
307
+ primaryActionId: "open-task",
308
+ linkHref: "/backend/staff/time-tracking/board?task={sourceEntityId}",
309
+ expiresAfterHours: 168
310
+ },
311
+ {
312
+ // Someone else assigned the recipient to a task through the task editor. Not sent
313
+ // for claims (self-assignment) or for the portal default assignee, who hears
314
+ // about the intake once through `staff.support_ticket.created`.
315
+ type: "staff.timesheets.time_task.assigned",
316
+ channels: ["in_app"],
317
+ module: "staff",
318
+ titleKey: "staff.notifications.timeTask.assigned.title",
319
+ bodyKey: "staff.notifications.timeTask.assigned.body",
320
+ icon: "user-check",
321
+ severity: "info",
322
+ actions: [
323
+ {
324
+ id: "open-task",
325
+ labelKey: "staff.notifications.timeTask.actions.open",
326
+ variant: "default",
327
+ icon: "external-link",
328
+ href: "/backend/staff/time-tracking/board?task={sourceEntityId}"
329
+ }
330
+ ],
331
+ primaryActionId: "open-task",
332
+ linkHref: "/backend/staff/time-tracking/board?task={sourceEntityId}",
333
+ expiresAfterHours: 168
242
334
  }
243
335
  ];
244
336
  var notifications_default = notificationTypes;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/modules/staff/notifications.ts"],
4
- "sourcesContent": ["import type { NotificationTypeDefinition } from '@open-mercato/shared/modules/notifications/types'\n\nexport const notificationTypes: NotificationTypeDefinition[] = [\n {\n type: 'staff.leave_request.pending',\n // Ships without push \u2014 operators re-enable it per type from the Notification Delivery settings.\n channels: ['in_app', 'email'],\n module: 'staff',\n titleKey: 'staff.notifications.leaveRequest.pending.title',\n bodyKey: 'staff.notifications.leaveRequest.pending.body',\n icon: 'calendar-off',\n severity: 'warning',\n actions: [\n {\n id: 'approve',\n labelKey: 'staff.notifications.leaveRequest.actions.approve',\n variant: 'default',\n icon: 'check',\n commandId: 'staff.leave-requests.accept',\n },\n {\n id: 'reject',\n labelKey: 'staff.notifications.leaveRequest.actions.reject',\n variant: 'destructive',\n icon: 'x',\n commandId: 'staff.leave-requests.reject',\n },\n ],\n primaryActionId: 'approve',\n linkHref: '/backend/staff/leave-requests/{sourceEntityId}',\n expiresAfterHours: 168,\n },\n {\n type: 'staff.leave_request.approved',\n // Ships without push \u2014 operators re-enable it per type from the Notification Delivery settings.\n channels: ['in_app', 'email'],\n module: 'staff',\n titleKey: 'staff.notifications.leaveRequest.approved.title',\n bodyKey: 'staff.notifications.leaveRequest.approved.body',\n icon: 'calendar-check',\n severity: 'success',\n actions: [\n {\n id: 'view',\n labelKey: 'common.view',\n variant: 'outline',\n href: '/backend/staff/leave-requests/{sourceEntityId}',\n icon: 'external-link',\n },\n ],\n linkHref: '/backend/staff/leave-requests/{sourceEntityId}',\n expiresAfterHours: 168, // 7 days\n },\n {\n type: 'staff.leave_request.rejected',\n // Ships without push \u2014 operators re-enable it per type from the Notification Delivery settings.\n channels: ['in_app', 'email'],\n module: 'staff',\n titleKey: 'staff.notifications.leaveRequest.rejected.title',\n bodyKey: 'staff.notifications.leaveRequest.rejected.body',\n icon: 'calendar-x',\n severity: 'warning',\n actions: [\n {\n id: 'view',\n labelKey: 'common.view',\n variant: 'outline',\n href: '/backend/staff/leave-requests/{sourceEntityId}',\n icon: 'external-link',\n },\n ],\n linkHref: '/backend/staff/leave-requests/{sourceEntityId}',\n expiresAfterHours: 168, // 7 days\n },\n {\n // Spec D-6: the \"Request access\" button on screens 2 and 17 raises a real\n // notification for every `staff.timesheets.projects.manage` holder. The\n // subscriber overrides `linkHref` with the requester-specific deep link so\n // the project team drawer opens with the requester pre-selected.\n type: 'staff.timesheets.project_access.requested',\n channels: ['in_app', 'email'],\n module: 'staff',\n titleKey: 'staff.notifications.timeProjectAccess.requested.title',\n bodyKey: 'staff.notifications.timeProjectAccess.requested.body',\n icon: 'user-plus',\n severity: 'info',\n actions: [\n {\n id: 'open-team',\n labelKey: 'staff.notifications.timeProjectAccess.actions.openTeam',\n variant: 'default',\n icon: 'users',\n href: '/backend/staff/time-tracking/projects/{sourceEntityId}?panel=team',\n },\n ],\n primaryActionId: 'open-team',\n linkHref: '/backend/staff/time-tracking/projects',\n expiresAfterHours: 168, // 7 days\n },\n {\n // Screen 4 budget card: \"Ostrzezenie przy 80% i 100% wykorzystania\". One type\n // covers both thresholds \u2014 the subscriber raises the severity to `error` for the\n // 100% crossing and carries the numbers in `bodyVariables`, so the two alerts\n // read differently without splitting the notification id.\n type: 'staff.timesheets.time_project.budget_threshold_reached',\n channels: ['in_app', 'email'],\n module: 'staff',\n titleKey: 'staff.notifications.timeProjectBudget.thresholdReached.title',\n bodyKey: 'staff.notifications.timeProjectBudget.thresholdReached.body',\n icon: 'gauge',\n severity: 'warning',\n actions: [\n {\n id: 'open-project',\n labelKey: 'staff.notifications.timeProjectBudget.actions.openProject',\n variant: 'default',\n icon: 'external-link',\n href: '/backend/staff/time-tracking/projects/{sourceEntityId}',\n },\n ],\n primaryActionId: 'open-project',\n linkHref: '/backend/staff/time-tracking/projects/{sourceEntityId}',\n expiresAfterHours: 168, // 7 days\n },\n {\n /**\n * EP-48. Raised by `subscribers/time-report-approved-notification.ts` when a\n * report is closed \u2014 closing IS the approval in this module: it freezes every\n * per-entry value and locks the entries, and `staff.timesheets.lock` is the\n * feature that gates it. The recipient is the person who drafted the report,\n * who otherwise learns about it only by reopening the screen.\n */\n type: 'staff.timesheets.time_report.approved',\n channels: ['in_app', 'email'],\n module: 'staff',\n titleKey: 'staff.notifications.timeReport.approved.title',\n bodyKey: 'staff.notifications.timeReport.approved.body',\n icon: 'file-check',\n severity: 'success',\n actions: [\n {\n id: 'open-report',\n labelKey: 'staff.notifications.timeReport.actions.openReport',\n variant: 'default',\n icon: 'external-link',\n href: '/backend/staff/time-tracking/reports/{sourceEntityId}',\n },\n ],\n primaryActionId: 'open-report',\n linkHref: '/backend/staff/time-tracking/reports/{sourceEntityId}',\n expiresAfterHours: 168, // 7 days\n },\n {\n /**\n * EP-48, contributable-only by design. The module has exactly one report\n * transition \u2014 draft \u2192 closed \u2014 so there is no \"submitted, awaiting a second\n * pair of eyes\" state for core to announce. This id exists so the multi-step\n * approval a `registerReportApprovalPolicy` contribution (EP-41) implements\n * has a published notification to raise instead of inventing its own, and so\n * the renderer and delivery preferences are already in place when it does.\n */\n type: 'staff.timesheets.time_report.ready_for_approval',\n channels: ['in_app', 'email'],\n module: 'staff',\n titleKey: 'staff.notifications.timeReport.readyForApproval.title',\n bodyKey: 'staff.notifications.timeReport.readyForApproval.body',\n icon: 'file-clock',\n severity: 'info',\n actions: [\n {\n id: 'review-report',\n labelKey: 'staff.notifications.timeReport.actions.reviewReport',\n variant: 'default',\n icon: 'external-link',\n href: '/backend/staff/time-tracking/reports/{sourceEntityId}',\n },\n ],\n primaryActionId: 'review-report',\n linkHref: '/backend/staff/time-tracking/reports/{sourceEntityId}',\n expiresAfterHours: 168, // 7 days\n },\n {\n /**\n * EP-48, contributable-only by design. \"This timer has been running for six\n * hours\" needs something that wakes up on a schedule and looks at open\n * timers; the module ships no periodic job and inventing one to justify an id\n * would be the tail wagging the dog. The id is the contract for a module that\n * does ship one.\n */\n type: 'staff.timesheets.time_entry.timer_running_long',\n channels: ['in_app'],\n module: 'staff',\n titleKey: 'staff.notifications.timeEntryTimer.runningLong.title',\n bodyKey: 'staff.notifications.timeEntryTimer.runningLong.body',\n icon: 'timer',\n severity: 'warning',\n actions: [\n {\n id: 'open-timesheet',\n labelKey: 'staff.notifications.timesheet.actions.openTimesheet',\n variant: 'default',\n icon: 'external-link',\n href: '/backend/staff/time-tracking/timesheet',\n },\n ],\n primaryActionId: 'open-timesheet',\n linkHref: '/backend/staff/time-tracking/timesheet',\n expiresAfterHours: 24,\n },\n {\n /**\n * EP-48, contributable-only by design. Whether a period is \"incomplete\" is\n * the capacity provider's question (EP-40), and the built-in provider spreads\n * one flat daily number over the caller's working days on demand \u2014 it has no\n * schedule and no opinion about when to complain. A contributed provider that\n * knows contract hours and leave is the thing that can raise this honestly.\n */\n type: 'staff.timesheets.timesheet.period_incomplete',\n channels: ['in_app', 'email'],\n module: 'staff',\n titleKey: 'staff.notifications.timesheet.periodIncomplete.title',\n bodyKey: 'staff.notifications.timesheet.periodIncomplete.body',\n icon: 'calendar-clock',\n severity: 'warning',\n actions: [\n {\n id: 'open-timesheet',\n labelKey: 'staff.notifications.timesheet.actions.openTimesheet',\n variant: 'default',\n icon: 'external-link',\n href: '/backend/staff/time-tracking/timesheet',\n },\n ],\n primaryActionId: 'open-timesheet',\n linkHref: '/backend/staff/time-tracking/timesheet',\n expiresAfterHours: 168, // 7 days\n },\n]\n\nexport default notificationTypes\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { NotificationTypeDefinition } from '@open-mercato/shared/modules/notifications/types'\n\nexport const notificationTypes: NotificationTypeDefinition[] = [\n {\n type: 'staff.leave_request.pending',\n // Ships without push \u2014 operators re-enable it per type from the Notification Delivery settings.\n channels: ['in_app', 'email'],\n module: 'staff',\n titleKey: 'staff.notifications.leaveRequest.pending.title',\n bodyKey: 'staff.notifications.leaveRequest.pending.body',\n icon: 'calendar-off',\n severity: 'warning',\n actions: [\n {\n id: 'approve',\n labelKey: 'staff.notifications.leaveRequest.actions.approve',\n variant: 'default',\n icon: 'check',\n commandId: 'staff.leave-requests.accept',\n },\n {\n id: 'reject',\n labelKey: 'staff.notifications.leaveRequest.actions.reject',\n variant: 'destructive',\n icon: 'x',\n commandId: 'staff.leave-requests.reject',\n },\n ],\n primaryActionId: 'approve',\n linkHref: '/backend/staff/leave-requests/{sourceEntityId}',\n expiresAfterHours: 168,\n },\n {\n type: 'staff.leave_request.approved',\n // Ships without push \u2014 operators re-enable it per type from the Notification Delivery settings.\n channels: ['in_app', 'email'],\n module: 'staff',\n titleKey: 'staff.notifications.leaveRequest.approved.title',\n bodyKey: 'staff.notifications.leaveRequest.approved.body',\n icon: 'calendar-check',\n severity: 'success',\n actions: [\n {\n id: 'view',\n labelKey: 'common.view',\n variant: 'outline',\n href: '/backend/staff/leave-requests/{sourceEntityId}',\n icon: 'external-link',\n },\n ],\n linkHref: '/backend/staff/leave-requests/{sourceEntityId}',\n expiresAfterHours: 168, // 7 days\n },\n {\n type: 'staff.leave_request.rejected',\n // Ships without push \u2014 operators re-enable it per type from the Notification Delivery settings.\n channels: ['in_app', 'email'],\n module: 'staff',\n titleKey: 'staff.notifications.leaveRequest.rejected.title',\n bodyKey: 'staff.notifications.leaveRequest.rejected.body',\n icon: 'calendar-x',\n severity: 'warning',\n actions: [\n {\n id: 'view',\n labelKey: 'common.view',\n variant: 'outline',\n href: '/backend/staff/leave-requests/{sourceEntityId}',\n icon: 'external-link',\n },\n ],\n linkHref: '/backend/staff/leave-requests/{sourceEntityId}',\n expiresAfterHours: 168, // 7 days\n },\n {\n // Spec D-6: the \"Request access\" button on screens 2 and 17 raises a real\n // notification for every `staff.timesheets.projects.manage` holder. The\n // subscriber overrides `linkHref` with the requester-specific deep link so\n // the project team drawer opens with the requester pre-selected.\n type: 'staff.timesheets.project_access.requested',\n channels: ['in_app', 'email'],\n module: 'staff',\n titleKey: 'staff.notifications.timeProjectAccess.requested.title',\n bodyKey: 'staff.notifications.timeProjectAccess.requested.body',\n icon: 'user-plus',\n severity: 'info',\n actions: [\n {\n id: 'open-team',\n labelKey: 'staff.notifications.timeProjectAccess.actions.openTeam',\n variant: 'default',\n icon: 'users',\n href: '/backend/staff/time-tracking/projects/{sourceEntityId}?panel=team',\n },\n ],\n primaryActionId: 'open-team',\n linkHref: '/backend/staff/time-tracking/projects',\n expiresAfterHours: 168, // 7 days\n },\n {\n // Screen 4 budget card: \"Ostrzezenie przy 80% i 100% wykorzystania\". One type\n // covers both thresholds \u2014 the subscriber raises the severity to `error` for the\n // 100% crossing and carries the numbers in `bodyVariables`, so the two alerts\n // read differently without splitting the notification id.\n type: 'staff.timesheets.time_project.budget_threshold_reached',\n channels: ['in_app', 'email'],\n module: 'staff',\n titleKey: 'staff.notifications.timeProjectBudget.thresholdReached.title',\n bodyKey: 'staff.notifications.timeProjectBudget.thresholdReached.body',\n icon: 'gauge',\n severity: 'warning',\n actions: [\n {\n id: 'open-project',\n labelKey: 'staff.notifications.timeProjectBudget.actions.openProject',\n variant: 'default',\n icon: 'external-link',\n href: '/backend/staff/time-tracking/projects/{sourceEntityId}',\n },\n ],\n primaryActionId: 'open-project',\n linkHref: '/backend/staff/time-tracking/projects/{sourceEntityId}',\n expiresAfterHours: 168, // 7 days\n },\n {\n /**\n * EP-48. Raised by `subscribers/time-report-approved-notification.ts` when a\n * report is closed \u2014 closing IS the approval in this module: it freezes every\n * per-entry value and locks the entries, and `staff.timesheets.lock` is the\n * feature that gates it. The recipient is the person who drafted the report,\n * who otherwise learns about it only by reopening the screen.\n */\n type: 'staff.timesheets.time_report.approved',\n channels: ['in_app', 'email'],\n module: 'staff',\n titleKey: 'staff.notifications.timeReport.approved.title',\n bodyKey: 'staff.notifications.timeReport.approved.body',\n icon: 'file-check',\n severity: 'success',\n actions: [\n {\n id: 'open-report',\n labelKey: 'staff.notifications.timeReport.actions.openReport',\n variant: 'default',\n icon: 'external-link',\n href: '/backend/staff/time-tracking/reports/{sourceEntityId}',\n },\n ],\n primaryActionId: 'open-report',\n linkHref: '/backend/staff/time-tracking/reports/{sourceEntityId}',\n expiresAfterHours: 168, // 7 days\n },\n {\n /**\n * EP-48, contributable-only by design. The module has exactly one report\n * transition \u2014 draft \u2192 closed \u2014 so there is no \"submitted, awaiting a second\n * pair of eyes\" state for core to announce. This id exists so the multi-step\n * approval a `registerReportApprovalPolicy` contribution (EP-41) implements\n * has a published notification to raise instead of inventing its own, and so\n * the renderer and delivery preferences are already in place when it does.\n */\n type: 'staff.timesheets.time_report.ready_for_approval',\n channels: ['in_app', 'email'],\n module: 'staff',\n titleKey: 'staff.notifications.timeReport.readyForApproval.title',\n bodyKey: 'staff.notifications.timeReport.readyForApproval.body',\n icon: 'file-clock',\n severity: 'info',\n actions: [\n {\n id: 'review-report',\n labelKey: 'staff.notifications.timeReport.actions.reviewReport',\n variant: 'default',\n icon: 'external-link',\n href: '/backend/staff/time-tracking/reports/{sourceEntityId}',\n },\n ],\n primaryActionId: 'review-report',\n linkHref: '/backend/staff/time-tracking/reports/{sourceEntityId}',\n expiresAfterHours: 168, // 7 days\n },\n {\n /**\n * EP-48, contributable-only by design. \"This timer has been running for six\n * hours\" needs something that wakes up on a schedule and looks at open\n * timers; the module ships no periodic job and inventing one to justify an id\n * would be the tail wagging the dog. The id is the contract for a module that\n * does ship one.\n */\n type: 'staff.timesheets.time_entry.timer_running_long',\n channels: ['in_app'],\n module: 'staff',\n titleKey: 'staff.notifications.timeEntryTimer.runningLong.title',\n bodyKey: 'staff.notifications.timeEntryTimer.runningLong.body',\n icon: 'timer',\n severity: 'warning',\n actions: [\n {\n id: 'open-timesheet',\n labelKey: 'staff.notifications.timesheet.actions.openTimesheet',\n variant: 'default',\n icon: 'external-link',\n href: '/backend/staff/time-tracking/timesheet',\n },\n ],\n primaryActionId: 'open-timesheet',\n linkHref: '/backend/staff/time-tracking/timesheet',\n expiresAfterHours: 24,\n },\n {\n /**\n * EP-48, contributable-only by design. Whether a period is \"incomplete\" is\n * the capacity provider's question (EP-40), and the built-in provider spreads\n * one flat daily number over the caller's working days on demand \u2014 it has no\n * schedule and no opinion about when to complain. A contributed provider that\n * knows contract hours and leave is the thing that can raise this honestly.\n */\n type: 'staff.timesheets.timesheet.period_incomplete',\n channels: ['in_app', 'email'],\n module: 'staff',\n titleKey: 'staff.notifications.timesheet.periodIncomplete.title',\n bodyKey: 'staff.notifications.timesheet.periodIncomplete.body',\n icon: 'calendar-clock',\n severity: 'warning',\n actions: [\n {\n id: 'open-timesheet',\n labelKey: 'staff.notifications.timesheet.actions.openTimesheet',\n variant: 'default',\n icon: 'external-link',\n href: '/backend/staff/time-tracking/timesheet',\n },\n ],\n primaryActionId: 'open-timesheet',\n linkHref: '/backend/staff/time-tracking/timesheet',\n expiresAfterHours: 168, // 7 days\n },\n {\n // Customer support tickets: raised for every portal ticket. The audience is the\n // assignee (when the project default applied) plus the project's active\n // assigners, falling back through owner and organization project managers.\n type: 'staff.support_ticket.created',\n channels: ['in_app', 'email'],\n module: 'staff',\n titleKey: 'staff.notifications.supportTicket.created.title',\n bodyKey: 'staff.notifications.supportTicket.created.body',\n icon: 'life-buoy',\n severity: 'info',\n actions: [\n {\n id: 'open-ticket',\n labelKey: 'staff.notifications.supportTicket.actions.open',\n variant: 'default',\n icon: 'external-link',\n href: '/backend/staff/time-tracking/support?task={sourceEntityId}',\n },\n ],\n primaryActionId: 'open-ticket',\n linkHref: '/backend/staff/time-tracking/support?task={sourceEntityId}',\n expiresAfterHours: 336,\n },\n {\n type: 'staff.support_ticket.customer_replied',\n channels: ['in_app', 'email'],\n module: 'staff',\n titleKey: 'staff.notifications.supportTicket.customerReplied.title',\n bodyKey: 'staff.notifications.supportTicket.customerReplied.body',\n icon: 'message-square',\n severity: 'info',\n actions: [\n {\n id: 'open-ticket',\n labelKey: 'staff.notifications.supportTicket.actions.open',\n variant: 'default',\n icon: 'external-link',\n href: '/backend/staff/time-tracking/support?task={sourceEntityId}',\n },\n ],\n primaryActionId: 'open-ticket',\n linkHref: '/backend/staff/time-tracking/support?task={sourceEntityId}',\n expiresAfterHours: 336,\n },\n {\n // A task in the project became unassigned (released or cleared): tells the\n // project's assigners there is claimable work.\n type: 'staff.timesheets.time_task.released',\n channels: ['in_app'],\n module: 'staff',\n titleKey: 'staff.notifications.timeTask.released.title',\n bodyKey: 'staff.notifications.timeTask.released.body',\n icon: 'hand',\n severity: 'info',\n actions: [\n {\n id: 'open-task',\n labelKey: 'staff.notifications.timeTask.actions.open',\n variant: 'default',\n icon: 'external-link',\n href: '/backend/staff/time-tracking/board?task={sourceEntityId}',\n },\n ],\n primaryActionId: 'open-task',\n linkHref: '/backend/staff/time-tracking/board?task={sourceEntityId}',\n expiresAfterHours: 168,\n },\n {\n // Someone else assigned the recipient to a task through the task editor. Not sent\n // for claims (self-assignment) or for the portal default assignee, who hears\n // about the intake once through `staff.support_ticket.created`.\n type: 'staff.timesheets.time_task.assigned',\n channels: ['in_app'],\n module: 'staff',\n titleKey: 'staff.notifications.timeTask.assigned.title',\n bodyKey: 'staff.notifications.timeTask.assigned.body',\n icon: 'user-check',\n severity: 'info',\n actions: [\n {\n id: 'open-task',\n labelKey: 'staff.notifications.timeTask.actions.open',\n variant: 'default',\n icon: 'external-link',\n href: '/backend/staff/time-tracking/board?task={sourceEntityId}',\n },\n ],\n primaryActionId: 'open-task',\n linkHref: '/backend/staff/time-tracking/board?task={sourceEntityId}',\n expiresAfterHours: 168,\n },\n]\n\nexport default notificationTypes\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,6 +1,8 @@
1
1
  import { appendWidgetsToRoles } from "@open-mercato/core/modules/dashboards/lib/role-widgets";
2
2
  import { seedStaffAddressTypes, seedStaffTeamExamples } from "./lib/seeds.js";
3
3
  import { seedStaffTimeTrackingExamples } from "./lib/timeTrackingSeeds.js";
4
+ import { resolveContainerProjectCodeGenerator, seedSupportDefaults } from "./lib/support/seedDefaults.js";
5
+ import { resolveTranslations } from "@open-mercato/shared/lib/i18n/server";
4
6
  const TIMESHEETS_DASHBOARD_WIDGET_IDS = [
5
7
  "staff.timesheets.timeReporting",
6
8
  "staff.timesheets.hoursByProject"
@@ -9,6 +11,8 @@ const setup = {
9
11
  seedDefaults: async (ctx) => {
10
12
  const scope = { tenantId: ctx.tenantId, organizationId: ctx.organizationId };
11
13
  await seedStaffAddressTypes(ctx.em, scope);
14
+ const { translate } = await resolveTranslations();
15
+ await seedSupportDefaults(ctx.em, scope, { translate, generateCode: resolveContainerProjectCodeGenerator(ctx.container) });
12
16
  await appendWidgetsToRoles(ctx.em, {
13
17
  tenantId: ctx.tenantId,
14
18
  organizationId: ctx.organizationId,
@@ -48,8 +52,8 @@ const setup = {
48
52
  * `portal_admin` holds `portal.*` and needs no entry.
49
53
  */
50
54
  defaultCustomerRoleFeatures: {
51
- buyer: ["portal.time_reports.view"],
52
- viewer: ["portal.time_reports.view"]
55
+ buyer: ["portal.time_reports.view", "portal.support_tickets.view", "portal.support_tickets.manage"],
56
+ viewer: ["portal.time_reports.view", "portal.support_tickets.view"]
53
57
  }
54
58
  };
55
59
  var setup_default = setup;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/modules/staff/setup.ts"],
4
- "sourcesContent": ["import type { ModuleSetupConfig } from '@open-mercato/shared/modules/setup'\nimport { appendWidgetsToRoles } from '@open-mercato/core/modules/dashboards/lib/role-widgets'\nimport { seedStaffAddressTypes, seedStaffTeamExamples } from './lib/seeds'\nimport { seedStaffTimeTrackingExamples } from './lib/timeTrackingSeeds'\n\nconst TIMESHEETS_DASHBOARD_WIDGET_IDS = [\n 'staff.timesheets.timeReporting',\n 'staff.timesheets.hoursByProject',\n]\n\nexport const setup: ModuleSetupConfig = {\n seedDefaults: async (ctx) => {\n const scope = { tenantId: ctx.tenantId, organizationId: ctx.organizationId }\n await seedStaffAddressTypes(ctx.em, scope)\n await appendWidgetsToRoles(ctx.em, {\n tenantId: ctx.tenantId,\n organizationId: ctx.organizationId,\n roleNames: ['superadmin', 'admin', 'employee'],\n widgetIds: TIMESHEETS_DASHBOARD_WIDGET_IDS,\n })\n },\n\n seedExamples: async (ctx) => {\n const scope = { tenantId: ctx.tenantId, organizationId: ctx.organizationId }\n await seedStaffTeamExamples(ctx.em, scope)\n // Runs after the team examples because every project it staffs, every task it\n // assigns and every hour it logs points at a staff member those seeds create.\n await seedStaffTimeTrackingExamples(ctx.em, scope)\n },\n\n defaultRoleFeatures: {\n admin: ['staff.*', 'staff.leave_requests.manage'],\n employee: [\n 'staff.leave_requests.send',\n 'staff.my_availability.view',\n 'staff.my_availability.manage',\n 'staff.my_leave_requests.view',\n 'staff.my_leave_requests.send',\n 'staff.timesheets.view',\n 'staff.timesheets.manage_own',\n 'staff.timesheets.projects.view',\n 'staff.timesheets.tasks.view',\n 'staff.timesheets.tasks.manage',\n 'staff.timesheets.rates.view',\n ],\n },\n\n /**\n * EP-50. `portal.time_reports.view` is a **customer** feature, granted through\n * `CustomerRoleAcl`, and it is deliberately absent from `acl.ts` \u2014 that file is\n * the staff feature catalog and the two namespaces are graded by different RBAC\n * services.\n *\n * `viewer` gets it as well as `buyer`: reading the hours already delivered is a\n * read, and a client who may see their invoices may see what they paid for.\n * `portal_admin` holds `portal.*` and needs no entry.\n */\n defaultCustomerRoleFeatures: {\n buyer: ['portal.time_reports.view'],\n viewer: ['portal.time_reports.view'],\n },\n}\n\nexport default setup\n"],
5
- "mappings": "AACA,SAAS,4BAA4B;AACrC,SAAS,uBAAuB,6BAA6B;AAC7D,SAAS,qCAAqC;AAE9C,MAAM,kCAAkC;AAAA,EACtC;AAAA,EACA;AACF;AAEO,MAAM,QAA2B;AAAA,EACtC,cAAc,OAAO,QAAQ;AAC3B,UAAM,QAAQ,EAAE,UAAU,IAAI,UAAU,gBAAgB,IAAI,eAAe;AAC3E,UAAM,sBAAsB,IAAI,IAAI,KAAK;AACzC,UAAM,qBAAqB,IAAI,IAAI;AAAA,MACjC,UAAU,IAAI;AAAA,MACd,gBAAgB,IAAI;AAAA,MACpB,WAAW,CAAC,cAAc,SAAS,UAAU;AAAA,MAC7C,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AAAA,EAEA,cAAc,OAAO,QAAQ;AAC3B,UAAM,QAAQ,EAAE,UAAU,IAAI,UAAU,gBAAgB,IAAI,eAAe;AAC3E,UAAM,sBAAsB,IAAI,IAAI,KAAK;AAGzC,UAAM,8BAA8B,IAAI,IAAI,KAAK;AAAA,EACnD;AAAA,EAEA,qBAAqB;AAAA,IACnB,OAAO,CAAC,WAAW,6BAA6B;AAAA,IAChD,UAAU;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,6BAA6B;AAAA,IAC3B,OAAO,CAAC,0BAA0B;AAAA,IAClC,QAAQ,CAAC,0BAA0B;AAAA,EACrC;AACF;AAEA,IAAO,gBAAQ;",
4
+ "sourcesContent": ["import type { ModuleSetupConfig } from '@open-mercato/shared/modules/setup'\nimport { appendWidgetsToRoles } from '@open-mercato/core/modules/dashboards/lib/role-widgets'\nimport { seedStaffAddressTypes, seedStaffTeamExamples } from './lib/seeds'\nimport { seedStaffTimeTrackingExamples } from './lib/timeTrackingSeeds'\nimport { resolveContainerProjectCodeGenerator, seedSupportDefaults } from './lib/support/seedDefaults'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\n\nconst TIMESHEETS_DASHBOARD_WIDGET_IDS = [\n 'staff.timesheets.timeReporting',\n 'staff.timesheets.hoursByProject',\n]\n\nexport const setup: ModuleSetupConfig = {\n seedDefaults: async (ctx) => {\n const scope = { tenantId: ctx.tenantId, organizationId: ctx.organizationId }\n await seedStaffAddressTypes(ctx.em, scope)\n const { translate } = await resolveTranslations()\n await seedSupportDefaults(ctx.em, scope, { translate, generateCode: resolveContainerProjectCodeGenerator(ctx.container) })\n await appendWidgetsToRoles(ctx.em, {\n tenantId: ctx.tenantId,\n organizationId: ctx.organizationId,\n roleNames: ['superadmin', 'admin', 'employee'],\n widgetIds: TIMESHEETS_DASHBOARD_WIDGET_IDS,\n })\n },\n\n seedExamples: async (ctx) => {\n const scope = { tenantId: ctx.tenantId, organizationId: ctx.organizationId }\n await seedStaffTeamExamples(ctx.em, scope)\n // Runs after the team examples because every project it staffs, every task it\n // assigns and every hour it logs points at a staff member those seeds create.\n await seedStaffTimeTrackingExamples(ctx.em, scope)\n },\n\n defaultRoleFeatures: {\n admin: ['staff.*', 'staff.leave_requests.manage'],\n employee: [\n 'staff.leave_requests.send',\n 'staff.my_availability.view',\n 'staff.my_availability.manage',\n 'staff.my_leave_requests.view',\n 'staff.my_leave_requests.send',\n 'staff.timesheets.view',\n 'staff.timesheets.manage_own',\n 'staff.timesheets.projects.view',\n 'staff.timesheets.tasks.view',\n 'staff.timesheets.tasks.manage',\n 'staff.timesheets.rates.view',\n ],\n },\n\n /**\n * EP-50. `portal.time_reports.view` is a **customer** feature, granted through\n * `CustomerRoleAcl`, and it is deliberately absent from `acl.ts` \u2014 that file is\n * the staff feature catalog and the two namespaces are graded by different RBAC\n * services.\n *\n * `viewer` gets it as well as `buyer`: reading the hours already delivered is a\n * read, and a client who may see their invoices may see what they paid for.\n * `portal_admin` holds `portal.*` and needs no entry.\n */\n defaultCustomerRoleFeatures: {\n buyer: ['portal.time_reports.view', 'portal.support_tickets.view', 'portal.support_tickets.manage'],\n viewer: ['portal.time_reports.view', 'portal.support_tickets.view'],\n },\n}\n\nexport default setup\n"],
5
+ "mappings": "AACA,SAAS,4BAA4B;AACrC,SAAS,uBAAuB,6BAA6B;AAC7D,SAAS,qCAAqC;AAC9C,SAAS,sCAAsC,2BAA2B;AAC1E,SAAS,2BAA2B;AAEpC,MAAM,kCAAkC;AAAA,EACtC;AAAA,EACA;AACF;AAEO,MAAM,QAA2B;AAAA,EACtC,cAAc,OAAO,QAAQ;AAC3B,UAAM,QAAQ,EAAE,UAAU,IAAI,UAAU,gBAAgB,IAAI,eAAe;AAC3E,UAAM,sBAAsB,IAAI,IAAI,KAAK;AACzC,UAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAChD,UAAM,oBAAoB,IAAI,IAAI,OAAO,EAAE,WAAW,cAAc,qCAAqC,IAAI,SAAS,EAAE,CAAC;AACzH,UAAM,qBAAqB,IAAI,IAAI;AAAA,MACjC,UAAU,IAAI;AAAA,MACd,gBAAgB,IAAI;AAAA,MACpB,WAAW,CAAC,cAAc,SAAS,UAAU;AAAA,MAC7C,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AAAA,EAEA,cAAc,OAAO,QAAQ;AAC3B,UAAM,QAAQ,EAAE,UAAU,IAAI,UAAU,gBAAgB,IAAI,eAAe;AAC3E,UAAM,sBAAsB,IAAI,IAAI,KAAK;AAGzC,UAAM,8BAA8B,IAAI,IAAI,KAAK;AAAA,EACnD;AAAA,EAEA,qBAAqB;AAAA,IACnB,OAAO,CAAC,WAAW,6BAA6B;AAAA,IAChD,UAAU;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,6BAA6B;AAAA,IAC3B,OAAO,CAAC,4BAA4B,+BAA+B,+BAA+B;AAAA,IAClG,QAAQ,CAAC,4BAA4B,6BAA6B;AAAA,EACpE;AACF;AAEA,IAAO,gBAAQ;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,26 @@
1
+ import { createLogger } from "@open-mercato/shared/lib/logger";
2
+ import { getTelemetryRuntime } from "@open-mercato/shared/lib/telemetry/runtime";
3
+ import { publishTicketReply, readEventScope } from "../lib/support/portalBroadcast.js";
4
+ const logger = createLogger("staff").child({ component: "subscribers/support-portal-comment-created" });
5
+ const metadata = {
6
+ event: "staff.timesheets.time_task_comment.created",
7
+ persistent: false,
8
+ id: "staff:support-portal-comment-created"
9
+ };
10
+ async function handle(payload, ctx) {
11
+ try {
12
+ if (payload.portalVisible !== true) return;
13
+ const scope = readEventScope(payload);
14
+ const commentId = typeof payload.id === "string" ? payload.id : null;
15
+ if (!scope || !commentId) return;
16
+ await publishTicketReply(ctx.resolve("em").fork(), commentId, scope);
17
+ } catch (err) {
18
+ logger.error("staff:support-portal-comment-created failed", { err, id: payload?.id ?? null });
19
+ getTelemetryRuntime()?.reportError(err, { module: "staff", code: "staff.support_portal_comment_created_failed" });
20
+ }
21
+ }
22
+ export {
23
+ handle as default,
24
+ metadata
25
+ };
26
+ //# sourceMappingURL=support-portal-comment-created.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/staff/subscribers/support-portal-comment-created.ts"],
4
+ "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport { getTelemetryRuntime } from '@open-mercato/shared/lib/telemetry/runtime'\nimport { publishTicketReply, readEventScope } from '../lib/support/portalBroadcast'\n\nconst logger = createLogger('staff').child({ component: 'subscribers/support-portal-comment-created' })\n\n/**\n * Ephemeral on purpose: `portal_updated` is portal-only, and the event bus does not\n * relay portal-only events across processes (open issue #2973). Run inline in the web\n * process that executed the command, where the portal SSE stream lives. Make this\n * persistent again once #2973 lands.\n */\nexport const metadata = {\n event: 'staff.timesheets.time_task_comment.created',\n persistent: false,\n id: 'staff:support-portal-comment-created',\n}\n\ntype ResolverContext = { resolve: <T = unknown>(name: string) => T }\n\ntype Payload = Record<string, unknown>\n\nexport default async function handle(payload: Payload, ctx: ResolverContext): Promise<void> {\n try {\n if (payload.portalVisible !== true) return\n const scope = readEventScope(payload)\n const commentId = typeof payload.id === 'string' ? payload.id : null\n if (!scope || !commentId) return\n await publishTicketReply((ctx.resolve('em') as EntityManager).fork(), commentId, scope)\n } catch (err) {\n logger.error('staff:support-portal-comment-created failed', { err, id: payload?.id ?? null })\n getTelemetryRuntime()?.reportError(err, { module: 'staff', code: 'staff.support_portal_comment_created_failed' })\n }\n}\n"],
5
+ "mappings": "AACA,SAAS,oBAAoB;AAC7B,SAAS,2BAA2B;AACpC,SAAS,oBAAoB,sBAAsB;AAEnD,MAAM,SAAS,aAAa,OAAO,EAAE,MAAM,EAAE,WAAW,6CAA6C,CAAC;AAQ/F,MAAM,WAAW;AAAA,EACtB,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,IAAI;AACN;AAMA,eAAO,OAA8B,SAAkB,KAAqC;AAC1F,MAAI;AACF,QAAI,QAAQ,kBAAkB,KAAM;AACpC,UAAM,QAAQ,eAAe,OAAO;AACpC,UAAM,YAAY,OAAO,QAAQ,OAAO,WAAW,QAAQ,KAAK;AAChE,QAAI,CAAC,SAAS,CAAC,UAAW;AAC1B,UAAM,mBAAoB,IAAI,QAAQ,IAAI,EAAoB,KAAK,GAAG,WAAW,KAAK;AAAA,EACxF,SAAS,KAAK;AACZ,WAAO,MAAM,+CAA+C,EAAE,KAAK,IAAI,SAAS,MAAM,KAAK,CAAC;AAC5F,wBAAoB,GAAG,YAAY,KAAK,EAAE,QAAQ,SAAS,MAAM,8CAA8C,CAAC;AAAA,EAClH;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,26 @@
1
+ import { createLogger } from "@open-mercato/shared/lib/logger";
2
+ import { getTelemetryRuntime } from "@open-mercato/shared/lib/telemetry/runtime";
3
+ import { publishTicketReply, readEventScope } from "../lib/support/portalBroadcast.js";
4
+ const logger = createLogger("staff").child({ component: "subscribers/support-portal-comment-deleted" });
5
+ const metadata = {
6
+ event: "staff.timesheets.time_task_comment.deleted",
7
+ persistent: false,
8
+ id: "staff:support-portal-comment-deleted"
9
+ };
10
+ async function handle(payload, ctx) {
11
+ try {
12
+ if (payload.portalVisible !== true) return;
13
+ const scope = readEventScope(payload);
14
+ const commentId = typeof payload.id === "string" ? payload.id : null;
15
+ if (!scope || !commentId) return;
16
+ await publishTicketReply(ctx.resolve("em").fork(), commentId, scope);
17
+ } catch (err) {
18
+ logger.error("staff:support-portal-comment-deleted failed", { err, id: payload?.id ?? null });
19
+ getTelemetryRuntime()?.reportError(err, { module: "staff", code: "staff.support_portal_comment_deleted_failed" });
20
+ }
21
+ }
22
+ export {
23
+ handle as default,
24
+ metadata
25
+ };
26
+ //# sourceMappingURL=support-portal-comment-deleted.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/staff/subscribers/support-portal-comment-deleted.ts"],
4
+ "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport { getTelemetryRuntime } from '@open-mercato/shared/lib/telemetry/runtime'\nimport { publishTicketReply, readEventScope } from '../lib/support/portalBroadcast'\n\nconst logger = createLogger('staff').child({ component: 'subscribers/support-portal-comment-deleted' })\n\n/**\n * Ephemeral on purpose: `portal_updated` is portal-only, and the event bus does not\n * relay portal-only events across processes (open issue #2973). Run inline in the web\n * process that executed the command, where the portal SSE stream lives. Make this\n * persistent again once #2973 lands.\n */\nexport const metadata = {\n event: 'staff.timesheets.time_task_comment.deleted',\n persistent: false,\n id: 'staff:support-portal-comment-deleted',\n}\n\ntype ResolverContext = { resolve: <T = unknown>(name: string) => T }\n\ntype Payload = Record<string, unknown>\n\nexport default async function handle(payload: Payload, ctx: ResolverContext): Promise<void> {\n try {\n if (payload.portalVisible !== true) return\n const scope = readEventScope(payload)\n const commentId = typeof payload.id === 'string' ? payload.id : null\n if (!scope || !commentId) return\n await publishTicketReply((ctx.resolve('em') as EntityManager).fork(), commentId, scope)\n } catch (err) {\n logger.error('staff:support-portal-comment-deleted failed', { err, id: payload?.id ?? null })\n getTelemetryRuntime()?.reportError(err, { module: 'staff', code: 'staff.support_portal_comment_deleted_failed' })\n }\n}\n"],
5
+ "mappings": "AACA,SAAS,oBAAoB;AAC7B,SAAS,2BAA2B;AACpC,SAAS,oBAAoB,sBAAsB;AAEnD,MAAM,SAAS,aAAa,OAAO,EAAE,MAAM,EAAE,WAAW,6CAA6C,CAAC;AAQ/F,MAAM,WAAW;AAAA,EACtB,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,IAAI;AACN;AAMA,eAAO,OAA8B,SAAkB,KAAqC;AAC1F,MAAI;AACF,QAAI,QAAQ,kBAAkB,KAAM;AACpC,UAAM,QAAQ,eAAe,OAAO;AACpC,UAAM,YAAY,OAAO,QAAQ,OAAO,WAAW,QAAQ,KAAK;AAChE,QAAI,CAAC,SAAS,CAAC,UAAW;AAC1B,UAAM,mBAAoB,IAAI,QAAQ,IAAI,EAAoB,KAAK,GAAG,WAAW,KAAK;AAAA,EACxF,SAAS,KAAK;AACZ,WAAO,MAAM,+CAA+C,EAAE,KAAK,IAAI,SAAS,MAAM,KAAK,CAAC;AAC5F,wBAAoB,GAAG,YAAY,KAAK,EAAE,QAAQ,SAAS,MAAM,8CAA8C,CAAC;AAAA,EAClH;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,26 @@
1
+ import { createLogger } from "@open-mercato/shared/lib/logger";
2
+ import { getTelemetryRuntime } from "@open-mercato/shared/lib/telemetry/runtime";
3
+ import { publishTicketReply, readEventScope } from "../lib/support/portalBroadcast.js";
4
+ const logger = createLogger("staff").child({ component: "subscribers/support-portal-comment-updated" });
5
+ const metadata = {
6
+ event: "staff.timesheets.time_task_comment.updated",
7
+ persistent: false,
8
+ id: "staff:support-portal-comment-updated"
9
+ };
10
+ async function handle(payload, ctx) {
11
+ try {
12
+ if (payload.portalVisible !== true) return;
13
+ const scope = readEventScope(payload);
14
+ const commentId = typeof payload.id === "string" ? payload.id : null;
15
+ if (!scope || !commentId) return;
16
+ await publishTicketReply(ctx.resolve("em").fork(), commentId, scope);
17
+ } catch (err) {
18
+ logger.error("staff:support-portal-comment-updated failed", { err, id: payload?.id ?? null });
19
+ getTelemetryRuntime()?.reportError(err, { module: "staff", code: "staff.support_portal_comment_updated_failed" });
20
+ }
21
+ }
22
+ export {
23
+ handle as default,
24
+ metadata
25
+ };
26
+ //# sourceMappingURL=support-portal-comment-updated.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/staff/subscribers/support-portal-comment-updated.ts"],
4
+ "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport { getTelemetryRuntime } from '@open-mercato/shared/lib/telemetry/runtime'\nimport { publishTicketReply, readEventScope } from '../lib/support/portalBroadcast'\n\nconst logger = createLogger('staff').child({ component: 'subscribers/support-portal-comment-updated' })\n\n/**\n * Ephemeral on purpose: `portal_updated` is portal-only, and the event bus does not\n * relay portal-only events across processes (open issue #2973). Run inline in the web\n * process that executed the command, where the portal SSE stream lives. Make this\n * persistent again once #2973 lands.\n */\nexport const metadata = {\n event: 'staff.timesheets.time_task_comment.updated',\n persistent: false,\n id: 'staff:support-portal-comment-updated',\n}\n\ntype ResolverContext = { resolve: <T = unknown>(name: string) => T }\n\ntype Payload = Record<string, unknown>\n\nexport default async function handle(payload: Payload, ctx: ResolverContext): Promise<void> {\n try {\n if (payload.portalVisible !== true) return\n const scope = readEventScope(payload)\n const commentId = typeof payload.id === 'string' ? payload.id : null\n if (!scope || !commentId) return\n await publishTicketReply((ctx.resolve('em') as EntityManager).fork(), commentId, scope)\n } catch (err) {\n logger.error('staff:support-portal-comment-updated failed', { err, id: payload?.id ?? null })\n getTelemetryRuntime()?.reportError(err, { module: 'staff', code: 'staff.support_portal_comment_updated_failed' })\n }\n}\n"],
5
+ "mappings": "AACA,SAAS,oBAAoB;AAC7B,SAAS,2BAA2B;AACpC,SAAS,oBAAoB,sBAAsB;AAEnD,MAAM,SAAS,aAAa,OAAO,EAAE,MAAM,EAAE,WAAW,6CAA6C,CAAC;AAQ/F,MAAM,WAAW;AAAA,EACtB,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,IAAI;AACN;AAMA,eAAO,OAA8B,SAAkB,KAAqC;AAC1F,MAAI;AACF,QAAI,QAAQ,kBAAkB,KAAM;AACpC,UAAM,QAAQ,eAAe,OAAO;AACpC,UAAM,YAAY,OAAO,QAAQ,OAAO,WAAW,QAAQ,KAAK;AAChE,QAAI,CAAC,SAAS,CAAC,UAAW;AAC1B,UAAM,mBAAoB,IAAI,QAAQ,IAAI,EAAoB,KAAK,GAAG,WAAW,KAAK;AAAA,EACxF,SAAS,KAAK;AACZ,WAAO,MAAM,+CAA+C,EAAE,KAAK,IAAI,SAAS,MAAM,KAAK,CAAC;AAC5F,wBAAoB,GAAG,YAAY,KAAK,EAAE,QAAQ,SAAS,MAAM,8CAA8C,CAAC;AAAA,EAClH;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,24 @@
1
+ import { createLogger } from "@open-mercato/shared/lib/logger";
2
+ import { fanOutStatusColumn, readEventScope } from "../lib/support/portalBroadcast.js";
3
+ const logger = createLogger("staff").child({ component: "subscribers/support-portal-status-column-updated" });
4
+ const metadata = {
5
+ event: "staff.timesheets.time_task_status.updated",
6
+ persistent: true,
7
+ id: "staff:support-portal-status-column-updated"
8
+ };
9
+ async function handle(payload, ctx) {
10
+ try {
11
+ const scope = readEventScope(payload);
12
+ const statusId = typeof payload.id === "string" ? payload.id : null;
13
+ if (!scope || !statusId) return;
14
+ await fanOutStatusColumn(ctx.resolve("em").fork(), statusId, scope);
15
+ } catch (err) {
16
+ logger.error("staff:support-portal-status-column-updated failed", { err, id: payload?.id ?? null });
17
+ throw err;
18
+ }
19
+ }
20
+ export {
21
+ handle as default,
22
+ metadata
23
+ };
24
+ //# sourceMappingURL=support-portal-status-column-updated.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/staff/subscribers/support-portal-status-column-updated.ts"],
4
+ "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport { fanOutStatusColumn, readEventScope } from '../lib/support/portalBroadcast'\n\nconst logger = createLogger('staff').child({ component: 'subscribers/support-portal-status-column-updated' })\n\n/**\n * Persistent, unlike the other support-portal subscribers: re-deriving every portal\n * ticket in a column is the one potentially expensive fan-out, so it runs on the\n * queue (retried on failure; `publishTaskPortalStatus` is compare-and-publish, so a\n * retry is idempotent) instead of inside the admin's request. Column flag edits are\n * rare, and until #2973 lands a `portal_updated` emitted from the worker may not\n * reach an open portal page live; the portal derives status on read, so the page is\n * correct on its next load.\n */\nexport const metadata = {\n event: 'staff.timesheets.time_task_status.updated',\n persistent: true,\n id: 'staff:support-portal-status-column-updated',\n}\n\ntype ResolverContext = { resolve: <T = unknown>(name: string) => T }\n\ntype Payload = Record<string, unknown>\n\nexport default async function handle(payload: Payload, ctx: ResolverContext): Promise<void> {\n try {\n const scope = readEventScope(payload)\n const statusId = typeof payload.id === 'string' ? payload.id : null\n if (!scope || !statusId) return\n await fanOutStatusColumn((ctx.resolve('em') as EntityManager).fork(), statusId, scope)\n } catch (err) {\n logger.error('staff:support-portal-status-column-updated failed', { err, id: payload?.id ?? null })\n throw err\n }\n}\n"],
5
+ "mappings": "AACA,SAAS,oBAAoB;AAC7B,SAAS,oBAAoB,sBAAsB;AAEnD,MAAM,SAAS,aAAa,OAAO,EAAE,MAAM,EAAE,WAAW,mDAAmD,CAAC;AAWrG,MAAM,WAAW;AAAA,EACtB,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,IAAI;AACN;AAMA,eAAO,OAA8B,SAAkB,KAAqC;AAC1F,MAAI;AACF,UAAM,QAAQ,eAAe,OAAO;AACpC,UAAM,WAAW,OAAO,QAAQ,OAAO,WAAW,QAAQ,KAAK;AAC/D,QAAI,CAAC,SAAS,CAAC,SAAU;AACzB,UAAM,mBAAoB,IAAI,QAAQ,IAAI,EAAoB,KAAK,GAAG,UAAU,KAAK;AAAA,EACvF,SAAS,KAAK;AACZ,WAAO,MAAM,qDAAqD,EAAE,KAAK,IAAI,SAAS,MAAM,KAAK,CAAC;AAClG,UAAM;AAAA,EACR;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,25 @@
1
+ import { createLogger } from "@open-mercato/shared/lib/logger";
2
+ import { getTelemetryRuntime } from "@open-mercato/shared/lib/telemetry/runtime";
3
+ import { publishTaskPortalStatus, readEventScope } from "../lib/support/portalBroadcast.js";
4
+ const logger = createLogger("staff").child({ component: "subscribers/support-portal-task-status-changed" });
5
+ const metadata = {
6
+ event: "staff.timesheets.time_task.status_changed",
7
+ persistent: false,
8
+ id: "staff:support-portal-task-status-changed"
9
+ };
10
+ async function handle(payload, ctx) {
11
+ try {
12
+ const scope = readEventScope(payload);
13
+ const taskId = typeof payload.id === "string" ? payload.id : null;
14
+ if (!scope || !taskId) return;
15
+ await publishTaskPortalStatus(ctx.resolve("em").fork(), taskId, scope, { always: true });
16
+ } catch (err) {
17
+ logger.error("staff:support-portal-task-status-changed failed", { err, id: payload?.id ?? null });
18
+ getTelemetryRuntime()?.reportError(err, { module: "staff", code: "staff.support_portal_task_status_changed_failed" });
19
+ }
20
+ }
21
+ export {
22
+ handle as default,
23
+ metadata
24
+ };
25
+ //# sourceMappingURL=support-portal-task-status-changed.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/staff/subscribers/support-portal-task-status-changed.ts"],
4
+ "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport { getTelemetryRuntime } from '@open-mercato/shared/lib/telemetry/runtime'\nimport { publishTaskPortalStatus, readEventScope } from '../lib/support/portalBroadcast'\n\nconst logger = createLogger('staff').child({ component: 'subscribers/support-portal-task-status-changed' })\n\n/**\n * Ephemeral on purpose: `portal_updated` is portal-only, and the event bus does not\n * relay portal-only events across processes (open issue #2973). Run inline in the web\n * process that executed the command, where the portal SSE stream lives. Make this\n * persistent again once #2973 lands.\n */\nexport const metadata = {\n event: 'staff.timesheets.time_task.status_changed',\n persistent: false,\n id: 'staff:support-portal-task-status-changed',\n}\n\ntype ResolverContext = { resolve: <T = unknown>(name: string) => T }\n\ntype Payload = Record<string, unknown>\n\nexport default async function handle(payload: Payload, ctx: ResolverContext): Promise<void> {\n try {\n const scope = readEventScope(payload)\n const taskId = typeof payload.id === 'string' ? payload.id : null\n if (!scope || !taskId) return\n await publishTaskPortalStatus((ctx.resolve('em') as EntityManager).fork(), taskId, scope, { always: true })\n } catch (err) {\n logger.error('staff:support-portal-task-status-changed failed', { err, id: payload?.id ?? null })\n getTelemetryRuntime()?.reportError(err, { module: 'staff', code: 'staff.support_portal_task_status_changed_failed' })\n }\n}\n"],
5
+ "mappings": "AACA,SAAS,oBAAoB;AAC7B,SAAS,2BAA2B;AACpC,SAAS,yBAAyB,sBAAsB;AAExD,MAAM,SAAS,aAAa,OAAO,EAAE,MAAM,EAAE,WAAW,iDAAiD,CAAC;AAQnG,MAAM,WAAW;AAAA,EACtB,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,IAAI;AACN;AAMA,eAAO,OAA8B,SAAkB,KAAqC;AAC1F,MAAI;AACF,UAAM,QAAQ,eAAe,OAAO;AACpC,UAAM,SAAS,OAAO,QAAQ,OAAO,WAAW,QAAQ,KAAK;AAC7D,QAAI,CAAC,SAAS,CAAC,OAAQ;AACvB,UAAM,wBAAyB,IAAI,QAAQ,IAAI,EAAoB,KAAK,GAAG,QAAQ,OAAO,EAAE,QAAQ,KAAK,CAAC;AAAA,EAC5G,SAAS,KAAK;AACZ,WAAO,MAAM,mDAAmD,EAAE,KAAK,IAAI,SAAS,MAAM,KAAK,CAAC;AAChG,wBAAoB,GAAG,YAAY,KAAK,EAAE,QAAQ,SAAS,MAAM,kDAAkD,CAAC;AAAA,EACtH;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,25 @@
1
+ import { createLogger } from "@open-mercato/shared/lib/logger";
2
+ import { getTelemetryRuntime } from "@open-mercato/shared/lib/telemetry/runtime";
3
+ import { publishTaskPortalStatus, readEventScope } from "../lib/support/portalBroadcast.js";
4
+ const logger = createLogger("staff").child({ component: "subscribers/support-portal-task-updated" });
5
+ const metadata = {
6
+ event: "staff.timesheets.time_task.updated",
7
+ persistent: false,
8
+ id: "staff:support-portal-task-updated"
9
+ };
10
+ async function handle(payload, ctx) {
11
+ try {
12
+ const scope = readEventScope(payload);
13
+ const taskId = typeof payload.id === "string" ? payload.id : null;
14
+ if (!scope || !taskId) return;
15
+ await publishTaskPortalStatus(ctx.resolve("em").fork(), taskId, scope);
16
+ } catch (err) {
17
+ logger.error("staff:support-portal-task-updated failed", { err, id: payload?.id ?? null });
18
+ getTelemetryRuntime()?.reportError(err, { module: "staff", code: "staff.support_portal_task_updated_failed" });
19
+ }
20
+ }
21
+ export {
22
+ handle as default,
23
+ metadata
24
+ };
25
+ //# sourceMappingURL=support-portal-task-updated.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/staff/subscribers/support-portal-task-updated.ts"],
4
+ "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport { getTelemetryRuntime } from '@open-mercato/shared/lib/telemetry/runtime'\nimport { publishTaskPortalStatus, readEventScope } from '../lib/support/portalBroadcast'\n\nconst logger = createLogger('staff').child({ component: 'subscribers/support-portal-task-updated' })\n\n/**\n * Ephemeral on purpose: `portal_updated` is portal-only, and the event bus does not\n * relay portal-only events across processes (open issue #2973). Run inline in the web\n * process that executed the command, where the portal SSE stream lives. Make this\n * persistent again once #2973 lands.\n */\nexport const metadata = {\n event: 'staff.timesheets.time_task.updated',\n persistent: false,\n id: 'staff:support-portal-task-updated',\n}\n\ntype ResolverContext = { resolve: <T = unknown>(name: string) => T }\n\ntype Payload = Record<string, unknown>\n\nexport default async function handle(payload: Payload, ctx: ResolverContext): Promise<void> {\n try {\n const scope = readEventScope(payload)\n const taskId = typeof payload.id === 'string' ? payload.id : null\n if (!scope || !taskId) return\n await publishTaskPortalStatus((ctx.resolve('em') as EntityManager).fork(), taskId, scope)\n } catch (err) {\n logger.error('staff:support-portal-task-updated failed', { err, id: payload?.id ?? null })\n getTelemetryRuntime()?.reportError(err, { module: 'staff', code: 'staff.support_portal_task_updated_failed' })\n }\n}\n"],
5
+ "mappings": "AACA,SAAS,oBAAoB;AAC7B,SAAS,2BAA2B;AACpC,SAAS,yBAAyB,sBAAsB;AAExD,MAAM,SAAS,aAAa,OAAO,EAAE,MAAM,EAAE,WAAW,0CAA0C,CAAC;AAQ5F,MAAM,WAAW;AAAA,EACtB,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,IAAI;AACN;AAMA,eAAO,OAA8B,SAAkB,KAAqC;AAC1F,MAAI;AACF,UAAM,QAAQ,eAAe,OAAO;AACpC,UAAM,SAAS,OAAO,QAAQ,OAAO,WAAW,QAAQ,KAAK;AAC7D,QAAI,CAAC,SAAS,CAAC,OAAQ;AACvB,UAAM,wBAAyB,IAAI,QAAQ,IAAI,EAAoB,KAAK,GAAG,QAAQ,KAAK;AAAA,EAC1F,SAAS,KAAK;AACZ,WAAO,MAAM,4CAA4C,EAAE,KAAK,IAAI,SAAS,MAAM,KAAK,CAAC;AACzF,wBAAoB,GAAG,YAAY,KAAK,EAAE,QAAQ,SAAS,MAAM,2CAA2C,CAAC;AAAA,EAC/G;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,25 @@
1
+ import { createLogger } from "@open-mercato/shared/lib/logger";
2
+ import { notifySupportTicket } from "../lib/support/notifications.js";
3
+ const logger = createLogger("staff").child({ component: "subscribers/support-ticket-created-notification" });
4
+ const metadata = {
5
+ event: "staff.support_ticket.created",
6
+ persistent: true,
7
+ id: "staff:support-ticket-created-notification"
8
+ };
9
+ async function handle(payload, ctx) {
10
+ try {
11
+ const taskId = typeof payload.taskId === "string" ? payload.taskId : null;
12
+ const tenantId = typeof payload.tenantId === "string" ? payload.tenantId : null;
13
+ const organizationId = typeof payload.organizationId === "string" ? payload.organizationId : null;
14
+ if (!taskId || !tenantId || !organizationId) return;
15
+ await notifySupportTicket(ctx, { taskId, tenantId, organizationId, kind: "created" });
16
+ } catch (err) {
17
+ logger.error("staff:support-ticket-created-notification failed", { err, id: payload?.id ?? null });
18
+ throw err;
19
+ }
20
+ }
21
+ export {
22
+ handle as default,
23
+ metadata
24
+ };
25
+ //# sourceMappingURL=support-ticket-created-notification.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/staff/subscribers/support-ticket-created-notification.ts"],
4
+ "sourcesContent": ["import { createLogger } from '@open-mercato/shared/lib/logger'\nimport { notifySupportTicket } from '../lib/support/notifications'\n\nconst logger = createLogger('staff').child({ component: 'subscribers/support-ticket-created-notification' })\n\nexport const metadata = {\n event: 'staff.support_ticket.created',\n persistent: true,\n id: 'staff:support-ticket-created-notification',\n}\n\ntype ResolverContext = { resolve: <T = unknown>(name: string) => T }\n\ntype Payload = Record<string, unknown>\n\nexport default async function handle(payload: Payload, ctx: ResolverContext): Promise<void> {\n try {\n const taskId = typeof payload.taskId === 'string' ? payload.taskId : null\n const tenantId = typeof payload.tenantId === 'string' ? payload.tenantId : null\n const organizationId = typeof payload.organizationId === 'string' ? payload.organizationId : null\n if (!taskId || !tenantId || !organizationId) return\n await notifySupportTicket(ctx, { taskId, tenantId, organizationId, kind: 'created' })\n } catch (err) {\n logger.error('staff:support-ticket-created-notification failed', { err, id: payload?.id ?? null })\n throw err\n }\n}\n"],
5
+ "mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,2BAA2B;AAEpC,MAAM,SAAS,aAAa,OAAO,EAAE,MAAM,EAAE,WAAW,kDAAkD,CAAC;AAEpG,MAAM,WAAW;AAAA,EACtB,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,IAAI;AACN;AAMA,eAAO,OAA8B,SAAkB,KAAqC;AAC1F,MAAI;AACF,UAAM,SAAS,OAAO,QAAQ,WAAW,WAAW,QAAQ,SAAS;AACrE,UAAM,WAAW,OAAO,QAAQ,aAAa,WAAW,QAAQ,WAAW;AAC3E,UAAM,iBAAiB,OAAO,QAAQ,mBAAmB,WAAW,QAAQ,iBAAiB;AAC7F,QAAI,CAAC,UAAU,CAAC,YAAY,CAAC,eAAgB;AAC7C,UAAM,oBAAoB,KAAK,EAAE,QAAQ,UAAU,gBAAgB,MAAM,UAAU,CAAC;AAAA,EACtF,SAAS,KAAK;AACZ,WAAO,MAAM,oDAAoD,EAAE,KAAK,IAAI,SAAS,MAAM,KAAK,CAAC;AACjG,UAAM;AAAA,EACR;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,25 @@
1
+ import { createLogger } from "@open-mercato/shared/lib/logger";
2
+ import { notifySupportTicket } from "../lib/support/notifications.js";
3
+ const logger = createLogger("staff").child({ component: "subscribers/support-ticket-customer-replied-notification" });
4
+ const metadata = {
5
+ event: "staff.support_ticket.customer_replied",
6
+ persistent: true,
7
+ id: "staff:support-ticket-customer-replied-notification"
8
+ };
9
+ async function handle(payload, ctx) {
10
+ try {
11
+ const taskId = typeof payload.taskId === "string" ? payload.taskId : null;
12
+ const tenantId = typeof payload.tenantId === "string" ? payload.tenantId : null;
13
+ const organizationId = typeof payload.organizationId === "string" ? payload.organizationId : null;
14
+ if (!taskId || !tenantId || !organizationId) return;
15
+ await notifySupportTicket(ctx, { taskId, tenantId, organizationId, kind: "customer_replied" });
16
+ } catch (err) {
17
+ logger.error("staff:support-ticket-customer-replied-notification failed", { err, id: payload?.id ?? null });
18
+ throw err;
19
+ }
20
+ }
21
+ export {
22
+ handle as default,
23
+ metadata
24
+ };
25
+ //# sourceMappingURL=support-ticket-customer-replied-notification.js.map