@open-mercato/core 0.6.5-develop.4384.1.ce2ec6eaaa → 0.6.5-develop.4393.1.de282b5dfd

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 (533) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/dist/generated/entities/channel_ingest_dead_letter/index.js +25 -0
  3. package/dist/generated/entities/channel_ingest_dead_letter/index.js.map +7 -0
  4. package/dist/generated/entities/channel_thread_mapping/index.js +25 -0
  5. package/dist/generated/entities/channel_thread_mapping/index.js.map +7 -0
  6. package/dist/generated/entities/channel_thread_token/index.js +17 -0
  7. package/dist/generated/entities/channel_thread_token/index.js.map +7 -0
  8. package/dist/generated/entities/communication_channel/index.js +43 -0
  9. package/dist/generated/entities/communication_channel/index.js.map +7 -0
  10. package/dist/generated/entities/customer_interaction/index.js +4 -0
  11. package/dist/generated/entities/customer_interaction/index.js.map +2 -2
  12. package/dist/generated/entities/external_conversation/index.js +25 -0
  13. package/dist/generated/entities/external_conversation/index.js.map +7 -0
  14. package/dist/generated/entities/external_message/index.js +25 -0
  15. package/dist/generated/entities/external_message/index.js.map +7 -0
  16. package/dist/generated/entities/integration_credentials/index.js +3 -1
  17. package/dist/generated/entities/integration_credentials/index.js.map +2 -2
  18. package/dist/generated/entities/message/index.js +2 -0
  19. package/dist/generated/entities/message/index.js.map +2 -2
  20. package/dist/generated/entities/message_channel_link/index.js +33 -0
  21. package/dist/generated/entities/message_channel_link/index.js.map +7 -0
  22. package/dist/generated/entities/message_reaction/index.js +25 -0
  23. package/dist/generated/entities/message_reaction/index.js.map +7 -0
  24. package/dist/generated/entities.ids.generated.js +11 -0
  25. package/dist/generated/entities.ids.generated.js.map +2 -2
  26. package/dist/generated/entity-fields-registry.js +117 -0
  27. package/dist/generated/entity-fields-registry.js.map +2 -2
  28. package/dist/helpers/integration/authFixtures.js +2 -1
  29. package/dist/helpers/integration/authFixtures.js.map +2 -2
  30. package/dist/helpers/integration/communicationChannelsFixtures.js +58 -0
  31. package/dist/helpers/integration/communicationChannelsFixtures.js.map +7 -0
  32. package/dist/modules/communication_channels/acl.js +47 -0
  33. package/dist/modules/communication_channels/acl.js.map +7 -0
  34. package/dist/modules/communication_channels/api/delete/channels/[id]/route.js +133 -0
  35. package/dist/modules/communication_channels/api/delete/channels/[id]/route.js.map +7 -0
  36. package/dist/modules/communication_channels/api/delete/messages/[messageId]/reactions/[reactionId]/route.js +113 -0
  37. package/dist/modules/communication_channels/api/delete/messages/[messageId]/reactions/[reactionId]/route.js.map +7 -0
  38. package/dist/modules/communication_channels/api/get/channels/[id]/health/route.js +138 -0
  39. package/dist/modules/communication_channels/api/get/channels/[id]/health/route.js.map +7 -0
  40. package/dist/modules/communication_channels/api/get/channels/[id]/route.js +93 -0
  41. package/dist/modules/communication_channels/api/get/channels/[id]/route.js.map +7 -0
  42. package/dist/modules/communication_channels/api/get/channels/route.js +96 -0
  43. package/dist/modules/communication_channels/api/get/channels/route.js.map +7 -0
  44. package/dist/modules/communication_channels/api/get/me/channels/route.js +82 -0
  45. package/dist/modules/communication_channels/api/get/me/channels/route.js.map +7 -0
  46. package/dist/modules/communication_channels/api/get/oauth/[provider]/callback/route.js +274 -0
  47. package/dist/modules/communication_channels/api/get/oauth/[provider]/callback/route.js.map +7 -0
  48. package/dist/modules/communication_channels/api/post/channels/[id]/import-history/route.js +168 -0
  49. package/dist/modules/communication_channels/api/post/channels/[id]/import-history/route.js.map +7 -0
  50. package/dist/modules/communication_channels/api/post/channels/[id]/poll-now/route.js +143 -0
  51. package/dist/modules/communication_channels/api/post/channels/[id]/poll-now/route.js.map +7 -0
  52. package/dist/modules/communication_channels/api/post/channels/[id]/push/register/route.js +127 -0
  53. package/dist/modules/communication_channels/api/post/channels/[id]/push/register/route.js.map +7 -0
  54. package/dist/modules/communication_channels/api/post/channels/[id]/set-primary/route.js +99 -0
  55. package/dist/modules/communication_channels/api/post/channels/[id]/set-primary/route.js.map +7 -0
  56. package/dist/modules/communication_channels/api/post/channels/[id]/test-send/route.js +197 -0
  57. package/dist/modules/communication_channels/api/post/channels/[id]/test-send/route.js.map +7 -0
  58. package/dist/modules/communication_channels/api/post/channels/connect/credentials/route.js +124 -0
  59. package/dist/modules/communication_channels/api/post/channels/connect/credentials/route.js.map +7 -0
  60. package/dist/modules/communication_channels/api/post/messages/[messageId]/reactions/route.js +120 -0
  61. package/dist/modules/communication_channels/api/post/messages/[messageId]/reactions/route.js.map +7 -0
  62. package/dist/modules/communication_channels/api/post/oauth/[provider]/initiate/route.js +157 -0
  63. package/dist/modules/communication_channels/api/post/oauth/[provider]/initiate/route.js.map +7 -0
  64. package/dist/modules/communication_channels/api/post/send-as-user/route.js +115 -0
  65. package/dist/modules/communication_channels/api/post/send-as-user/route.js.map +7 -0
  66. package/dist/modules/communication_channels/api/post/test-seed/route.js +217 -0
  67. package/dist/modules/communication_channels/api/post/test-seed/route.js.map +7 -0
  68. package/dist/modules/communication_channels/api/post/webhook/[provider]/route.js +175 -0
  69. package/dist/modules/communication_channels/api/post/webhook/[provider]/route.js.map +7 -0
  70. package/dist/modules/communication_channels/api/post/webhooks/gmail/route.js +123 -0
  71. package/dist/modules/communication_channels/api/post/webhooks/gmail/route.js.map +7 -0
  72. package/dist/modules/communication_channels/api/put/threads/[threadId]/assign/route.js +117 -0
  73. package/dist/modules/communication_channels/api/put/threads/[threadId]/assign/route.js.map +7 -0
  74. package/dist/modules/communication_channels/backend/communication_channels/channels/[id]/page.js +180 -0
  75. package/dist/modules/communication_channels/backend/communication_channels/channels/[id]/page.js.map +7 -0
  76. package/dist/modules/communication_channels/backend/communication_channels/channels/[id]/page.meta.js +36 -0
  77. package/dist/modules/communication_channels/backend/communication_channels/channels/[id]/page.meta.js.map +7 -0
  78. package/dist/modules/communication_channels/backend/communication_channels/channels/page.js +107 -0
  79. package/dist/modules/communication_channels/backend/communication_channels/channels/page.js.map +7 -0
  80. package/dist/modules/communication_channels/backend/communication_channels/channels/page.meta.js +38 -0
  81. package/dist/modules/communication_channels/backend/communication_channels/channels/page.meta.js.map +7 -0
  82. package/dist/modules/communication_channels/backend/profile/communication-channels/page.js +727 -0
  83. package/dist/modules/communication_channels/backend/profile/communication-channels/page.js.map +7 -0
  84. package/dist/modules/communication_channels/backend/profile/communication-channels/page.meta.js +38 -0
  85. package/dist/modules/communication_channels/backend/profile/communication-channels/page.meta.js.map +7 -0
  86. package/dist/modules/communication_channels/commands/connect-credential-channel.js +154 -0
  87. package/dist/modules/communication_channels/commands/connect-credential-channel.js.map +7 -0
  88. package/dist/modules/communication_channels/commands/delete-channel.js +137 -0
  89. package/dist/modules/communication_channels/commands/delete-channel.js.map +7 -0
  90. package/dist/modules/communication_channels/commands/deliver-outbound-message.js +400 -0
  91. package/dist/modules/communication_channels/commands/deliver-outbound-message.js.map +7 -0
  92. package/dist/modules/communication_channels/commands/disconnect-channel.js +163 -0
  93. package/dist/modules/communication_channels/commands/disconnect-channel.js.map +7 -0
  94. package/dist/modules/communication_channels/commands/ingest-inbound-message.js +413 -0
  95. package/dist/modules/communication_channels/commands/ingest-inbound-message.js.map +7 -0
  96. package/dist/modules/communication_channels/commands/interceptors.js +68 -0
  97. package/dist/modules/communication_channels/commands/interceptors.js.map +7 -0
  98. package/dist/modules/communication_channels/commands/process-inbound-reaction.js +198 -0
  99. package/dist/modules/communication_channels/commands/process-inbound-reaction.js.map +7 -0
  100. package/dist/modules/communication_channels/commands/push-register.js +146 -0
  101. package/dist/modules/communication_channels/commands/push-register.js.map +7 -0
  102. package/dist/modules/communication_channels/commands/push-renew.js +23 -0
  103. package/dist/modules/communication_channels/commands/push-renew.js.map +7 -0
  104. package/dist/modules/communication_channels/commands/push-unregister.js +108 -0
  105. package/dist/modules/communication_channels/commands/push-unregister.js.map +7 -0
  106. package/dist/modules/communication_channels/commands/queue-import-history.js +113 -0
  107. package/dist/modules/communication_channels/commands/queue-import-history.js.map +7 -0
  108. package/dist/modules/communication_channels/commands/reassign-conversation.js +193 -0
  109. package/dist/modules/communication_channels/commands/reassign-conversation.js.map +7 -0
  110. package/dist/modules/communication_channels/commands/set-primary-channel.js +114 -0
  111. package/dist/modules/communication_channels/commands/set-primary-channel.js.map +7 -0
  112. package/dist/modules/communication_channels/commands/toggle-outbound-reaction.js +260 -0
  113. package/dist/modules/communication_channels/commands/toggle-outbound-reaction.js.map +7 -0
  114. package/dist/modules/communication_channels/data/enrichers.js +286 -0
  115. package/dist/modules/communication_channels/data/enrichers.js.map +7 -0
  116. package/dist/modules/communication_channels/data/entities.js +447 -0
  117. package/dist/modules/communication_channels/data/entities.js.map +7 -0
  118. package/dist/modules/communication_channels/data/extensions.js +67 -0
  119. package/dist/modules/communication_channels/data/extensions.js.map +7 -0
  120. package/dist/modules/communication_channels/data/validators.js +123 -0
  121. package/dist/modules/communication_channels/data/validators.js.map +7 -0
  122. package/dist/modules/communication_channels/di.js +35 -0
  123. package/dist/modules/communication_channels/di.js.map +7 -0
  124. package/dist/modules/communication_channels/encryption.js +12 -0
  125. package/dist/modules/communication_channels/encryption.js.map +7 -0
  126. package/dist/modules/communication_channels/events.js +124 -0
  127. package/dist/modules/communication_channels/events.js.map +7 -0
  128. package/dist/modules/communication_channels/index.js +20 -0
  129. package/dist/modules/communication_channels/index.js.map +7 -0
  130. package/dist/modules/communication_channels/lib/access-control.js +43 -0
  131. package/dist/modules/communication_channels/lib/access-control.js.map +7 -0
  132. package/dist/modules/communication_channels/lib/adapter-compat.js +36 -0
  133. package/dist/modules/communication_channels/lib/adapter-compat.js.map +7 -0
  134. package/dist/modules/communication_channels/lib/adapter-registry-singleton.js +22 -0
  135. package/dist/modules/communication_channels/lib/adapter-registry-singleton.js.map +7 -0
  136. package/dist/modules/communication_channels/lib/adapter.js +1 -0
  137. package/dist/modules/communication_channels/lib/adapter.js.map +7 -0
  138. package/dist/modules/communication_channels/lib/connect-channel.js +95 -0
  139. package/dist/modules/communication_channels/lib/connect-channel.js.map +7 -0
  140. package/dist/modules/communication_channels/lib/contact-resolver.js +79 -0
  141. package/dist/modules/communication_channels/lib/contact-resolver.js.map +7 -0
  142. package/dist/modules/communication_channels/lib/credential-refresh.js +97 -0
  143. package/dist/modules/communication_channels/lib/credential-refresh.js.map +7 -0
  144. package/dist/modules/communication_channels/lib/dead-letter.js +62 -0
  145. package/dist/modules/communication_channels/lib/dead-letter.js.map +7 -0
  146. package/dist/modules/communication_channels/lib/email-capabilities.js +47 -0
  147. package/dist/modules/communication_channels/lib/email-capabilities.js.map +7 -0
  148. package/dist/modules/communication_channels/lib/email-contact.js +14 -0
  149. package/dist/modules/communication_channels/lib/email-contact.js.map +7 -0
  150. package/dist/modules/communication_channels/lib/email-mime.js +259 -0
  151. package/dist/modules/communication_channels/lib/email-mime.js.map +7 -0
  152. package/dist/modules/communication_channels/lib/error-classification.js +101 -0
  153. package/dist/modules/communication_channels/lib/error-classification.js.map +7 -0
  154. package/dist/modules/communication_channels/lib/gmail-pubsub-jwt.js +185 -0
  155. package/dist/modules/communication_channels/lib/gmail-pubsub-jwt.js.map +7 -0
  156. package/dist/modules/communication_channels/lib/mutation-guards.js +114 -0
  157. package/dist/modules/communication_channels/lib/mutation-guards.js.map +7 -0
  158. package/dist/modules/communication_channels/lib/oauth-client-config.js +32 -0
  159. package/dist/modules/communication_channels/lib/oauth-client-config.js.map +7 -0
  160. package/dist/modules/communication_channels/lib/oauth-state.js +128 -0
  161. package/dist/modules/communication_channels/lib/oauth-state.js.map +7 -0
  162. package/dist/modules/communication_channels/lib/oauth-token.js +45 -0
  163. package/dist/modules/communication_channels/lib/oauth-token.js.map +7 -0
  164. package/dist/modules/communication_channels/lib/pg-errors.js +11 -0
  165. package/dist/modules/communication_channels/lib/pg-errors.js.map +7 -0
  166. package/dist/modules/communication_channels/lib/provider-health.js +24 -0
  167. package/dist/modules/communication_channels/lib/provider-health.js.map +7 -0
  168. package/dist/modules/communication_channels/lib/push-state.js +19 -0
  169. package/dist/modules/communication_channels/lib/push-state.js.map +7 -0
  170. package/dist/modules/communication_channels/lib/queue.js +54 -0
  171. package/dist/modules/communication_channels/lib/queue.js.map +7 -0
  172. package/dist/modules/communication_channels/lib/reaction-processor-types.js +5 -0
  173. package/dist/modules/communication_channels/lib/reaction-processor-types.js.map +7 -0
  174. package/dist/modules/communication_channels/lib/reaction-semantics.js +11 -0
  175. package/dist/modules/communication_channels/lib/reaction-semantics.js.map +7 -0
  176. package/dist/modules/communication_channels/lib/registry.js +67 -0
  177. package/dist/modules/communication_channels/lib/registry.js.map +7 -0
  178. package/dist/modules/communication_channels/lib/route-mutation-guard.js +43 -0
  179. package/dist/modules/communication_channels/lib/route-mutation-guard.js.map +7 -0
  180. package/dist/modules/communication_channels/lib/sanitize-channel-html.js +96 -0
  181. package/dist/modules/communication_channels/lib/sanitize-channel-html.js.map +7 -0
  182. package/dist/modules/communication_channels/lib/send-as-user.js +194 -0
  183. package/dist/modules/communication_channels/lib/send-as-user.js.map +7 -0
  184. package/dist/modules/communication_channels/lib/system-user.js +22 -0
  185. package/dist/modules/communication_channels/lib/system-user.js.map +7 -0
  186. package/dist/modules/communication_channels/lib/test-seed.js +68 -0
  187. package/dist/modules/communication_channels/lib/test-seed.js.map +7 -0
  188. package/dist/modules/communication_channels/lib/thread-matcher.js +263 -0
  189. package/dist/modules/communication_channels/lib/thread-matcher.js.map +7 -0
  190. package/dist/modules/communication_channels/lib/thread-token.js +219 -0
  191. package/dist/modules/communication_channels/lib/thread-token.js.map +7 -0
  192. package/dist/modules/communication_channels/lib/use-connect-channel.js +61 -0
  193. package/dist/modules/communication_channels/lib/use-connect-channel.js.map +7 -0
  194. package/dist/modules/communication_channels/migrations/Migration20260526134719_communication_channels.js +50 -0
  195. package/dist/modules/communication_channels/migrations/Migration20260526134719_communication_channels.js.map +7 -0
  196. package/dist/modules/communication_channels/migrations/Migration20260527195446_communication_channels.js +19 -0
  197. package/dist/modules/communication_channels/migrations/Migration20260527195446_communication_channels.js.map +7 -0
  198. package/dist/modules/communication_channels/migrations/Migration20260529231848_communication_channels.js +13 -0
  199. package/dist/modules/communication_channels/migrations/Migration20260529231848_communication_channels.js.map +7 -0
  200. package/dist/modules/communication_channels/migrations/Migration20260531120000_communication_channels.js +17 -0
  201. package/dist/modules/communication_channels/migrations/Migration20260531120000_communication_channels.js.map +7 -0
  202. package/dist/modules/communication_channels/notifications.client.js +51 -0
  203. package/dist/modules/communication_channels/notifications.client.js.map +7 -0
  204. package/dist/modules/communication_channels/notifications.handlers.js +53 -0
  205. package/dist/modules/communication_channels/notifications.handlers.js.map +7 -0
  206. package/dist/modules/communication_channels/notifications.js +56 -0
  207. package/dist/modules/communication_channels/notifications.js.map +7 -0
  208. package/dist/modules/communication_channels/setup.js +105 -0
  209. package/dist/modules/communication_channels/setup.js.map +7 -0
  210. package/dist/modules/communication_channels/subscribers/channel-requires-reauth-notification.js +71 -0
  211. package/dist/modules/communication_channels/subscribers/channel-requires-reauth-notification.js.map +7 -0
  212. package/dist/modules/communication_channels/subscribers/outbound-bridge.js +103 -0
  213. package/dist/modules/communication_channels/subscribers/outbound-bridge.js.map +7 -0
  214. package/dist/modules/communication_channels/subscribers/user-deleted-cascade.js +51 -0
  215. package/dist/modules/communication_channels/subscribers/user-deleted-cascade.js.map +7 -0
  216. package/dist/modules/communication_channels/widgets/components.js +7 -0
  217. package/dist/modules/communication_channels/widgets/components.js.map +7 -0
  218. package/dist/modules/communication_channels/widgets/injection/channel-badge/widget.client.js +18 -0
  219. package/dist/modules/communication_channels/widgets/injection/channel-badge/widget.client.js.map +7 -0
  220. package/dist/modules/communication_channels/widgets/injection/channel-badge/widget.js +30 -0
  221. package/dist/modules/communication_channels/widgets/injection/channel-badge/widget.js.map +7 -0
  222. package/dist/modules/communication_channels/widgets/injection/channel-info-panel/widget.client.js +185 -0
  223. package/dist/modules/communication_channels/widgets/injection/channel-info-panel/widget.client.js.map +7 -0
  224. package/dist/modules/communication_channels/widgets/injection/channel-info-panel/widget.js +17 -0
  225. package/dist/modules/communication_channels/widgets/injection/channel-info-panel/widget.js.map +7 -0
  226. package/dist/modules/communication_channels/widgets/injection/channel-payload-renderer/widget.client.js +44 -0
  227. package/dist/modules/communication_channels/widgets/injection/channel-payload-renderer/widget.client.js.map +7 -0
  228. package/dist/modules/communication_channels/widgets/injection/channel-payload-renderer/widget.js +17 -0
  229. package/dist/modules/communication_channels/widgets/injection/channel-payload-renderer/widget.js.map +7 -0
  230. package/dist/modules/communication_channels/widgets/injection/profile-channels-menu/widget.js +23 -0
  231. package/dist/modules/communication_channels/widgets/injection/profile-channels-menu/widget.js.map +7 -0
  232. package/dist/modules/communication_channels/widgets/injection/reaction-bar/widget.client.js +141 -0
  233. package/dist/modules/communication_channels/widgets/injection/reaction-bar/widget.client.js.map +7 -0
  234. package/dist/modules/communication_channels/widgets/injection/reaction-bar/widget.js +17 -0
  235. package/dist/modules/communication_channels/widgets/injection/reaction-bar/widget.js.map +7 -0
  236. package/dist/modules/communication_channels/widgets/injection-table.js +38 -0
  237. package/dist/modules/communication_channels/widgets/injection-table.js.map +7 -0
  238. package/dist/modules/communication_channels/widgets/notifications/ChannelRequiresReauthRenderer.js +25 -0
  239. package/dist/modules/communication_channels/widgets/notifications/ChannelRequiresReauthRenderer.js.map +7 -0
  240. package/dist/modules/communication_channels/widgets/notifications/MessageReceivedRenderer.js +19 -0
  241. package/dist/modules/communication_channels/widgets/notifications/MessageReceivedRenderer.js.map +7 -0
  242. package/dist/modules/communication_channels/widgets/notifications/index.js +7 -0
  243. package/dist/modules/communication_channels/widgets/notifications/index.js.map +7 -0
  244. package/dist/modules/communication_channels/workers/channel-import-history.js +185 -0
  245. package/dist/modules/communication_channels/workers/channel-import-history.js.map +7 -0
  246. package/dist/modules/communication_channels/workers/gmail-history-sync.js +154 -0
  247. package/dist/modules/communication_channels/workers/gmail-history-sync.js.map +7 -0
  248. package/dist/modules/communication_channels/workers/gmail-renew-watch.js +95 -0
  249. package/dist/modules/communication_channels/workers/gmail-renew-watch.js.map +7 -0
  250. package/dist/modules/communication_channels/workers/inbound-processor.js +56 -0
  251. package/dist/modules/communication_channels/workers/inbound-processor.js.map +7 -0
  252. package/dist/modules/communication_channels/workers/outbound-delivery.js +85 -0
  253. package/dist/modules/communication_channels/workers/outbound-delivery.js.map +7 -0
  254. package/dist/modules/communication_channels/workers/poll-channel.js +240 -0
  255. package/dist/modules/communication_channels/workers/poll-channel.js.map +7 -0
  256. package/dist/modules/communication_channels/workers/poll-tick.js +132 -0
  257. package/dist/modules/communication_channels/workers/poll-tick.js.map +7 -0
  258. package/dist/modules/communication_channels/workers/reaction-processor.js +192 -0
  259. package/dist/modules/communication_channels/workers/reaction-processor.js.map +7 -0
  260. package/dist/modules/customers/acl.js +18 -0
  261. package/dist/modules/customers/acl.js.map +2 -2
  262. package/dist/modules/customers/api/activities/route.js +9 -0
  263. package/dist/modules/customers/api/activities/route.js.map +2 -2
  264. package/dist/modules/customers/api/companies/[id]/route.js +18 -7
  265. package/dist/modules/customers/api/companies/[id]/route.js.map +2 -2
  266. package/dist/modules/customers/api/interactions/[id]/visibility/route.js +151 -0
  267. package/dist/modules/customers/api/interactions/[id]/visibility/route.js.map +7 -0
  268. package/dist/modules/customers/api/interactions/counts/route.js +6 -0
  269. package/dist/modules/customers/api/interactions/counts/route.js.map +2 -2
  270. package/dist/modules/customers/api/interactions/route.js +26 -7
  271. package/dist/modules/customers/api/interactions/route.js.map +2 -2
  272. package/dist/modules/customers/api/people/[id]/email-threads/route.js +82 -0
  273. package/dist/modules/customers/api/people/[id]/email-threads/route.js.map +7 -0
  274. package/dist/modules/customers/api/people/[id]/emails/route.js +157 -0
  275. package/dist/modules/customers/api/people/[id]/emails/route.js.map +7 -0
  276. package/dist/modules/customers/api/people/[id]/route.js +12 -4
  277. package/dist/modules/customers/api/people/[id]/route.js.map +2 -2
  278. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +10 -0
  279. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
  280. package/dist/modules/customers/commands/deals.js +46 -5
  281. package/dist/modules/customers/commands/deals.js.map +2 -2
  282. package/dist/modules/customers/commands/interactions.js +16 -0
  283. package/dist/modules/customers/commands/interactions.js.map +2 -2
  284. package/dist/modules/customers/components/detail/ActivityCard.js +32 -0
  285. package/dist/modules/customers/components/detail/ActivityCard.js.map +2 -2
  286. package/dist/modules/customers/components/detail/ComposeEmailDialog.js +242 -0
  287. package/dist/modules/customers/components/detail/ComposeEmailDialog.js.map +7 -0
  288. package/dist/modules/customers/components/detail/DealForm.js +2 -1
  289. package/dist/modules/customers/components/detail/DealForm.js.map +2 -2
  290. package/dist/modules/customers/components/detail/DealsSection.js +10 -0
  291. package/dist/modules/customers/components/detail/DealsSection.js.map +2 -2
  292. package/dist/modules/customers/components/detail/EmailCardActions.js +179 -0
  293. package/dist/modules/customers/components/detail/EmailCardActions.js.map +7 -0
  294. package/dist/modules/customers/components/detail/EmailReplyForwardActions.js +52 -0
  295. package/dist/modules/customers/components/detail/EmailReplyForwardActions.js.map +7 -0
  296. package/dist/modules/customers/components/detail/PersonDetailTabs.js +7 -1
  297. package/dist/modules/customers/components/detail/PersonDetailTabs.js.map +2 -2
  298. package/dist/modules/customers/components/detail/PersonEmailThreadsTab.js +366 -0
  299. package/dist/modules/customers/components/detail/PersonEmailThreadsTab.js.map +7 -0
  300. package/dist/modules/customers/data/enrichers.js +133 -2
  301. package/dist/modules/customers/data/enrichers.js.map +2 -2
  302. package/dist/modules/customers/data/entities.js +18 -0
  303. package/dist/modules/customers/data/entities.js.map +2 -2
  304. package/dist/modules/customers/data/extensions.js +16 -0
  305. package/dist/modules/customers/data/extensions.js.map +7 -0
  306. package/dist/modules/customers/encryption.js +11 -0
  307. package/dist/modules/customers/encryption.js.map +2 -2
  308. package/dist/modules/customers/events.js +4 -1
  309. package/dist/modules/customers/events.js.map +2 -2
  310. package/dist/modules/customers/lib/findPeopleByAddresses.js +64 -0
  311. package/dist/modules/customers/lib/findPeopleByAddresses.js.map +7 -0
  312. package/dist/modules/customers/lib/kysely.js.map +2 -2
  313. package/dist/modules/customers/lib/link-channel-message-handler.js +303 -0
  314. package/dist/modules/customers/lib/link-channel-message-handler.js.map +7 -0
  315. package/dist/modules/customers/lib/personEmailThreads.js +205 -0
  316. package/dist/modules/customers/lib/personEmailThreads.js.map +7 -0
  317. package/dist/modules/customers/lib/visibilityFilter.js +51 -0
  318. package/dist/modules/customers/lib/visibilityFilter.js.map +7 -0
  319. package/dist/modules/customers/migrations/Migration20260527012240_customers.js +20 -0
  320. package/dist/modules/customers/migrations/Migration20260527012240_customers.js.map +7 -0
  321. package/dist/modules/customers/setup.js +2 -1
  322. package/dist/modules/customers/setup.js.map +2 -2
  323. package/dist/modules/customers/subscribers/link-channel-message-received.js +12 -0
  324. package/dist/modules/customers/subscribers/link-channel-message-received.js.map +7 -0
  325. package/dist/modules/customers/subscribers/link-channel-message-sent.js +12 -0
  326. package/dist/modules/customers/subscribers/link-channel-message-sent.js.map +7 -0
  327. package/dist/modules/integrations/data/entities.js +8 -1
  328. package/dist/modules/integrations/data/entities.js.map +2 -2
  329. package/dist/modules/integrations/lib/credentials-service.js +29 -14
  330. package/dist/modules/integrations/lib/credentials-service.js.map +2 -2
  331. package/dist/modules/integrations/migrations/Migration20260526154136_integrations.js +15 -0
  332. package/dist/modules/integrations/migrations/Migration20260526154136_integrations.js.map +7 -0
  333. package/dist/modules/messages/commands/messages.js +70 -8
  334. package/dist/modules/messages/commands/messages.js.map +2 -2
  335. package/dist/modules/messages/components/ComposeMessagePageClient.js +24 -13
  336. package/dist/modules/messages/components/ComposeMessagePageClient.js.map +2 -2
  337. package/dist/modules/messages/components/MessageDetailPageClient.js +39 -2
  338. package/dist/modules/messages/components/MessageDetailPageClient.js.map +2 -2
  339. package/dist/modules/messages/components/MessagesInboxPageClient.js +1 -0
  340. package/dist/modules/messages/components/MessagesInboxPageClient.js.map +2 -2
  341. package/dist/modules/messages/data/entities.js +8 -1
  342. package/dist/modules/messages/data/entities.js.map +2 -2
  343. package/dist/modules/messages/migrations/Migration20260531130000.js +15 -0
  344. package/dist/modules/messages/migrations/Migration20260531130000.js.map +7 -0
  345. package/dist/modules/messages/widgets/injection-table.js +7 -0
  346. package/dist/modules/messages/widgets/injection-table.js.map +7 -0
  347. package/generated/entities/channel_ingest_dead_letter/index.ts +11 -0
  348. package/generated/entities/channel_thread_mapping/index.ts +11 -0
  349. package/generated/entities/channel_thread_token/index.ts +7 -0
  350. package/generated/entities/communication_channel/index.ts +20 -0
  351. package/generated/entities/customer_interaction/index.ts +2 -0
  352. package/generated/entities/external_conversation/index.ts +11 -0
  353. package/generated/entities/external_message/index.ts +11 -0
  354. package/generated/entities/integration_credentials/index.ts +1 -0
  355. package/generated/entities/message/index.ts +1 -0
  356. package/generated/entities/message_channel_link/index.ts +15 -0
  357. package/generated/entities/message_reaction/index.ts +11 -0
  358. package/generated/entities.ids.generated.ts +11 -0
  359. package/generated/entity-fields-registry.ts +117 -0
  360. package/package.json +9 -7
  361. package/src/helpers/integration/authFixtures.ts +4 -1
  362. package/src/helpers/integration/communicationChannelsFixtures.ts +124 -0
  363. package/src/modules/communication_channels/acl.ts +43 -0
  364. package/src/modules/communication_channels/api/delete/channels/[id]/route.ts +163 -0
  365. package/src/modules/communication_channels/api/delete/messages/[messageId]/reactions/[reactionId]/route.ts +143 -0
  366. package/src/modules/communication_channels/api/get/channels/[id]/health/route.ts +173 -0
  367. package/src/modules/communication_channels/api/get/channels/[id]/route.ts +111 -0
  368. package/src/modules/communication_channels/api/get/channels/route.ts +109 -0
  369. package/src/modules/communication_channels/api/get/me/channels/route.ts +100 -0
  370. package/src/modules/communication_channels/api/get/oauth/[provider]/callback/route.ts +355 -0
  371. package/src/modules/communication_channels/api/post/channels/[id]/import-history/route.ts +206 -0
  372. package/src/modules/communication_channels/api/post/channels/[id]/poll-now/route.ts +174 -0
  373. package/src/modules/communication_channels/api/post/channels/[id]/push/register/route.ts +158 -0
  374. package/src/modules/communication_channels/api/post/channels/[id]/set-primary/route.ts +114 -0
  375. package/src/modules/communication_channels/api/post/channels/[id]/test-send/route.ts +241 -0
  376. package/src/modules/communication_channels/api/post/channels/connect/credentials/route.ts +134 -0
  377. package/src/modules/communication_channels/api/post/messages/[messageId]/reactions/route.ts +143 -0
  378. package/src/modules/communication_channels/api/post/oauth/[provider]/initiate/route.ts +192 -0
  379. package/src/modules/communication_channels/api/post/send-as-user/route.ts +125 -0
  380. package/src/modules/communication_channels/api/post/test-seed/route.ts +267 -0
  381. package/src/modules/communication_channels/api/post/webhook/[provider]/route.ts +227 -0
  382. package/src/modules/communication_channels/api/post/webhooks/gmail/route.ts +161 -0
  383. package/src/modules/communication_channels/api/put/threads/[threadId]/assign/route.ts +132 -0
  384. package/src/modules/communication_channels/backend/communication_channels/channels/[id]/page.meta.ts +34 -0
  385. package/src/modules/communication_channels/backend/communication_channels/channels/[id]/page.tsx +250 -0
  386. package/src/modules/communication_channels/backend/communication_channels/channels/page.meta.ts +36 -0
  387. package/src/modules/communication_channels/backend/communication_channels/channels/page.tsx +137 -0
  388. package/src/modules/communication_channels/backend/profile/communication-channels/page.meta.ts +36 -0
  389. package/src/modules/communication_channels/backend/profile/communication-channels/page.tsx +907 -0
  390. package/src/modules/communication_channels/commands/connect-credential-channel.ts +243 -0
  391. package/src/modules/communication_channels/commands/delete-channel.ts +193 -0
  392. package/src/modules/communication_channels/commands/deliver-outbound-message.ts +579 -0
  393. package/src/modules/communication_channels/commands/disconnect-channel.ts +241 -0
  394. package/src/modules/communication_channels/commands/ingest-inbound-message.ts +602 -0
  395. package/src/modules/communication_channels/commands/interceptors.ts +104 -0
  396. package/src/modules/communication_channels/commands/process-inbound-reaction.ts +265 -0
  397. package/src/modules/communication_channels/commands/push-register.ts +203 -0
  398. package/src/modules/communication_channels/commands/push-renew.ts +49 -0
  399. package/src/modules/communication_channels/commands/push-unregister.ts +168 -0
  400. package/src/modules/communication_channels/commands/queue-import-history.ts +180 -0
  401. package/src/modules/communication_channels/commands/reassign-conversation.ts +273 -0
  402. package/src/modules/communication_channels/commands/set-primary-channel.ts +154 -0
  403. package/src/modules/communication_channels/commands/toggle-outbound-reaction.ts +347 -0
  404. package/src/modules/communication_channels/data/enrichers.ts +413 -0
  405. package/src/modules/communication_channels/data/entities.ts +546 -0
  406. package/src/modules/communication_channels/data/extensions.ts +76 -0
  407. package/src/modules/communication_channels/data/validators.ts +138 -0
  408. package/src/modules/communication_channels/di.ts +40 -0
  409. package/src/modules/communication_channels/encryption.ts +44 -0
  410. package/src/modules/communication_channels/events.ts +122 -0
  411. package/src/modules/communication_channels/i18n/de.json +138 -0
  412. package/src/modules/communication_channels/i18n/en.json +138 -0
  413. package/src/modules/communication_channels/i18n/es.json +138 -0
  414. package/src/modules/communication_channels/i18n/pl.json +138 -0
  415. package/src/modules/communication_channels/index.ts +19 -0
  416. package/src/modules/communication_channels/lib/access-control.ts +110 -0
  417. package/src/modules/communication_channels/lib/adapter-compat.ts +57 -0
  418. package/src/modules/communication_channels/lib/adapter-registry-singleton.ts +35 -0
  419. package/src/modules/communication_channels/lib/adapter.ts +605 -0
  420. package/src/modules/communication_channels/lib/connect-channel.ts +163 -0
  421. package/src/modules/communication_channels/lib/contact-resolver.ts +162 -0
  422. package/src/modules/communication_channels/lib/credential-refresh.ts +197 -0
  423. package/src/modules/communication_channels/lib/dead-letter.ts +87 -0
  424. package/src/modules/communication_channels/lib/email-capabilities.ts +60 -0
  425. package/src/modules/communication_channels/lib/email-contact.ts +17 -0
  426. package/src/modules/communication_channels/lib/email-mime.ts +425 -0
  427. package/src/modules/communication_channels/lib/error-classification.ts +144 -0
  428. package/src/modules/communication_channels/lib/gmail-pubsub-jwt.ts +278 -0
  429. package/src/modules/communication_channels/lib/mutation-guards.ts +215 -0
  430. package/src/modules/communication_channels/lib/oauth-client-config.ts +79 -0
  431. package/src/modules/communication_channels/lib/oauth-state.ts +228 -0
  432. package/src/modules/communication_channels/lib/oauth-token.ts +81 -0
  433. package/src/modules/communication_channels/lib/pg-errors.ts +12 -0
  434. package/src/modules/communication_channels/lib/provider-health.ts +47 -0
  435. package/src/modules/communication_channels/lib/push-state.ts +38 -0
  436. package/src/modules/communication_channels/lib/queue.ts +66 -0
  437. package/src/modules/communication_channels/lib/reaction-processor-types.ts +51 -0
  438. package/src/modules/communication_channels/lib/reaction-semantics.ts +48 -0
  439. package/src/modules/communication_channels/lib/registry.ts +99 -0
  440. package/src/modules/communication_channels/lib/route-mutation-guard.ts +68 -0
  441. package/src/modules/communication_channels/lib/sanitize-channel-html.ts +129 -0
  442. package/src/modules/communication_channels/lib/send-as-user.ts +284 -0
  443. package/src/modules/communication_channels/lib/system-user.ts +74 -0
  444. package/src/modules/communication_channels/lib/test-seed.ts +140 -0
  445. package/src/modules/communication_channels/lib/thread-matcher.ts +430 -0
  446. package/src/modules/communication_channels/lib/thread-token.ts +355 -0
  447. package/src/modules/communication_channels/lib/use-connect-channel.ts +73 -0
  448. package/src/modules/communication_channels/migrations/.snapshot-open-mercato.json +2142 -0
  449. package/src/modules/communication_channels/migrations/Migration20260526134719_communication_channels.ts +55 -0
  450. package/src/modules/communication_channels/migrations/Migration20260527195446_communication_channels.ts +20 -0
  451. package/src/modules/communication_channels/migrations/Migration20260529231848_communication_channels.ts +13 -0
  452. package/src/modules/communication_channels/migrations/Migration20260531120000_communication_channels.ts +24 -0
  453. package/src/modules/communication_channels/notifications.client.ts +50 -0
  454. package/src/modules/communication_channels/notifications.handlers.ts +86 -0
  455. package/src/modules/communication_channels/notifications.ts +52 -0
  456. package/src/modules/communication_channels/setup.ts +158 -0
  457. package/src/modules/communication_channels/subscribers/channel-requires-reauth-notification.ts +118 -0
  458. package/src/modules/communication_channels/subscribers/outbound-bridge.ts +175 -0
  459. package/src/modules/communication_channels/subscribers/user-deleted-cascade.ts +100 -0
  460. package/src/modules/communication_channels/widgets/components.ts +36 -0
  461. package/src/modules/communication_channels/widgets/injection/channel-badge/widget.client.tsx +38 -0
  462. package/src/modules/communication_channels/widgets/injection/channel-badge/widget.ts +51 -0
  463. package/src/modules/communication_channels/widgets/injection/channel-info-panel/widget.client.tsx +278 -0
  464. package/src/modules/communication_channels/widgets/injection/channel-info-panel/widget.ts +24 -0
  465. package/src/modules/communication_channels/widgets/injection/channel-payload-renderer/widget.client.tsx +63 -0
  466. package/src/modules/communication_channels/widgets/injection/channel-payload-renderer/widget.ts +29 -0
  467. package/src/modules/communication_channels/widgets/injection/profile-channels-menu/widget.ts +34 -0
  468. package/src/modules/communication_channels/widgets/injection/reaction-bar/widget.client.tsx +177 -0
  469. package/src/modules/communication_channels/widgets/injection/reaction-bar/widget.ts +26 -0
  470. package/src/modules/communication_channels/widgets/injection-table.ts +47 -0
  471. package/src/modules/communication_channels/widgets/notifications/ChannelRequiresReauthRenderer.tsx +48 -0
  472. package/src/modules/communication_channels/widgets/notifications/MessageReceivedRenderer.tsx +45 -0
  473. package/src/modules/communication_channels/widgets/notifications/index.ts +2 -0
  474. package/src/modules/communication_channels/workers/channel-import-history.ts +252 -0
  475. package/src/modules/communication_channels/workers/gmail-history-sync.ts +223 -0
  476. package/src/modules/communication_channels/workers/gmail-renew-watch.ts +141 -0
  477. package/src/modules/communication_channels/workers/inbound-processor.ts +114 -0
  478. package/src/modules/communication_channels/workers/outbound-delivery.ts +155 -0
  479. package/src/modules/communication_channels/workers/poll-channel.ts +391 -0
  480. package/src/modules/communication_channels/workers/poll-tick.ts +210 -0
  481. package/src/modules/communication_channels/workers/reaction-processor.ts +264 -0
  482. package/src/modules/customers/acl.ts +18 -0
  483. package/src/modules/customers/api/activities/route.ts +13 -0
  484. package/src/modules/customers/api/companies/[id]/route.ts +21 -1
  485. package/src/modules/customers/api/interactions/[id]/visibility/route.ts +179 -0
  486. package/src/modules/customers/api/interactions/counts/route.ts +10 -0
  487. package/src/modules/customers/api/interactions/route.ts +51 -5
  488. package/src/modules/customers/api/people/[id]/email-threads/route.ts +92 -0
  489. package/src/modules/customers/api/people/[id]/emails/route.ts +184 -0
  490. package/src/modules/customers/api/people/[id]/route.ts +17 -2
  491. package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +11 -1
  492. package/src/modules/customers/commands/deals.ts +65 -6
  493. package/src/modules/customers/commands/interactions.ts +30 -0
  494. package/src/modules/customers/components/detail/ActivityCard.tsx +48 -0
  495. package/src/modules/customers/components/detail/ComposeEmailDialog.tsx +329 -0
  496. package/src/modules/customers/components/detail/DealForm.tsx +2 -1
  497. package/src/modules/customers/components/detail/DealsSection.tsx +26 -0
  498. package/src/modules/customers/components/detail/EmailCardActions.tsx +258 -0
  499. package/src/modules/customers/components/detail/EmailReplyForwardActions.tsx +53 -0
  500. package/src/modules/customers/components/detail/PersonDetailTabs.tsx +8 -1
  501. package/src/modules/customers/components/detail/PersonEmailThreadsTab.tsx +448 -0
  502. package/src/modules/customers/data/enrichers.ts +252 -1
  503. package/src/modules/customers/data/entities.ts +46 -1
  504. package/src/modules/customers/data/extensions.ts +26 -0
  505. package/src/modules/customers/encryption.ts +11 -0
  506. package/src/modules/customers/events.ts +4 -0
  507. package/src/modules/customers/i18n/de.json +41 -0
  508. package/src/modules/customers/i18n/en.json +41 -0
  509. package/src/modules/customers/i18n/es.json +41 -0
  510. package/src/modules/customers/i18n/pl.json +41 -0
  511. package/src/modules/customers/lib/findPeopleByAddresses.ts +107 -0
  512. package/src/modules/customers/lib/kysely.ts +16 -0
  513. package/src/modules/customers/lib/link-channel-message-handler.ts +571 -0
  514. package/src/modules/customers/lib/personEmailThreads.ts +325 -0
  515. package/src/modules/customers/lib/visibilityFilter.ts +152 -0
  516. package/src/modules/customers/migrations/.snapshot-open-mercato.json +61 -0
  517. package/src/modules/customers/migrations/Migration20260527012240_customers.ts +23 -0
  518. package/src/modules/customers/setup.ts +1 -0
  519. package/src/modules/customers/subscribers/link-channel-message-received.ts +21 -0
  520. package/src/modules/customers/subscribers/link-channel-message-sent.ts +21 -0
  521. package/src/modules/integrations/AGENTS.md +9 -0
  522. package/src/modules/integrations/data/entities.ts +21 -1
  523. package/src/modules/integrations/lib/credentials-service.ts +49 -13
  524. package/src/modules/integrations/migrations/.snapshot-open-mercato.json +26 -1
  525. package/src/modules/integrations/migrations/Migration20260526154136_integrations.ts +15 -0
  526. package/src/modules/messages/commands/messages.ts +101 -8
  527. package/src/modules/messages/components/ComposeMessagePageClient.tsx +17 -0
  528. package/src/modules/messages/components/MessageDetailPageClient.tsx +43 -0
  529. package/src/modules/messages/components/MessagesInboxPageClient.tsx +4 -0
  530. package/src/modules/messages/data/entities.ts +11 -0
  531. package/src/modules/messages/migrations/.snapshot-open-mercato.json +18 -0
  532. package/src/modules/messages/migrations/Migration20260531130000.ts +15 -0
  533. package/src/modules/messages/widgets/injection-table.ts +29 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../src/modules/customers/backend/customers/people-v2/%5Bid%5D/page.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useRouter, useSearchParams } from 'next/navigation'\nimport { User, Hash, Users, Building2 } from 'lucide-react'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { CrudForm } from '@open-mercato/ui/backend/CrudForm'\nimport { CollapsibleZoneLayout, type ZoneSectionDescriptor } from '@open-mercato/ui/backend/crud/CollapsibleZoneLayout'\nimport { updateCrud, deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { apiCallOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { E } from '#generated/entities.ids.generated'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useOrganizationScopeDetail } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { AttachmentsSection, ErrorMessage, LoadingMessage, RecordNotFoundState, type SectionAction } from '@open-mercato/ui/backend/detail'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { InjectionSpot, useInjectionWidgets } from '@open-mercato/ui/backend/injection/InjectionSpot'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { createTranslatorWithFallback } from '@open-mercato/shared/lib/i18n/translate'\n\nimport { ActivitiesSection } from '../../../../components/detail/ActivitiesSection'\nimport { ActivitiesCard } from '../../../../components/detail/ActivitiesCard'\nimport type { ActivityKind } from '../../../../components/detail/ActivitiesAddNewMenu'\nimport { DealsSection } from '../../../../components/detail/DealsSection'\nimport { TasksSection } from '../../../../components/detail/TasksSection'\nimport type { TagSummary } from '../../../../components/detail/types'\nimport { ScheduleActivityDialog, type ScheduleActivityEditData } from '../../../../components/detail/ScheduleActivityDialog'\nimport { PersonDetailHeader } from '../../../../components/detail/PersonDetailHeader'\nimport { ChangelogTab } from '../../../../components/detail/ChangelogTab'\nimport { PersonDetailTabs, resolveLegacyTab, type PersonTabId } from '../../../../components/detail/PersonDetailTabs'\nimport { PersonCompaniesSection } from '../../../../components/detail/PersonCompaniesSection'\nimport { MobilePersonDetail } from '../../../../components/detail/MobilePersonDetail'\nimport type { TagsSectionController } from '@open-mercato/ui/backend/detail'\nimport {\n buildPersonEditPayload,\n createPersonEditFields,\n createPersonPersonalDataGroups,\n createPersonEditSchema,\n mapPersonOverviewToFormValues,\n type PersonEditFormValues,\n type PersonOverview,\n} from '../../../../components/formConfig'\nimport { coerceDisplayName, coerceDisplayNameOrNull } from '../../../../lib/displayName'\n\nexport default function PersonDetailV2Page({ params }: { params?: { id?: string } }) {\n const id = params?.id\n const t = useT()\n const router = useRouter()\n const searchParams = useSearchParams()\n const { organizationId } = useOrganizationScopeDetail()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n\n const detailTranslator = React.useMemo(() => createTranslatorWithFallback(t), [t])\n\n\n const formSchema = React.useMemo(() => createPersonEditSchema(), [])\n const fields = React.useMemo(() => createPersonEditFields(t), [t])\n\n const [data, setData] = React.useState<PersonOverview | null>(null)\n const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [isNotFound, setIsNotFound] = React.useState(false)\n\n // Form state lifted for header Save button\n const [isDirty, setIsDirty] = React.useState(false)\n const [isSaving, setIsSaving] = React.useState(false)\n const formWrapperRef = React.useRef<HTMLDivElement>(null)\n\n const initialTab = React.useMemo(() => {\n return resolveLegacyTab(searchParams?.get('tab'))\n }, [searchParams])\n const [activeTab, setActiveTab] = React.useState<PersonTabId>(initialTab)\n const [sectionAction, setSectionAction] = React.useState<SectionAction | null>(null)\n const [scheduleDialogOpen, setScheduleDialogOpen] = React.useState(false)\n const [scheduleEditData, setScheduleEditData] = React.useState<ScheduleActivityEditData | null>(null)\n const [activityRefreshKey, setActivityRefreshKey] = React.useState(0)\n const [dealCount, setDealCount] = React.useState(0)\n\n const currentPersonId = data?.person?.id ?? null\n const mutationContextId = React.useMemo(\n () => (currentPersonId ? `customer-person:${currentPersonId}` : `customer-person:${id ?? 'pending'}`),\n [currentPersonId, id],\n )\n const { runMutation, retryLastMutation } = useGuardedMutation<{\n formId: string\n personId?: string | null\n resourceKind: string\n resourceId?: string\n data: PersonOverview | null\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: mutationContextId,\n blockedMessage: t('ui.forms.flash.saveBlocked', 'Save blocked by validation'),\n })\n const personDisplayName = coerceDisplayName(data?.person?.displayName)\n const personName = personDisplayName.trim().length\n ? personDisplayName\n : t('customers.people.list.deleteFallbackName', 'this person')\n\n const personDisplayNameForGroups = personDisplayName.trim().length\n ? personDisplayName.trim()\n : null\n\n const scheduleDialogCompanyName = coerceDisplayNameOrNull(\n data?.company?.displayName ?? data?.companies?.[0]?.displayName ?? null,\n )\n\n const groups = React.useMemo(\n () => createPersonPersonalDataGroups(t, { entityName: personDisplayNameForGroups }),\n [t, personDisplayNameForGroups],\n )\n\n const zoneSections = React.useMemo<ZoneSectionDescriptor[]>(() => [\n { id: 'personalData', icon: User, label: t('customers.people.form.groups.personalData', 'Personal data') },\n { id: 'companyRole', icon: Building2, label: t('customers.people.form.groups.companyRole', 'Company & role') },\n { id: 'customFields', icon: Hash, label: t('customers.people.form.groups.customAttributes', 'Custom attributes') },\n { id: 'roles', icon: Users, label: t('customers.people.form.groups.roles', 'My roles') },\n ], [t])\n\n // Data loading\n const initialLoadDoneRef = React.useRef(false)\n const loadData = React.useCallback(async () => {\n if (!id) {\n setIsNotFound(true)\n setIsLoading(false)\n return\n }\n if (!initialLoadDoneRef.current) {\n setIsLoading(true)\n }\n setError(null)\n setIsNotFound(false)\n try {\n const payload = await readApiResultOrThrow<PersonOverview>(\n `/api/customers/people/${encodeURIComponent(id)}`,\n undefined,\n { errorMessage: t('customers.people.detail.error.load', 'Failed to load person.') },\n )\n setData(payload as PersonOverview)\n } catch (err) {\n if ((err as { status?: number }).status === 404) {\n setIsNotFound(true)\n } else {\n const message = err instanceof Error ? err.message : t('customers.people.detail.error.load', 'Failed to load person.')\n setError(message)\n }\n if (!initialLoadDoneRef.current) setData(null)\n } finally {\n setIsLoading(false)\n initialLoadDoneRef.current = true\n }\n }, [id, t])\n\n React.useEffect(() => {\n loadData().catch((err) => console.warn('[people-v2] loadData failed', err))\n }, [loadData])\n\n React.useEffect(() => {\n setDealCount(data?.counts?.deals ?? 0)\n }, [data?.counts?.deals])\n\n const handleActivityCreated = React.useCallback(() => {\n setActivityRefreshKey((k) => k + 1)\n loadData().catch((err) => console.warn('[people-v2] reload after activity failed', err))\n }, [loadData])\n\n const plannedActivities = React.useMemo(() => {\n return data?.plannedActivitiesPreview ?? []\n }, [data?.plannedActivitiesPreview])\n\n // Injection context for UMES\n const injectionContext = React.useMemo(\n () => ({\n formId: mutationContextId,\n personId: currentPersonId,\n resourceKind: 'customers.person',\n resourceId: currentPersonId ?? (id ?? undefined),\n data,\n retryLastMutation,\n }),\n [currentPersonId, data, id, mutationContextId, retryLastMutation],\n )\n const runMutationWithContext = React.useCallback(\n async <T,>(operation: () => Promise<T>, mutationPayload?: Record<string, unknown>): Promise<T> => {\n return runMutation({\n operation,\n mutationPayload,\n context: injectionContext,\n })\n },\n [injectionContext, runMutation],\n )\n\n const handleAddActivity = React.useCallback((kind: ActivityKind) => {\n setScheduleEditData({\n id: '',\n interactionType: kind,\n title: null,\n body: null,\n scheduledAt: null,\n durationMinutes: null,\n location: null,\n allDay: null,\n recurrenceRule: null,\n recurrenceEnd: null,\n participants: null,\n reminderMinutes: null,\n visibility: null,\n linkedEntities: null,\n guestPermissions: null,\n })\n setScheduleDialogOpen(true)\n }, [])\n\n const handleEditActivity = React.useCallback((activity: { id: string; interactionType?: string; title?: string | null; body?: string | null; scheduledAt?: string | null; occurredAt?: string | null; [key: string]: unknown }) => {\n const raw = activity as Record<string, unknown>\n const durationValue = typeof raw.duration === 'number'\n ? raw.duration\n : typeof raw.durationMinutes === 'number'\n ? raw.durationMinutes as number\n : null\n // Forward `customValues` so per-type chip state (callPhoneNumber, callDirection,\n // taskPriority, \u2026) round-trips on edit (#1808 phone persistence).\n // Forward `occurredAt` so historical activity edits prefill from the original\n // moment instead of \"today\" (#1807 prefill).\n const editPayload = {\n id: activity.id,\n interactionType: typeof activity.interactionType === 'string' ? activity.interactionType : undefined,\n title: typeof activity.title === 'string' ? activity.title : null,\n body: typeof activity.body === 'string' ? activity.body : null,\n scheduledAt: typeof activity.scheduledAt === 'string' ? activity.scheduledAt : null,\n occurredAt: typeof activity.occurredAt === 'string' ? activity.occurredAt : null,\n durationMinutes: durationValue,\n location: typeof raw.location === 'string' ? raw.location as string : null,\n allDay: typeof raw.allDay === 'boolean' ? raw.allDay as boolean : null,\n recurrenceRule: typeof raw.recurrenceRule === 'string' ? raw.recurrenceRule as string : null,\n recurrenceEnd: typeof raw.recurrenceEnd === 'string' ? raw.recurrenceEnd as string : null,\n participants: Array.isArray(raw.participants) ? raw.participants as ScheduleActivityEditData['participants'] : null,\n reminderMinutes: typeof raw.reminderMinutes === 'number' ? raw.reminderMinutes as number : null,\n visibility: typeof raw.visibility === 'string' ? raw.visibility as string : null,\n linkedEntities: Array.isArray(raw.linkedEntities) ? raw.linkedEntities as ScheduleActivityEditData['linkedEntities'] : null,\n guestPermissions: raw.guestPermissions && typeof raw.guestPermissions === 'object'\n ? raw.guestPermissions as ScheduleActivityEditData['guestPermissions']\n : null,\n customValues: raw.customValues && typeof raw.customValues === 'object'\n ? raw.customValues as Record<string, unknown>\n : null,\n phoneNumber: typeof raw.phoneNumber === 'string' ? raw.phoneNumber as string : null,\n } as ScheduleActivityEditData & { customValues?: Record<string, unknown> | null; phoneNumber?: string | null }\n setScheduleEditData(editPayload)\n setScheduleDialogOpen(true)\n }, [])\n\n // Injected tabs from UMES\n const { widgets: injectedTabWidgets } = useInjectionWidgets('detail:customers.person:tabs', {\n context: injectionContext,\n triggerOnLoad: true,\n })\n\n const injectedTabs = React.useMemo(\n () =>\n (injectedTabWidgets ?? [])\n .filter((widget) => (widget.placement?.kind ?? 'tab') === 'tab')\n .map((widget) => {\n const tabId = widget.placement?.groupId ?? widget.widgetId\n const label = widget.placement?.groupLabel ?? widget.module.metadata.title ?? tabId\n const priority = typeof widget.placement?.priority === 'number' ? widget.placement.priority : 0\n const render = () => (\n <widget.module.Widget\n context={injectionContext}\n data={data}\n onDataChange={(next: unknown) => setData(next as PersonOverview)}\n />\n )\n return { id: tabId, label, priority, render }\n })\n .sort((a, b) => b.priority - a.priority),\n [data, injectedTabWidgets, injectionContext],\n )\n\n const injectedTabMap = React.useMemo(() => new Map(injectedTabs.map((tab) => [tab.id, tab.render])), [injectedTabs])\n\n // Tags\n const handleTagsChange = React.useCallback((nextTags: TagSummary[]) => {\n setData((prev) => (prev ? { ...prev, tags: nextTags } : prev))\n }, [])\n const tagsSectionControllerRef = React.useRef<TagsSectionController | null>(null)\n\n // Section action (for tabs that expose add/create buttons)\n const handleSectionActionChange = React.useCallback((action: SectionAction | null) => {\n setSectionAction((prev) => (action !== null ? action : prev))\n }, [])\n\n React.useEffect(() => {\n setSectionAction(null)\n }, [activeTab])\n\n // Deals scope\n const dealsScope = React.useMemo(\n () => (currentPersonId ? ({ kind: 'person', entityId: currentPersonId } as const) : null),\n [currentPersonId],\n )\n\n const initialValues = React.useMemo(\n () => (data ? mapPersonOverviewToFormValues(data) : undefined),\n [data],\n )\n\n // Form submit/delete\n const handleFormSubmit = React.useCallback(\n async (values: PersonEditFormValues) => {\n setIsSaving(true)\n try {\n await tagsSectionControllerRef.current?.flush()\n\n let payload: Record<string, unknown>\n try {\n payload = buildPersonEditPayload(values, organizationId)\n } catch (err) {\n if (err instanceof Error && err.message === 'DISPLAY_NAME_REQUIRED') {\n const message = t('customers.people.form.displayName.error')\n throw createCrudFormError(message, { displayName: message })\n }\n throw err\n }\n\n await updateCrud('customers/people', payload)\n flash(t('customers.people.form.updateSuccess', 'Person updated.'), 'success')\n await loadData()\n } finally {\n setIsSaving(false)\n }\n },\n [loadData, organizationId, t],\n )\n\n const handleFormDelete = React.useCallback(\n async () => {\n const personId = data?.person?.id ?? ''\n if (!personId) return\n const approved = await confirm({\n title: t('customers.people.detail.deleteConfirmTitle', 'Delete person?'),\n description: t('customers.people.detail.deleteConfirmDescription', 'This action cannot be undone.'),\n confirmText: t('customers.people.detail.actions.delete', 'Delete'),\n cancelText: t('customers.people.detail.actions.cancel', 'Cancel'),\n variant: 'destructive',\n })\n if (!approved) return\n await runMutationWithContext(\n () => deleteCrud('customers/people', { id: personId }),\n { id: personId, operation: 'deletePerson' },\n )\n flash(t('customers.people.list.deleteSuccess', 'Person deleted.'), 'success')\n router.push('/backend/customers/people')\n },\n [confirm, data?.person?.id, router, runMutationWithContext, t],\n )\n\n const handleHeaderSave = React.useCallback(() => {\n const form = formWrapperRef.current?.querySelector('form')\n if (form) form.requestSubmit()\n }, [])\n\n // Counts for tab badges\n const interactionCount = data?.counts?.activities ?? 0\n const todoCount = data?.counts?.todos ?? 0\n const companyCount = data?.counts?.companies ?? (data?.companies?.length ?? (data?.company ? 1 : 0))\n\n // Loading / error states\n if (isLoading) {\n return (\n <Page>\n <PageBody>\n <LoadingMessage label={t('customers.people.detail.loading', 'Loading person\u2026')} />\n </PageBody>\n </Page>\n )\n }\n\n if (isNotFound) {\n return (\n <Page>\n <PageBody>\n <RecordNotFoundState\n label={t('customers.people.detail.error.notFound', 'Person not found.')}\n backHref=\"/backend/customers/people\"\n backLabel={t('customers.people.detail.actions.backToList', 'Back to people')}\n />\n </PageBody>\n </Page>\n )\n }\n\n if (error || !data?.person?.id || !initialValues) {\n return (\n <Page>\n <PageBody>\n <ErrorMessage\n label={error ?? t('customers.people.detail.error.load', 'Failed to load person.')}\n action={(\n <Button asChild variant=\"outline\">\n <Link href=\"/backend/customers/people\">\n {t('customers.people.detail.actions.backToList', 'Back to people')}\n </Link>\n </Button>\n )}\n />\n </PageBody>\n </Page>\n )\n }\n\n const personId = data.person.id\n const useCanonicalInteractions = data.interactionMode === 'canonical'\n\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-4\">\n {/* UMES header injection */}\n <InjectionSpot spotId=\"detail:customers.person:header\" context={injectionContext} data={data} />\n <InjectionSpot spotId=\"detail:customers.person:status-badges\" context={injectionContext} data={data} />\n\n {/* Persistent person header */}\n <PersonDetailHeader\n data={data}\n onTagsChange={handleTagsChange}\n tagsSectionControllerRef={tagsSectionControllerRef}\n onSave={handleHeaderSave}\n onDelete={handleFormDelete}\n isDirty={isDirty}\n isSaving={isSaving}\n onOpenCompaniesTab={() => setActiveTab('companies')}\n onDataReload={() => { loadData().catch((err) => console.warn('[people-v2] onDataReload failed', err)) }}\n onFocusField={(fieldName) => {\n const selectorMap: Record<string, string> = {\n primaryEmail: 'input[type=\"email\"]',\n primaryPhone: 'input[type=\"tel\"]',\n }\n const selector = selectorMap[fieldName]\n const input = selector ? formWrapperRef.current?.querySelector<HTMLInputElement>(selector) : null\n if (input) {\n input.scrollIntoView({ behavior: 'smooth', block: 'center' })\n requestAnimationFrame(() => input.focus())\n }\n }}\n />\n\n {/* Zone content shared between desktop (CollapsibleZoneLayout) and mobile (MobilePersonDetail). */}\n {(() => {\n const zone1Content = (\n <div ref={formWrapperRef}>\n <CrudForm<PersonEditFormValues>\n embedded\n trackDirtyWhenEmbedded\n injectionSpotId=\"customers.person\"\n entityIds={[E.customers.customer_entity, E.customers.customer_person_profile]}\n schema={formSchema}\n fields={fields}\n groups={groups}\n initialValues={initialValues}\n onSubmit={handleFormSubmit}\n onDelete={handleFormDelete}\n hideFooterActions\n collapsibleGroups={{ pageType: 'person-v2', chevronPosition: 'right' }}\n sortableGroups={{ pageType: 'person-v2' }}\n onDirtyChange={setIsDirty}\n />\n </div>\n )\n const zone2Content = (\n <PersonDetailTabs\n activeTab={activeTab}\n onTabChange={setActiveTab}\n injectedTabs={injectedTabs.map((tab) => ({ id: tab.id, label: tab.label }))}\n activitiesCount={interactionCount}\n dealsCount={dealCount}\n companiesCount={companyCount}\n tasksCount={todoCount}\n sectionAction={sectionAction}\n >\n <div className=\"min-w-0\">\n {(() => {\n // Injected tab content\n const injected = injectedTabMap.get(activeTab)\n if (injected) return injected()\n\n if (activeTab === 'activities') {\n return (\n <div className=\"space-y-4\">\n <ActivitiesCard\n entityId={personId}\n plannedActivities={plannedActivities}\n refreshKey={activityRefreshKey}\n onAddNew={handleAddActivity}\n onEditActivity={handleEditActivity}\n entityCompanyName={data.company?.displayName ?? data.companies?.[0]?.displayName ?? null}\n />\n <ActivitiesSection\n entityId={personId}\n entityName={personName}\n useCanonicalInteractions={useCanonicalInteractions}\n runGuardedMutation={runMutationWithContext}\n onDataRefresh={handleActivityCreated}\n refreshKey={activityRefreshKey}\n addActionLabel={t('customers.people.detail.activities.add', 'Log activity')}\n emptyState={{\n title: t('customers.people.detail.emptyState.activities.title', 'No activities logged yet'),\n actionLabel: t('customers.people.detail.emptyState.activities.action', 'Log activity'),\n }}\n onActionChange={handleSectionActionChange}\n onEditActivity={handleEditActivity}\n />\n </div>\n )\n }\n\n if (activeTab === 'deals') {\n return (\n <DealsSection\n scope={dealsScope}\n emptyLabel={t('customers.people.detail.empty.deals', 'No deals linked to this person.')}\n addActionLabel={t('customers.people.detail.actions.addDeal', 'Add deal')}\n emptyState={{\n title: t('customers.people.detail.emptyState.deals.title', 'No deals yet'),\n actionLabel: t('customers.people.detail.emptyState.deals.action', 'Create a deal'),\n }}\n onActionChange={handleSectionActionChange}\n translator={detailTranslator}\n runGuardedMutation={runMutationWithContext}\n onCountDelta={(delta) => setDealCount((current) => Math.max(0, current + delta))}\n />\n )\n }\n\n if (activeTab === 'companies') {\n return (\n <PersonCompaniesSection\n personId={personId}\n personName={personName}\n initialLinkedCompanies={data?.companies ?? []}\n onChanged={loadData}\n runGuardedMutation={runMutationWithContext}\n />\n )\n }\n\n if (activeTab === 'tasks') {\n return (\n <TasksSection\n entityId={personId}\n initialTasks={[]}\n useCanonicalInteractions={useCanonicalInteractions}\n runGuardedMutation={runMutationWithContext}\n onDataRefresh={loadData}\n emptyLabel={t('customers.people.detail.empty.todos', 'No tasks linked to this person.')}\n addActionLabel={t('customers.people.detail.tasks.add', 'Add task')}\n emptyState={{\n title: t('customers.people.detail.emptyState.tasks.title', 'Plan what happens next'),\n actionLabel: t('customers.people.detail.emptyState.tasks.action', 'Create task'),\n }}\n onActionChange={handleSectionActionChange}\n translator={detailTranslator}\n entityName={personName}\n dialogContextKey=\"customers.people.detail.tasks.dialog.context\"\n dialogContextFallback=\"This task will be linked to {{name}}\"\n />\n )\n }\n\n if (activeTab === 'files') {\n return (\n <AttachmentsSection\n entityId={E.customers.customer_entity}\n recordId={personId}\n title={t('customers.people.detail.tabs.files', 'Files')}\n description={t('customers.people.detail.files.subtitle', 'Upload and manage files linked to this person.')}\n />\n )\n }\n\n if (activeTab === 'changelog') {\n return <ChangelogTab entityId={personId} entityType=\"person\" />\n }\n\n return null\n })()}\n </div>\n </PersonDetailTabs>\n )\n return (\n <>\n <div className=\"md:hidden\">\n <MobilePersonDetail zone1={zone1Content} zone2={zone2Content} />\n </div>\n <div className=\"hidden md:block\">\n <CollapsibleZoneLayout\n pageType=\"person-v2\"\n entityName={personName}\n isDirty={isDirty}\n sections={zoneSections}\n zone1={zone1Content}\n zone2={zone2Content}\n />\n </div>\n </>\n )\n })()}\n\n {/* UMES footer injection */}\n <InjectionSpot spotId=\"detail:customers.person:footer\" context={injectionContext} data={data} />\n\n {/* Schedule Activity Dialog \u2014 opened from PlannedActivities \"+ Schedule\" or other triggers */}\n <ScheduleActivityDialog\n open={scheduleDialogOpen}\n onClose={() => { setScheduleDialogOpen(false); setScheduleEditData(null) }}\n entityId={personId}\n entityName={personName}\n companyName={scheduleDialogCompanyName}\n entityType=\"person\"\n onActivityCreated={handleActivityCreated}\n editData={scheduleEditData}\n />\n {ConfirmDialogElement}\n </div>\n </PageBody>\n </Page>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useRouter, useSearchParams } from 'next/navigation'\nimport { User, Hash, Users, Building2 } from 'lucide-react'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { CrudForm } from '@open-mercato/ui/backend/CrudForm'\nimport { CollapsibleZoneLayout, type ZoneSectionDescriptor } from '@open-mercato/ui/backend/crud/CollapsibleZoneLayout'\nimport { updateCrud, deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { apiCallOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { E } from '#generated/entities.ids.generated'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useOrganizationScopeDetail } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { AttachmentsSection, ErrorMessage, LoadingMessage, RecordNotFoundState, type SectionAction } from '@open-mercato/ui/backend/detail'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { InjectionSpot, useInjectionWidgets } from '@open-mercato/ui/backend/injection/InjectionSpot'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { createTranslatorWithFallback } from '@open-mercato/shared/lib/i18n/translate'\n\nimport { ActivitiesSection } from '../../../../components/detail/ActivitiesSection'\nimport { PersonEmailThreadsTab } from '../../../../components/detail/PersonEmailThreadsTab'\nimport { ActivitiesCard } from '../../../../components/detail/ActivitiesCard'\nimport type { ActivityKind } from '../../../../components/detail/ActivitiesAddNewMenu'\nimport { DealsSection } from '../../../../components/detail/DealsSection'\nimport { TasksSection } from '../../../../components/detail/TasksSection'\nimport type { TagSummary } from '../../../../components/detail/types'\nimport { ScheduleActivityDialog, type ScheduleActivityEditData } from '../../../../components/detail/ScheduleActivityDialog'\nimport { PersonDetailHeader } from '../../../../components/detail/PersonDetailHeader'\nimport { ChangelogTab } from '../../../../components/detail/ChangelogTab'\nimport { PersonDetailTabs, resolveLegacyTab, type PersonTabId } from '../../../../components/detail/PersonDetailTabs'\nimport { PersonCompaniesSection } from '../../../../components/detail/PersonCompaniesSection'\nimport { MobilePersonDetail } from '../../../../components/detail/MobilePersonDetail'\nimport type { TagsSectionController } from '@open-mercato/ui/backend/detail'\nimport {\n buildPersonEditPayload,\n createPersonEditFields,\n createPersonPersonalDataGroups,\n createPersonEditSchema,\n mapPersonOverviewToFormValues,\n type PersonEditFormValues,\n type PersonOverview,\n} from '../../../../components/formConfig'\nimport { coerceDisplayName, coerceDisplayNameOrNull } from '../../../../lib/displayName'\n\nexport default function PersonDetailV2Page({ params }: { params?: { id?: string } }) {\n const id = params?.id\n const t = useT()\n const router = useRouter()\n const searchParams = useSearchParams()\n const { organizationId } = useOrganizationScopeDetail()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n\n const detailTranslator = React.useMemo(() => createTranslatorWithFallback(t), [t])\n\n\n const formSchema = React.useMemo(() => createPersonEditSchema(), [])\n const fields = React.useMemo(() => createPersonEditFields(t), [t])\n\n const [data, setData] = React.useState<PersonOverview | null>(null)\n const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [isNotFound, setIsNotFound] = React.useState(false)\n\n // Form state lifted for header Save button\n const [isDirty, setIsDirty] = React.useState(false)\n const [isSaving, setIsSaving] = React.useState(false)\n const formWrapperRef = React.useRef<HTMLDivElement>(null)\n\n const initialTab = React.useMemo(() => {\n return resolveLegacyTab(searchParams?.get('tab'))\n }, [searchParams])\n const [activeTab, setActiveTab] = React.useState<PersonTabId>(initialTab)\n const [sectionAction, setSectionAction] = React.useState<SectionAction | null>(null)\n const [scheduleDialogOpen, setScheduleDialogOpen] = React.useState(false)\n const [scheduleEditData, setScheduleEditData] = React.useState<ScheduleActivityEditData | null>(null)\n const [activityRefreshKey, setActivityRefreshKey] = React.useState(0)\n const [dealCount, setDealCount] = React.useState(0)\n\n const currentPersonId = data?.person?.id ?? null\n const mutationContextId = React.useMemo(\n () => (currentPersonId ? `customer-person:${currentPersonId}` : `customer-person:${id ?? 'pending'}`),\n [currentPersonId, id],\n )\n const { runMutation, retryLastMutation } = useGuardedMutation<{\n formId: string\n personId?: string | null\n resourceKind: string\n resourceId?: string\n data: PersonOverview | null\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: mutationContextId,\n blockedMessage: t('ui.forms.flash.saveBlocked', 'Save blocked by validation'),\n })\n const personDisplayName = coerceDisplayName(data?.person?.displayName)\n const personName = personDisplayName.trim().length\n ? personDisplayName\n : t('customers.people.list.deleteFallbackName', 'this person')\n\n const personDisplayNameForGroups = personDisplayName.trim().length\n ? personDisplayName.trim()\n : null\n\n const scheduleDialogCompanyName = coerceDisplayNameOrNull(\n data?.company?.displayName ?? data?.companies?.[0]?.displayName ?? null,\n )\n\n const groups = React.useMemo(\n () => createPersonPersonalDataGroups(t, { entityName: personDisplayNameForGroups }),\n [t, personDisplayNameForGroups],\n )\n\n const zoneSections = React.useMemo<ZoneSectionDescriptor[]>(() => [\n { id: 'personalData', icon: User, label: t('customers.people.form.groups.personalData', 'Personal data') },\n { id: 'companyRole', icon: Building2, label: t('customers.people.form.groups.companyRole', 'Company & role') },\n { id: 'customFields', icon: Hash, label: t('customers.people.form.groups.customAttributes', 'Custom attributes') },\n { id: 'roles', icon: Users, label: t('customers.people.form.groups.roles', 'My roles') },\n ], [t])\n\n // Data loading\n const initialLoadDoneRef = React.useRef(false)\n const loadData = React.useCallback(async () => {\n if (!id) {\n setIsNotFound(true)\n setIsLoading(false)\n return\n }\n if (!initialLoadDoneRef.current) {\n setIsLoading(true)\n }\n setError(null)\n setIsNotFound(false)\n try {\n const payload = await readApiResultOrThrow<PersonOverview>(\n `/api/customers/people/${encodeURIComponent(id)}`,\n undefined,\n { errorMessage: t('customers.people.detail.error.load', 'Failed to load person.') },\n )\n setData(payload as PersonOverview)\n } catch (err) {\n if ((err as { status?: number }).status === 404) {\n setIsNotFound(true)\n } else {\n const message = err instanceof Error ? err.message : t('customers.people.detail.error.load', 'Failed to load person.')\n setError(message)\n }\n if (!initialLoadDoneRef.current) setData(null)\n } finally {\n setIsLoading(false)\n initialLoadDoneRef.current = true\n }\n }, [id, t])\n\n React.useEffect(() => {\n loadData().catch((err) => console.warn('[people-v2] loadData failed', err))\n }, [loadData])\n\n React.useEffect(() => {\n setDealCount(data?.counts?.deals ?? 0)\n }, [data?.counts?.deals])\n\n const handleActivityCreated = React.useCallback(() => {\n setActivityRefreshKey((k) => k + 1)\n loadData().catch((err) => console.warn('[people-v2] reload after activity failed', err))\n }, [loadData])\n\n const plannedActivities = React.useMemo(() => {\n return data?.plannedActivitiesPreview ?? []\n }, [data?.plannedActivitiesPreview])\n\n // Injection context for UMES\n const injectionContext = React.useMemo(\n () => ({\n formId: mutationContextId,\n personId: currentPersonId,\n resourceKind: 'customers.person',\n resourceId: currentPersonId ?? (id ?? undefined),\n data,\n retryLastMutation,\n }),\n [currentPersonId, data, id, mutationContextId, retryLastMutation],\n )\n const runMutationWithContext = React.useCallback(\n async <T,>(operation: () => Promise<T>, mutationPayload?: Record<string, unknown>): Promise<T> => {\n return runMutation({\n operation,\n mutationPayload,\n context: injectionContext,\n })\n },\n [injectionContext, runMutation],\n )\n\n const handleAddActivity = React.useCallback((kind: ActivityKind) => {\n setScheduleEditData({\n id: '',\n interactionType: kind,\n title: null,\n body: null,\n scheduledAt: null,\n durationMinutes: null,\n location: null,\n allDay: null,\n recurrenceRule: null,\n recurrenceEnd: null,\n participants: null,\n reminderMinutes: null,\n visibility: null,\n linkedEntities: null,\n guestPermissions: null,\n })\n setScheduleDialogOpen(true)\n }, [])\n\n const handleEditActivity = React.useCallback((activity: { id: string; interactionType?: string; title?: string | null; body?: string | null; scheduledAt?: string | null; occurredAt?: string | null; [key: string]: unknown }) => {\n const raw = activity as Record<string, unknown>\n const durationValue = typeof raw.duration === 'number'\n ? raw.duration\n : typeof raw.durationMinutes === 'number'\n ? raw.durationMinutes as number\n : null\n // Forward `customValues` so per-type chip state (callPhoneNumber, callDirection,\n // taskPriority, \u2026) round-trips on edit (#1808 phone persistence).\n // Forward `occurredAt` so historical activity edits prefill from the original\n // moment instead of \"today\" (#1807 prefill).\n const editPayload = {\n id: activity.id,\n interactionType: typeof activity.interactionType === 'string' ? activity.interactionType : undefined,\n title: typeof activity.title === 'string' ? activity.title : null,\n body: typeof activity.body === 'string' ? activity.body : null,\n scheduledAt: typeof activity.scheduledAt === 'string' ? activity.scheduledAt : null,\n occurredAt: typeof activity.occurredAt === 'string' ? activity.occurredAt : null,\n durationMinutes: durationValue,\n location: typeof raw.location === 'string' ? raw.location as string : null,\n allDay: typeof raw.allDay === 'boolean' ? raw.allDay as boolean : null,\n recurrenceRule: typeof raw.recurrenceRule === 'string' ? raw.recurrenceRule as string : null,\n recurrenceEnd: typeof raw.recurrenceEnd === 'string' ? raw.recurrenceEnd as string : null,\n participants: Array.isArray(raw.participants) ? raw.participants as ScheduleActivityEditData['participants'] : null,\n reminderMinutes: typeof raw.reminderMinutes === 'number' ? raw.reminderMinutes as number : null,\n visibility: typeof raw.visibility === 'string' ? raw.visibility as string : null,\n linkedEntities: Array.isArray(raw.linkedEntities) ? raw.linkedEntities as ScheduleActivityEditData['linkedEntities'] : null,\n guestPermissions: raw.guestPermissions && typeof raw.guestPermissions === 'object'\n ? raw.guestPermissions as ScheduleActivityEditData['guestPermissions']\n : null,\n customValues: raw.customValues && typeof raw.customValues === 'object'\n ? raw.customValues as Record<string, unknown>\n : null,\n phoneNumber: typeof raw.phoneNumber === 'string' ? raw.phoneNumber as string : null,\n } as ScheduleActivityEditData & { customValues?: Record<string, unknown> | null; phoneNumber?: string | null }\n setScheduleEditData(editPayload)\n setScheduleDialogOpen(true)\n }, [])\n\n // Injected tabs from UMES\n const { widgets: injectedTabWidgets } = useInjectionWidgets('detail:customers.person:tabs', {\n context: injectionContext,\n triggerOnLoad: true,\n })\n\n const injectedTabs = React.useMemo(\n () =>\n (injectedTabWidgets ?? [])\n .filter((widget) => (widget.placement?.kind ?? 'tab') === 'tab')\n .map((widget) => {\n const tabId = widget.placement?.groupId ?? widget.widgetId\n const label = widget.placement?.groupLabel ?? widget.module.metadata.title ?? tabId\n const priority = typeof widget.placement?.priority === 'number' ? widget.placement.priority : 0\n const render = () => (\n <widget.module.Widget\n context={injectionContext}\n data={data}\n onDataChange={(next: unknown) => setData(next as PersonOverview)}\n />\n )\n return { id: tabId, label, priority, render }\n })\n .sort((a, b) => b.priority - a.priority),\n [data, injectedTabWidgets, injectionContext],\n )\n\n const injectedTabMap = React.useMemo(() => new Map(injectedTabs.map((tab) => [tab.id, tab.render])), [injectedTabs])\n\n // Tags\n const handleTagsChange = React.useCallback((nextTags: TagSummary[]) => {\n setData((prev) => (prev ? { ...prev, tags: nextTags } : prev))\n }, [])\n const tagsSectionControllerRef = React.useRef<TagsSectionController | null>(null)\n\n // Section action (for tabs that expose add/create buttons)\n const handleSectionActionChange = React.useCallback((action: SectionAction | null) => {\n setSectionAction((prev) => (action !== null ? action : prev))\n }, [])\n\n React.useEffect(() => {\n setSectionAction(null)\n }, [activeTab])\n\n // Deals scope\n const dealsScope = React.useMemo(\n () => (currentPersonId ? ({ kind: 'person', entityId: currentPersonId } as const) : null),\n [currentPersonId],\n )\n\n const initialValues = React.useMemo(\n () => (data ? mapPersonOverviewToFormValues(data) : undefined),\n [data],\n )\n\n // Form submit/delete\n const handleFormSubmit = React.useCallback(\n async (values: PersonEditFormValues) => {\n setIsSaving(true)\n try {\n await tagsSectionControllerRef.current?.flush()\n\n let payload: Record<string, unknown>\n try {\n payload = buildPersonEditPayload(values, organizationId)\n } catch (err) {\n if (err instanceof Error && err.message === 'DISPLAY_NAME_REQUIRED') {\n const message = t('customers.people.form.displayName.error')\n throw createCrudFormError(message, { displayName: message })\n }\n throw err\n }\n\n await updateCrud('customers/people', payload)\n flash(t('customers.people.form.updateSuccess', 'Person updated.'), 'success')\n await loadData()\n } finally {\n setIsSaving(false)\n }\n },\n [loadData, organizationId, t],\n )\n\n const handleFormDelete = React.useCallback(\n async () => {\n const personId = data?.person?.id ?? ''\n if (!personId) return\n const approved = await confirm({\n title: t('customers.people.detail.deleteConfirmTitle', 'Delete person?'),\n description: t('customers.people.detail.deleteConfirmDescription', 'This action cannot be undone.'),\n confirmText: t('customers.people.detail.actions.delete', 'Delete'),\n cancelText: t('customers.people.detail.actions.cancel', 'Cancel'),\n variant: 'destructive',\n })\n if (!approved) return\n await runMutationWithContext(\n () => deleteCrud('customers/people', { id: personId }),\n { id: personId, operation: 'deletePerson' },\n )\n flash(t('customers.people.list.deleteSuccess', 'Person deleted.'), 'success')\n router.push('/backend/customers/people')\n },\n [confirm, data?.person?.id, router, runMutationWithContext, t],\n )\n\n const handleHeaderSave = React.useCallback(() => {\n const form = formWrapperRef.current?.querySelector('form')\n if (form) form.requestSubmit()\n }, [])\n\n // Counts for tab badges\n const interactionCount = data?.counts?.activities ?? 0\n const todoCount = data?.counts?.todos ?? 0\n const companyCount = data?.counts?.companies ?? (data?.companies?.length ?? (data?.company ? 1 : 0))\n\n // Loading / error states\n if (isLoading) {\n return (\n <Page>\n <PageBody>\n <LoadingMessage label={t('customers.people.detail.loading', 'Loading person\u2026')} />\n </PageBody>\n </Page>\n )\n }\n\n if (isNotFound) {\n return (\n <Page>\n <PageBody>\n <RecordNotFoundState\n label={t('customers.people.detail.error.notFound', 'Person not found.')}\n backHref=\"/backend/customers/people\"\n backLabel={t('customers.people.detail.actions.backToList', 'Back to people')}\n />\n </PageBody>\n </Page>\n )\n }\n\n if (error || !data?.person?.id || !initialValues) {\n return (\n <Page>\n <PageBody>\n <ErrorMessage\n label={error ?? t('customers.people.detail.error.load', 'Failed to load person.')}\n action={(\n <Button asChild variant=\"outline\">\n <Link href=\"/backend/customers/people\">\n {t('customers.people.detail.actions.backToList', 'Back to people')}\n </Link>\n </Button>\n )}\n />\n </PageBody>\n </Page>\n )\n }\n\n const personId = data.person.id\n const useCanonicalInteractions = data.interactionMode === 'canonical'\n\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-4\">\n {/* UMES header injection (third-party extensions) */}\n <InjectionSpot spotId=\"detail:customers.person:header\" context={injectionContext} data={data} />\n <InjectionSpot spotId=\"detail:customers.person:status-badges\" context={injectionContext} data={data} />\n\n {/* Persistent person header */}\n <PersonDetailHeader\n data={data}\n onTagsChange={handleTagsChange}\n tagsSectionControllerRef={tagsSectionControllerRef}\n onSave={handleHeaderSave}\n onDelete={handleFormDelete}\n isDirty={isDirty}\n isSaving={isSaving}\n onOpenCompaniesTab={() => setActiveTab('companies')}\n onDataReload={() => { loadData().catch((err) => console.warn('[people-v2] onDataReload failed', err)) }}\n onFocusField={(fieldName) => {\n const selectorMap: Record<string, string> = {\n primaryEmail: 'input[type=\"email\"]',\n primaryPhone: 'input[type=\"tel\"]',\n }\n const selector = selectorMap[fieldName]\n const input = selector ? formWrapperRef.current?.querySelector<HTMLInputElement>(selector) : null\n if (input) {\n input.scrollIntoView({ behavior: 'smooth', block: 'center' })\n requestAnimationFrame(() => input.focus())\n }\n }}\n />\n\n {/* Zone content shared between desktop (CollapsibleZoneLayout) and mobile (MobilePersonDetail). */}\n {(() => {\n const zone1Content = (\n <div ref={formWrapperRef}>\n <CrudForm<PersonEditFormValues>\n embedded\n trackDirtyWhenEmbedded\n injectionSpotId=\"customers.person\"\n entityIds={[E.customers.customer_entity, E.customers.customer_person_profile]}\n schema={formSchema}\n fields={fields}\n groups={groups}\n initialValues={initialValues}\n onSubmit={handleFormSubmit}\n onDelete={handleFormDelete}\n hideFooterActions\n collapsibleGroups={{ pageType: 'person-v2', chevronPosition: 'right' }}\n sortableGroups={{ pageType: 'person-v2' }}\n onDirtyChange={setIsDirty}\n />\n </div>\n )\n const zone2Content = (\n <PersonDetailTabs\n activeTab={activeTab}\n onTabChange={setActiveTab}\n injectedTabs={injectedTabs.map((tab) => ({ id: tab.id, label: tab.label }))}\n activitiesCount={interactionCount}\n dealsCount={dealCount}\n companiesCount={companyCount}\n tasksCount={todoCount}\n sectionAction={sectionAction}\n >\n <div className=\"min-w-0\">\n {(() => {\n // Injected tab content\n const injected = injectedTabMap.get(activeTab)\n if (injected) return injected()\n\n if (activeTab === 'activities') {\n return (\n <div className=\"space-y-4\">\n <ActivitiesCard\n entityId={personId}\n plannedActivities={plannedActivities}\n refreshKey={activityRefreshKey}\n onAddNew={handleAddActivity}\n onEditActivity={handleEditActivity}\n entityCompanyName={data.company?.displayName ?? data.companies?.[0]?.displayName ?? null}\n />\n <ActivitiesSection\n entityId={personId}\n entityName={personName}\n useCanonicalInteractions={useCanonicalInteractions}\n runGuardedMutation={runMutationWithContext}\n onDataRefresh={handleActivityCreated}\n refreshKey={activityRefreshKey}\n addActionLabel={t('customers.people.detail.activities.add', 'Log activity')}\n emptyState={{\n title: t('customers.people.detail.emptyState.activities.title', 'No activities logged yet'),\n actionLabel: t('customers.people.detail.emptyState.activities.action', 'Log activity'),\n }}\n onActionChange={handleSectionActionChange}\n onEditActivity={handleEditActivity}\n />\n </div>\n )\n }\n\n if (activeTab === 'emails') {\n return (\n <PersonEmailThreadsTab\n personId={personId}\n defaultRecipient={data.person?.primaryEmail ?? null}\n />\n )\n }\n\n if (activeTab === 'deals') {\n return (\n <DealsSection\n scope={dealsScope}\n emptyLabel={t('customers.people.detail.empty.deals', 'No deals linked to this person.')}\n addActionLabel={t('customers.people.detail.actions.addDeal', 'Add deal')}\n emptyState={{\n title: t('customers.people.detail.emptyState.deals.title', 'No deals yet'),\n actionLabel: t('customers.people.detail.emptyState.deals.action', 'Create a deal'),\n }}\n onActionChange={handleSectionActionChange}\n translator={detailTranslator}\n runGuardedMutation={runMutationWithContext}\n onCountDelta={(delta) => setDealCount((current) => Math.max(0, current + delta))}\n />\n )\n }\n\n if (activeTab === 'companies') {\n return (\n <PersonCompaniesSection\n personId={personId}\n personName={personName}\n initialLinkedCompanies={data?.companies ?? []}\n onChanged={loadData}\n runGuardedMutation={runMutationWithContext}\n />\n )\n }\n\n if (activeTab === 'tasks') {\n return (\n <TasksSection\n entityId={personId}\n initialTasks={[]}\n useCanonicalInteractions={useCanonicalInteractions}\n runGuardedMutation={runMutationWithContext}\n onDataRefresh={loadData}\n emptyLabel={t('customers.people.detail.empty.todos', 'No tasks linked to this person.')}\n addActionLabel={t('customers.people.detail.tasks.add', 'Add task')}\n emptyState={{\n title: t('customers.people.detail.emptyState.tasks.title', 'Plan what happens next'),\n actionLabel: t('customers.people.detail.emptyState.tasks.action', 'Create task'),\n }}\n onActionChange={handleSectionActionChange}\n translator={detailTranslator}\n entityName={personName}\n dialogContextKey=\"customers.people.detail.tasks.dialog.context\"\n dialogContextFallback=\"This task will be linked to {{name}}\"\n />\n )\n }\n\n if (activeTab === 'files') {\n return (\n <AttachmentsSection\n entityId={E.customers.customer_entity}\n recordId={personId}\n title={t('customers.people.detail.tabs.files', 'Files')}\n description={t('customers.people.detail.files.subtitle', 'Upload and manage files linked to this person.')}\n />\n )\n }\n\n if (activeTab === 'changelog') {\n return <ChangelogTab entityId={personId} entityType=\"person\" />\n }\n\n return null\n })()}\n </div>\n </PersonDetailTabs>\n )\n return (\n <>\n <div className=\"md:hidden\">\n <MobilePersonDetail zone1={zone1Content} zone2={zone2Content} />\n </div>\n <div className=\"hidden md:block\">\n <CollapsibleZoneLayout\n pageType=\"person-v2\"\n entityName={personName}\n isDirty={isDirty}\n sections={zoneSections}\n zone1={zone1Content}\n zone2={zone2Content}\n />\n </div>\n </>\n )\n })()}\n\n {/* UMES footer injection */}\n <InjectionSpot spotId=\"detail:customers.person:footer\" context={injectionContext} data={data} />\n\n {/* Schedule Activity Dialog \u2014 opened from PlannedActivities \"+ Schedule\" or other triggers */}\n <ScheduleActivityDialog\n open={scheduleDialogOpen}\n onClose={() => { setScheduleDialogOpen(false); setScheduleEditData(null) }}\n entityId={personId}\n entityName={personName}\n companyName={scheduleDialogCompanyName}\n entityType=\"person\"\n onActivityCreated={handleActivityCreated}\n editData={scheduleEditData}\n />\n {ConfirmDialogElement}\n </div>\n </PageBody>\n </Page>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["personId"]
7
7
  }
@@ -71,6 +71,22 @@ async function resolvePipelineStageValue(em, pipelineStageId, tenantId, organiza
71
71
  });
