@open-mercato/core 0.4.5-develop-754ef4d2f0 → 0.4.5-develop-9f9549ebc8

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 (434) hide show
  1. package/dist/generated/entities/message/index.js +65 -0
  2. package/dist/generated/entities/message/index.js.map +7 -0
  3. package/dist/generated/entities/message_access_token/index.js +19 -0
  4. package/dist/generated/entities/message_access_token/index.js.map +7 -0
  5. package/dist/generated/entities/message_confirmation/index.js +21 -0
  6. package/dist/generated/entities/message_confirmation/index.js.map +7 -0
  7. package/dist/generated/entities/message_object/index.js +23 -0
  8. package/dist/generated/entities/message_object/index.js.map +7 -0
  9. package/dist/generated/entities/message_recipient/index.js +31 -0
  10. package/dist/generated/entities/message_recipient/index.js.map +7 -0
  11. package/dist/generated/entities.ids.generated.js +8 -0
  12. package/dist/generated/entities.ids.generated.js.map +2 -2
  13. package/dist/generated/entity-fields-registry.js +10 -0
  14. package/dist/generated/entity-fields-registry.js.map +2 -2
  15. package/dist/modules/auth/components/AclEditor.js +4 -2
  16. package/dist/modules/auth/components/AclEditor.js.map +2 -2
  17. package/dist/modules/auth/frontend/reset.js +3 -3
  18. package/dist/modules/auth/frontend/reset.js.map +2 -2
  19. package/dist/modules/customers/backend/customers/deals/[id]/page.js +27 -8
  20. package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
  21. package/dist/modules/customers/lib/messageObjectPreviews.js +131 -0
  22. package/dist/modules/customers/lib/messageObjectPreviews.js.map +7 -0
  23. package/dist/modules/customers/message-objects.js +71 -0
  24. package/dist/modules/customers/message-objects.js.map +7 -0
  25. package/dist/modules/customers/widgets/messages/CustomerMessageObjectDetail.js +51 -0
  26. package/dist/modules/customers/widgets/messages/CustomerMessageObjectDetail.js.map +7 -0
  27. package/dist/modules/customers/widgets/messages/CustomerMessageObjectPreview.js +35 -0
  28. package/dist/modules/customers/widgets/messages/CustomerMessageObjectPreview.js.map +7 -0
  29. package/dist/modules/customers/widgets/messages/index.js +7 -0
  30. package/dist/modules/customers/widgets/messages/index.js.map +7 -0
  31. package/dist/modules/dashboards/components/WidgetVisibilityEditor.js +35 -6
  32. package/dist/modules/dashboards/components/WidgetVisibilityEditor.js.map +2 -2
  33. package/dist/modules/messages/acl.js +15 -0
  34. package/dist/modules/messages/acl.js.map +7 -0
  35. package/dist/modules/messages/api/[id]/actions/[actionId]/route.js +92 -0
  36. package/dist/modules/messages/api/[id]/actions/[actionId]/route.js.map +7 -0
  37. package/dist/modules/messages/api/[id]/archive/route.js +120 -0
  38. package/dist/modules/messages/api/[id]/archive/route.js.map +7 -0
  39. package/dist/modules/messages/api/[id]/attachments/route.js +195 -0
  40. package/dist/modules/messages/api/[id]/attachments/route.js.map +7 -0
  41. package/dist/modules/messages/api/[id]/confirmation/route.js +67 -0
  42. package/dist/modules/messages/api/[id]/confirmation/route.js.map +7 -0
  43. package/dist/modules/messages/api/[id]/conversation/archive/route.js +68 -0
  44. package/dist/modules/messages/api/[id]/conversation/archive/route.js.map +7 -0
  45. package/dist/modules/messages/api/[id]/conversation/read/route.js +68 -0
  46. package/dist/modules/messages/api/[id]/conversation/read/route.js.map +7 -0
  47. package/dist/modules/messages/api/[id]/conversation/route.js +68 -0
  48. package/dist/modules/messages/api/[id]/conversation/route.js.map +7 -0
  49. package/dist/modules/messages/api/[id]/forward/route.js +85 -0
  50. package/dist/modules/messages/api/[id]/forward/route.js.map +7 -0
  51. package/dist/modules/messages/api/[id]/forward-preview/route.js +70 -0
  52. package/dist/modules/messages/api/[id]/forward-preview/route.js.map +7 -0
  53. package/dist/modules/messages/api/[id]/read/route.js +120 -0
  54. package/dist/modules/messages/api/[id]/read/route.js.map +7 -0
  55. package/dist/modules/messages/api/[id]/reply/route.js +87 -0
  56. package/dist/modules/messages/api/[id]/reply/route.js.map +7 -0
  57. package/dist/modules/messages/api/[id]/route.js +350 -0
  58. package/dist/modules/messages/api/[id]/route.js.map +7 -0
  59. package/dist/modules/messages/api/object-types/route.js +54 -0
  60. package/dist/modules/messages/api/object-types/route.js.map +7 -0
  61. package/dist/modules/messages/api/openapi.js +261 -0
  62. package/dist/modules/messages/api/openapi.js.map +7 -0
  63. package/dist/modules/messages/api/route.js +262 -0
  64. package/dist/modules/messages/api/route.js.map +7 -0
  65. package/dist/modules/messages/api/token/[token]/route.js +99 -0
  66. package/dist/modules/messages/api/token/[token]/route.js.map +7 -0
  67. package/dist/modules/messages/api/types/route.js +40 -0
  68. package/dist/modules/messages/api/types/route.js.map +7 -0
  69. package/dist/modules/messages/api/unread-count/route.js +43 -0
  70. package/dist/modules/messages/api/unread-count/route.js.map +7 -0
  71. package/dist/modules/messages/backend/messages/[id]/page.js +10 -0
  72. package/dist/modules/messages/backend/messages/[id]/page.js.map +7 -0
  73. package/dist/modules/messages/backend/messages/[id]/page.meta.js +16 -0
  74. package/dist/modules/messages/backend/messages/[id]/page.meta.js.map +7 -0
  75. package/dist/modules/messages/backend/messages/compose/page.js +10 -0
  76. package/dist/modules/messages/backend/messages/compose/page.js.map +7 -0
  77. package/dist/modules/messages/backend/messages/compose/page.meta.js +17 -0
  78. package/dist/modules/messages/backend/messages/compose/page.meta.js.map +7 -0
  79. package/dist/modules/messages/backend/page.js +10 -0
  80. package/dist/modules/messages/backend/page.js.map +7 -0
  81. package/dist/modules/messages/backend/page.meta.js +33 -0
  82. package/dist/modules/messages/backend/page.meta.js.map +7 -0
  83. package/dist/modules/messages/commands/actions.js +265 -0
  84. package/dist/modules/messages/commands/actions.js.map +7 -0
  85. package/dist/modules/messages/commands/attachments.js +217 -0
  86. package/dist/modules/messages/commands/attachments.js.map +7 -0
  87. package/dist/modules/messages/commands/confirmations.js +151 -0
  88. package/dist/modules/messages/commands/confirmations.js.map +7 -0
  89. package/dist/modules/messages/commands/conversation.js +240 -0
  90. package/dist/modules/messages/commands/conversation.js.map +7 -0
  91. package/dist/modules/messages/commands/messages.js +748 -0
  92. package/dist/modules/messages/commands/messages.js.map +7 -0
  93. package/dist/modules/messages/commands/recipients.js +259 -0
  94. package/dist/modules/messages/commands/recipients.js.map +7 -0
  95. package/dist/modules/messages/commands/shared.js +258 -0
  96. package/dist/modules/messages/commands/shared.js.map +7 -0
  97. package/dist/modules/messages/commands/tokens.js +69 -0
  98. package/dist/modules/messages/commands/tokens.js.map +7 -0
  99. package/dist/modules/messages/components/ComposeMessagePageClient.js +24 -0
  100. package/dist/modules/messages/components/ComposeMessagePageClient.js.map +7 -0
  101. package/dist/modules/messages/components/MessageDetailPageClient.js +261 -0
  102. package/dist/modules/messages/components/MessageDetailPageClient.js.map +7 -0
  103. package/dist/modules/messages/components/MessagesInboxPageClient.js +390 -0
  104. package/dist/modules/messages/components/MessagesInboxPageClient.js.map +7 -0
  105. package/dist/modules/messages/components/confirmation/MessageConfirmationActions.js +31 -0
  106. package/dist/modules/messages/components/confirmation/MessageConfirmationActions.js.map +7 -0
  107. package/dist/modules/messages/components/confirmation/MessageConfirmationContent.js +69 -0
  108. package/dist/modules/messages/components/confirmation/MessageConfirmationContent.js.map +7 -0
  109. package/dist/modules/messages/components/defaults/DefaultMessageActions.js +31 -0
  110. package/dist/modules/messages/components/defaults/DefaultMessageActions.js.map +7 -0
  111. package/dist/modules/messages/components/defaults/DefaultMessageContent.js +19 -0
  112. package/dist/modules/messages/components/defaults/DefaultMessageContent.js.map +7 -0
  113. package/dist/modules/messages/components/defaults/DefaultMessageListItem.js +90 -0
  114. package/dist/modules/messages/components/defaults/DefaultMessageListItem.js.map +7 -0
  115. package/dist/modules/messages/components/defaults/MessageRecordObjectDetail.js +86 -0
  116. package/dist/modules/messages/components/defaults/MessageRecordObjectDetail.js.map +7 -0
  117. package/dist/modules/messages/components/defaults/MessageRecordObjectPreview.js +61 -0
  118. package/dist/modules/messages/components/defaults/MessageRecordObjectPreview.js.map +7 -0
  119. package/dist/modules/messages/components/message-detail/detail-panels.js +27 -0
  120. package/dist/modules/messages/components/message-detail/detail-panels.js.map +7 -0
  121. package/dist/modules/messages/components/message-detail/hooks/useMessageDetails.js +52 -0
  122. package/dist/modules/messages/components/message-detail/hooks/useMessageDetails.js.map +7 -0
  123. package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsActions.js +289 -0
  124. package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsActions.js.map +7 -0
  125. package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsConversation.js +103 -0
  126. package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsConversation.js.map +7 -0
  127. package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsQueries.js +78 -0
  128. package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsQueries.js.map +7 -0
  129. package/dist/modules/messages/components/message-detail/panels/MainMessageHeader.js +94 -0
  130. package/dist/modules/messages/components/message-detail/panels/MainMessageHeader.js.map +7 -0
  131. package/dist/modules/messages/components/message-detail/panels/MessageHeader.js +110 -0
  132. package/dist/modules/messages/components/message-detail/panels/MessageHeader.js.map +7 -0
  133. package/dist/modules/messages/components/message-detail/panels/MessageListComponent.js +58 -0
  134. package/dist/modules/messages/components/message-detail/panels/MessageListComponent.js.map +7 -0
  135. package/dist/modules/messages/components/message-detail/panels/actions-panel.js +51 -0
  136. package/dist/modules/messages/components/message-detail/panels/actions-panel.js.map +7 -0
  137. package/dist/modules/messages/components/message-detail/panels/attachments-panel.js +66 -0
  138. package/dist/modules/messages/components/message-detail/panels/attachments-panel.js.map +7 -0
  139. package/dist/modules/messages/components/message-detail/panels/body-panel.js +20 -0
  140. package/dist/modules/messages/components/message-detail/panels/body-panel.js.map +7 -0
  141. package/dist/modules/messages/components/message-detail/panels/composer-dialogs.js +36 -0
  142. package/dist/modules/messages/components/message-detail/panels/composer-dialogs.js.map +7 -0
  143. package/dist/modules/messages/components/message-detail/panels/dialogs.js +96 -0
  144. package/dist/modules/messages/components/message-detail/panels/dialogs.js.map +7 -0
  145. package/dist/modules/messages/components/message-detail/panels/index.js +25 -0
  146. package/dist/modules/messages/components/message-detail/panels/index.js.map +7 -0
  147. package/dist/modules/messages/components/message-detail/panels/meta-panel.js +14 -0
  148. package/dist/modules/messages/components/message-detail/panels/meta-panel.js.map +7 -0
  149. package/dist/modules/messages/components/message-detail/panels/objects-panel.js +51 -0
  150. package/dist/modules/messages/components/message-detail/panels/objects-panel.js.map +7 -0
  151. package/dist/modules/messages/components/message-detail/panels/thread-panel.js +54 -0
  152. package/dist/modules/messages/components/message-detail/panels/thread-panel.js.map +7 -0
  153. package/dist/modules/messages/components/message-detail/types.js +1 -0
  154. package/dist/modules/messages/components/message-detail/types.js.map +7 -0
  155. package/dist/modules/messages/components/message-detail/utils.js +54 -0
  156. package/dist/modules/messages/components/message-detail/utils.js.map +7 -0
  157. package/dist/modules/messages/components/utils/PriorityBadge.js +52 -0
  158. package/dist/modules/messages/components/utils/PriorityBadge.js.map +7 -0
  159. package/dist/modules/messages/components/utils/typeUiRegistry.js +77 -0
  160. package/dist/modules/messages/components/utils/typeUiRegistry.js.map +7 -0
  161. package/dist/modules/messages/data/entities.js +309 -0
  162. package/dist/modules/messages/data/entities.js.map +7 -0
  163. package/dist/modules/messages/data/validators.js +272 -0
  164. package/dist/modules/messages/data/validators.js.map +7 -0
  165. package/dist/modules/messages/emails/MessageEmail.js +108 -0
  166. package/dist/modules/messages/emails/MessageEmail.js.map +7 -0
  167. package/dist/modules/messages/events.js +24 -0
  168. package/dist/modules/messages/events.js.map +7 -0
  169. package/dist/modules/messages/frontend/messages/view/[token]/page.js +247 -0
  170. package/dist/modules/messages/frontend/messages/view/[token]/page.js.map +7 -0
  171. package/dist/modules/messages/frontend/messages/view/[token]/page.meta.js +9 -0
  172. package/dist/modules/messages/frontend/messages/view/[token]/page.meta.js.map +7 -0
  173. package/dist/modules/messages/index.js +21 -0
  174. package/dist/modules/messages/index.js.map +7 -0
  175. package/dist/modules/messages/lib/actions.js +141 -0
  176. package/dist/modules/messages/lib/actions.js.map +7 -0
  177. package/dist/modules/messages/lib/attachments.js +131 -0
  178. package/dist/modules/messages/lib/attachments.js.map +7 -0
  179. package/dist/modules/messages/lib/constants.js +7 -0
  180. package/dist/modules/messages/lib/constants.js.map +7 -0
  181. package/dist/modules/messages/lib/email-sender.js +201 -0
  182. package/dist/modules/messages/lib/email-sender.js.map +7 -0
  183. package/dist/modules/messages/lib/forwarding.js +179 -0
  184. package/dist/modules/messages/lib/forwarding.js.map +7 -0
  185. package/dist/modules/messages/lib/message-objects-registry.js +49 -0
  186. package/dist/modules/messages/lib/message-objects-registry.js.map +7 -0
  187. package/dist/modules/messages/lib/message-types-registry.js +41 -0
  188. package/dist/modules/messages/lib/message-types-registry.js.map +7 -0
  189. package/dist/modules/messages/lib/object-validation.js +20 -0
  190. package/dist/modules/messages/lib/object-validation.js.map +7 -0
  191. package/dist/modules/messages/lib/operationMetadata.js +21 -0
  192. package/dist/modules/messages/lib/operationMetadata.js.map +7 -0
  193. package/dist/modules/messages/lib/priorityUtils.js +61 -0
  194. package/dist/modules/messages/lib/priorityUtils.js.map +7 -0
  195. package/dist/modules/messages/lib/routeHelpers.js +44 -0
  196. package/dist/modules/messages/lib/routeHelpers.js.map +7 -0
  197. package/dist/modules/messages/message-objects.js +7 -0
  198. package/dist/modules/messages/message-objects.js.map +7 -0
  199. package/dist/modules/messages/message-types.js +67 -0
  200. package/dist/modules/messages/message-types.js.map +7 -0
  201. package/dist/modules/messages/migrations/Migration20260213181243.js +31 -0
  202. package/dist/modules/messages/migrations/Migration20260213181243.js.map +7 -0
  203. package/dist/modules/messages/migrations/Migration20260215165126.js +16 -0
  204. package/dist/modules/messages/migrations/Migration20260215165126.js.map +7 -0
  205. package/dist/modules/messages/notifications.js +27 -0
  206. package/dist/modules/messages/notifications.js.map +7 -0
  207. package/dist/modules/messages/setup.js +21 -0
  208. package/dist/modules/messages/setup.js.map +7 -0
  209. package/dist/modules/messages/subscribers/message-notification.js +108 -0
  210. package/dist/modules/messages/subscribers/message-notification.js.map +7 -0
  211. package/dist/modules/messages/workers/send-email.worker.js +253 -0
  212. package/dist/modules/messages/workers/send-email.worker.js.map +7 -0
  213. package/dist/modules/sales/backend/sales/documents/[id]/page.js +30 -11
  214. package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
  215. package/dist/modules/sales/commands/payments.js +12 -6
  216. package/dist/modules/sales/commands/payments.js.map +2 -2
  217. package/dist/modules/sales/lib/messageObjectPreviews.js +114 -0
  218. package/dist/modules/sales/lib/messageObjectPreviews.js.map +7 -0
  219. package/dist/modules/sales/message-objects.js +57 -0
  220. package/dist/modules/sales/message-objects.js.map +7 -0
  221. package/dist/modules/sales/widgets/messages/SalesDocumentMessageDetail.js +51 -0
  222. package/dist/modules/sales/widgets/messages/SalesDocumentMessageDetail.js.map +7 -0
  223. package/dist/modules/sales/widgets/messages/SalesDocumentMessagePreview.js +36 -0
  224. package/dist/modules/sales/widgets/messages/SalesDocumentMessagePreview.js.map +7 -0
  225. package/dist/modules/sales/widgets/messages/index.js +7 -0
  226. package/dist/modules/sales/widgets/messages/index.js.map +7 -0
  227. package/dist/modules/staff/backend/staff/leave-requests/[id]/page.js +55 -1
  228. package/dist/modules/staff/backend/staff/leave-requests/[id]/page.js.map +2 -2
  229. package/dist/modules/staff/backend/staff/my-leave-requests/[id]/page.js +60 -1
  230. package/dist/modules/staff/backend/staff/my-leave-requests/[id]/page.js.map +2 -2
  231. package/dist/modules/staff/backend/staff/team-members/[id]/page.js +2 -19
  232. package/dist/modules/staff/backend/staff/team-members/[id]/page.js.map +2 -2
  233. package/dist/modules/staff/components/LeaveRequestDetail.js +112 -0
  234. package/dist/modules/staff/components/LeaveRequestDetail.js.map +7 -0
  235. package/dist/modules/staff/components/LeaveRequestForm.js +3 -1
  236. package/dist/modules/staff/components/LeaveRequestForm.js.map +2 -2
  237. package/dist/modules/staff/components/LeaveRequestPreview.js +43 -0
  238. package/dist/modules/staff/components/LeaveRequestPreview.js.map +7 -0
  239. package/dist/modules/staff/lib/messageObjectPreviews.js +148 -0
  240. package/dist/modules/staff/lib/messageObjectPreviews.js.map +7 -0
  241. package/dist/modules/staff/message-objects.js +104 -0
  242. package/dist/modules/staff/message-objects.js.map +7 -0
  243. package/dist/modules/staff/message-types.js +23 -0
  244. package/dist/modules/staff/message-types.js.map +7 -0
  245. package/dist/modules/staff/widgets/messages/StaffMessageObjectDetail.js +51 -0
  246. package/dist/modules/staff/widgets/messages/StaffMessageObjectDetail.js.map +7 -0
  247. package/dist/modules/staff/widgets/messages/StaffMessageObjectPreview.js +34 -0
  248. package/dist/modules/staff/widgets/messages/StaffMessageObjectPreview.js.map +7 -0
  249. package/dist/modules/staff/widgets/messages/index.js +7 -0
  250. package/dist/modules/staff/widgets/messages/index.js.map +7 -0
  251. package/dist/modules/workflows/backend/definitions/visual-editor/page.js +6 -6
  252. package/dist/modules/workflows/backend/definitions/visual-editor/page.js.map +2 -2
  253. package/generated/entities/message/index.ts +31 -0
  254. package/generated/entities/message_access_token/index.ts +8 -0
  255. package/generated/entities/message_confirmation/index.ts +9 -0
  256. package/generated/entities/message_object/index.ts +10 -0
  257. package/generated/entities/message_recipient/index.ts +14 -0
  258. package/generated/entities.ids.generated.ts +8 -0
  259. package/generated/entity-fields-registry.ts +10 -0
  260. package/jest.setup.ts +5 -0
  261. package/package.json +2 -2
  262. package/src/modules/attachments/i18n/de.json +4 -0
  263. package/src/modules/attachments/i18n/en.json +4 -0
  264. package/src/modules/attachments/i18n/es.json +4 -0
  265. package/src/modules/attachments/i18n/pl.json +4 -0
  266. package/src/modules/auth/components/AclEditor.tsx +4 -2
  267. package/src/modules/auth/frontend/reset.tsx +3 -3
  268. package/src/modules/auth/i18n/de.json +5 -0
  269. package/src/modules/auth/i18n/en.json +5 -0
  270. package/src/modules/auth/i18n/es.json +5 -0
  271. package/src/modules/auth/i18n/pl.json +5 -0
  272. package/src/modules/catalog/i18n/de.json +21 -0
  273. package/src/modules/catalog/i18n/en.json +21 -0
  274. package/src/modules/catalog/i18n/es.json +21 -0
  275. package/src/modules/catalog/i18n/pl.json +21 -0
  276. package/src/modules/currencies/i18n/de.json +6 -0
  277. package/src/modules/currencies/i18n/en.json +6 -0
  278. package/src/modules/currencies/i18n/es.json +6 -0
  279. package/src/modules/currencies/i18n/pl.json +6 -0
  280. package/src/modules/customers/backend/customers/deals/[id]/page.tsx +20 -4
  281. package/src/modules/customers/i18n/de.json +26 -1
  282. package/src/modules/customers/i18n/en.json +25 -0
  283. package/src/modules/customers/i18n/es.json +25 -0
  284. package/src/modules/customers/i18n/pl.json +25 -0
  285. package/src/modules/customers/lib/messageObjectPreviews.ts +154 -0
  286. package/src/modules/customers/message-objects.ts +70 -0
  287. package/src/modules/customers/widgets/messages/CustomerMessageObjectDetail.tsx +57 -0
  288. package/src/modules/customers/widgets/messages/CustomerMessageObjectPreview.tsx +49 -0
  289. package/src/modules/customers/widgets/messages/index.ts +2 -0
  290. package/src/modules/dashboards/components/WidgetVisibilityEditor.tsx +41 -5
  291. package/src/modules/dashboards/i18n/de.json +5 -1
  292. package/src/modules/dashboards/i18n/en.json +5 -1
  293. package/src/modules/dashboards/i18n/es.json +5 -1
  294. package/src/modules/dashboards/i18n/pl.json +5 -1
  295. package/src/modules/dictionaries/i18n/de.json +14 -1
  296. package/src/modules/dictionaries/i18n/en.json +14 -1
  297. package/src/modules/dictionaries/i18n/es.json +14 -1
  298. package/src/modules/dictionaries/i18n/pl.json +14 -1
  299. package/src/modules/feature_toggles/i18n/de.json +3 -0
  300. package/src/modules/feature_toggles/i18n/en.json +3 -0
  301. package/src/modules/feature_toggles/i18n/es.json +3 -0
  302. package/src/modules/feature_toggles/i18n/pl.json +3 -0
  303. package/src/modules/messages/acl.ts +11 -0
  304. package/src/modules/messages/api/[id]/actions/[actionId]/route.ts +103 -0
  305. package/src/modules/messages/api/[id]/archive/route.ts +138 -0
  306. package/src/modules/messages/api/[id]/attachments/route.ts +217 -0
  307. package/src/modules/messages/api/[id]/confirmation/route.ts +73 -0
  308. package/src/modules/messages/api/[id]/conversation/archive/route.ts +69 -0
  309. package/src/modules/messages/api/[id]/conversation/read/route.ts +69 -0
  310. package/src/modules/messages/api/[id]/conversation/route.ts +69 -0
  311. package/src/modules/messages/api/[id]/forward/route.ts +87 -0
  312. package/src/modules/messages/api/[id]/forward-preview/route.ts +75 -0
  313. package/src/modules/messages/api/[id]/read/route.ts +138 -0
  314. package/src/modules/messages/api/[id]/reply/route.ts +89 -0
  315. package/src/modules/messages/api/[id]/route.ts +401 -0
  316. package/src/modules/messages/api/object-types/route.ts +54 -0
  317. package/src/modules/messages/api/openapi.ts +261 -0
  318. package/src/modules/messages/api/route.ts +374 -0
  319. package/src/modules/messages/api/token/[token]/route.ts +103 -0
  320. package/src/modules/messages/api/types/route.ts +39 -0
  321. package/src/modules/messages/api/unread-count/route.ts +55 -0
  322. package/src/modules/messages/backend/messages/[id]/page.meta.ts +12 -0
  323. package/src/modules/messages/backend/messages/[id]/page.tsx +12 -0
  324. package/src/modules/messages/backend/messages/compose/page.meta.ts +13 -0
  325. package/src/modules/messages/backend/messages/compose/page.tsx +12 -0
  326. package/src/modules/messages/backend/page.meta.ts +31 -0
  327. package/src/modules/messages/backend/page.tsx +12 -0
  328. package/src/modules/messages/commands/actions.ts +307 -0
  329. package/src/modules/messages/commands/attachments.ts +227 -0
  330. package/src/modules/messages/commands/confirmations.ts +183 -0
  331. package/src/modules/messages/commands/conversation.ts +292 -0
  332. package/src/modules/messages/commands/messages.ts +845 -0
  333. package/src/modules/messages/commands/recipients.ts +281 -0
  334. package/src/modules/messages/commands/shared.ts +350 -0
  335. package/src/modules/messages/commands/tokens.ts +80 -0
  336. package/src/modules/messages/components/ComposeMessagePageClient.tsx +23 -0
  337. package/src/modules/messages/components/MessageDetailPageClient.tsx +287 -0
  338. package/src/modules/messages/components/MessagesInboxPageClient.tsx +469 -0
  339. package/src/modules/messages/components/confirmation/MessageConfirmationActions.tsx +35 -0
  340. package/src/modules/messages/components/confirmation/MessageConfirmationContent.tsx +88 -0
  341. package/src/modules/messages/components/defaults/DefaultMessageActions.tsx +37 -0
  342. package/src/modules/messages/components/defaults/DefaultMessageContent.tsx +21 -0
  343. package/src/modules/messages/components/defaults/DefaultMessageListItem.tsx +102 -0
  344. package/src/modules/messages/components/defaults/MessageRecordObjectDetail.tsx +114 -0
  345. package/src/modules/messages/components/defaults/MessageRecordObjectPreview.tsx +74 -0
  346. package/src/modules/messages/components/message-detail/detail-panels.ts +13 -0
  347. package/src/modules/messages/components/message-detail/hooks/useMessageDetails.ts +56 -0
  348. package/src/modules/messages/components/message-detail/hooks/useMessageDetailsActions.ts +367 -0
  349. package/src/modules/messages/components/message-detail/hooks/useMessageDetailsConversation.ts +134 -0
  350. package/src/modules/messages/components/message-detail/hooks/useMessageDetailsQueries.ts +102 -0
  351. package/src/modules/messages/components/message-detail/panels/MainMessageHeader.tsx +108 -0
  352. package/src/modules/messages/components/message-detail/panels/MessageHeader.tsx +144 -0
  353. package/src/modules/messages/components/message-detail/panels/MessageListComponent.tsx +63 -0
  354. package/src/modules/messages/components/message-detail/panels/actions-panel.tsx +66 -0
  355. package/src/modules/messages/components/message-detail/panels/attachments-panel.tsx +86 -0
  356. package/src/modules/messages/components/message-detail/panels/body-panel.tsx +32 -0
  357. package/src/modules/messages/components/message-detail/panels/composer-dialogs.tsx +42 -0
  358. package/src/modules/messages/components/message-detail/panels/dialogs.tsx +107 -0
  359. package/src/modules/messages/components/message-detail/panels/index.ts +11 -0
  360. package/src/modules/messages/components/message-detail/panels/meta-panel.tsx +19 -0
  361. package/src/modules/messages/components/message-detail/panels/objects-panel.tsx +65 -0
  362. package/src/modules/messages/components/message-detail/panels/thread-panel.tsx +65 -0
  363. package/src/modules/messages/components/message-detail/types.ts +114 -0
  364. package/src/modules/messages/components/message-detail/utils.ts +62 -0
  365. package/src/modules/messages/components/utils/PriorityBadge.tsx +63 -0
  366. package/src/modules/messages/components/utils/typeUiRegistry.ts +106 -0
  367. package/src/modules/messages/data/entities.ts +284 -0
  368. package/src/modules/messages/data/validators.ts +297 -0
  369. package/src/modules/messages/emails/MessageEmail.tsx +143 -0
  370. package/src/modules/messages/events.ts +24 -0
  371. package/src/modules/messages/frontend/messages/view/[token]/page.meta.ts +5 -0
  372. package/src/modules/messages/frontend/messages/view/[token]/page.tsx +389 -0
  373. package/src/modules/messages/i18n/de.json +240 -0
  374. package/src/modules/messages/i18n/en.json +240 -0
  375. package/src/modules/messages/i18n/es.json +240 -0
  376. package/src/modules/messages/i18n/pl.json +240 -0
  377. package/src/modules/messages/index.ts +19 -0
  378. package/src/modules/messages/lib/actions.ts +204 -0
  379. package/src/modules/messages/lib/attachments.ts +197 -0
  380. package/src/modules/messages/lib/constants.ts +2 -0
  381. package/src/modules/messages/lib/email-sender.ts +255 -0
  382. package/src/modules/messages/lib/forwarding.ts +240 -0
  383. package/src/modules/messages/lib/message-objects-registry.ts +60 -0
  384. package/src/modules/messages/lib/message-types-registry.ts +48 -0
  385. package/src/modules/messages/lib/object-validation.ts +26 -0
  386. package/src/modules/messages/lib/operationMetadata.ts +43 -0
  387. package/src/modules/messages/lib/priorityUtils.ts +76 -0
  388. package/src/modules/messages/lib/routeHelpers.ts +65 -0
  389. package/src/modules/messages/message-objects.ts +5 -0
  390. package/src/modules/messages/message-types.ts +65 -0
  391. package/src/modules/messages/migrations/.snapshot-open-mercato.json +957 -0
  392. package/src/modules/messages/migrations/Migration20260213181243.ts +34 -0
  393. package/src/modules/messages/migrations/Migration20260215165126.ts +16 -0
  394. package/src/modules/messages/notifications.ts +25 -0
  395. package/src/modules/messages/setup.ts +19 -0
  396. package/src/modules/messages/subscribers/message-notification.ts +138 -0
  397. package/src/modules/messages/workers/send-email.worker.ts +321 -0
  398. package/src/modules/query_index/i18n/es.json +2 -2
  399. package/src/modules/resources/i18n/de.json +57 -0
  400. package/src/modules/resources/i18n/en.json +57 -0
  401. package/src/modules/resources/i18n/es.json +57 -0
  402. package/src/modules/resources/i18n/pl.json +57 -0
  403. package/src/modules/sales/backend/sales/documents/[id]/page.tsx +23 -7
  404. package/src/modules/sales/commands/payments.ts +12 -6
  405. package/src/modules/sales/i18n/de.json +26 -0
  406. package/src/modules/sales/i18n/en.json +26 -0
  407. package/src/modules/sales/i18n/es.json +26 -0
  408. package/src/modules/sales/i18n/pl.json +26 -0
  409. package/src/modules/sales/lib/messageObjectPreviews.ts +150 -0
  410. package/src/modules/sales/message-objects.ts +56 -0
  411. package/src/modules/sales/widgets/messages/SalesDocumentMessageDetail.tsx +57 -0
  412. package/src/modules/sales/widgets/messages/SalesDocumentMessagePreview.tsx +46 -0
  413. package/src/modules/sales/widgets/messages/index.ts +2 -0
  414. package/src/modules/staff/backend/staff/leave-requests/[id]/page.tsx +54 -0
  415. package/src/modules/staff/backend/staff/my-leave-requests/[id]/page.tsx +58 -0
  416. package/src/modules/staff/backend/staff/team-members/[id]/page.tsx +2 -32
  417. package/src/modules/staff/components/LeaveRequestDetail.tsx +135 -0
  418. package/src/modules/staff/components/LeaveRequestForm.tsx +3 -0
  419. package/src/modules/staff/components/LeaveRequestPreview.tsx +74 -0
  420. package/src/modules/staff/i18n/de.json +22 -0
  421. package/src/modules/staff/i18n/en.json +22 -0
  422. package/src/modules/staff/i18n/es.json +22 -0
  423. package/src/modules/staff/i18n/pl.json +22 -0
  424. package/src/modules/staff/lib/messageObjectPreviews.ts +182 -0
  425. package/src/modules/staff/message-objects.ts +102 -0
  426. package/src/modules/staff/message-types.ts +21 -0
  427. package/src/modules/staff/widgets/messages/StaffMessageObjectDetail.tsx +57 -0
  428. package/src/modules/staff/widgets/messages/StaffMessageObjectPreview.tsx +44 -0
  429. package/src/modules/staff/widgets/messages/index.ts +2 -0
  430. package/src/modules/workflows/backend/definitions/visual-editor/page.tsx +6 -6
  431. package/src/modules/workflows/i18n/de.json +41 -0
  432. package/src/modules/workflows/i18n/en.json +41 -0
  433. package/src/modules/workflows/i18n/es.json +41 -0
  434. package/src/modules/workflows/i18n/pl.json +41 -0