72
72
  return entry?.value ?? stage.label;
73
73
  }
74
+ function resolvePipelineAssignment(input) {
75
+ const requestedPipelineId = input.pipelineId ?? null;
76
+ const requestedPipelineStageId = input.pipelineStageId ?? null;
77
+ if (requestedPipelineStageId && !input.stageSnapshot) {
78
+ throw new CrudHttpError(400, { error: "Pipeline stage not found" });
79
+ }
80
+ if (requestedPipelineId && input.stageSnapshot && input.stageSnapshot.pipelineId !== requestedPipelineId) {
81
+ throw new CrudHttpError(400, {
82
+ error: "Pipeline stage does not belong to the selected pipeline"
83
+ });
84
+ }
85
+ return {
86
+ pipelineId: requestedPipelineId ?? input.stageSnapshot?.pipelineId ?? null,
87
+ pipelineStageId: requestedPipelineStageId
88
+ };
89
+ }
74
90
  async function upsertDealStageTransition(em, input) {
75
91
  let existing = null;
76
92
  try {
@@ -262,10 +278,19 @@ const createDealCommand = {
262
278
  const normalizedTransitionAuthorUserId = normalizeAuthorUserId(null, ctx.auth);
263
279
  let deal;
264
280
  let stageSnapshot = null;
281
+ let pipelineAssignment = {
282
+ pipelineId: null,
283
+ pipelineStageId: null
284
+ };
265
285
  let resolvedPipelineStageLabel = null;
266
286
  await withAtomicFlush(em, [
267
287
  async () => {
268
288
  stageSnapshot = parsed.pipelineStageId ? await loadPipelineStageSnapshot(em, parsed.pipelineStageId, parsed.tenantId, parsed.organizationId) : null;
289
+ pipelineAssignment = resolvePipelineAssignment({
290
+ pipelineId: parsed.pipelineId,
291
+ pipelineStageId: parsed.pipelineStageId,
292
+ stageSnapshot
293
+ });
269
294
  resolvedPipelineStageLabel = stageSnapshot ? (await ensureDictionaryEntry(em, {
270
295
  tenantId: parsed.tenantId,
271
296
  organizationId: parsed.organizationId,
@@ -281,8 +306,8 @@ const createDealCommand = {
281
306
  description: parsed.description ?? null,
282
307
  status: parsed.status ?? "open",
283
308
  pipelineStage: resolvedPipelineStageLabel,
284
- pipelineId: parsed.pipelineId ?? null,
285
- pipelineStageId: parsed.pipelineStageId ?? null,
309
+ pipelineId: pipelineAssignment.pipelineId,
310
+ pipelineStageId: pipelineAssignment.pipelineStageId,
286
311
  valueAmount: toNumericString(parsed.valueAmount),
287
312
  valueCurrency: parsed.valueCurrency ?? null,
288
313
  probability: parsed.probability ?? null,
@@ -390,11 +415,25 @@ const updateDealCommand = {
390
415
  const previousPipelineStageId = record.pipelineStageId ?? null;
391
416
  const normalizedTransitionAuthorUserId = normalizeAuthorUserId(null, ctx.auth);
392
417
  let nextStageSnapshot = null;
418
+ let nextPipelineAssignment = {
419
+ pipelineId: record.pipelineId ?? null,
420
+ pipelineStageId: record.pipelineStageId ?? null
421
+ };
393
422
  let nextPipelineStageLabel = null;
394
423
  let resolvedCurrentPipelineStageLabel = null;
395
424
  await withAtomicFlush(em, [
396
425
  async () => {
397
- nextStageSnapshot = parsed.pipelineStageId ? await loadPipelineStageSnapshot(em, parsed.pipelineStageId, record.tenantId, record.organizationId) : null;
426
+ const pipelineAssignmentChanged = parsed.pipelineId !== void 0 || parsed.pipelineStageId !== void 0;
427
+ const requestedPipelineStageId = parsed.pipelineStageId !== void 0 ? parsed.pipelineStageId ?? null : record.pipelineStageId ?? null;
428
+ const requestedPipelineId = parsed.pipelineId !== void 0 ? parsed.pipelineId ?? null : record.pipelineId ?? null;
429
+ nextStageSnapshot = requestedPipelineStageId && (pipelineAssignmentChanged || !record.pipelineStage) ? await loadPipelineStageSnapshot(em, requestedPipelineStageId, record.tenantId, record.organizationId) : null;
430
+ if (pipelineAssignmentChanged) {
431
+ nextPipelineAssignment = resolvePipelineAssignment({
432
+ pipelineId: requestedPipelineId,
433
+ pipelineStageId: requestedPipelineStageId,
434
+ stageSnapshot: nextStageSnapshot
435
+ });
436
+ }
398
437
  nextPipelineStageLabel = nextStageSnapshot ? (await ensureDictionaryEntry(em, {
399
438
  tenantId: record.tenantId,
400
439
  organizationId: record.organizationId,
@@ -408,8 +447,10 @@ const updateDealCommand = {
408
447
  if (parsed.description !== void 0) record.description = parsed.description ?? null;
409
448
  if (parsed.status !== void 0) record.status = parsed.status ?? record.status;
410
449
  if (parsed.pipelineStage !== void 0) record.pipelineStage = parsed.pipelineStage ?? null;
411
- if (parsed.pipelineId !== void 0) record.pipelineId = parsed.pipelineId ?? null;
412
- if (parsed.pipelineStageId !== void 0) record.pipelineStageId = parsed.pipelineStageId ?? null;
450
+ if (parsed.pipelineId !== void 0 || parsed.pipelineStageId !== void 0 && nextStageSnapshot) {
451
+ record.pipelineId = nextPipelineAssignment.pipelineId;
452
+ }
453
+ if (parsed.pipelineStageId !== void 0) record.pipelineStageId = nextPipelineAssignment.pipelineStageId;
413
454
  if (nextPipelineStageLabel && (parsed.pipelineStageId !== void 0 || !record.pipelineStage)) {
414
455
  record.pipelineStage = nextPipelineStageLabel;
415
456
  } else if (resolvedCurrentPipelineStageLabel && (parsed.pipelineStageId !== void 0 || !record.pipelineStage)) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/customers/commands/deals.ts"],
4
- "sourcesContent": ["import { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport {\n parseWithCustomFields,\n setCustomFieldsIfAny,\n emitCrudSideEffects,\n emitCrudUndoSideEffects,\n requireId,\n normalizeAuthorUserId,\n} from '@open-mercato/shared/lib/commands/helpers'\nimport { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport {\n CustomerDeal,\n CustomerDealPersonLink,\n CustomerDealCompanyLink,\n CustomerDealStageTransition,\n CustomerPipelineStage,\n} from '../data/entities'\nimport {\n dealCreateSchema,\n dealUpdateSchema,\n type DealCreateInput,\n type DealUpdateInput,\n} from '../data/validators'\nimport {\n ensureOrganizationScope,\n ensureTenantScope,\n requireCustomerEntity,\n ensureSameScope,\n extractUndoPayload,\n ensureDictionaryEntry,\n} from './shared'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport {\n loadCustomFieldSnapshot,\n buildCustomFieldResetMap,\n type CustomFieldChangeSet,\n} from '@open-mercato/shared/lib/commands/customFieldSnapshots'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport type { CrudIndexerConfig, CrudEventsConfig } from '@open-mercato/shared/lib/crud/types'\nimport { E } from '#generated/entities.ids.generated'\nimport { findWithDecryption, findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { isMissingDealStageTransitionTable, warnMissingDealStageTransitionTable } from '../lib/dealStageTransitionTable'\n\nconst DEAL_ENTITY_ID = 'customers:customer_deal'\nconst dealCrudIndexer: CrudIndexerConfig<CustomerDeal> = {\n entityType: E.customers.customer_deal,\n}\n\nconst dealCrudEvents: CrudEventsConfig = {\n module: 'customers',\n entity: 'deal',\n persistent: true,\n buildPayload: (ctx) => ({\n id: ctx.identifiers.id,\n organizationId: ctx.identifiers.organizationId,\n tenantId: ctx.identifiers.tenantId,\n }),\n}\n\ntype PipelineStageSnapshot = {\n id: string\n pipelineId: string\n label: string\n order: number\n}\n\ntype DealStageTransitionSnapshot = {\n id: string\n pipelineId: string\n stageId: string\n stageLabel: string\n stageOrder: number\n transitionedAt: Date\n transitionedByUserId: string | null\n}\n\nasync function loadPipelineStageSnapshot(\n em: EntityManager,\n pipelineStageId: string,\n tenantId: string,\n organizationId: string,\n): Promise<PipelineStageSnapshot | null> {\n const stage = await findOneWithDecryption(em, CustomerPipelineStage, { id: pipelineStageId }, {}, { tenantId, organizationId })\n if (!stage) return null\n return {\n id: stage.id,\n pipelineId: stage.pipelineId,\n label: stage.label,\n order: stage.order,\n }\n}\n\nasync function resolvePipelineStageValue(\n em: EntityManager,\n pipelineStageId: string,\n tenantId: string,\n organizationId: string,\n): Promise<string | null> {\n const stage = await loadPipelineStageSnapshot(em, pipelineStageId, tenantId, organizationId)\n if (!stage) return null\n const entry = await ensureDictionaryEntry(em, {\n tenantId,\n organizationId,\n kind: 'pipeline_stage',\n value: stage.label,\n })\n return entry?.value ?? stage.label\n}\n\nasync function upsertDealStageTransition(\n em: EntityManager,\n input: {\n deal: CustomerDeal\n pipelineId: string\n stageId: string\n stageLabel: string\n stageOrder: number\n transitionedByUserId: string | null\n transitionedAt?: Date\n },\n): Promise<void> {\n let existing: CustomerDealStageTransition | null = null\n try {\n existing = await findOneWithDecryption(\n em,\n CustomerDealStageTransition,\n { deal: input.deal.id, stageId: input.stageId, deletedAt: null },\n {},\n { tenantId: input.deal.tenantId, organizationId: input.deal.organizationId },\n )\n } catch (error) {\n if (!isMissingDealStageTransitionTable(error)) {\n throw error\n }\n warnMissingDealStageTransitionTable('customers.commands.deals.upsertTransition')\n return\n }\n const transitionedAt = input.transitionedAt ?? new Date()\n if (existing) {\n existing.pipelineId = input.pipelineId\n existing.stageLabel = input.stageLabel\n existing.stageOrder = input.stageOrder\n existing.transitionedAt = transitionedAt\n existing.transitionedByUserId = input.transitionedByUserId\n existing.deletedAt = null\n existing.isActive = true\n return\n }\n\n const transition = em.create(CustomerDealStageTransition, {\n organizationId: input.deal.organizationId,\n tenantId: input.deal.tenantId,\n deal: input.deal,\n pipelineId: input.pipelineId,\n stageId: input.stageId,\n stageLabel: input.stageLabel,\n stageOrder: input.stageOrder,\n transitionedAt,\n transitionedByUserId: input.transitionedByUserId,\n isActive: true,\n })\n em.persist(transition)\n}\n\nasync function deleteDealStageTransitions(em: EntityManager, deal: CustomerDeal): Promise<void> {\n try {\n await em.nativeDelete(CustomerDealStageTransition, { deal: deal.id })\n } catch (error) {\n if (!isMissingDealStageTransitionTable(error)) {\n throw error\n }\n warnMissingDealStageTransitionTable('customers.commands.deals.deleteTransitions')\n }\n}\n\nasync function restoreDealStageTransitions(\n em: EntityManager,\n deal: CustomerDeal,\n transitions: DealStageTransitionSnapshot[],\n): Promise<void> {\n if (!transitions.length) return\n for (const transitionSnapshot of transitions) {\n const transition = em.create(CustomerDealStageTransition, {\n id: transitionSnapshot.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n deal,\n pipelineId: transitionSnapshot.pipelineId,\n stageId: transitionSnapshot.stageId,\n stageLabel: transitionSnapshot.stageLabel,\n stageOrder: transitionSnapshot.stageOrder,\n transitionedAt: transitionSnapshot.transitionedAt,\n transitionedByUserId: transitionSnapshot.transitionedByUserId,\n isActive: true,\n })\n em.persist(transition)\n }\n}\n\ntype DealSnapshot = {\n deal: {\n id: string\n organizationId: string\n tenantId: string\n title: string\n description: string | null\n status: string\n pipelineStage: string | null\n pipelineId: string | null\n pipelineStageId: string | null\n valueAmount: string | null\n valueCurrency: string | null\n probability: number | null\n expectedCloseAt: Date | null\n ownerUserId: string | null\n source: string | null\n closureOutcome: string | null\n lossReasonId: string | null\n lossNotes: string | null\n }\n people: string[]\n companies: string[]\n transitions: DealStageTransitionSnapshot[]\n custom?: Record<string, unknown>\n}\n\ntype DealUndoPayload = {\n before?: DealSnapshot | null\n after?: DealSnapshot | null\n}\n\ntype DealChangeMap = Record<string, { from: unknown; to: unknown }> & {\n custom?: CustomFieldChangeSet\n}\n\nasync function loadDealSnapshot(em: EntityManager, id: string): Promise<DealSnapshot | null> {\n const deal = await findOneWithDecryption(em, CustomerDeal, { id, deletedAt: null })\n if (!deal) return null\n const decryptionScope = { tenantId: deal.tenantId ?? null, organizationId: deal.organizationId ?? null }\n const peopleLinks = await findWithDecryption(\n em,\n CustomerDealPersonLink,\n { deal: deal },\n { populate: ['person'] },\n decryptionScope,\n )\n const companyLinks = await findWithDecryption(\n em,\n CustomerDealCompanyLink,\n { deal: deal },\n { populate: ['company'] },\n decryptionScope,\n )\n const transitions = await findWithDecryption(\n em,\n CustomerDealStageTransition,\n { deal: deal.id, deletedAt: null },\n { orderBy: { stageOrder: 'ASC', transitionedAt: 'ASC' } },\n decryptionScope,\n ).catch((error: unknown) => {\n if (!isMissingDealStageTransitionTable(error)) {\n throw error\n }\n warnMissingDealStageTransitionTable('customers.commands.deals.loadSnapshot')\n return [] as CustomerDealStageTransition[]\n })\n const custom = await loadCustomFieldSnapshot(em, {\n entityId: DEAL_ENTITY_ID,\n recordId: deal.id,\n tenantId: deal.tenantId,\n organizationId: deal.organizationId,\n })\n return {\n deal: {\n id: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n title: deal.title,\n description: deal.description ?? null,\n status: deal.status,\n pipelineStage: deal.pipelineStage ?? null,\n pipelineId: deal.pipelineId ?? null,\n pipelineStageId: deal.pipelineStageId ?? null,\n valueAmount: deal.valueAmount ?? null,\n valueCurrency: deal.valueCurrency ?? null,\n probability: deal.probability ?? null,\n expectedCloseAt: deal.expectedCloseAt ?? null,\n ownerUserId: deal.ownerUserId ?? null,\n source: deal.source ?? null,\n closureOutcome: deal.closureOutcome ?? null,\n lossReasonId: deal.lossReasonId ?? null,\n lossNotes: deal.lossNotes ?? null,\n },\n people: peopleLinks.map((link) =>\n typeof link.person === 'string' ? link.person : link.person.id\n ),\n companies: companyLinks.map((link) =>\n typeof link.company === 'string' ? link.company : link.company.id\n ),\n transitions: transitions.map((transition) => ({\n id: transition.id,\n pipelineId: transition.pipelineId,\n stageId: transition.stageId,\n stageLabel: transition.stageLabel,\n stageOrder: transition.stageOrder,\n transitionedAt: transition.transitionedAt,\n transitionedByUserId: transition.transitionedByUserId ?? null,\n })),\n custom,\n }\n}\n\nfunction toNumericString(value: number | null | undefined): string | null {\n if (value === undefined || value === null) return null\n return value.toString()\n}\n\nasync function syncDealPeople(\n em: EntityManager,\n deal: CustomerDeal,\n personIds: string[] | undefined | null\n): Promise<void> {\n if (personIds === undefined) return\n await em.nativeDelete(CustomerDealPersonLink, { deal })\n if (!personIds || !personIds.length) return\n const unique = Array.from(new Set(personIds))\n for (const personId of unique) {\n const person = await requireCustomerEntity(em, personId, 'person', 'Person not found')\n ensureSameScope(person, deal.organizationId, deal.tenantId)\n const link = em.create(CustomerDealPersonLink, {\n deal,\n person,\n })\n em.persist(link)\n }\n}\n\nasync function syncDealCompanies(\n em: EntityManager,\n deal: CustomerDeal,\n companyIds: string[] | undefined | null\n): Promise<void> {\n if (companyIds === undefined) return\n await em.nativeDelete(CustomerDealCompanyLink, { deal })\n if (!companyIds || !companyIds.length) return\n const unique = Array.from(new Set(companyIds))\n for (const companyId of unique) {\n const company = await requireCustomerEntity(em, companyId, 'company', 'Company not found')\n ensureSameScope(company, deal.organizationId, deal.tenantId)\n const link = em.create(CustomerDealCompanyLink, {\n deal,\n company,\n })\n em.persist(link)\n }\n}\n\nconst createDealCommand: CommandHandler<DealCreateInput, { dealId: string }> = {\n id: 'customers.deals.create',\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(dealCreateSchema, rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const normalizedTransitionAuthorUserId = normalizeAuthorUserId(null, ctx.auth)\n let deal!: CustomerDeal\n let stageSnapshot: PipelineStageSnapshot | null = null\n let resolvedPipelineStageLabel: string | null = null\n await withAtomicFlush(em, [\n async () => {\n stageSnapshot = parsed.pipelineStageId\n ? await loadPipelineStageSnapshot(em, parsed.pipelineStageId, parsed.tenantId, parsed.organizationId)\n : null\n resolvedPipelineStageLabel = stageSnapshot\n ? (await ensureDictionaryEntry(em, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n kind: 'pipeline_stage',\n value: stageSnapshot.label,\n }))?.value ?? stageSnapshot.label\n : parsed.pipelineStage ?? null\n },\n async () => {\n deal = em.create(CustomerDeal, {\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n title: parsed.title,\n description: parsed.description ?? null,\n status: parsed.status ?? 'open',\n pipelineStage: resolvedPipelineStageLabel,\n pipelineId: parsed.pipelineId ?? null,\n pipelineStageId: parsed.pipelineStageId ?? null,\n valueAmount: toNumericString(parsed.valueAmount),\n valueCurrency: parsed.valueCurrency ?? null,\n probability: parsed.probability ?? null,\n expectedCloseAt: parsed.expectedCloseAt ?? null,\n ownerUserId: parsed.ownerUserId ?? null,\n source: parsed.source ?? null,\n closureOutcome: parsed.closureOutcome ?? null,\n lossReasonId: parsed.lossReasonId ?? null,\n lossNotes: parsed.lossNotes ?? null,\n })\n em.persist(deal)\n await em.flush()\n },\n async () => {\n const snapshot = stageSnapshot\n if (!snapshot) return\n await upsertDealStageTransition(em, {\n deal,\n pipelineId: snapshot.pipelineId,\n stageId: snapshot.id,\n stageLabel: snapshot.label,\n stageOrder: snapshot.order,\n transitionedByUserId: normalizedTransitionAuthorUserId,\n })\n },\n () => syncDealPeople(em, deal, parsed.personIds ?? []),\n () => syncDealCompanies(em, deal, parsed.companyIds ?? []),\n ], { transaction: true })\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: DEAL_ENTITY_ID,\n recordId: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n values: custom,\n notify: false,\n })\n\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: deal,\n identifiers: {\n id: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n },\n indexer: dealCrudIndexer,\n events: dealCrudEvents,\n })\n\n return { dealId: deal.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadDealSnapshot(em, result.dealId)\n },\n buildLog: async ({ result, ctx }) => {\n const { translate } = await resolveTranslations()\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadDealSnapshot(em, result.dealId)\n return {\n actionLabel: translate('customers.audit.deals.create', 'Create deal'),\n resourceKind: 'customers.deal',\n resourceId: result.dealId,\n tenantId: snapshot?.deal.tenantId ?? null,\n organizationId: snapshot?.deal.organizationId ?? null,\n snapshotAfter: snapshot ?? null,\n payload: {\n undo: {\n after: snapshot,\n } satisfies DealUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const dealId = logEntry?.resourceId\n if (!dealId) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const deal = await findOneWithDecryption(em, CustomerDeal, { id: dealId })\n if (!deal) return\n await deleteDealStageTransitions(em, deal)\n await em.nativeDelete(CustomerDealPersonLink, { deal })\n await em.nativeDelete(CustomerDealCompanyLink, { deal })\n em.remove(deal)\n await em.flush()\n },\n}\n\nconst updateDealCommand: CommandHandler<DealUpdateInput, { dealId: string }> = {\n id: 'customers.deals.update',\n async prepare(rawInput, ctx) {\n const { parsed } = parseWithCustomFields(dealUpdateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadDealSnapshot(em, parsed.id)\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(dealUpdateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const deal = await findOneWithDecryption(em, CustomerDeal, { id: parsed.id, deletedAt: null })\n const record = deal ?? null\n if (!record) throw new CrudHttpError(404, { error: 'Deal not found' })\n ensureTenantScope(ctx, record.tenantId)\n ensureOrganizationScope(ctx, record.organizationId)\n\n const previousStatus = record.status\n const previousPipelineStageId = record.pipelineStageId ?? null\n const normalizedTransitionAuthorUserId = normalizeAuthorUserId(null, ctx.auth)\n\n let nextStageSnapshot: PipelineStageSnapshot | null = null\n let nextPipelineStageLabel: string | null = null\n let resolvedCurrentPipelineStageLabel: string | null = null\n\n await withAtomicFlush(em, [\n async () => {\n nextStageSnapshot = parsed.pipelineStageId\n ? await loadPipelineStageSnapshot(em, parsed.pipelineStageId, record.tenantId, record.organizationId)\n : null\n nextPipelineStageLabel = nextStageSnapshot\n ? (await ensureDictionaryEntry(em, {\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n kind: 'pipeline_stage',\n value: nextStageSnapshot.label,\n }))?.value ?? nextStageSnapshot.label\n : null\n resolvedCurrentPipelineStageLabel =\n !nextStageSnapshot && record.pipelineStageId && (parsed.pipelineStageId !== undefined || !record.pipelineStage)\n ? await resolvePipelineStageValue(em, record.pipelineStageId, record.tenantId, record.organizationId)\n : null\n },\n () => {\n if (parsed.title !== undefined) record.title = parsed.title\n if (parsed.description !== undefined) record.description = parsed.description ?? null\n if (parsed.status !== undefined) record.status = parsed.status ?? record.status\n if (parsed.pipelineStage !== undefined) record.pipelineStage = parsed.pipelineStage ?? null\n if (parsed.pipelineId !== undefined) record.pipelineId = parsed.pipelineId ?? null\n if (parsed.pipelineStageId !== undefined) record.pipelineStageId = parsed.pipelineStageId ?? null\n\n if (nextPipelineStageLabel && (parsed.pipelineStageId !== undefined || !record.pipelineStage)) {\n record.pipelineStage = nextPipelineStageLabel\n } else if (resolvedCurrentPipelineStageLabel && (parsed.pipelineStageId !== undefined || !record.pipelineStage)) {\n record.pipelineStage = resolvedCurrentPipelineStageLabel\n }\n\n if (parsed.valueAmount !== undefined) record.valueAmount = toNumericString(parsed.valueAmount)\n if (parsed.valueCurrency !== undefined) record.valueCurrency = parsed.valueCurrency ?? null\n if (parsed.probability !== undefined) record.probability = parsed.probability ?? null\n if (parsed.expectedCloseAt !== undefined) record.expectedCloseAt = parsed.expectedCloseAt ?? null\n if (parsed.ownerUserId !== undefined) record.ownerUserId = parsed.ownerUserId ?? null\n if (parsed.source !== undefined) record.source = parsed.source ?? null\n if (parsed.closureOutcome !== undefined) record.closureOutcome = parsed.closureOutcome ?? null\n if (parsed.lossReasonId !== undefined) record.lossReasonId = parsed.lossReasonId ?? null\n if (parsed.lossNotes !== undefined) record.lossNotes = parsed.lossNotes ?? null\n },\n async () => {\n // CRITICAL: persist the scalar mutations above before any further `em.findOne` / sync\n // helpers run inside this transaction. MikroORM v7's identity-map silently discards\n // pending scalar changes on `record` if a query (such as the stage-transition lookup\n // inside `upsertDealStageTransition`, or the linked-entity finds inside\n // `syncDealPeople` / `syncDealCompanies`) executes on the same `EntityManager`\n // before we explicitly flush. Without this flush, the entire kanban drag-and-drop\n // returns 200 OK but never actually updates `customer_deals` rows \u2014 the card\n // snaps back to its source lane on the next refetch (see SPEC-018).\n await em.flush()\n },\n async () => {\n const snapshot = nextStageSnapshot\n if (!snapshot) return\n const shouldRecord =\n parsed.pipelineStageId !== undefined &&\n parsed.pipelineStageId !== null &&\n parsed.pipelineStageId !== previousPipelineStageId\n if (!shouldRecord) return\n await upsertDealStageTransition(em, {\n deal: record,\n pipelineId: snapshot.pipelineId,\n stageId: snapshot.id,\n stageLabel: nextPipelineStageLabel ?? snapshot.label,\n stageOrder: snapshot.order,\n transitionedByUserId: normalizedTransitionAuthorUserId,\n })\n },\n () => syncDealPeople(em, record, parsed.personIds),\n () => syncDealCompanies(em, record, parsed.companyIds),\n ], { transaction: true })\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: DEAL_ENTITY_ID,\n recordId: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n values: custom,\n notify: false,\n })\n\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: record,\n identifiers: {\n id: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n },\n indexer: dealCrudIndexer,\n events: dealCrudEvents,\n })\n\n // Emit a lifecycle event for deal won/lost status changes; the notifications\n // subscriber translates these into recipient notifications.\n const newStatus = record.status\n const normalizedStatus = newStatus === 'win' ? 'won' : newStatus === 'loose' ? 'lost' : newStatus\n if (previousStatus !== newStatus && (normalizedStatus === 'won' || normalizedStatus === 'lost')) {\n const closureEvent = normalizedStatus === 'won' ? 'customers.deal.won' : 'customers.deal.lost'\n try {\n const eventBus = ctx.container.resolve('eventBus') as { emitEvent(event: string, payload: unknown, options?: unknown): Promise<void> } | undefined\n if (eventBus) {\n await eventBus.emitEvent(\n closureEvent,\n {\n id: record.id,\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n ownerUserId: record.ownerUserId ?? null,\n title: record.title,\n valueAmount: record.valueAmount ?? null,\n valueCurrency: record.valueCurrency ?? null,\n },\n { persistent: true },\n )\n }\n } catch (err) {\n console.warn('[customers.deals.update] deal closure event emit failed', closureEvent, err)\n }\n }\n\n return { dealId: record.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadDealSnapshot(em, result.dealId)\n },\n buildLog: async ({ result, snapshots, ctx }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as DealSnapshot | undefined\n if (!before) return null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const afterSnapshot = await loadDealSnapshot(em, result.dealId)\n return {\n actionLabel: translate('customers.audit.deals.update', 'Update deal'),\n resourceKind: 'customers.deal',\n resourceId: before.deal.id,\n tenantId: before.deal.tenantId,\n organizationId: before.deal.organizationId,\n snapshotBefore: before,\n snapshotAfter: afterSnapshot ?? null,\n payload: {\n undo: {\n before,\n after: afterSnapshot ?? null,\n } satisfies DealUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<DealUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const normalizedTransitionAuthorUserId = normalizeAuthorUserId(null, ctx.auth)\n let deal = await findOneWithDecryption(em, CustomerDeal, { id: before.deal.id })\n if (!deal) {\n deal = em.create(CustomerDeal, {\n id: before.deal.id,\n organizationId: before.deal.organizationId,\n tenantId: before.deal.tenantId,\n title: before.deal.title,\n description: before.deal.description,\n status: before.deal.status,\n pipelineStage: before.deal.pipelineStage,\n pipelineId: before.deal.pipelineId,\n pipelineStageId: before.deal.pipelineStageId,\n valueAmount: before.deal.valueAmount,\n valueCurrency: before.deal.valueCurrency,\n probability: before.deal.probability,\n expectedCloseAt: before.deal.expectedCloseAt,\n ownerUserId: before.deal.ownerUserId,\n source: before.deal.source,\n closureOutcome: before.deal.closureOutcome,\n lossReasonId: before.deal.lossReasonId,\n lossNotes: before.deal.lossNotes,\n })\n em.persist(deal)\n }\n const revertedStageSnapshot = before.deal.pipelineStageId\n ? await loadPipelineStageSnapshot(em, before.deal.pipelineStageId, before.deal.tenantId, before.deal.organizationId)\n : null\n const existingTransition = before.deal.pipelineStageId\n ? before.transitions.find((transition) => transition.stageId === before.deal.pipelineStageId) ?? null\n : null\n const shouldRecordRevertTransition =\n before.deal.pipelineStageId !== (payload?.after?.deal.pipelineStageId ?? null) &&\n !!before.deal.pipelineStageId &&\n !!(revertedStageSnapshot?.pipelineId ?? before.deal.pipelineId ?? existingTransition?.pipelineId) &&\n !!(revertedStageSnapshot?.label ?? before.deal.pipelineStage ?? existingTransition?.stageLabel)\n\n await withAtomicFlush(em, [\n () => {\n deal.title = before.deal.title\n deal.description = before.deal.description\n deal.status = before.deal.status\n deal.pipelineStage = before.deal.pipelineStage\n deal.pipelineId = before.deal.pipelineId\n deal.pipelineStageId = before.deal.pipelineStageId\n deal.valueAmount = before.deal.valueAmount\n deal.valueCurrency = before.deal.valueCurrency\n deal.probability = before.deal.probability\n deal.expectedCloseAt = before.deal.expectedCloseAt\n deal.ownerUserId = before.deal.ownerUserId\n deal.source = before.deal.source\n deal.closureOutcome = before.deal.closureOutcome\n deal.lossReasonId = before.deal.lossReasonId\n deal.lossNotes = before.deal.lossNotes\n },\n async () => {\n // Mirror of the fix applied to the forward `execute` path: persist the scalar\n // mutations on `deal` before any further `em.findOne` (the transition lookup\n // inside `upsertDealStageTransition`) or sync-helper queries run on the same EM.\n // MikroORM v7 silently discards the pending scalar changes if we don't flush here\n // (see SPEC-018), which would make an undo of a kanban stage move silently no-op.\n await em.flush()\n },\n async () => {\n if (!shouldRecordRevertTransition || !before.deal.pipelineStageId) return\n const pipelineId = revertedStageSnapshot?.pipelineId ?? before.deal.pipelineId ?? existingTransition?.pipelineId\n const stageLabel = revertedStageSnapshot?.label ?? before.deal.pipelineStage ?? existingTransition?.stageLabel\n if (!pipelineId || !stageLabel) return\n await upsertDealStageTransition(em, {\n deal,\n pipelineId,\n stageId: before.deal.pipelineStageId,\n stageLabel,\n stageOrder: revertedStageSnapshot?.order ?? existingTransition?.stageOrder ?? 0,\n transitionedByUserId: normalizedTransitionAuthorUserId,\n })\n },\n () => syncDealPeople(em, deal, before.people),\n () => syncDealCompanies(em, deal, before.companies),\n ], { transaction: true })\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: deal,\n identifiers: {\n id: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n },\n indexer: dealCrudIndexer,\n events: dealCrudEvents,\n })\n\n const resetValues = buildCustomFieldResetMap(before.custom, payload?.after?.custom)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: DEAL_ENTITY_ID,\n recordId: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n values: resetValues,\n notify: false,\n })\n }\n },\n}\n\nconst deleteDealCommand: CommandHandler<{ body?: Record<string, unknown>; query?: Record<string, unknown> }, { dealId: string }> =\n {\n id: 'customers.deals.delete',\n async prepare(input, ctx) {\n const id = requireId(input, 'Deal id required')\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadDealSnapshot(em, id)\n return snapshot ? { before: snapshot } : {}\n },\n async execute(input, ctx) {\n const id = requireId(input, 'Deal id required')\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const deal = await findOneWithDecryption(em, CustomerDeal, { id, deletedAt: null })\n const record = deal ?? null\n if (!record) throw new CrudHttpError(404, { error: 'Deal not found' })\n ensureTenantScope(ctx, record.tenantId)\n ensureOrganizationScope(ctx, record.organizationId)\n await deleteDealStageTransitions(em, record)\n await em.nativeDelete(CustomerDealPersonLink, { deal: record })\n await em.nativeDelete(CustomerDealCompanyLink, { deal: record })\n em.remove(record)\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'deleted',\n entity: record,\n identifiers: {\n id: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n },\n indexer: dealCrudIndexer,\n events: dealCrudEvents,\n })\n return { dealId: record.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as DealSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('customers.audit.deals.delete', 'Delete deal'),\n resourceKind: 'customers.deal',\n resourceId: before.deal.id,\n tenantId: before.deal.tenantId,\n organizationId: before.deal.organizationId,\n snapshotBefore: before,\n payload: {\n undo: {\n before,\n } satisfies DealUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<DealUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let deal = await findOneWithDecryption(em, CustomerDeal, { id: before.deal.id })\n if (!deal) {\n deal = em.create(CustomerDeal, {\n id: before.deal.id,\n organizationId: before.deal.organizationId,\n tenantId: before.deal.tenantId,\n title: before.deal.title,\n description: before.deal.description,\n status: before.deal.status,\n pipelineStage: before.deal.pipelineStage,\n pipelineId: before.deal.pipelineId,\n pipelineStageId: before.deal.pipelineStageId,\n valueAmount: before.deal.valueAmount,\n valueCurrency: before.deal.valueCurrency,\n probability: before.deal.probability,\n expectedCloseAt: before.deal.expectedCloseAt,\n ownerUserId: before.deal.ownerUserId,\n source: before.deal.source,\n closureOutcome: before.deal.closureOutcome,\n lossReasonId: before.deal.lossReasonId,\n lossNotes: before.deal.lossNotes,\n })\n em.persist(deal)\n }\n await withAtomicFlush(em, [\n () => syncDealPeople(em, deal, before.people),\n () => syncDealCompanies(em, deal, before.companies),\n () => deleteDealStageTransitions(em, deal),\n () => restoreDealStageTransitions(em, deal, before.transitions),\n ], { transaction: true })\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'created',\n entity: deal,\n identifiers: {\n id: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n },\n indexer: dealCrudIndexer,\n events: dealCrudEvents,\n })\n\n const resetValues = buildCustomFieldResetMap(before.custom, undefined)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: DEAL_ENTITY_ID,\n recordId: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n values: resetValues,\n notify: false,\n })\n }\n },\n }\n\nregisterCommand(createDealCommand)\nregisterCommand(updateDealCommand)\nregisterCommand(deleteDealCommand)\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport {\n parseWithCustomFields,\n setCustomFieldsIfAny,\n emitCrudSideEffects,\n emitCrudUndoSideEffects,\n requireId,\n normalizeAuthorUserId,\n} from '@open-mercato/shared/lib/commands/helpers'\nimport { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport {\n CustomerDeal,\n CustomerDealPersonLink,\n CustomerDealCompanyLink,\n CustomerDealStageTransition,\n CustomerPipelineStage,\n} from '../data/entities'\nimport {\n dealCreateSchema,\n dealUpdateSchema,\n type DealCreateInput,\n type DealUpdateInput,\n} from '../data/validators'\nimport {\n ensureOrganizationScope,\n ensureTenantScope,\n requireCustomerEntity,\n ensureSameScope,\n extractUndoPayload,\n ensureDictionaryEntry,\n} from './shared'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport {\n loadCustomFieldSnapshot,\n buildCustomFieldResetMap,\n type CustomFieldChangeSet,\n} from '@open-mercato/shared/lib/commands/customFieldSnapshots'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport type { CrudIndexerConfig, CrudEventsConfig } from '@open-mercato/shared/lib/crud/types'\nimport { E } from '#generated/entities.ids.generated'\nimport { findWithDecryption, findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { isMissingDealStageTransitionTable, warnMissingDealStageTransitionTable } from '../lib/dealStageTransitionTable'\n\nconst DEAL_ENTITY_ID = 'customers:customer_deal'\nconst dealCrudIndexer: CrudIndexerConfig<CustomerDeal> = {\n entityType: E.customers.customer_deal,\n}\n\nconst dealCrudEvents: CrudEventsConfig = {\n module: 'customers',\n entity: 'deal',\n persistent: true,\n buildPayload: (ctx) => ({\n id: ctx.identifiers.id,\n organizationId: ctx.identifiers.organizationId,\n tenantId: ctx.identifiers.tenantId,\n }),\n}\n\ntype PipelineStageSnapshot = {\n id: string\n pipelineId: string\n label: string\n order: number\n}\n\ntype DealStageTransitionSnapshot = {\n id: string\n pipelineId: string\n stageId: string\n stageLabel: string\n stageOrder: number\n transitionedAt: Date\n transitionedByUserId: string | null\n}\n\nasync function loadPipelineStageSnapshot(\n em: EntityManager,\n pipelineStageId: string,\n tenantId: string,\n organizationId: string,\n): Promise<PipelineStageSnapshot | null> {\n const stage = await findOneWithDecryption(em, CustomerPipelineStage, { id: pipelineStageId }, {}, { tenantId, organizationId })\n if (!stage) return null\n return {\n id: stage.id,\n pipelineId: stage.pipelineId,\n label: stage.label,\n order: stage.order,\n }\n}\n\nasync function resolvePipelineStageValue(\n em: EntityManager,\n pipelineStageId: string,\n tenantId: string,\n organizationId: string,\n): Promise<string | null> {\n const stage = await loadPipelineStageSnapshot(em, pipelineStageId, tenantId, organizationId)\n if (!stage) return null\n const entry = await ensureDictionaryEntry(em, {\n tenantId,\n organizationId,\n kind: 'pipeline_stage',\n value: stage.label,\n })\n return entry?.value ?? stage.label\n}\n\nfunction resolvePipelineAssignment(input: {\n pipelineId?: string | null\n pipelineStageId?: string | null\n stageSnapshot: PipelineStageSnapshot | null\n}): { pipelineId: string | null; pipelineStageId: string | null } {\n const requestedPipelineId = input.pipelineId ?? null\n const requestedPipelineStageId = input.pipelineStageId ?? null\n\n if (requestedPipelineStageId && !input.stageSnapshot) {\n throw new CrudHttpError(400, { error: 'Pipeline stage not found' })\n }\n\n if (\n requestedPipelineId &&\n input.stageSnapshot &&\n input.stageSnapshot.pipelineId !== requestedPipelineId\n ) {\n throw new CrudHttpError(400, {\n error: 'Pipeline stage does not belong to the selected pipeline',\n })\n }\n\n return {\n pipelineId: requestedPipelineId ?? input.stageSnapshot?.pipelineId ?? null,\n pipelineStageId: requestedPipelineStageId,\n }\n}\n\nasync function upsertDealStageTransition(\n em: EntityManager,\n input: {\n deal: CustomerDeal\n pipelineId: string\n stageId: string\n stageLabel: string\n stageOrder: number\n transitionedByUserId: string | null\n transitionedAt?: Date\n },\n): Promise<void> {\n let existing: CustomerDealStageTransition | null = null\n try {\n existing = await findOneWithDecryption(\n em,\n CustomerDealStageTransition,\n { deal: input.deal.id, stageId: input.stageId, deletedAt: null },\n {},\n { tenantId: input.deal.tenantId, organizationId: input.deal.organizationId },\n )\n } catch (error) {\n if (!isMissingDealStageTransitionTable(error)) {\n throw error\n }\n warnMissingDealStageTransitionTable('customers.commands.deals.upsertTransition')\n return\n }\n const transitionedAt = input.transitionedAt ?? new Date()\n if (existing) {\n existing.pipelineId = input.pipelineId\n existing.stageLabel = input.stageLabel\n existing.stageOrder = input.stageOrder\n existing.transitionedAt = transitionedAt\n existing.transitionedByUserId = input.transitionedByUserId\n existing.deletedAt = null\n existing.isActive = true\n return\n }\n\n const transition = em.create(CustomerDealStageTransition, {\n organizationId: input.deal.organizationId,\n tenantId: input.deal.tenantId,\n deal: input.deal,\n pipelineId: input.pipelineId,\n stageId: input.stageId,\n stageLabel: input.stageLabel,\n stageOrder: input.stageOrder,\n transitionedAt,\n transitionedByUserId: input.transitionedByUserId,\n isActive: true,\n })\n em.persist(transition)\n}\n\nasync function deleteDealStageTransitions(em: EntityManager, deal: CustomerDeal): Promise<void> {\n try {\n await em.nativeDelete(CustomerDealStageTransition, { deal: deal.id })\n } catch (error) {\n if (!isMissingDealStageTransitionTable(error)) {\n throw error\n }\n warnMissingDealStageTransitionTable('customers.commands.deals.deleteTransitions')\n }\n}\n\nasync function restoreDealStageTransitions(\n em: EntityManager,\n deal: CustomerDeal,\n transitions: DealStageTransitionSnapshot[],\n): Promise<void> {\n if (!transitions.length) return\n for (const transitionSnapshot of transitions) {\n const transition = em.create(CustomerDealStageTransition, {\n id: transitionSnapshot.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n deal,\n pipelineId: transitionSnapshot.pipelineId,\n stageId: transitionSnapshot.stageId,\n stageLabel: transitionSnapshot.stageLabel,\n stageOrder: transitionSnapshot.stageOrder,\n transitionedAt: transitionSnapshot.transitionedAt,\n transitionedByUserId: transitionSnapshot.transitionedByUserId,\n isActive: true,\n })\n em.persist(transition)\n }\n}\n\ntype DealSnapshot = {\n deal: {\n id: string\n organizationId: string\n tenantId: string\n title: string\n description: string | null\n status: string\n pipelineStage: string | null\n pipelineId: string | null\n pipelineStageId: string | null\n valueAmount: string | null\n valueCurrency: string | null\n probability: number | null\n expectedCloseAt: Date | null\n ownerUserId: string | null\n source: string | null\n closureOutcome: string | null\n lossReasonId: string | null\n lossNotes: string | null\n }\n people: string[]\n companies: string[]\n transitions: DealStageTransitionSnapshot[]\n custom?: Record<string, unknown>\n}\n\ntype DealUndoPayload = {\n before?: DealSnapshot | null\n after?: DealSnapshot | null\n}\n\ntype DealChangeMap = Record<string, { from: unknown; to: unknown }> & {\n custom?: CustomFieldChangeSet\n}\n\nasync function loadDealSnapshot(em: EntityManager, id: string): Promise<DealSnapshot | null> {\n const deal = await findOneWithDecryption(em, CustomerDeal, { id, deletedAt: null })\n if (!deal) return null\n const decryptionScope = { tenantId: deal.tenantId ?? null, organizationId: deal.organizationId ?? null }\n const peopleLinks = await findWithDecryption(\n em,\n CustomerDealPersonLink,\n { deal: deal },\n { populate: ['person'] },\n decryptionScope,\n )\n const companyLinks = await findWithDecryption(\n em,\n CustomerDealCompanyLink,\n { deal: deal },\n { populate: ['company'] },\n decryptionScope,\n )\n const transitions = await findWithDecryption(\n em,\n CustomerDealStageTransition,\n { deal: deal.id, deletedAt: null },\n { orderBy: { stageOrder: 'ASC', transitionedAt: 'ASC' } },\n decryptionScope,\n ).catch((error: unknown) => {\n if (!isMissingDealStageTransitionTable(error)) {\n throw error\n }\n warnMissingDealStageTransitionTable('customers.commands.deals.loadSnapshot')\n return [] as CustomerDealStageTransition[]\n })\n const custom = await loadCustomFieldSnapshot(em, {\n entityId: DEAL_ENTITY_ID,\n recordId: deal.id,\n tenantId: deal.tenantId,\n organizationId: deal.organizationId,\n })\n return {\n deal: {\n id: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n title: deal.title,\n description: deal.description ?? null,\n status: deal.status,\n pipelineStage: deal.pipelineStage ?? null,\n pipelineId: deal.pipelineId ?? null,\n pipelineStageId: deal.pipelineStageId ?? null,\n valueAmount: deal.valueAmount ?? null,\n valueCurrency: deal.valueCurrency ?? null,\n probability: deal.probability ?? null,\n expectedCloseAt: deal.expectedCloseAt ?? null,\n ownerUserId: deal.ownerUserId ?? null,\n source: deal.source ?? null,\n closureOutcome: deal.closureOutcome ?? null,\n lossReasonId: deal.lossReasonId ?? null,\n lossNotes: deal.lossNotes ?? null,\n },\n people: peopleLinks.map((link) =>\n typeof link.person === 'string' ? link.person : link.person.id\n ),\n companies: companyLinks.map((link) =>\n typeof link.company === 'string' ? link.company : link.company.id\n ),\n transitions: transitions.map((transition) => ({\n id: transition.id,\n pipelineId: transition.pipelineId,\n stageId: transition.stageId,\n stageLabel: transition.stageLabel,\n stageOrder: transition.stageOrder,\n transitionedAt: transition.transitionedAt,\n transitionedByUserId: transition.transitionedByUserId ?? null,\n })),\n custom,\n }\n}\n\nfunction toNumericString(value: number | null | undefined): string | null {\n if (value === undefined || value === null) return null\n return value.toString()\n}\n\nasync function syncDealPeople(\n em: EntityManager,\n deal: CustomerDeal,\n personIds: string[] | undefined | null\n): Promise<void> {\n if (personIds === undefined) return\n await em.nativeDelete(CustomerDealPersonLink, { deal })\n if (!personIds || !personIds.length) return\n const unique = Array.from(new Set(personIds))\n for (const personId of unique) {\n const person = await requireCustomerEntity(em, personId, 'person', 'Person not found')\n ensureSameScope(person, deal.organizationId, deal.tenantId)\n const link = em.create(CustomerDealPersonLink, {\n deal,\n person,\n })\n em.persist(link)\n }\n}\n\nasync function syncDealCompanies(\n em: EntityManager,\n deal: CustomerDeal,\n companyIds: string[] | undefined | null\n): Promise<void> {\n if (companyIds === undefined) return\n await em.nativeDelete(CustomerDealCompanyLink, { deal })\n if (!companyIds || !companyIds.length) return\n const unique = Array.from(new Set(companyIds))\n for (const companyId of unique) {\n const company = await requireCustomerEntity(em, companyId, 'company', 'Company not found')\n ensureSameScope(company, deal.organizationId, deal.tenantId)\n const link = em.create(CustomerDealCompanyLink, {\n deal,\n company,\n })\n em.persist(link)\n }\n}\n\nconst createDealCommand: CommandHandler<DealCreateInput, { dealId: string }> = {\n id: 'customers.deals.create',\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(dealCreateSchema, rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const normalizedTransitionAuthorUserId = normalizeAuthorUserId(null, ctx.auth)\n let deal!: CustomerDeal\n let stageSnapshot: PipelineStageSnapshot | null = null\n let pipelineAssignment: { pipelineId: string | null; pipelineStageId: string | null } = {\n pipelineId: null,\n pipelineStageId: null,\n }\n let resolvedPipelineStageLabel: string | null = null\n await withAtomicFlush(em, [\n async () => {\n stageSnapshot = parsed.pipelineStageId\n ? await loadPipelineStageSnapshot(em, parsed.pipelineStageId, parsed.tenantId, parsed.organizationId)\n : null\n pipelineAssignment = resolvePipelineAssignment({\n pipelineId: parsed.pipelineId,\n pipelineStageId: parsed.pipelineStageId,\n stageSnapshot,\n })\n resolvedPipelineStageLabel = stageSnapshot\n ? (await ensureDictionaryEntry(em, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n kind: 'pipeline_stage',\n value: stageSnapshot.label,\n }))?.value ?? stageSnapshot.label\n : parsed.pipelineStage ?? null\n },\n async () => {\n deal = em.create(CustomerDeal, {\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n title: parsed.title,\n description: parsed.description ?? null,\n status: parsed.status ?? 'open',\n pipelineStage: resolvedPipelineStageLabel,\n pipelineId: pipelineAssignment.pipelineId,\n pipelineStageId: pipelineAssignment.pipelineStageId,\n valueAmount: toNumericString(parsed.valueAmount),\n valueCurrency: parsed.valueCurrency ?? null,\n probability: parsed.probability ?? null,\n expectedCloseAt: parsed.expectedCloseAt ?? null,\n ownerUserId: parsed.ownerUserId ?? null,\n source: parsed.source ?? null,\n closureOutcome: parsed.closureOutcome ?? null,\n lossReasonId: parsed.lossReasonId ?? null,\n lossNotes: parsed.lossNotes ?? null,\n })\n em.persist(deal)\n await em.flush()\n },\n async () => {\n const snapshot = stageSnapshot\n if (!snapshot) return\n await upsertDealStageTransition(em, {\n deal,\n pipelineId: snapshot.pipelineId,\n stageId: snapshot.id,\n stageLabel: snapshot.label,\n stageOrder: snapshot.order,\n transitionedByUserId: normalizedTransitionAuthorUserId,\n })\n },\n () => syncDealPeople(em, deal, parsed.personIds ?? []),\n () => syncDealCompanies(em, deal, parsed.companyIds ?? []),\n ], { transaction: true })\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: DEAL_ENTITY_ID,\n recordId: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n values: custom,\n notify: false,\n })\n\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: deal,\n identifiers: {\n id: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n },\n indexer: dealCrudIndexer,\n events: dealCrudEvents,\n })\n\n return { dealId: deal.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadDealSnapshot(em, result.dealId)\n },\n buildLog: async ({ result, ctx }) => {\n const { translate } = await resolveTranslations()\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadDealSnapshot(em, result.dealId)\n return {\n actionLabel: translate('customers.audit.deals.create', 'Create deal'),\n resourceKind: 'customers.deal',\n resourceId: result.dealId,\n tenantId: snapshot?.deal.tenantId ?? null,\n organizationId: snapshot?.deal.organizationId ?? null,\n snapshotAfter: snapshot ?? null,\n payload: {\n undo: {\n after: snapshot,\n } satisfies DealUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const dealId = logEntry?.resourceId\n if (!dealId) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const deal = await findOneWithDecryption(em, CustomerDeal, { id: dealId })\n if (!deal) return\n await deleteDealStageTransitions(em, deal)\n await em.nativeDelete(CustomerDealPersonLink, { deal })\n await em.nativeDelete(CustomerDealCompanyLink, { deal })\n em.remove(deal)\n await em.flush()\n },\n}\n\nconst updateDealCommand: CommandHandler<DealUpdateInput, { dealId: string }> = {\n id: 'customers.deals.update',\n async prepare(rawInput, ctx) {\n const { parsed } = parseWithCustomFields(dealUpdateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadDealSnapshot(em, parsed.id)\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(dealUpdateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const deal = await findOneWithDecryption(em, CustomerDeal, { id: parsed.id, deletedAt: null })\n const record = deal ?? null\n if (!record) throw new CrudHttpError(404, { error: 'Deal not found' })\n ensureTenantScope(ctx, record.tenantId)\n ensureOrganizationScope(ctx, record.organizationId)\n\n const previousStatus = record.status\n const previousPipelineStageId = record.pipelineStageId ?? null\n const normalizedTransitionAuthorUserId = normalizeAuthorUserId(null, ctx.auth)\n\n let nextStageSnapshot: PipelineStageSnapshot | null = null\n let nextPipelineAssignment: { pipelineId: string | null; pipelineStageId: string | null } = {\n pipelineId: record.pipelineId ?? null,\n pipelineStageId: record.pipelineStageId ?? null,\n }\n let nextPipelineStageLabel: string | null = null\n let resolvedCurrentPipelineStageLabel: string | null = null\n\n await withAtomicFlush(em, [\n async () => {\n const pipelineAssignmentChanged =\n parsed.pipelineId !== undefined || parsed.pipelineStageId !== undefined\n const requestedPipelineStageId =\n parsed.pipelineStageId !== undefined\n ? parsed.pipelineStageId ?? null\n : record.pipelineStageId ?? null\n const requestedPipelineId =\n parsed.pipelineId !== undefined ? parsed.pipelineId ?? null : record.pipelineId ?? null\n\n nextStageSnapshot = requestedPipelineStageId && (pipelineAssignmentChanged || !record.pipelineStage)\n ? await loadPipelineStageSnapshot(em, requestedPipelineStageId, record.tenantId, record.organizationId)\n : null\n if (pipelineAssignmentChanged) {\n nextPipelineAssignment = resolvePipelineAssignment({\n pipelineId: requestedPipelineId,\n pipelineStageId: requestedPipelineStageId,\n stageSnapshot: nextStageSnapshot,\n })\n }\n nextPipelineStageLabel = nextStageSnapshot\n ? (await ensureDictionaryEntry(em, {\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n kind: 'pipeline_stage',\n value: nextStageSnapshot.label,\n }))?.value ?? nextStageSnapshot.label\n : null\n resolvedCurrentPipelineStageLabel =\n !nextStageSnapshot && record.pipelineStageId && (parsed.pipelineStageId !== undefined || !record.pipelineStage)\n ? await resolvePipelineStageValue(em, record.pipelineStageId, record.tenantId, record.organizationId)\n : null\n },\n () => {\n if (parsed.title !== undefined) record.title = parsed.title\n if (parsed.description !== undefined) record.description = parsed.description ?? null\n if (parsed.status !== undefined) record.status = parsed.status ?? record.status\n if (parsed.pipelineStage !== undefined) record.pipelineStage = parsed.pipelineStage ?? null\n if (parsed.pipelineId !== undefined || (parsed.pipelineStageId !== undefined && nextStageSnapshot)) {\n record.pipelineId = nextPipelineAssignment.pipelineId\n }\n if (parsed.pipelineStageId !== undefined) record.pipelineStageId = nextPipelineAssignment.pipelineStageId\n\n if (nextPipelineStageLabel && (parsed.pipelineStageId !== undefined || !record.pipelineStage)) {\n record.pipelineStage = nextPipelineStageLabel\n } else if (resolvedCurrentPipelineStageLabel && (parsed.pipelineStageId !== undefined || !record.pipelineStage)) {\n record.pipelineStage = resolvedCurrentPipelineStageLabel\n }\n\n if (parsed.valueAmount !== undefined) record.valueAmount = toNumericString(parsed.valueAmount)\n if (parsed.valueCurrency !== undefined) record.valueCurrency = parsed.valueCurrency ?? null\n if (parsed.probability !== undefined) record.probability = parsed.probability ?? null\n if (parsed.expectedCloseAt !== undefined) record.expectedCloseAt = parsed.expectedCloseAt ?? null\n if (parsed.ownerUserId !== undefined) record.ownerUserId = parsed.ownerUserId ?? null\n if (parsed.source !== undefined) record.source = parsed.source ?? null\n if (parsed.closureOutcome !== undefined) record.closureOutcome = parsed.closureOutcome ?? null\n if (parsed.lossReasonId !== undefined) record.lossReasonId = parsed.lossReasonId ?? null\n if (parsed.lossNotes !== undefined) record.lossNotes = parsed.lossNotes ?? null\n },\n async () => {\n // CRITICAL: persist the scalar mutations above before any further `em.findOne` / sync\n // helpers run inside this transaction. MikroORM v7's identity-map silently discards\n // pending scalar changes on `record` if a query (such as the stage-transition lookup\n // inside `upsertDealStageTransition`, or the linked-entity finds inside\n // `syncDealPeople` / `syncDealCompanies`) executes on the same `EntityManager`\n // before we explicitly flush. Without this flush, the entire kanban drag-and-drop\n // returns 200 OK but never actually updates `customer_deals` rows \u2014 the card\n // snaps back to its source lane on the next refetch (see SPEC-018).\n await em.flush()\n },\n async () => {\n const snapshot = nextStageSnapshot\n if (!snapshot) return\n const shouldRecord =\n parsed.pipelineStageId !== undefined &&\n parsed.pipelineStageId !== null &&\n parsed.pipelineStageId !== previousPipelineStageId\n if (!shouldRecord) return\n await upsertDealStageTransition(em, {\n deal: record,\n pipelineId: snapshot.pipelineId,\n stageId: snapshot.id,\n stageLabel: nextPipelineStageLabel ?? snapshot.label,\n stageOrder: snapshot.order,\n transitionedByUserId: normalizedTransitionAuthorUserId,\n })\n },\n () => syncDealPeople(em, record, parsed.personIds),\n () => syncDealCompanies(em, record, parsed.companyIds),\n ], { transaction: true })\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: DEAL_ENTITY_ID,\n recordId: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n values: custom,\n notify: false,\n })\n\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: record,\n identifiers: {\n id: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n },\n indexer: dealCrudIndexer,\n events: dealCrudEvents,\n })\n\n // Emit a lifecycle event for deal won/lost status changes; the notifications\n // subscriber translates these into recipient notifications.\n const newStatus = record.status\n const normalizedStatus = newStatus === 'win' ? 'won' : newStatus === 'loose' ? 'lost' : newStatus\n if (previousStatus !== newStatus && (normalizedStatus === 'won' || normalizedStatus === 'lost')) {\n const closureEvent = normalizedStatus === 'won' ? 'customers.deal.won' : 'customers.deal.lost'\n try {\n const eventBus = ctx.container.resolve('eventBus') as { emitEvent(event: string, payload: unknown, options?: unknown): Promise<void> } | undefined\n if (eventBus) {\n await eventBus.emitEvent(\n closureEvent,\n {\n id: record.id,\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n ownerUserId: record.ownerUserId ?? null,\n title: record.title,\n valueAmount: record.valueAmount ?? null,\n valueCurrency: record.valueCurrency ?? null,\n },\n { persistent: true },\n )\n }\n } catch (err) {\n console.warn('[customers.deals.update] deal closure event emit failed', closureEvent, err)\n }\n }\n\n return { dealId: record.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadDealSnapshot(em, result.dealId)\n },\n buildLog: async ({ result, snapshots, ctx }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as DealSnapshot | undefined\n if (!before) return null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const afterSnapshot = await loadDealSnapshot(em, result.dealId)\n return {\n actionLabel: translate('customers.audit.deals.update', 'Update deal'),\n resourceKind: 'customers.deal',\n resourceId: before.deal.id,\n tenantId: before.deal.tenantId,\n organizationId: before.deal.organizationId,\n snapshotBefore: before,\n snapshotAfter: afterSnapshot ?? null,\n payload: {\n undo: {\n before,\n after: afterSnapshot ?? null,\n } satisfies DealUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<DealUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const normalizedTransitionAuthorUserId = normalizeAuthorUserId(null, ctx.auth)\n let deal = await findOneWithDecryption(em, CustomerDeal, { id: before.deal.id })\n if (!deal) {\n deal = em.create(CustomerDeal, {\n id: before.deal.id,\n organizationId: before.deal.organizationId,\n tenantId: before.deal.tenantId,\n title: before.deal.title,\n description: before.deal.description,\n status: before.deal.status,\n pipelineStage: before.deal.pipelineStage,\n pipelineId: before.deal.pipelineId,\n pipelineStageId: before.deal.pipelineStageId,\n valueAmount: before.deal.valueAmount,\n valueCurrency: before.deal.valueCurrency,\n probability: before.deal.probability,\n expectedCloseAt: before.deal.expectedCloseAt,\n ownerUserId: before.deal.ownerUserId,\n source: before.deal.source,\n closureOutcome: before.deal.closureOutcome,\n lossReasonId: before.deal.lossReasonId,\n lossNotes: before.deal.lossNotes,\n })\n em.persist(deal)\n }\n const revertedStageSnapshot = before.deal.pipelineStageId\n ? await loadPipelineStageSnapshot(em, before.deal.pipelineStageId, before.deal.tenantId, before.deal.organizationId)\n : null\n const existingTransition = before.deal.pipelineStageId\n ? before.transitions.find((transition) => transition.stageId === before.deal.pipelineStageId) ?? null\n : null\n const shouldRecordRevertTransition =\n before.deal.pipelineStageId !== (payload?.after?.deal.pipelineStageId ?? null) &&\n !!before.deal.pipelineStageId &&\n !!(revertedStageSnapshot?.pipelineId ?? before.deal.pipelineId ?? existingTransition?.pipelineId) &&\n !!(revertedStageSnapshot?.label ?? before.deal.pipelineStage ?? existingTransition?.stageLabel)\n\n await withAtomicFlush(em, [\n () => {\n deal.title = before.deal.title\n deal.description = before.deal.description\n deal.status = before.deal.status\n deal.pipelineStage = before.deal.pipelineStage\n deal.pipelineId = before.deal.pipelineId\n deal.pipelineStageId = before.deal.pipelineStageId\n deal.valueAmount = before.deal.valueAmount\n deal.valueCurrency = before.deal.valueCurrency\n deal.probability = before.deal.probability\n deal.expectedCloseAt = before.deal.expectedCloseAt\n deal.ownerUserId = before.deal.ownerUserId\n deal.source = before.deal.source\n deal.closureOutcome = before.deal.closureOutcome\n deal.lossReasonId = before.deal.lossReasonId\n deal.lossNotes = before.deal.lossNotes\n },\n async () => {\n // Mirror of the fix applied to the forward `execute` path: persist the scalar\n // mutations on `deal` before any further `em.findOne` (the transition lookup\n // inside `upsertDealStageTransition`) or sync-helper queries run on the same EM.\n // MikroORM v7 silently discards the pending scalar changes if we don't flush here\n // (see SPEC-018), which would make an undo of a kanban stage move silently no-op.\n await em.flush()\n },\n async () => {\n if (!shouldRecordRevertTransition || !before.deal.pipelineStageId) return\n const pipelineId = revertedStageSnapshot?.pipelineId ?? before.deal.pipelineId ?? existingTransition?.pipelineId\n const stageLabel = revertedStageSnapshot?.label ?? before.deal.pipelineStage ?? existingTransition?.stageLabel\n if (!pipelineId || !stageLabel) return\n await upsertDealStageTransition(em, {\n deal,\n pipelineId,\n stageId: before.deal.pipelineStageId,\n stageLabel,\n stageOrder: revertedStageSnapshot?.order ?? existingTransition?.stageOrder ?? 0,\n transitionedByUserId: normalizedTransitionAuthorUserId,\n })\n },\n () => syncDealPeople(em, deal, before.people),\n () => syncDealCompanies(em, deal, before.companies),\n ], { transaction: true })\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: deal,\n identifiers: {\n id: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n },\n indexer: dealCrudIndexer,\n events: dealCrudEvents,\n })\n\n const resetValues = buildCustomFieldResetMap(before.custom, payload?.after?.custom)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: DEAL_ENTITY_ID,\n recordId: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n values: resetValues,\n notify: false,\n })\n }\n },\n}\n\nconst deleteDealCommand: CommandHandler<{ body?: Record<string, unknown>; query?: Record<string, unknown> }, { dealId: string }> =\n {\n id: 'customers.deals.delete',\n async prepare(input, ctx) {\n const id = requireId(input, 'Deal id required')\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadDealSnapshot(em, id)\n return snapshot ? { before: snapshot } : {}\n },\n async execute(input, ctx) {\n const id = requireId(input, 'Deal id required')\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const deal = await findOneWithDecryption(em, CustomerDeal, { id, deletedAt: null })\n const record = deal ?? null\n if (!record) throw new CrudHttpError(404, { error: 'Deal not found' })\n ensureTenantScope(ctx, record.tenantId)\n ensureOrganizationScope(ctx, record.organizationId)\n await deleteDealStageTransitions(em, record)\n await em.nativeDelete(CustomerDealPersonLink, { deal: record })\n await em.nativeDelete(CustomerDealCompanyLink, { deal: record })\n em.remove(record)\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'deleted',\n entity: record,\n identifiers: {\n id: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n },\n indexer: dealCrudIndexer,\n events: dealCrudEvents,\n })\n return { dealId: record.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as DealSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('customers.audit.deals.delete', 'Delete deal'),\n resourceKind: 'customers.deal',\n resourceId: before.deal.id,\n tenantId: before.deal.tenantId,\n organizationId: before.deal.organizationId,\n snapshotBefore: before,\n payload: {\n undo: {\n before,\n } satisfies DealUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<DealUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let deal = await findOneWithDecryption(em, CustomerDeal, { id: before.deal.id })\n if (!deal) {\n deal = em.create(CustomerDeal, {\n id: before.deal.id,\n organizationId: before.deal.organizationId,\n tenantId: before.deal.tenantId,\n title: before.deal.title,\n description: before.deal.description,\n status: before.deal.status,\n pipelineStage: before.deal.pipelineStage,\n pipelineId: before.deal.pipelineId,\n pipelineStageId: before.deal.pipelineStageId,\n valueAmount: before.deal.valueAmount,\n valueCurrency: before.deal.valueCurrency,\n probability: before.deal.probability,\n expectedCloseAt: before.deal.expectedCloseAt,\n ownerUserId: before.deal.ownerUserId,\n source: before.deal.source,\n closureOutcome: before.deal.closureOutcome,\n lossReasonId: before.deal.lossReasonId,\n lossNotes: before.deal.lossNotes,\n })\n em.persist(deal)\n }\n await withAtomicFlush(em, [\n () => syncDealPeople(em, deal, before.people),\n () => syncDealCompanies(em, deal, before.companies),\n () => deleteDealStageTransitions(em, deal),\n () => restoreDealStageTransitions(em, deal, before.transitions),\n ], { transaction: true })\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'created',\n entity: deal,\n identifiers: {\n id: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n },\n indexer: dealCrudIndexer,\n events: dealCrudEvents,\n })\n\n const resetValues = buildCustomFieldResetMap(before.custom, undefined)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: DEAL_ENTITY_ID,\n recordId: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n values: resetValues,\n notify: false,\n })\n }\n },\n }\n\nregisterCommand(createDealCommand)\nregisterCommand(updateDealCommand)\nregisterCommand(deleteDealCommand)\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -33,6 +33,7 @@ import {
33
33
  import { CrudHttpError } from "@open-mercato/shared/lib/crud/errors";
34
34
  import { findOneWithDecryption } from "@open-mercato/shared/lib/encryption/find";
35
35
  import { recomputeNextInteraction } from "../lib/interactionProjection.js";
36
+ import { canChangeEmailVisibility } from "../lib/visibilityFilter.js";
36
37
  const INTERACTION_ENTITY_ID = "customers:customer_interaction";
37
38
  const interactionCrudIndexer = {
38
39
  entityType: "customers:customer_interaction"
@@ -327,6 +328,21 @@ const updateInteractionCommand = {
327
328
  if (!interaction2) throw new CrudHttpError(404, { error: "Interaction not found" });
328
329
  ensureTenantScope(ctx, interaction2.tenantId);
329
330
  ensureOrganizationScope(ctx, interaction2.organizationId);
331
+ if (parsed.visibility !== void 0 && interaction2.interactionType === "email" && (parsed.visibility ?? null) !== (interaction2.visibility ?? null)) {
332
+ const actorUserId = ctx.auth?.sub ?? null;
333
+ if (!canChangeEmailVisibility({
334
+ interactionType: interaction2.interactionType,
335
+ currentVisibility: interaction2.visibility,
336
+ nextVisibility: parsed.visibility,
337
+ authorUserId: interaction2.authorUserId,
338
+ actorUserId,
339
+ // v1 strict owner-only: only the author may flip visibility; no admin
340
+ // bypass (canChangeEmailVisibility ignores caller features in v1).
341
+ userFeatures: void 0
342
+ })) {
343
+ throw new CrudHttpError(404, { error: "Email not found" });
344
+ }
345
+ }
330
346
  if (parsed.dealId !== void 0) {
331
347
  if (parsed.dealId) {
332
348
  await requireDealInScope(trx, parsed.dealId, interaction2.tenantId, interaction2.organizationId);