@@ -0,0 +1,31 @@
1
+ import { Migration } from "@mikro-orm/migrations";
2
+ class Migration20260213181243 extends Migration {
3
+ async up() {
4
+ this.addSql(`create table "messages" ("id" uuid not null default gen_random_uuid(), "type" text not null default 'default', "thread_id" uuid null, "parent_message_id" uuid null, "sender_user_id" uuid not null, "subject" text not null, "body" text not null, "body_format" text not null default 'text', "priority" text not null default 'normal', "status" text not null default 'draft', "is_draft" boolean not null default true, "sent_at" timestamptz null, "action_data" jsonb null, "action_result" jsonb null, "action_taken" text null, "action_taken_by_user_id" uuid null, "action_taken_at" timestamptz null, "send_via_email" boolean not null default false, "tenant_id" uuid not null, "organization_id" uuid null, "created_at" timestamptz not null, "updated_at" timestamptz not null, "deleted_at" timestamptz null, "visibility" text null, "source_entity_type" text null, "source_entity_id" uuid null, "external_email" text null, "external_name" text null, "external_email_sent_at" timestamptz null, "external_email_failed_at" timestamptz null, "external_email_error" text null, constraint "messages_pkey" primary key ("id"));`);
5
+ this.addSql(`create index "messages_tenant_idx" on "messages" ("tenant_id", "organization_id");`);
6
+ this.addSql(`create index "messages_type_idx" on "messages" ("type", "tenant_id");`);
7
+ this.addSql(`create index "messages_thread_idx" on "messages" ("thread_id");`);
8
+ this.addSql(`create index "messages_sender_idx" on "messages" ("sender_user_id", "sent_at");`);
9
+ this.addSql(`create table "message_access_tokens" ("id" uuid not null default gen_random_uuid(), "message_id" uuid not null, "recipient_user_id" uuid not null, "token" text not null, "expires_at" timestamptz not null, "used_at" timestamptz null, "use_count" int not null default 0, "created_at" timestamptz not null, constraint "message_access_tokens_pkey" primary key ("id"));`);
10
+ this.addSql(`alter table "message_access_tokens" add constraint "message_access_tokens_token_unique" unique ("token");`);
11
+ this.addSql(`create index "message_access_tokens_message_idx" on "message_access_tokens" ("message_id");`);
12
+ this.addSql(`create index "message_access_tokens_token_idx" on "message_access_tokens" ("token");`);
13
+ this.addSql(`create table "message_objects" ("id" uuid not null default gen_random_uuid(), "message_id" uuid not null, "entity_module" text not null, "entity_type" text not null, "entity_id" uuid not null, "action_required" boolean not null default false, "action_type" text null, "action_label" text null, "entity_snapshot" jsonb null, "created_at" timestamptz not null, constraint "message_objects_pkey" primary key ("id"));`);
14
+ this.addSql(`create index "message_objects_entity_idx" on "message_objects" ("entity_type", "entity_id");`);
15
+ this.addSql(`create index "message_objects_message_idx" on "message_objects" ("message_id");`);
16
+ this.addSql(`create table "message_recipients" ("id" uuid not null default gen_random_uuid(), "message_id" uuid not null, "recipient_user_id" uuid not null, "recipient_type" text not null default 'to', "status" text not null default 'unread', "read_at" timestamptz null, "archived_at" timestamptz null, "deleted_at" timestamptz null, "email_sent_at" timestamptz null, "email_delivered_at" timestamptz null, "email_opened_at" timestamptz null, "email_failed_at" timestamptz null, "email_error" text null, "created_at" timestamptz not null, constraint "message_recipients_pkey" primary key ("id"));`);
17
+ this.addSql(`alter table "message_recipients" add constraint "message_recipients_message_user_unique" unique ("message_id", "recipient_user_id");`);
18
+ this.addSql(`create index "message_recipients_message_idx" on "message_recipients" ("message_id");`);
19
+ this.addSql(`create index "message_recipients_user_idx" on "message_recipients" ("recipient_user_id", "status");`);
20
+ }
21
+ async down() {
22
+ this.addSql(`drop table if exists "message_recipients" cascade;`);
23
+ this.addSql(`drop table if exists "message_objects" cascade;`);
24
+ this.addSql(`drop table if exists "message_access_tokens" cascade;`);
25
+ this.addSql(`drop table if exists "messages" cascade;`);
26
+ }
27
+ }
28
+ export {
29
+ Migration20260213181243
30
+ };
31
+ //# sourceMappingURL=Migration20260213181243.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/messages/migrations/Migration20260213181243.ts"],
4
+ "sourcesContent": ["import { Migration } from '@mikro-orm/migrations';\n\nexport class Migration20260213181243 extends Migration {\n\n override async up(): Promise<void> {\n this.addSql(`create table \"messages\" (\"id\" uuid not null default gen_random_uuid(), \"type\" text not null default 'default', \"thread_id\" uuid null, \"parent_message_id\" uuid null, \"sender_user_id\" uuid not null, \"subject\" text not null, \"body\" text not null, \"body_format\" text not null default 'text', \"priority\" text not null default 'normal', \"status\" text not null default 'draft', \"is_draft\" boolean not null default true, \"sent_at\" timestamptz null, \"action_data\" jsonb null, \"action_result\" jsonb null, \"action_taken\" text null, \"action_taken_by_user_id\" uuid null, \"action_taken_at\" timestamptz null, \"send_via_email\" boolean not null default false, \"tenant_id\" uuid not null, \"organization_id\" uuid null, \"created_at\" timestamptz not null, \"updated_at\" timestamptz not null, \"deleted_at\" timestamptz null, \"visibility\" text null, \"source_entity_type\" text null, \"source_entity_id\" uuid null, \"external_email\" text null, \"external_name\" text null, \"external_email_sent_at\" timestamptz null, \"external_email_failed_at\" timestamptz null, \"external_email_error\" text null, constraint \"messages_pkey\" primary key (\"id\"));`);\n this.addSql(`create index \"messages_tenant_idx\" on \"messages\" (\"tenant_id\", \"organization_id\");`);\n this.addSql(`create index \"messages_type_idx\" on \"messages\" (\"type\", \"tenant_id\");`);\n this.addSql(`create index \"messages_thread_idx\" on \"messages\" (\"thread_id\");`);\n this.addSql(`create index \"messages_sender_idx\" on \"messages\" (\"sender_user_id\", \"sent_at\");`);\n\n this.addSql(`create table \"message_access_tokens\" (\"id\" uuid not null default gen_random_uuid(), \"message_id\" uuid not null, \"recipient_user_id\" uuid not null, \"token\" text not null, \"expires_at\" timestamptz not null, \"used_at\" timestamptz null, \"use_count\" int not null default 0, \"created_at\" timestamptz not null, constraint \"message_access_tokens_pkey\" primary key (\"id\"));`);\n this.addSql(`alter table \"message_access_tokens\" add constraint \"message_access_tokens_token_unique\" unique (\"token\");`);\n this.addSql(`create index \"message_access_tokens_message_idx\" on \"message_access_tokens\" (\"message_id\");`);\n this.addSql(`create index \"message_access_tokens_token_idx\" on \"message_access_tokens\" (\"token\");`);\n\n this.addSql(`create table \"message_objects\" (\"id\" uuid not null default gen_random_uuid(), \"message_id\" uuid not null, \"entity_module\" text not null, \"entity_type\" text not null, \"entity_id\" uuid not null, \"action_required\" boolean not null default false, \"action_type\" text null, \"action_label\" text null, \"entity_snapshot\" jsonb null, \"created_at\" timestamptz not null, constraint \"message_objects_pkey\" primary key (\"id\"));`);\n this.addSql(`create index \"message_objects_entity_idx\" on \"message_objects\" (\"entity_type\", \"entity_id\");`);\n this.addSql(`create index \"message_objects_message_idx\" on \"message_objects\" (\"message_id\");`);\n\n this.addSql(`create table \"message_recipients\" (\"id\" uuid not null default gen_random_uuid(), \"message_id\" uuid not null, \"recipient_user_id\" uuid not null, \"recipient_type\" text not null default 'to', \"status\" text not null default 'unread', \"read_at\" timestamptz null, \"archived_at\" timestamptz null, \"deleted_at\" timestamptz null, \"email_sent_at\" timestamptz null, \"email_delivered_at\" timestamptz null, \"email_opened_at\" timestamptz null, \"email_failed_at\" timestamptz null, \"email_error\" text null, \"created_at\" timestamptz not null, constraint \"message_recipients_pkey\" primary key (\"id\"));`);\n this.addSql(`alter table \"message_recipients\" add constraint \"message_recipients_message_user_unique\" unique (\"message_id\", \"recipient_user_id\");`);\n this.addSql(`create index \"message_recipients_message_idx\" on \"message_recipients\" (\"message_id\");`);\n this.addSql(`create index \"message_recipients_user_idx\" on \"message_recipients\" (\"recipient_user_id\", \"status\");`);\n }\n\n override async down(): Promise<void> {\n this.addSql(`drop table if exists \"message_recipients\" cascade;`);\n this.addSql(`drop table if exists \"message_objects\" cascade;`);\n this.addSql(`drop table if exists \"message_access_tokens\" cascade;`);\n this.addSql(`drop table if exists \"messages\" cascade;`);\n }\n\n}\n"],
5
+ "mappings": "AAAA,SAAS,iBAAiB;AAEnB,MAAM,gCAAgC,UAAU;AAAA,EAErD,MAAe,KAAoB;AACjC,SAAK,OAAO,wlCAAwlC;AACpmC,SAAK,OAAO,oFAAoF;AAChG,SAAK,OAAO,uEAAuE;AACnF,SAAK,OAAO,iEAAiE;AAC7E,SAAK,OAAO,iFAAiF;AAE7F,SAAK,OAAO,8WAA8W;AAC1X,SAAK,OAAO,2GAA2G;AACvH,SAAK,OAAO,6FAA6F;AACzG,SAAK,OAAO,sFAAsF;AAElG,SAAK,OAAO,+ZAA+Z;AAC3a,SAAK,OAAO,8FAA8F;AAC1G,SAAK,OAAO,iFAAiF;AAE7F,SAAK,OAAO,ykBAAykB;AACrlB,SAAK,OAAO,sIAAsI;AAClJ,SAAK,OAAO,uFAAuF;AACnG,SAAK,OAAO,qGAAqG;AAAA,EACnH;AAAA,EAEA,MAAe,OAAsB;AACnC,SAAK,OAAO,oDAAoD;AAChE,SAAK,OAAO,iDAAiD;AAC7D,SAAK,OAAO,uDAAuD;AACnE,SAAK,OAAO,0CAA0C;AAAA,EACxD;AAEF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,16 @@
1
+ import { Migration } from "@mikro-orm/migrations";
2
+ class Migration20260215165126 extends Migration {
3
+ async up() {
4
+ this.addSql(`create table "message_confirmations" ("id" uuid not null default gen_random_uuid(), "message_id" uuid not null, "tenant_id" uuid not null, "organization_id" uuid null, "confirmed" boolean not null default true, "confirmed_by_user_id" uuid null, "confirmed_at" timestamptz null, "created_at" timestamptz not null, "updated_at" timestamptz not null, constraint "message_confirmations_pkey" primary key ("id"));`);
5
+ this.addSql(`create index "message_confirmations_scope_idx" on "message_confirmations" ("tenant_id", "organization_id");`);
6
+ this.addSql(`create index "message_confirmations_message_idx" on "message_confirmations" ("message_id");`);
7
+ this.addSql(`alter table "message_confirmations" add constraint "message_confirmations_message_unique" unique ("message_id");`);
8
+ }
9
+ async down() {
10
+ this.addSql(`drop table if exists "message_confirmations" cascade;`);
11
+ }
12
+ }
13
+ export {
14
+ Migration20260215165126
15
+ };
16
+ //# sourceMappingURL=Migration20260215165126.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/messages/migrations/Migration20260215165126.ts"],
4
+ "sourcesContent": ["import { Migration } from '@mikro-orm/migrations';\n\nexport class Migration20260215165126 extends Migration {\n\n override async up(): Promise<void> {\n this.addSql(`create table \"message_confirmations\" (\"id\" uuid not null default gen_random_uuid(), \"message_id\" uuid not null, \"tenant_id\" uuid not null, \"organization_id\" uuid null, \"confirmed\" boolean not null default true, \"confirmed_by_user_id\" uuid null, \"confirmed_at\" timestamptz null, \"created_at\" timestamptz not null, \"updated_at\" timestamptz not null, constraint \"message_confirmations_pkey\" primary key (\"id\"));`);\n this.addSql(`create index \"message_confirmations_scope_idx\" on \"message_confirmations\" (\"tenant_id\", \"organization_id\");`);\n this.addSql(`create index \"message_confirmations_message_idx\" on \"message_confirmations\" (\"message_id\");`);\n this.addSql(`alter table \"message_confirmations\" add constraint \"message_confirmations_message_unique\" unique (\"message_id\");`);\n }\n\n override async down(): Promise<void> {\n this.addSql(`drop table if exists \"message_confirmations\" cascade;`);\n }\n\n}\n"],
5
+ "mappings": "AAAA,SAAS,iBAAiB;AAEnB,MAAM,gCAAgC,UAAU;AAAA,EAErD,MAAe,KAAoB;AACjC,SAAK,OAAO,0ZAA0Z;AACta,SAAK,OAAO,6GAA6G;AACzH,SAAK,OAAO,6FAA6F;AACzG,SAAK,OAAO,kHAAkH;AAAA,EAChI;AAAA,EAEA,MAAe,OAAsB;AACnC,SAAK,OAAO,uDAAuD;AAAA,EACrE;AAEF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,27 @@
1
+ const notificationTypes = [
2
+ {
3
+ type: "messages.new",
4
+ module: "messages",
5
+ titleKey: "messages.notifications.new.title",
6
+ bodyKey: "messages.notifications.new.body",
7
+ icon: "mail",
8
+ severity: "info",
9
+ actions: [
10
+ {
11
+ id: "view",
12
+ labelKey: "common.view",
13
+ variant: "outline",
14
+ href: "/backend/messages/{sourceEntityId}",
15
+ icon: "external-link"
16
+ }
17
+ ],
18
+ linkHref: "/backend/messages/{sourceEntityId}",
19
+ expiresAfterHours: 168
20
+ }
21
+ ];
22
+ var notifications_default = notificationTypes;
23
+ export {
24
+ notifications_default as default,
25
+ notificationTypes
26
+ };
27
+ //# sourceMappingURL=notifications.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/modules/messages/notifications.ts"],
4
+ "sourcesContent": ["import type { NotificationTypeDefinition } from '@open-mercato/shared/modules/notifications/types'\n\nexport const notificationTypes: NotificationTypeDefinition[] = [\n {\n type: 'messages.new',\n module: 'messages',\n titleKey: 'messages.notifications.new.title',\n bodyKey: 'messages.notifications.new.body',\n icon: 'mail',\n severity: 'info',\n actions: [\n {\n id: 'view',\n labelKey: 'common.view',\n variant: 'outline',\n href: '/backend/messages/{sourceEntityId}',\n icon: 'external-link',\n },\n ],\n linkHref: '/backend/messages/{sourceEntityId}',\n expiresAfterHours: 168,\n },\n]\n\nexport default notificationTypes\n"],
5
+ "mappings": "AAEO,MAAM,oBAAkD;AAAA,EAC7D;AAAA,IACE,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,SAAS;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP;AAAA,QACE,IAAI;AAAA,QACJ,UAAU;AAAA,QACV,SAAS;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,mBAAmB;AAAA,EACrB;AACF;AAEA,IAAO,wBAAQ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,21 @@
1
+ const setup = {
2
+ defaultRoleFeatures: {
3
+ superadmin: ["messages.*"],
4
+ admin: [
5
+ "messages.*"
6
+ ],
7
+ employee: [
8
+ "messages.view",
9
+ "messages.compose",
10
+ "messages.attach",
11
+ "messages.attach_files",
12
+ "messages.actions"
13
+ ]
14
+ }
15
+ };
16
+ var setup_default = setup;
17
+ export {
18
+ setup_default as default,
19
+ setup
20
+ };
21
+ //# sourceMappingURL=setup.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/modules/messages/setup.ts"],
4
+ "sourcesContent": ["import type { ModuleSetupConfig } from '@open-mercato/shared/modules/setup'\n\nexport const setup: ModuleSetupConfig = {\n defaultRoleFeatures: {\n superadmin: ['messages.*'],\n admin: [\n 'messages.*',\n ],\n employee: [\n 'messages.view',\n 'messages.compose',\n 'messages.attach',\n 'messages.attach_files',\n 'messages.actions',\n ],\n },\n}\n\nexport default setup\n"],
5
+ "mappings": "AAEO,MAAM,QAA2B;AAAA,EACtC,qBAAqB;AAAA,IACnB,YAAY,CAAC,YAAY;AAAA,IACzB,OAAO;AAAA,MACL;AAAA,IACF;AAAA,IACA,UAAU;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAO,gBAAQ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,108 @@
1
+ import { findOneWithDecryption } from "@open-mercato/shared/lib/encryption/find";
2
+ import { createQueue } from "@open-mercato/queue";
3
+ import { buildBatchNotificationFromType } from "../../notifications/lib/notificationBuilder.js";
4
+ import { resolveNotificationService } from "../../notifications/lib/notificationService.js";
5
+ import {
6
+ MESSAGES_EMAIL_QUEUE_NAME
7
+ } from "../workers/send-email.worker.js";
8
+ import { User } from "../../auth/data/entities.js";
9
+ import { Message } from "../data/entities.js";
10
+ import { notificationTypes } from "../notifications.js";
11
+ const metadata = {
12
+ event: "messages.message.sent",
13
+ persistent: true,
14
+ id: "messages:queue-email-delivery"
15
+ };
16
+ async function resolveNotificationVariables(payload, ctx) {
17
+ try {
18
+ const em = ctx.resolve("em")?.fork();
19
+ if (!em) return { title: "", from: "" };
20
+ const scope = {
21
+ tenantId: payload.tenantId,
22
+ organizationId: payload.organizationId ?? null
23
+ };
24
+ const whereUser = {
25
+ id: payload.senderUserId,
26
+ tenantId: payload.tenantId,
27
+ deletedAt: null
28
+ };
29
+ if (payload.organizationId !== void 0) {
30
+ whereUser.organizationId = payload.organizationId;
31
+ }
32
+ const [message, sender] = await Promise.all([
33
+ findOneWithDecryption(
34
+ em,
35
+ Message,
36
+ {
37
+ id: payload.messageId,
38
+ tenantId: payload.tenantId,
39
+ deletedAt: null
40
+ },
41
+ void 0,
42
+ scope
43
+ ),
44
+ findOneWithDecryption(
45
+ em,
46
+ User,
47
+ whereUser,
48
+ void 0,
49
+ scope
50
+ )
51
+ ]);
52
+ return {
53
+ title: typeof message?.subject === "string" ? message.subject : "",
54
+ from: typeof sender?.name === "string" && sender.name.trim().length > 0 ? sender.name : typeof sender?.email === "string" ? sender.email : ""
55
+ };
56
+ } catch {
57
+ return { title: "", from: "" };
58
+ }
59
+ }
60
+ async function handle(payload, ctx) {
61
+ const uniqueRecipientUserIds = Array.from(new Set(payload.recipientUserIds));
62
+ const typeDef = notificationTypes.find((type) => type.type === "messages.new");
63
+ if (typeDef && uniqueRecipientUserIds.length > 0) {
64
+ const variables = await resolveNotificationVariables(payload, ctx);
65
+ const notificationService = resolveNotificationService(ctx);
66
+ const notificationInput = buildBatchNotificationFromType(typeDef, {
67
+ recipientUserIds: uniqueRecipientUserIds,
68
+ titleVariables: variables,
69
+ bodyVariables: variables,
70
+ sourceEntityType: "message",
71
+ sourceEntityId: payload.messageId,
72
+ linkHref: `/backend/messages/${payload.messageId}`
73
+ });
74
+ await notificationService.createBatch(notificationInput, {
75
+ tenantId: payload.tenantId,
76
+ organizationId: payload.organizationId ?? null
77
+ });
78
+ }
79
+ if (!payload.sendViaEmail) {
80
+ return;
81
+ }
82
+ const strategy = process.env.QUEUE_STRATEGY === "async" ? "async" : "local";
83
+ const emailQueue = createQueue(MESSAGES_EMAIL_QUEUE_NAME, strategy);
84
+ for (const recipientUserId of uniqueRecipientUserIds) {
85
+ await emailQueue.enqueue({
86
+ type: "recipient",
87
+ messageId: payload.messageId,
88
+ recipientUserId,
89
+ tenantId: payload.tenantId,
90
+ organizationId: payload.organizationId ?? null
91
+ });
92
+ }
93
+ const externalEmail = payload.externalEmail?.trim();
94
+ if (externalEmail) {
95
+ await emailQueue.enqueue({
96
+ type: "external",
97
+ messageId: payload.messageId,
98
+ email: externalEmail,
99
+ tenantId: payload.tenantId,
100
+ organizationId: payload.organizationId ?? null
101
+ });
102
+ }
103
+ }
104
+ export {
105
+ handle as default,
106
+ metadata
107
+ };
108
+ //# sourceMappingURL=message-notification.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/messages/subscribers/message-notification.ts"],
4
+ "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { createQueue } from '@open-mercato/queue'\nimport { buildBatchNotificationFromType } from '../../notifications/lib/notificationBuilder'\nimport { resolveNotificationService } from '../../notifications/lib/notificationService'\nimport {\n MESSAGES_EMAIL_QUEUE_NAME,\n type SendMessageEmailJob,\n} from '../workers/send-email.worker'\nimport { User } from '../../auth/data/entities'\nimport { Message } from '../data/entities'\nimport { notificationTypes } from '../notifications'\n\nexport const metadata = {\n event: 'messages.message.sent',\n persistent: true,\n id: 'messages:queue-email-delivery',\n}\n\ntype MessageSentPayload = {\n messageId: string\n senderUserId: string\n recipientUserIds: string[]\n sendViaEmail: boolean\n externalEmail?: string | null\n forwardedFrom?: string\n replyTo?: string\n tenantId: string\n organizationId?: string | null\n}\n\ntype ResolverContext = {\n resolve: <T = unknown>(name: string) => T\n}\n\nasync function resolveNotificationVariables(payload: MessageSentPayload, ctx: ResolverContext): Promise<{ title: string; from: string }> {\n try {\n const em = ctx.resolve<EntityManager>('em')?.fork()\n if (!em) return { title: '', from: '' }\n\n const scope = {\n tenantId: payload.tenantId,\n organizationId: payload.organizationId ?? null,\n }\n const whereUser: { id: string; tenantId: string; deletedAt: null; organizationId?: string | null } = {\n id: payload.senderUserId,\n tenantId: payload.tenantId,\n deletedAt: null,\n }\n if (payload.organizationId !== undefined) {\n whereUser.organizationId = payload.organizationId\n }\n\n const [message, sender] = await Promise.all([\n findOneWithDecryption(\n em,\n Message,\n {\n id: payload.messageId,\n tenantId: payload.tenantId,\n deletedAt: null,\n },\n undefined,\n scope,\n ),\n findOneWithDecryption(\n em,\n User,\n whereUser,\n undefined,\n scope,\n ),\n ])\n\n return {\n title: typeof message?.subject === 'string' ? message.subject : '',\n from: typeof sender?.name === 'string' && sender.name.trim().length > 0\n ? sender.name\n : typeof sender?.email === 'string'\n ? sender.email\n : '',\n }\n } catch {\n return { title: '', from: '' }\n }\n}\n\n\nexport default async function handle(payload: MessageSentPayload, ctx: ResolverContext): Promise<void> {\n const uniqueRecipientUserIds = Array.from(new Set(payload.recipientUserIds))\n\n const typeDef = notificationTypes.find((type) => type.type === 'messages.new')\n if (typeDef && uniqueRecipientUserIds.length > 0) {\n const variables = await resolveNotificationVariables(payload, ctx)\n const notificationService = resolveNotificationService(ctx)\n const notificationInput = buildBatchNotificationFromType(typeDef, {\n recipientUserIds: uniqueRecipientUserIds,\n titleVariables: variables,\n bodyVariables: variables,\n sourceEntityType: 'message',\n sourceEntityId: payload.messageId,\n linkHref: `/backend/messages/${payload.messageId}`,\n })\n await notificationService.createBatch(notificationInput, {\n tenantId: payload.tenantId,\n organizationId: payload.organizationId ?? null,\n })\n }\n\n if (!payload.sendViaEmail) {\n return\n }\n\n const strategy = process.env.QUEUE_STRATEGY === 'async' ? 'async' : 'local'\n\n const emailQueue = createQueue<SendMessageEmailJob>(MESSAGES_EMAIL_QUEUE_NAME, strategy)\n\n for (const recipientUserId of uniqueRecipientUserIds) {\n await emailQueue.enqueue({\n type: 'recipient',\n messageId: payload.messageId,\n recipientUserId,\n tenantId: payload.tenantId,\n organizationId: payload.organizationId ?? null,\n })\n }\n\n const externalEmail = payload.externalEmail?.trim()\n if (externalEmail) {\n await emailQueue.enqueue({\n type: 'external',\n messageId: payload.messageId,\n email: externalEmail,\n tenantId: payload.tenantId,\n organizationId: payload.organizationId ?? null,\n })\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,253 @@
1
+ import { findOneWithDecryption } from "@open-mercato/shared/lib/encryption/find";
2
+ import { User } from "../../auth/data/entities.js";
3
+ import { Message, MessageObject, MessageRecipient } from "../data/entities.js";
4
+ import { emitMessagesEvent } from "../events.js";
5
+ import { getMessageEmailAttachments } from "../lib/attachments.js";
6
+ import {
7
+ sendMessageEmailToExternal,
8
+ sendMessageEmailToRecipient
9
+ } from "../lib/email-sender.js";
10
+ const MESSAGES_EMAIL_QUEUE_NAME = "messages-email";
11
+ const metadata = {
12
+ queue: MESSAGES_EMAIL_QUEUE_NAME,
13
+ id: "messages:send-email",
14
+ concurrency: 10
15
+ };
16
+ async function emitEmailDeliveryEvent(ctx, eventId, payload) {
17
+ const eventBus = ctx.resolve("eventBus");
18
+ if (!eventBus || typeof eventBus !== "object" || typeof eventBus.emit !== "function") {
19
+ return;
20
+ }
21
+ await emitMessagesEvent(eventId, payload, { persistent: true });
22
+ }
23
+ async function resolveSender(em, message) {
24
+ const sender = await findOneWithDecryption(
25
+ em,
26
+ User,
27
+ {
28
+ id: message.senderUserId,
29
+ tenantId: message.tenantId,
30
+ deletedAt: null
31
+ },
32
+ void 0,
33
+ { tenantId: message.tenantId, organizationId: message.organizationId ?? null }
34
+ );
35
+ return {
36
+ name: sender?.name ?? null,
37
+ email: sender?.email ?? null
38
+ };
39
+ }
40
+ async function resolveMessageScope(em, payload) {
41
+ return await em.findOne(Message, {
42
+ id: payload.messageId,
43
+ tenantId: payload.tenantId,
44
+ organizationId: payload.organizationId ?? null,
45
+ deletedAt: null
46
+ });
47
+ }
48
+ async function claimRecipientDelivery(em, payload) {
49
+ const claimTimestamp = /* @__PURE__ */ new Date();
50
+ const updatedRows = await em.nativeUpdate(
51
+ MessageRecipient,
52
+ {
53
+ messageId: payload.messageId,
54
+ recipientUserId: payload.recipientUserId,
55
+ emailSentAt: null
56
+ },
57
+ {
58
+ emailSentAt: claimTimestamp,
59
+ emailFailedAt: null,
60
+ emailError: null
61
+ }
62
+ );
63
+ return updatedRows > 0 ? claimTimestamp : null;
64
+ }
65
+ async function releaseRecipientClaim(em, payload, claimTimestamp, errorMessage) {
66
+ await em.nativeUpdate(
67
+ MessageRecipient,
68
+ {
69
+ messageId: payload.messageId,
70
+ recipientUserId: payload.recipientUserId,
71
+ emailSentAt: claimTimestamp
72
+ },
73
+ {
74
+ emailSentAt: null,
75
+ emailFailedAt: /* @__PURE__ */ new Date(),
76
+ emailError: errorMessage
77
+ }
78
+ );
79
+ }
80
+ async function claimExternalDelivery(em, payload) {
81
+ const claimTimestamp = /* @__PURE__ */ new Date();
82
+ const updatedRows = await em.nativeUpdate(
83
+ Message,
84
+ {
85
+ id: payload.messageId,
86
+ tenantId: payload.tenantId,
87
+ organizationId: payload.organizationId ?? null,
88
+ externalEmailSentAt: null
89
+ },
90
+ {
91
+ externalEmailSentAt: claimTimestamp,
92
+ externalEmailFailedAt: null,
93
+ externalEmailError: null
94
+ }
95
+ );
96
+ return updatedRows > 0 ? claimTimestamp : null;
97
+ }
98
+ async function releaseExternalClaim(em, payload, claimTimestamp, errorMessage) {
99
+ await em.nativeUpdate(
100
+ Message,
101
+ {
102
+ id: payload.messageId,
103
+ tenantId: payload.tenantId,
104
+ organizationId: payload.organizationId ?? null,
105
+ externalEmailSentAt: claimTimestamp
106
+ },
107
+ {
108
+ externalEmailSentAt: null,
109
+ externalEmailFailedAt: /* @__PURE__ */ new Date(),
110
+ externalEmailError: errorMessage
111
+ }
112
+ );
113
+ }
114
+ async function handle(job, ctx) {
115
+ const { payload } = job;
116
+ const em = ctx.resolve("em").fork();
117
+ const message = await resolveMessageScope(em, payload);
118
+ if (!message) {
119
+ console.error("[messages:send-email] Message not found", payload.messageId);
120
+ return;
121
+ }
122
+ const objects = await em.find(MessageObject, { messageId: message.id });
123
+ const attachments = await getMessageEmailAttachments(
124
+ em,
125
+ message.id,
126
+ message.organizationId ?? null,
127
+ message.tenantId
128
+ );
129
+ const sender = await resolveSender(em, message);
130
+ if (payload.type === "external") {
131
+ const externalClaimTimestamp = await claimExternalDelivery(em, payload);
132
+ if (!externalClaimTimestamp) {
133
+ return;
134
+ }
135
+ try {
136
+ await sendMessageEmailToExternal({
137
+ message,
138
+ email: payload.email,
139
+ sender,
140
+ objects,
141
+ attachments
142
+ });
143
+ await emitEmailDeliveryEvent(ctx, "messages.message.email_sent", {
144
+ messageId: message.id,
145
+ target: "external",
146
+ email: payload.email,
147
+ tenantId: message.tenantId,
148
+ organizationId: message.organizationId ?? null
149
+ });
150
+ } catch (error) {
151
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
152
+ await releaseExternalClaim(
153
+ em,
154
+ payload,
155
+ externalClaimTimestamp,
156
+ errorMessage
157
+ );
158
+ await emitEmailDeliveryEvent(ctx, "messages.message.email_failed", {
159
+ messageId: message.id,
160
+ target: "external",
161
+ email: payload.email,
162
+ error: errorMessage,
163
+ tenantId: message.tenantId,
164
+ organizationId: message.organizationId ?? null
165
+ });
166
+ console.error("[messages:send-email] External email send failed", error);
167
+ }
168
+ return;
169
+ }
170
+ const recipientRecord = await em.findOne(MessageRecipient, {
171
+ messageId: payload.messageId,
172
+ recipientUserId: payload.recipientUserId
173
+ });
174
+ if (!recipientRecord) {
175
+ console.error("[messages:send-email] Recipient row not found", payload);
176
+ return;
177
+ }
178
+ if (recipientRecord.emailSentAt) {
179
+ return;
180
+ }
181
+ const recipientClaimTimestamp = await claimRecipientDelivery(em, payload);
182
+ if (!recipientClaimTimestamp) {
183
+ return;
184
+ }
185
+ const recipientUser = await findOneWithDecryption(
186
+ em,
187
+ User,
188
+ {
189
+ id: payload.recipientUserId,
190
+ tenantId: message.tenantId,
191
+ deletedAt: null
192
+ },
193
+ void 0,
194
+ { tenantId: message.tenantId, organizationId: message.organizationId ?? null }
195
+ );
196
+ const recipientEmail = recipientUser?.email?.trim();
197
+ if (!recipientEmail) {
198
+ await releaseRecipientClaim(
199
+ em,
200
+ payload,
201
+ recipientClaimTimestamp,
202
+ "Recipient has no email address"
203
+ );
204
+ return;
205
+ }
206
+ try {
207
+ await sendMessageEmailToRecipient({
208
+ em,
209
+ message,
210
+ recipientUserId: payload.recipientUserId,
211
+ recipientEmail,
212
+ sender,
213
+ objects,
214
+ attachments
215
+ });
216
+ await emitEmailDeliveryEvent(ctx, "messages.message.email_sent", {
217
+ messageId: message.id,
218
+ target: "recipient",
219
+ recipientUserId: payload.recipientUserId,
220
+ email: recipientEmail,
221
+ tenantId: message.tenantId,
222
+ organizationId: message.organizationId ?? null
223
+ });
224
+ } catch (error) {
225
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
226
+ await releaseRecipientClaim(
227
+ em,
228
+ payload,
229
+ recipientClaimTimestamp,
230
+ errorMessage
231
+ );
232
+ await emitEmailDeliveryEvent(ctx, "messages.message.email_failed", {
233
+ messageId: message.id,
234
+ target: "recipient",
235
+ recipientUserId: payload.recipientUserId,
236
+ email: recipientEmail,
237
+ error: errorMessage,
238
+ tenantId: message.tenantId,
239
+ organizationId: message.organizationId ?? null
240
+ });
241
+ console.error("[messages:send-email] Recipient email send failed", error);
242
+ }
243
+ }
244
+ export {
245
+ MESSAGES_EMAIL_QUEUE_NAME,
246
+ claimExternalDelivery,
247
+ claimRecipientDelivery,
248
+ handle as default,
249
+ metadata,
250
+ releaseExternalClaim,
251
+ releaseRecipientClaim
252
+ };
253
+ //# sourceMappingURL=send-email.worker.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/messages/workers/send-email.worker.ts"],
4
+ "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport type { JobContext, QueuedJob, WorkerMeta } from '@open-mercato/queue'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { User } from '../../auth/data/entities'\nimport { Message, MessageObject, MessageRecipient } from '../data/entities'\nimport { emitMessagesEvent } from '../events'\nimport { getMessageEmailAttachments } from '../lib/attachments'\nimport {\n sendMessageEmailToExternal,\n sendMessageEmailToRecipient,\n} from '../lib/email-sender'\n\nexport const MESSAGES_EMAIL_QUEUE_NAME = 'messages-email'\n\nexport type SendMessageEmailToRecipientJob = {\n type: 'recipient'\n messageId: string\n recipientUserId: string\n tenantId: string\n organizationId?: string | null\n}\n\nexport type SendMessageEmailToExternalJob = {\n type: 'external'\n messageId: string\n email: string\n tenantId: string\n organizationId?: string | null\n}\n\nexport type SendMessageEmailJob = SendMessageEmailToRecipientJob | SendMessageEmailToExternalJob\n\nexport const metadata: WorkerMeta = {\n queue: MESSAGES_EMAIL_QUEUE_NAME,\n id: 'messages:send-email',\n concurrency: 10,\n}\n\ntype HandlerContext = {\n resolve: <T = unknown>(name: string) => T\n}\n\nasync function emitEmailDeliveryEvent(\n ctx: HandlerContext,\n eventId: 'messages.message.email_sent' | 'messages.message.email_failed',\n payload: {\n messageId: string\n target: 'recipient' | 'external'\n recipientUserId?: string\n email?: string\n error?: string\n tenantId: string\n organizationId?: string | null\n }\n) {\n const eventBus = ctx.resolve<{ emit?: unknown } | null>('eventBus')\n if (!eventBus || typeof eventBus !== 'object' || typeof (eventBus as { emit?: unknown }).emit !== 'function') {\n return\n }\n await emitMessagesEvent(eventId, payload, { persistent: true })\n}\n\nasync function resolveSender(em: EntityManager, message: Message) {\n const sender = await findOneWithDecryption(\n em,\n User,\n {\n id: message.senderUserId,\n tenantId: message.tenantId,\n deletedAt: null,\n },\n undefined,\n { tenantId: message.tenantId, organizationId: message.organizationId ?? null }\n )\n return {\n name: sender?.name ?? null,\n email: sender?.email ?? null,\n }\n}\n\nasync function resolveMessageScope(\n em: EntityManager,\n payload: SendMessageEmailJob\n) {\n return await em.findOne(Message, {\n id: payload.messageId,\n tenantId: payload.tenantId,\n organizationId: payload.organizationId ?? null,\n deletedAt: null,\n })\n}\n\nexport async function claimRecipientDelivery(\n em: EntityManager,\n payload: SendMessageEmailToRecipientJob,\n): Promise<Date | null> {\n const claimTimestamp = new Date()\n const updatedRows = await em.nativeUpdate(\n MessageRecipient,\n {\n messageId: payload.messageId,\n recipientUserId: payload.recipientUserId,\n emailSentAt: null,\n },\n {\n emailSentAt: claimTimestamp,\n emailFailedAt: null,\n emailError: null,\n },\n )\n return updatedRows > 0 ? claimTimestamp : null\n}\n\nexport async function releaseRecipientClaim(\n em: EntityManager,\n payload: SendMessageEmailToRecipientJob,\n claimTimestamp: Date,\n errorMessage: string,\n): Promise<void> {\n await em.nativeUpdate(\n MessageRecipient,\n {\n messageId: payload.messageId,\n recipientUserId: payload.recipientUserId,\n emailSentAt: claimTimestamp,\n },\n {\n emailSentAt: null,\n emailFailedAt: new Date(),\n emailError: errorMessage,\n },\n )\n}\n\nexport async function claimExternalDelivery(\n em: EntityManager,\n payload: SendMessageEmailToExternalJob,\n): Promise<Date | null> {\n const claimTimestamp = new Date()\n const updatedRows = await em.nativeUpdate(\n Message,\n {\n id: payload.messageId,\n tenantId: payload.tenantId,\n organizationId: payload.organizationId ?? null,\n externalEmailSentAt: null,\n },\n {\n externalEmailSentAt: claimTimestamp,\n externalEmailFailedAt: null,\n externalEmailError: null,\n },\n )\n return updatedRows > 0 ? claimTimestamp : null\n}\n\nexport async function releaseExternalClaim(\n em: EntityManager,\n payload: SendMessageEmailToExternalJob,\n claimTimestamp: Date,\n errorMessage: string,\n): Promise<void> {\n await em.nativeUpdate(\n Message,\n {\n id: payload.messageId,\n tenantId: payload.tenantId,\n organizationId: payload.organizationId ?? null,\n externalEmailSentAt: claimTimestamp,\n },\n {\n externalEmailSentAt: null,\n externalEmailFailedAt: new Date(),\n externalEmailError: errorMessage,\n },\n )\n}\n\nexport default async function handle(\n job: QueuedJob<SendMessageEmailJob>,\n ctx: JobContext & HandlerContext\n): Promise<void> {\n const { payload } = job\n const em = (ctx.resolve('em') as EntityManager).fork()\n\n const message = await resolveMessageScope(em, payload)\n if (!message) {\n console.error('[messages:send-email] Message not found', payload.messageId)\n return\n }\n\n const objects = await em.find(MessageObject, { messageId: message.id })\n const attachments = await getMessageEmailAttachments(\n em,\n message.id,\n message.organizationId ?? null,\n message.tenantId\n )\n const sender = await resolveSender(em, message)\n\n if (payload.type === 'external') {\n const externalClaimTimestamp = await claimExternalDelivery(em, payload)\n if (!externalClaimTimestamp) {\n return\n }\n\n try {\n await sendMessageEmailToExternal({\n message,\n email: payload.email,\n sender,\n objects,\n attachments,\n })\n await emitEmailDeliveryEvent(ctx, 'messages.message.email_sent', {\n messageId: message.id,\n target: 'external',\n email: payload.email,\n tenantId: message.tenantId,\n organizationId: message.organizationId ?? null,\n })\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error'\n await releaseExternalClaim(\n em,\n payload,\n externalClaimTimestamp,\n errorMessage,\n )\n await emitEmailDeliveryEvent(ctx, 'messages.message.email_failed', {\n messageId: message.id,\n target: 'external',\n email: payload.email,\n error: errorMessage,\n tenantId: message.tenantId,\n organizationId: message.organizationId ?? null,\n })\n console.error('[messages:send-email] External email send failed', error)\n }\n return\n }\n\n const recipientRecord = await em.findOne(MessageRecipient, {\n messageId: payload.messageId,\n recipientUserId: payload.recipientUserId,\n })\n if (!recipientRecord) {\n console.error('[messages:send-email] Recipient row not found', payload)\n return\n }\n\n if (recipientRecord.emailSentAt) {\n return\n }\n\n const recipientClaimTimestamp = await claimRecipientDelivery(em, payload)\n if (!recipientClaimTimestamp) {\n return\n }\n\n const recipientUser = await findOneWithDecryption(\n em,\n User,\n {\n id: payload.recipientUserId,\n tenantId: message.tenantId,\n deletedAt: null,\n },\n undefined,\n { tenantId: message.tenantId, organizationId: message.organizationId ?? null }\n )\n\n const recipientEmail = recipientUser?.email?.trim()\n if (!recipientEmail) {\n await releaseRecipientClaim(\n em,\n payload,\n recipientClaimTimestamp,\n 'Recipient has no email address',\n )\n return\n }\n\n try {\n await sendMessageEmailToRecipient({\n em,\n message,\n recipientUserId: payload.recipientUserId,\n recipientEmail,\n sender,\n objects,\n attachments,\n })\n await emitEmailDeliveryEvent(ctx, 'messages.message.email_sent', {\n messageId: message.id,\n target: 'recipient',\n recipientUserId: payload.recipientUserId,\n email: recipientEmail,\n tenantId: message.tenantId,\n organizationId: message.organizationId ?? null,\n })\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error'\n await releaseRecipientClaim(\n em,\n payload,\n recipientClaimTimestamp,\n errorMessage,\n )\n await emitEmailDeliveryEvent(ctx, 'messages.message.email_failed', {\n messageId: message.id,\n target: 'recipient',\n recipientUserId: payload.recipientUserId,\n email: recipientEmail,\n error: errorMessage,\n tenantId: message.tenantId,\n organizationId: message.organizationId ?? null,\n })\n console.error('[messages:send-email] Recipient email send failed', error)\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { useSearchParams, useRouter } from "next/navigation";
5
5
  import { Page, PageBody } from "@open-mercato/ui/backend/Page";
@@ -21,6 +21,7 @@ import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, D
21
21
  import { ArrowRightLeft, Building2, CreditCard, Mail, Pencil, Plus, Send, Store, Truck, UserRound, Wand2, X } from "lucide-react";
22
22
  import { FormHeader } from "@open-mercato/ui/backend/forms";
23
23
  import { VersionHistoryAction } from "@open-mercato/ui/backend/version-history";
24
+ import { SendObjectMessageDialog } from "@open-mercato/ui/backend/messages";
24
25
  import Link from "next/link";
25
26
  import { flash } from "@open-mercato/ui/backend/FlashMessages";
26
27
  import { apiCall, apiCallOrThrow, readApiResultOrThrow } from "@open-mercato/ui/backend/utils/apiCall";
@@ -3664,16 +3665,34 @@ function SalesDocumentDetailPage({
3664
3665
  mode: "detail",
3665
3666
  backHref: kind === "order" ? "/backend/sales/orders" : "/backend/sales/quotes",
3666
3667
  backLabel: t("sales.documents.detail.back", "Back to documents"),
3667
- utilityActions: record ? /* @__PURE__ */ jsx(
3668
- VersionHistoryAction,
3669
- {
3670
- config: {
3671
- resourceKind: kind === "order" ? "sales.order" : "sales.quote",
3672
- resourceId: record.id
3673
- },
3674
- t
3675
- }
3676
- ) : null,
3668
+ utilityActions: record ? /* @__PURE__ */ jsxs(Fragment, { children: [
3669
+ /* @__PURE__ */ jsx(
3670
+ SendObjectMessageDialog,
3671
+ {
3672
+ object: {
3673
+ entityModule: "sales",
3674
+ entityType: kind,
3675
+ entityId: record.id,
3676
+ sourceEntityType: kind === "order" ? "sales.order" : "sales.quote",
3677
+ sourceEntityId: record.id
3678
+ },
3679
+ defaultValues: {
3680
+ sourceEntityType: kind === "order" ? "sales.order" : "sales.quote",
3681
+ sourceEntityId: record.id
3682
+ }
3683
+ }
3684
+ ),
3685
+ /* @__PURE__ */ jsx(
3686
+ VersionHistoryAction,
3687
+ {
3688
+ config: {
3689
+ resourceKind: kind === "order" ? "sales.order" : "sales.quote",
3690
+ resourceId: record.id
3691
+ },
3692
+ t
3693
+ }
3694
+ )
3695
+ ] }) : null,
3677
3696
  entityTypeLabel: kind === "order" ? t("sales.documents.detail.order", "Sales order") : t("sales.documents.detail.quote", "Sales quote"),
3678
3697
  title: canEditNumber ? /* @__PURE__ */ jsx(
3679
3698
  InlineTextEditor,