@open-mercato/core 0.8.1-develop.7296.1.2111d779db → 0.8.1-develop.7441.1.b42958b98c

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 (2353) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/AGENTS.md +4 -5
  3. package/dist/generated/entities/availability_policy/index.js +41 -0
  4. package/dist/generated/entities/availability_policy/index.js.map +7 -0
  5. package/dist/generated/entities/communication_channel/index.js +3 -1
  6. package/dist/generated/entities/communication_channel/index.js.map +2 -2
  7. package/dist/generated/entities/customer_email_conversation_share/index.js +21 -0
  8. package/dist/generated/entities/customer_email_conversation_share/index.js.map +7 -0
  9. package/dist/generated/entities/customer_group/index.js +33 -0
  10. package/dist/generated/entities/customer_group/index.js.map +7 -0
  11. package/dist/generated/entities/customer_group_membership/index.js +29 -0
  12. package/dist/generated/entities/customer_group_membership/index.js.map +7 -0
  13. package/dist/generated/entities/customer_group_terms/index.js +33 -0
  14. package/dist/generated/entities/customer_group_terms/index.js.map +7 -0
  15. package/dist/generated/entities/customer_interaction/index.js +2 -0
  16. package/dist/generated/entities/customer_interaction/index.js.map +2 -2
  17. package/dist/generated/entities/form/index.js +35 -0
  18. package/dist/generated/entities/form/index.js.map +7 -0
  19. package/dist/generated/entities/form_access_audit/index.js +21 -0
  20. package/dist/generated/entities/form_access_audit/index.js.map +7 -0
  21. package/dist/generated/entities/form_attachment/index.js +29 -0
  22. package/dist/generated/entities/form_attachment/index.js.map +7 -0
  23. package/dist/generated/entities/form_consent_record/index.js +37 -0
  24. package/dist/generated/entities/form_consent_record/index.js.map +7 -0
  25. package/dist/generated/entities/form_distribution/index.js +47 -0
  26. package/dist/generated/entities/form_distribution/index.js.map +7 -0
  27. package/dist/generated/entities/form_invitation/index.js +49 -0
  28. package/dist/generated/entities/form_invitation/index.js.map +7 -0
  29. package/dist/generated/entities/form_submission/index.js +39 -0
  30. package/dist/generated/entities/form_submission/index.js.map +7 -0
  31. package/dist/generated/entities/form_submission_actor/index.js +23 -0
  32. package/dist/generated/entities/form_submission_actor/index.js.map +7 -0
  33. package/dist/generated/entities/form_submission_revision/index.js +29 -0
  34. package/dist/generated/entities/form_submission_revision/index.js.map +7 -0
  35. package/dist/generated/entities/form_version/index.js +37 -0
  36. package/dist/generated/entities/form_version/index.js.map +7 -0
  37. package/dist/generated/entities/forms_encryption_key/index.js +15 -0
  38. package/dist/generated/entities/forms_encryption_key/index.js.map +7 -0
  39. package/dist/generated/entities.ids.generated.js +27 -2
  40. package/dist/generated/entities.ids.generated.js.map +2 -2
  41. package/dist/generated/entity-fields-registry.js +269 -0
  42. package/dist/generated/entity-fields-registry.js.map +2 -2
  43. package/dist/helpers/integration/communicationChannelsFixtures.js +16 -0
  44. package/dist/helpers/integration/communicationChannelsFixtures.js.map +2 -2
  45. package/dist/helpers/integration/customerGroupsFixtures.js +88 -0
  46. package/dist/helpers/integration/customerGroupsFixtures.js.map +7 -0
  47. package/dist/helpers/integration/formsFixtures.js +448 -0
  48. package/dist/helpers/integration/formsFixtures.js.map +7 -0
  49. package/dist/modules/api_docs/api/get/version.js +19 -7
  50. package/dist/modules/api_docs/api/get/version.js.map +2 -2
  51. package/dist/modules/api_keys/api/keys/route.js +74 -169
  52. package/dist/modules/api_keys/api/keys/route.js.map +2 -2
  53. package/dist/modules/api_keys/backend/api-keys/create/page.js +1 -1
  54. package/dist/modules/api_keys/backend/api-keys/create/page.js.map +2 -2
  55. package/dist/modules/api_keys/commands/keys.js +140 -0
  56. package/dist/modules/api_keys/commands/keys.js.map +7 -0
  57. package/dist/modules/api_keys/services/apiKeyService.js +72 -43
  58. package/dist/modules/api_keys/services/apiKeyService.js.map +2 -2
  59. package/dist/modules/attachments/api/file/[id]/route.js +9 -2
  60. package/dist/modules/attachments/api/file/[id]/route.js.map +2 -2
  61. package/dist/modules/attachments/api/image/[id]/[[...slug]]/route.js +6 -2
  62. package/dist/modules/attachments/api/image/[id]/[[...slug]]/route.js.map +2 -2
  63. package/dist/modules/attachments/api/route.js +10 -4
  64. package/dist/modules/attachments/api/route.js.map +2 -2
  65. package/dist/modules/attachments/components/AttachmentLibrary.js +16 -6
  66. package/dist/modules/attachments/components/AttachmentLibrary.js.map +2 -2
  67. package/dist/modules/attachments/lib/access.js +1 -3
  68. package/dist/modules/attachments/lib/access.js.map +2 -2
  69. package/dist/modules/attachments/lib/requestScope.js +13 -4
  70. package/dist/modules/attachments/lib/requestScope.js.map +2 -2
  71. package/dist/modules/audit_logs/api/audit-logs/actions/export/route.js +6 -1
  72. package/dist/modules/audit_logs/api/audit-logs/actions/export/route.js.map +2 -2
  73. package/dist/modules/audit_logs/api/audit-logs/actions/redo/route.js +36 -6
  74. package/dist/modules/audit_logs/api/audit-logs/actions/redo/route.js.map +3 -3
  75. package/dist/modules/audit_logs/api/audit-logs/actions/route.js +6 -1
  76. package/dist/modules/audit_logs/api/audit-logs/actions/route.js.map +2 -2
  77. package/dist/modules/audit_logs/api/audit-logs/actions/undo/route.js +34 -4
  78. package/dist/modules/audit_logs/api/audit-logs/actions/undo/route.js.map +2 -2
  79. package/dist/modules/audit_logs/data/validators.js +1 -0
  80. package/dist/modules/audit_logs/data/validators.js.map +2 -2
  81. package/dist/modules/audit_logs/lib/actorSubject.js +65 -0
  82. package/dist/modules/audit_logs/lib/actorSubject.js.map +7 -0
  83. package/dist/modules/audit_logs/lib/replayAuthorization.js +41 -0
  84. package/dist/modules/audit_logs/lib/replayAuthorization.js.map +7 -0
  85. package/dist/modules/audit_logs/services/actionLogService.js +162 -39
  86. package/dist/modules/audit_logs/services/actionLogService.js.map +3 -3
  87. package/dist/modules/auth/api/features.js +1 -1
  88. package/dist/modules/auth/api/features.js.map +2 -2
  89. package/dist/modules/auth/cli.js +29 -17
  90. package/dist/modules/auth/cli.js.map +2 -2
  91. package/dist/modules/auth/commands/acl.js +25 -36
  92. package/dist/modules/auth/commands/acl.js.map +2 -2
  93. package/dist/modules/auth/commands/interceptors.js +22 -0
  94. package/dist/modules/auth/commands/interceptors.js.map +7 -0
  95. package/dist/modules/auth/commands/roles.js +421 -147
  96. package/dist/modules/auth/commands/roles.js.map +2 -2
  97. package/dist/modules/auth/commands/users.js +543 -69
  98. package/dist/modules/auth/commands/users.js.map +2 -2
  99. package/dist/modules/auth/lib/authorizationStateLocks.js +249 -0
  100. package/dist/modules/auth/lib/authorizationStateLocks.js.map +7 -0
  101. package/dist/modules/auth/lib/commandReplay.js +144 -0
  102. package/dist/modules/auth/lib/commandReplay.js.map +7 -0
  103. package/dist/modules/auth/lib/executionPrincipal.js +32 -25
  104. package/dist/modules/auth/lib/executionPrincipal.js.map +2 -2
  105. package/dist/modules/auth/lib/grantChecks.js +7 -2
  106. package/dist/modules/auth/lib/grantChecks.js.map +2 -2
  107. package/dist/modules/auth/lib/setup-app.js +85 -49
  108. package/dist/modules/auth/lib/setup-app.js.map +2 -2
  109. package/dist/modules/auth/lib/tokenHash.js +13 -1
  110. package/dist/modules/auth/lib/tokenHash.js.map +2 -2
  111. package/dist/modules/auth/services/rbacService.js +386 -5
  112. package/dist/modules/auth/services/rbacService.js.map +3 -3
  113. package/dist/modules/availability/acl.js +16 -0
  114. package/dist/modules/availability/acl.js.map +7 -0
  115. package/dist/modules/availability/api/check/route.js +115 -0
  116. package/dist/modules/availability/api/check/route.js.map +7 -0
  117. package/dist/modules/availability/api/openapi.js +27 -0
  118. package/dist/modules/availability/api/openapi.js.map +7 -0
  119. package/dist/modules/availability/api/policies/resolve-preview/route.js +72 -0
  120. package/dist/modules/availability/api/policies/resolve-preview/route.js.map +7 -0
  121. package/dist/modules/availability/api/policies/route.js +203 -0
  122. package/dist/modules/availability/api/policies/route.js.map +7 -0
  123. package/dist/modules/availability/backend/availability/check/page.js +185 -0
  124. package/dist/modules/availability/backend/availability/check/page.js.map +7 -0
  125. package/dist/modules/availability/backend/availability/check/page.meta.js +16 -0
  126. package/dist/modules/availability/backend/availability/check/page.meta.js.map +7 -0
  127. package/dist/modules/availability/backend/availability/policies/ResolutionPreviewPanel.js +83 -0
  128. package/dist/modules/availability/backend/availability/policies/ResolutionPreviewPanel.js.map +7 -0
  129. package/dist/modules/availability/backend/availability/policies/ScopeFields.js +53 -0
  130. package/dist/modules/availability/backend/availability/policies/ScopeFields.js.map +7 -0
  131. package/dist/modules/availability/backend/availability/policies/StockManagedField.js +32 -0
  132. package/dist/modules/availability/backend/availability/policies/StockManagedField.js.map +7 -0
  133. package/dist/modules/availability/backend/availability/policies/[id]/page.js +168 -0
  134. package/dist/modules/availability/backend/availability/policies/[id]/page.js.map +7 -0
  135. package/dist/modules/availability/backend/availability/policies/[id]/page.meta.js +12 -0
  136. package/dist/modules/availability/backend/availability/policies/[id]/page.meta.js.map +7 -0
  137. package/dist/modules/availability/backend/availability/policies/create/page.js +119 -0
  138. package/dist/modules/availability/backend/availability/policies/create/page.js.map +7 -0
  139. package/dist/modules/availability/backend/availability/policies/create/page.meta.js +12 -0
  140. package/dist/modules/availability/backend/availability/policies/create/page.meta.js.map +7 -0
  141. package/dist/modules/availability/backend/availability/policies/formGroups.js +77 -0
  142. package/dist/modules/availability/backend/availability/policies/formGroups.js.map +7 -0
  143. package/dist/modules/availability/backend/availability/policies/page.js +207 -0
  144. package/dist/modules/availability/backend/availability/policies/page.js.map +7 -0
  145. package/dist/modules/availability/backend/availability/policies/page.meta.js +16 -0
  146. package/dist/modules/availability/backend/availability/policies/page.meta.js.map +7 -0
  147. package/dist/modules/availability/backend/availability/policies/policyPayload.js +28 -0
  148. package/dist/modules/availability/backend/availability/policies/policyPayload.js.map +7 -0
  149. package/dist/modules/availability/commands/policies.js +364 -0
  150. package/dist/modules/availability/commands/policies.js.map +7 -0
  151. package/dist/modules/availability/commands/scope.js +19 -0
  152. package/dist/modules/availability/commands/scope.js.map +7 -0
  153. package/dist/modules/availability/data/entities.js +94 -0
  154. package/dist/modules/availability/data/entities.js.map +7 -0
  155. package/dist/modules/availability/data/validators.js +59 -0
  156. package/dist/modules/availability/data/validators.js.map +7 -0
  157. package/dist/modules/availability/di.js +50 -0
  158. package/dist/modules/availability/di.js.map +7 -0
  159. package/dist/modules/availability/events.js +18 -0
  160. package/dist/modules/availability/events.js.map +7 -0
  161. package/dist/modules/availability/index.js +15 -0
  162. package/dist/modules/availability/index.js.map +7 -0
  163. package/dist/modules/availability/lib/catalogTarget.js +42 -0
  164. package/dist/modules/availability/lib/catalogTarget.js.map +7 -0
  165. package/dist/modules/availability/lib/organizationScope.js +10 -0
  166. package/dist/modules/availability/lib/organizationScope.js.map +7 -0
  167. package/dist/modules/availability/lib/policyResolution.js +150 -0
  168. package/dist/modules/availability/lib/policyResolution.js.map +7 -0
  169. package/dist/modules/availability/lib/tryResolve.js +11 -0
  170. package/dist/modules/availability/lib/tryResolve.js.map +7 -0
  171. package/dist/modules/availability/migrations/Migration20260922095844_availability.js +16 -0
  172. package/dist/modules/availability/migrations/Migration20260922095844_availability.js.map +7 -0
  173. package/dist/modules/availability/migrations/Migration20260930120000_availability.js +20 -0
  174. package/dist/modules/availability/migrations/Migration20260930120000_availability.js.map +7 -0
  175. package/dist/modules/availability/setup.js +12 -0
  176. package/dist/modules/availability/setup.js.map +7 -0
  177. package/dist/modules/catalog/api/categories/bulk-create/route.js +110 -0
  178. package/dist/modules/catalog/api/categories/bulk-create/route.js.map +7 -0
  179. package/dist/modules/catalog/api/categories/route.js +56 -8
  180. package/dist/modules/catalog/api/categories/route.js.map +2 -2
  181. package/dist/modules/catalog/api/products/bulk-create/route.js +110 -0
  182. package/dist/modules/catalog/api/products/bulk-create/route.js.map +7 -0
  183. package/dist/modules/catalog/api/products/route.js +55 -31
  184. package/dist/modules/catalog/api/products/route.js.map +3 -3
  185. package/dist/modules/catalog/backend/catalog/products/[id]/page.js +2 -6
  186. package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
  187. package/dist/modules/catalog/backend/catalog/products/create/page.js +12 -4
  188. package/dist/modules/catalog/backend/catalog/products/create/page.js.map +2 -2
  189. package/dist/modules/catalog/commands/categories.js +1 -0
  190. package/dist/modules/catalog/commands/categories.js.map +2 -2
  191. package/dist/modules/catalog/commands/productDeleteChildren.js +389 -0
  192. package/dist/modules/catalog/commands/productDeleteChildren.js.map +7 -0
  193. package/dist/modules/catalog/commands/products.js +57 -19
  194. package/dist/modules/catalog/commands/products.js.map +2 -2
  195. package/dist/modules/catalog/components/PriceKindSettings.js +5 -19
  196. package/dist/modules/catalog/components/PriceKindSettings.js.map +2 -2
  197. package/dist/modules/catalog/components/products/ProductUomSection.js +26 -29
  198. package/dist/modules/catalog/components/products/ProductUomSection.js.map +2 -2
  199. package/dist/modules/catalog/components/products/productForm.js +3 -2
  200. package/dist/modules/catalog/components/products/productForm.js.map +2 -2
  201. package/dist/modules/catalog/data/validators.js +15 -0
  202. package/dist/modules/catalog/data/validators.js.map +2 -2
  203. package/dist/modules/catalog/di.js +3 -2
  204. package/dist/modules/catalog/di.js.map +2 -2
  205. package/dist/modules/catalog/events.js +9 -3
  206. package/dist/modules/catalog/events.js.map +2 -2
  207. package/dist/modules/catalog/lib/bulkCreateCategories.js +237 -0
  208. package/dist/modules/catalog/lib/bulkCreateCategories.js.map +7 -0
  209. package/dist/modules/catalog/lib/bulkCreateCheckpoint.js +82 -0
  210. package/dist/modules/catalog/lib/bulkCreateCheckpoint.js.map +7 -0
  211. package/dist/modules/catalog/lib/bulkCreateMutationGuards.js +39 -0
  212. package/dist/modules/catalog/lib/bulkCreateMutationGuards.js.map +7 -0
  213. package/dist/modules/catalog/lib/bulkCreateProducts.js +241 -0
  214. package/dist/modules/catalog/lib/bulkCreateProducts.js.map +7 -0
  215. package/dist/modules/catalog/lib/bulkDelete.js +10 -11
  216. package/dist/modules/catalog/lib/bulkDelete.js.map +2 -2
  217. package/dist/modules/catalog/lib/catalogQueue.js +14 -0
  218. package/dist/modules/catalog/lib/catalogQueue.js.map +7 -0
  219. package/dist/modules/catalog/lib/currencyOptions.js +25 -0
  220. package/dist/modules/catalog/lib/currencyOptions.js.map +7 -0
  221. package/dist/modules/catalog/lib/productSearch.js +8 -0
  222. package/dist/modules/catalog/lib/productSearch.js.map +7 -0
  223. package/dist/modules/catalog/lib/seeds.js +2 -42
  224. package/dist/modules/catalog/lib/seeds.js.map +2 -2
  225. package/dist/modules/catalog/lib/unitLabels.js +53 -0
  226. package/dist/modules/catalog/lib/unitLabels.js.map +7 -0
  227. package/dist/modules/catalog/migrations/Migration20260914120000.js +29 -0
  228. package/dist/modules/catalog/migrations/Migration20260914120000.js.map +7 -0
  229. package/dist/modules/catalog/migrations/Migration20260914120100.js +28 -0
  230. package/dist/modules/catalog/migrations/Migration20260914120100.js.map +7 -0
  231. package/dist/modules/catalog/workers/catalog-category-bulk-create.js +40 -0
  232. package/dist/modules/catalog/workers/catalog-category-bulk-create.js.map +7 -0
  233. package/dist/modules/catalog/workers/catalog-product-bulk-create.js +40 -0
  234. package/dist/modules/catalog/workers/catalog-product-bulk-create.js.map +7 -0
  235. package/dist/modules/communication_channels/acl.js +8 -0
  236. package/dist/modules/communication_channels/acl.js.map +2 -2
  237. package/dist/modules/communication_channels/api/get/me/channels/route.js +4 -0
  238. package/dist/modules/communication_channels/api/get/me/channels/route.js.map +2 -2
  239. package/dist/modules/communication_channels/api/get/oauth/[provider]/callback/route.js +22 -0
  240. package/dist/modules/communication_channels/api/get/oauth/[provider]/callback/route.js.map +2 -2
  241. package/dist/modules/communication_channels/api/post/channels/[id]/import-history/route.js +4 -4
  242. package/dist/modules/communication_channels/api/post/channels/[id]/import-history/route.js.map +2 -2
  243. package/dist/modules/communication_channels/api/post/channels/[id]/test-send/route.js +2 -1
  244. package/dist/modules/communication_channels/api/post/channels/[id]/test-send/route.js.map +2 -2
  245. package/dist/modules/communication_channels/api/post/channels/connect/credentials/route.js +4 -6
  246. package/dist/modules/communication_channels/api/post/channels/connect/credentials/route.js.map +2 -2
  247. package/dist/modules/communication_channels/api/post/channels/connect/tenant-credentials/route.js +4 -6
  248. package/dist/modules/communication_channels/api/post/channels/connect/tenant-credentials/route.js.map +2 -2
  249. package/dist/modules/communication_channels/api/post/test-seed/route.js +90 -20
  250. package/dist/modules/communication_channels/api/post/test-seed/route.js.map +3 -3
  251. package/dist/modules/communication_channels/api/put/channels/[id]/visibility/route.js +137 -0
  252. package/dist/modules/communication_channels/api/put/channels/[id]/visibility/route.js.map +7 -0
  253. package/dist/modules/communication_channels/backend/profile/communication-channels/page.js +175 -107
  254. package/dist/modules/communication_channels/backend/profile/communication-channels/page.js.map +2 -2
  255. package/dist/modules/communication_channels/commands/ingest-inbound-message.js +2 -1
  256. package/dist/modules/communication_channels/commands/ingest-inbound-message.js.map +2 -2
  257. package/dist/modules/communication_channels/commands/set-channel-visibility.js +88 -0
  258. package/dist/modules/communication_channels/commands/set-channel-visibility.js.map +7 -0
  259. package/dist/modules/communication_channels/data/enrichers.js +18 -9
  260. package/dist/modules/communication_channels/data/enrichers.js.map +2 -2
  261. package/dist/modules/communication_channels/data/entities.js +4 -0
  262. package/dist/modules/communication_channels/data/entities.js.map +2 -2
  263. package/dist/modules/communication_channels/di.js +9 -1
  264. package/dist/modules/communication_channels/di.js.map +2 -2
  265. package/dist/modules/communication_channels/events.js +7 -0
  266. package/dist/modules/communication_channels/events.js.map +2 -2
  267. package/dist/modules/communication_channels/index.js +1 -1
  268. package/dist/modules/communication_channels/index.js.map +1 -1
  269. package/dist/modules/communication_channels/lib/access-control.js +2 -1
  270. package/dist/modules/communication_channels/lib/access-control.js.map +2 -2
  271. package/dist/modules/communication_channels/lib/channel-thread-access.js +60 -0
  272. package/dist/modules/communication_channels/lib/channel-thread-access.js.map +7 -0
  273. package/dist/modules/communication_channels/lib/credential-refresh.js +11 -2
  274. package/dist/modules/communication_channels/lib/credential-refresh.js.map +2 -2
  275. package/dist/modules/communication_channels/lib/inbound-message-origin.js +18 -0
  276. package/dist/modules/communication_channels/lib/inbound-message-origin.js.map +7 -0
  277. package/dist/modules/communication_channels/lib/oauth-state.js +37 -0
  278. package/dist/modules/communication_channels/lib/oauth-state.js.map +2 -2
  279. package/dist/modules/communication_channels/lib/outbound-delivery-intent.js +12 -0
  280. package/dist/modules/communication_channels/lib/outbound-delivery-intent.js.map +7 -0
  281. package/dist/modules/communication_channels/lib/send-as-user.js +1 -1
  282. package/dist/modules/communication_channels/lib/send-as-user.js.map +2 -2
  283. package/dist/modules/communication_channels/migrations/Migration20260825141000_communication_channels.js +14 -0
  284. package/dist/modules/communication_channels/migrations/Migration20260825141000_communication_channels.js.map +7 -0
  285. package/dist/modules/communication_channels/setup.js +6 -2
  286. package/dist/modules/communication_channels/setup.js.map +2 -2
  287. package/dist/modules/communication_channels/subscribers/outbound-bridge.js +8 -2
  288. package/dist/modules/communication_channels/subscribers/outbound-bridge.js.map +2 -2
  289. package/dist/modules/communication_channels/workers/gmail-history-sync.js +1 -1
  290. package/dist/modules/communication_channels/workers/gmail-history-sync.js.map +2 -2
  291. package/dist/modules/communication_channels/workers/poll-channel.js +1 -1
  292. package/dist/modules/communication_channels/workers/poll-channel.js.map +2 -2
  293. package/dist/modules/communication_channels/workers/reaction-processor.js +2 -2
  294. package/dist/modules/communication_channels/workers/reaction-processor.js.map +2 -2
  295. package/dist/modules/configs/api/upgrade-actions/route.js +2 -1
  296. package/dist/modules/configs/api/upgrade-actions/route.js.map +2 -2
  297. package/dist/modules/configs/cli.js +2 -2
  298. package/dist/modules/configs/cli.js.map +2 -2
  299. package/dist/modules/configs/lib/upgrade-actions.js +28 -6
  300. package/dist/modules/configs/lib/upgrade-actions.js.map +2 -2
  301. package/dist/modules/configs/services/upgradeActionsService.js +44 -30
  302. package/dist/modules/configs/services/upgradeActionsService.js.map +2 -2
  303. package/dist/modules/currencies/api/currencies/route.js +11 -5
  304. package/dist/modules/currencies/api/currencies/route.js.map +2 -2
  305. package/dist/modules/currencies/api/exchange-rates/route.js +11 -5
  306. package/dist/modules/currencies/api/exchange-rates/route.js.map +2 -2
  307. package/dist/modules/customer_groups/acl.js +14 -0
  308. package/dist/modules/customer_groups/acl.js.map +7 -0
  309. package/dist/modules/customer_groups/api/customer-groups/[id]/terms/route.js +266 -0
  310. package/dist/modules/customer_groups/api/customer-groups/[id]/terms/route.js.map +7 -0
  311. package/dist/modules/customer_groups/api/customer-groups/crud.js +473 -0
  312. package/dist/modules/customer_groups/api/customer-groups/crud.js.map +7 -0
  313. package/dist/modules/customer_groups/api/customer-groups/explain-terms/route.js +143 -0
  314. package/dist/modules/customer_groups/api/customer-groups/explain-terms/route.js.map +7 -0
  315. package/dist/modules/customer_groups/api/customer-groups/memberships/crud.js +383 -0
  316. package/dist/modules/customer_groups/api/customer-groups/memberships/crud.js.map +7 -0
  317. package/dist/modules/customer_groups/api/customer-groups/memberships/route.js +66 -0
  318. package/dist/modules/customer_groups/api/customer-groups/memberships/route.js.map +7 -0
  319. package/dist/modules/customer_groups/api/customer-groups/reconcile/adopt/route.js +133 -0
  320. package/dist/modules/customer_groups/api/customer-groups/reconcile/adopt/route.js.map +7 -0
  321. package/dist/modules/customer_groups/api/customer-groups/reconcile/route.js +80 -0
  322. package/dist/modules/customer_groups/api/customer-groups/reconcile/route.js.map +7 -0
  323. package/dist/modules/customer_groups/api/customer-groups/reorder/route.js +127 -0
  324. package/dist/modules/customer_groups/api/customer-groups/reorder/route.js.map +7 -0
  325. package/dist/modules/customer_groups/api/customer-groups/route.js +62 -0
  326. package/dist/modules/customer_groups/api/customer-groups/route.js.map +7 -0
  327. package/dist/modules/customer_groups/api/openapi.js +27 -0
  328. package/dist/modules/customer_groups/api/openapi.js.map +7 -0
  329. package/dist/modules/customer_groups/backend/customer-groups/[id]/edit/page.js +328 -0
  330. package/dist/modules/customer_groups/backend/customer-groups/[id]/edit/page.js.map +7 -0
  331. package/dist/modules/customer_groups/backend/customer-groups/[id]/edit/page.meta.js +16 -0
  332. package/dist/modules/customer_groups/backend/customer-groups/[id]/edit/page.meta.js.map +7 -0
  333. package/dist/modules/customer_groups/backend/customer-groups/create/page.js +249 -0
  334. package/dist/modules/customer_groups/backend/customer-groups/create/page.js.map +7 -0
  335. package/dist/modules/customer_groups/backend/customer-groups/create/page.meta.js +27 -0
  336. package/dist/modules/customer_groups/backend/customer-groups/create/page.meta.js.map +7 -0
  337. package/dist/modules/customer_groups/backend/customer-groups/orphans/page.js +139 -0
  338. package/dist/modules/customer_groups/backend/customer-groups/orphans/page.js.map +7 -0
  339. package/dist/modules/customer_groups/backend/customer-groups/orphans/page.meta.js +16 -0
  340. package/dist/modules/customer_groups/backend/customer-groups/orphans/page.meta.js.map +7 -0
  341. package/dist/modules/customer_groups/backend/customer-groups/page.js +364 -0
  342. package/dist/modules/customer_groups/backend/customer-groups/page.js.map +7 -0
  343. package/dist/modules/customer_groups/backend/customer-groups/page.meta.js +15 -0
  344. package/dist/modules/customer_groups/backend/customer-groups/page.meta.js.map +7 -0
  345. package/dist/modules/customer_groups/cli.js +72 -0
  346. package/dist/modules/customer_groups/cli.js.map +7 -0
  347. package/dist/modules/customer_groups/commands/reorderGroups.js +96 -0
  348. package/dist/modules/customer_groups/commands/reorderGroups.js.map +7 -0
  349. package/dist/modules/customer_groups/components/CustomerGroupDefaultField.js +41 -0
  350. package/dist/modules/customer_groups/components/CustomerGroupDefaultField.js.map +7 -0
  351. package/dist/modules/customer_groups/components/CustomerGroupParentField.js +156 -0
  352. package/dist/modules/customer_groups/components/CustomerGroupParentField.js.map +7 -0
  353. package/dist/modules/customer_groups/components/CustomerGroupTermsPriceKindField.js +94 -0
  354. package/dist/modules/customer_groups/components/CustomerGroupTermsPriceKindField.js.map +7 -0
  355. package/dist/modules/customer_groups/components/CustomerGroupTermsSection.js +197 -0
  356. package/dist/modules/customer_groups/components/CustomerGroupTermsSection.js.map +7 -0
  357. package/dist/modules/customer_groups/components/GroupPickerField.js +116 -0
  358. package/dist/modules/customer_groups/components/GroupPickerField.js.map +7 -0
  359. package/dist/modules/customer_groups/components/OrphanBanner.js +75 -0
  360. package/dist/modules/customer_groups/components/OrphanBanner.js.map +7 -0
  361. package/dist/modules/customer_groups/components/customerGroupTree.js +57 -0
  362. package/dist/modules/customer_groups/components/customerGroupTree.js.map +7 -0
  363. package/dist/modules/customer_groups/data/entities.js +226 -0
  364. package/dist/modules/customer_groups/data/entities.js.map +7 -0
  365. package/dist/modules/customer_groups/data/validators.js +153 -0
  366. package/dist/modules/customer_groups/data/validators.js.map +7 -0
  367. package/dist/modules/customer_groups/di.js +20 -0
  368. package/dist/modules/customer_groups/di.js.map +7 -0
  369. package/dist/modules/customer_groups/events.js +22 -0
  370. package/dist/modules/customer_groups/events.js.map +7 -0
  371. package/dist/modules/customer_groups/index.js +15 -0
  372. package/dist/modules/customer_groups/index.js.map +7 -0
  373. package/dist/modules/customer_groups/lib/createConflictRecheck.js +29 -0
  374. package/dist/modules/customer_groups/lib/createConflictRecheck.js.map +7 -0
  375. package/dist/modules/customer_groups/lib/customerScope.js +81 -0
  376. package/dist/modules/customer_groups/lib/customerScope.js.map +7 -0
  377. package/dist/modules/customer_groups/lib/groupEvents.js +31 -0
  378. package/dist/modules/customer_groups/lib/groupEvents.js.map +7 -0
  379. package/dist/modules/customer_groups/lib/priceKindScope.js +16 -0
  380. package/dist/modules/customer_groups/lib/priceKindScope.js.map +7 -0
  381. package/dist/modules/customer_groups/lib/reconcile.js +161 -0
  382. package/dist/modules/customer_groups/lib/reconcile.js.map +7 -0
  383. package/dist/modules/customer_groups/migrations/Migration20260922095316_customer_groups.js +27 -0
  384. package/dist/modules/customer_groups/migrations/Migration20260922095316_customer_groups.js.map +7 -0
  385. package/dist/modules/customer_groups/migrations/Migration20260922103033_customer_groups.js +19 -0
  386. package/dist/modules/customer_groups/migrations/Migration20260922103033_customer_groups.js.map +7 -0
  387. package/dist/modules/customer_groups/migrations/Migration20260922105444_customer_groups.js +19 -0
  388. package/dist/modules/customer_groups/migrations/Migration20260922105444_customer_groups.js.map +7 -0
  389. package/dist/modules/customer_groups/migrations/Migration20260923193330_customer_groups.js +19 -0
  390. package/dist/modules/customer_groups/migrations/Migration20260923193330_customer_groups.js.map +7 -0
  391. package/dist/modules/customer_groups/migrations/Migration20260929083000_customer_groups.js +20 -0
  392. package/dist/modules/customer_groups/migrations/Migration20260929083000_customer_groups.js.map +7 -0
  393. package/dist/modules/customer_groups/services/customerGroupsService.js +190 -0
  394. package/dist/modules/customer_groups/services/customerGroupsService.js.map +7 -0
  395. package/dist/modules/customer_groups/setup.js +13 -0
  396. package/dist/modules/customer_groups/setup.js.map +7 -0
  397. package/dist/modules/customer_groups/widgets/injection/group-picker-field/widget.js +31 -0
  398. package/dist/modules/customer_groups/widgets/injection/group-picker-field/widget.js.map +7 -0
  399. package/dist/modules/customer_groups/widgets/injection/person-groups-explain-terms.js +166 -0
  400. package/dist/modules/customer_groups/widgets/injection/person-groups-explain-terms.js.map +7 -0
  401. package/dist/modules/customer_groups/widgets/injection/person-groups-tab/widget.js +17 -0
  402. package/dist/modules/customer_groups/widgets/injection/person-groups-tab/widget.js.map +7 -0
  403. package/dist/modules/customer_groups/widgets/injection/person-groups-tab.js +457 -0
  404. package/dist/modules/customer_groups/widgets/injection/person-groups-tab.js.map +7 -0
  405. package/dist/modules/customer_groups/widgets/injection-table.js +33 -0
  406. package/dist/modules/customer_groups/widgets/injection-table.js.map +7 -0
  407. package/dist/modules/customers/acl.js +13 -0
  408. package/dist/modules/customers/acl.js.map +2 -2
  409. package/dist/modules/customers/api/activities/route.js +9 -1
  410. package/dist/modules/customers/api/activities/route.js.map +2 -2
  411. package/dist/modules/customers/api/companies/[id]/people/route.js +2 -1
  412. package/dist/modules/customers/api/companies/[id]/people/route.js.map +2 -2
  413. package/dist/modules/customers/api/companies/[id]/route.js +19 -7
  414. package/dist/modules/customers/api/companies/[id]/route.js.map +2 -2
  415. package/dist/modules/customers/api/deals/[id]/companies/route.js +2 -1
  416. package/dist/modules/customers/api/deals/[id]/companies/route.js.map +2 -2
  417. package/dist/modules/customers/api/deals/[id]/people/route.js +60 -6
  418. package/dist/modules/customers/api/deals/[id]/people/route.js.map +2 -2
  419. package/dist/modules/customers/api/deals/map/route.js +7 -2
  420. package/dist/modules/customers/api/deals/map/route.js.map +2 -2
  421. package/dist/modules/customers/api/dictionaries/context.js +2 -1
  422. package/dist/modules/customers/api/dictionaries/context.js.map +2 -2
  423. package/dist/modules/customers/api/entity-roles-factory.js +3 -2
  424. package/dist/modules/customers/api/entity-roles-factory.js.map +2 -2
  425. package/dist/modules/customers/api/interactions/[id]/visibility/route.js +2 -1
  426. package/dist/modules/customers/api/interactions/[id]/visibility/route.js.map +2 -2
  427. package/dist/modules/customers/api/interactions/cancel/route.js +2 -1
  428. package/dist/modules/customers/api/interactions/cancel/route.js.map +2 -2
  429. package/dist/modules/customers/api/interactions/complete/route.js +2 -1
  430. package/dist/modules/customers/api/interactions/complete/route.js.map +2 -2
  431. package/dist/modules/customers/api/interactions/conflicts/route.js +10 -6
  432. package/dist/modules/customers/api/interactions/conflicts/route.js.map +2 -2
  433. package/dist/modules/customers/api/interactions/counts/route.js +24 -4
  434. package/dist/modules/customers/api/interactions/counts/route.js.map +2 -2
  435. package/dist/modules/customers/api/interactions/route.js +31 -8
  436. package/dist/modules/customers/api/interactions/route.js.map +2 -2
  437. package/dist/modules/customers/api/labels/assign/route.js +2 -1
  438. package/dist/modules/customers/api/labels/assign/route.js.map +2 -2
  439. package/dist/modules/customers/api/labels/route.js +3 -2
  440. package/dist/modules/customers/api/labels/route.js.map +2 -2
  441. package/dist/modules/customers/api/labels/unassign/route.js +2 -1
  442. package/dist/modules/customers/api/labels/unassign/route.js.map +2 -2
  443. package/dist/modules/customers/api/people/[id]/companies/context.js +7 -2
  444. package/dist/modules/customers/api/people/[id]/companies/context.js.map +2 -2
  445. package/dist/modules/customers/api/people/[id]/email-share/route.js +218 -0
  446. package/dist/modules/customers/api/people/[id]/email-share/route.js.map +7 -0
  447. package/dist/modules/customers/api/people/[id]/email-threads/route.js +11 -2
  448. package/dist/modules/customers/api/people/[id]/email-threads/route.js.map +2 -2
  449. package/dist/modules/customers/api/people/[id]/emails/route.js +2 -1
  450. package/dist/modules/customers/api/people/[id]/emails/route.js.map +2 -2
  451. package/dist/modules/customers/api/people/[id]/route.js +20 -19
  452. package/dist/modules/customers/api/people/[id]/route.js.map +2 -2
  453. package/dist/modules/customers/api/people/check-phone/route.js +2 -1
  454. package/dist/modules/customers/api/people/check-phone/route.js.map +2 -2
  455. package/dist/modules/customers/api/pipeline-stages/reorder/route.js +3 -2
  456. package/dist/modules/customers/api/pipeline-stages/reorder/route.js.map +2 -2
  457. package/dist/modules/customers/api/pipeline-stages/route.js +3 -3
  458. package/dist/modules/customers/api/pipeline-stages/route.js.map +2 -2
  459. package/dist/modules/customers/api/pipelines/route.js +3 -3
  460. package/dist/modules/customers/api/pipelines/route.js.map +2 -2
  461. package/dist/modules/customers/api/settings/address-format/route.js +2 -1
  462. package/dist/modules/customers/api/settings/address-format/route.js.map +2 -2
  463. package/dist/modules/customers/api/settings/dictionary-sort-modes/route.js +2 -1
  464. package/dist/modules/customers/api/settings/dictionary-sort-modes/route.js.map +2 -2
  465. package/dist/modules/customers/api/settings/stuck-threshold/route.js +2 -1
  466. package/dist/modules/customers/api/settings/stuck-threshold/route.js.map +2 -2
  467. package/dist/modules/customers/api/tags/assign/route.js +2 -1
  468. package/dist/modules/customers/api/tags/assign/route.js.map +2 -2
  469. package/dist/modules/customers/api/tags/unassign/route.js +2 -1
  470. package/dist/modules/customers/api/tags/unassign/route.js.map +2 -2
  471. package/dist/modules/customers/backend/customers/companies/[id]/page.js +4 -2
  472. package/dist/modules/customers/backend/customers/companies/[id]/page.js.map +2 -2
  473. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealAssociations.js +6 -25
  474. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealAssociations.js.map +2 -2
  475. package/dist/modules/customers/backend/customers/deals/[id]/page.js +21 -18
  476. package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
  477. package/dist/modules/customers/backend/customers/deals/components/ReassignOwnerDialog.js +93 -0
  478. package/dist/modules/customers/backend/customers/deals/components/ReassignOwnerDialog.js.map +7 -0
  479. package/dist/modules/customers/backend/customers/deals/page.js +111 -1
  480. package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
  481. package/dist/modules/customers/backend/customers/people/[id]/page.js +4 -2
  482. package/dist/modules/customers/backend/customers/people/[id]/page.js.map +2 -2
  483. package/dist/modules/customers/commands/addresses.js +83 -15
  484. package/dist/modules/customers/commands/addresses.js.map +2 -2
  485. package/dist/modules/customers/commands/companies.js +10 -4
  486. package/dist/modules/customers/commands/companies.js.map +2 -2
  487. package/dist/modules/customers/commands/emailConversationShares.js +177 -0
  488. package/dist/modules/customers/commands/emailConversationShares.js.map +7 -0
  489. package/dist/modules/customers/commands/index.js +1 -0
  490. package/dist/modules/customers/commands/index.js.map +2 -2
  491. package/dist/modules/customers/commands/interactions.js +48 -23
  492. package/dist/modules/customers/commands/interactions.js.map +3 -3
  493. package/dist/modules/customers/commands/people.js +3 -2
  494. package/dist/modules/customers/commands/people.js.map +2 -2
  495. package/dist/modules/customers/commands/shared.js +4 -0
  496. package/dist/modules/customers/commands/shared.js.map +2 -2
  497. package/dist/modules/customers/components/calendar/types.js.map +1 -1
  498. package/dist/modules/customers/components/detail/CompanyPeopleSection.js +81 -354
  499. package/dist/modules/customers/components/detail/CompanyPeopleSection.js.map +2 -2
  500. package/dist/modules/customers/components/detail/CreatePersonDialog.js +12 -11
  501. package/dist/modules/customers/components/detail/CreatePersonDialog.js.map +2 -2
  502. package/dist/modules/customers/components/detail/DealForm.js +73 -5
  503. package/dist/modules/customers/components/detail/DealForm.js.map +2 -2
  504. package/dist/modules/customers/components/detail/DealOwnerSelect.js +96 -0
  505. package/dist/modules/customers/components/detail/DealOwnerSelect.js.map +7 -0
  506. package/dist/modules/customers/components/detail/DealPeopleSection.js +206 -0
  507. package/dist/modules/customers/components/detail/DealPeopleSection.js.map +7 -0
  508. package/dist/modules/customers/components/detail/DealsSection.js +8 -14
  509. package/dist/modules/customers/components/detail/DealsSection.js.map +2 -2
  510. package/dist/modules/customers/components/detail/LinkedPeopleSection.js +342 -0
  511. package/dist/modules/customers/components/detail/LinkedPeopleSection.js.map +7 -0
  512. package/dist/modules/customers/components/detail/PersonCard.js +5 -2
  513. package/dist/modules/customers/components/detail/PersonCard.js.map +2 -2
  514. package/dist/modules/customers/components/detail/PersonEmailShareControl.js +190 -0
  515. package/dist/modules/customers/components/detail/PersonEmailShareControl.js.map +7 -0
  516. package/dist/modules/customers/components/detail/PersonEmailThreadsTab.js +17 -0
  517. package/dist/modules/customers/components/detail/PersonEmailThreadsTab.js.map +2 -2
  518. package/dist/modules/customers/components/detail/ScheduleActivityDialog.js +5 -2
  519. package/dist/modules/customers/components/detail/ScheduleActivityDialog.js.map +2 -2
  520. package/dist/modules/customers/components/detail/create/CreateDealForm.js +19 -0
  521. package/dist/modules/customers/components/detail/create/CreateDealForm.js.map +2 -2
  522. package/dist/modules/customers/components/detail/create/DealDetailsFields.js +11 -0
  523. package/dist/modules/customers/components/detail/create/DealDetailsFields.js.map +2 -2
  524. package/dist/modules/customers/components/detail/create/DealSectionCard.js +2 -2
  525. package/dist/modules/customers/components/detail/create/DealSectionCard.js.map +2 -2
  526. package/dist/modules/customers/components/detail/create/dealFormTypes.js +1 -0
  527. package/dist/modules/customers/components/detail/create/dealFormTypes.js.map +2 -2
  528. package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js +1 -1
  529. package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js.map +2 -2
  530. package/dist/modules/customers/components/formConfig.js +2 -0
  531. package/dist/modules/customers/components/formConfig.js.map +2 -2
  532. package/dist/modules/customers/components/linking/LinkEntityDialog.js +8 -0
  533. package/dist/modules/customers/components/linking/LinkEntityDialog.js.map +2 -2
  534. package/dist/modules/customers/components/linking/adapters/personAdapter.js +3 -0
  535. package/dist/modules/customers/components/linking/adapters/personAdapter.js.map +2 -2
  536. package/dist/modules/customers/data/enrichers.js +40 -2
  537. package/dist/modules/customers/data/enrichers.js.map +2 -2
  538. package/dist/modules/customers/data/entities.js +56 -0
  539. package/dist/modules/customers/data/entities.js.map +2 -2
  540. package/dist/modules/customers/data/validators.js +11 -0
  541. package/dist/modules/customers/data/validators.js.map +2 -2
  542. package/dist/modules/customers/events.js +6 -1
  543. package/dist/modules/customers/events.js.map +2 -2
  544. package/dist/modules/customers/lib/assignableStaff.js +14 -0
  545. package/dist/modules/customers/lib/assignableStaff.js.map +2 -2
  546. package/dist/modules/customers/lib/calendar/editorPayload.js +17 -13
  547. package/dist/modules/customers/lib/calendar/editorPayload.js.map +2 -2
  548. package/dist/modules/customers/lib/calendar/mapItem.js +1 -0
  549. package/dist/modules/customers/lib/calendar/mapItem.js.map +2 -2
  550. package/dist/modules/customers/lib/conversationShares.js +126 -0
  551. package/dist/modules/customers/lib/conversationShares.js.map +7 -0
  552. package/dist/modules/customers/lib/dealsOrganizationScope.js +5 -3
  553. package/dist/modules/customers/lib/dealsOrganizationScope.js.map +2 -2
  554. package/dist/modules/customers/lib/interactionRequestContext.js +2 -1
  555. package/dist/modules/customers/lib/interactionRequestContext.js.map +2 -2
  556. package/dist/modules/customers/lib/link-channel-message-handler.js +19 -9
  557. package/dist/modules/customers/lib/link-channel-message-handler.js.map +2 -2
  558. package/dist/modules/customers/lib/personDetailCacheTags.js +32 -0
  559. package/dist/modules/customers/lib/personDetailCacheTags.js.map +7 -0
  560. package/dist/modules/customers/lib/personEmailThreads.js +26 -5
  561. package/dist/modules/customers/lib/personEmailThreads.js.map +2 -2
  562. package/dist/modules/customers/lib/reassignDealOwner.js +25 -0
  563. package/dist/modules/customers/lib/reassignDealOwner.js.map +7 -0
  564. package/dist/modules/customers/lib/userNames.js +26 -0
  565. package/dist/modules/customers/lib/userNames.js.map +7 -0
  566. package/dist/modules/customers/lib/visibilityFilter.js +70 -2
  567. package/dist/modules/customers/lib/visibilityFilter.js.map +2 -2
  568. package/dist/modules/customers/migrations/Migration20260825120000_customers.js +18 -0
  569. package/dist/modules/customers/migrations/Migration20260825120000_customers.js.map +7 -0
  570. package/dist/modules/customers/migrations/Migration20260825140000_customers.js +27 -0
  571. package/dist/modules/customers/migrations/Migration20260825140000_customers.js.map +7 -0
  572. package/dist/modules/customers/setup.js +1 -0
  573. package/dist/modules/customers/setup.js.map +2 -2
  574. package/dist/modules/customers/subscribers/channel-visibility-changed.js +16 -0
  575. package/dist/modules/customers/subscribers/channel-visibility-changed.js.map +7 -0
  576. package/dist/modules/dashboards/api/widgets/data/batch/route.js +3 -8
  577. package/dist/modules/dashboards/api/widgets/data/batch/route.js.map +2 -2
  578. package/dist/modules/dashboards/api/widgets/data/route.js +10 -15
  579. package/dist/modules/dashboards/api/widgets/data/route.js.map +2 -2
  580. package/dist/modules/dashboards/lib/aggregations.js +1 -1
  581. package/dist/modules/dashboards/lib/aggregations.js.map +2 -2
  582. package/dist/modules/dashboards/lib/widgetScope.js +2 -7
  583. package/dist/modules/dashboards/lib/widgetScope.js.map +2 -2
  584. package/dist/modules/data_sync/api/runs/[id]/cancel.js +4 -1
  585. package/dist/modules/data_sync/api/runs/[id]/cancel.js.map +2 -2
  586. package/dist/modules/data_sync/backend/data-sync/page.js +497 -329
  587. package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
  588. package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.js +248 -113
  589. package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.js.map +3 -3
  590. package/dist/modules/data_sync/components/useDataSyncRunAccess.js +17 -0
  591. package/dist/modules/data_sync/components/useDataSyncRunAccess.js.map +7 -0
  592. package/dist/modules/data_sync/lib/resume-point.js +21 -0
  593. package/dist/modules/data_sync/lib/resume-point.js.map +7 -0
  594. package/dist/modules/data_sync/lib/start-run.js +52 -2
  595. package/dist/modules/data_sync/lib/start-run.js.map +2 -2
  596. package/dist/modules/data_sync/lib/sync-run-service.js +22 -33
  597. package/dist/modules/data_sync/lib/sync-run-service.js.map +3 -3
  598. package/dist/modules/devices/api/[id]/route.js +3 -2
  599. package/dist/modules/devices/api/[id]/route.js.map +2 -2
  600. package/dist/modules/devices/api/admin/devices/route.js +2 -1
  601. package/dist/modules/devices/api/admin/devices/route.js.map +2 -2
  602. package/dist/modules/devices/api/route.js +2 -1
  603. package/dist/modules/devices/api/route.js.map +2 -2
  604. package/dist/modules/dictionaries/api/[dictionaryId]/route.js.map +2 -2
  605. package/dist/modules/dictionaries/api/context.js +2 -1
  606. package/dist/modules/dictionaries/api/context.js.map +2 -2
  607. package/dist/modules/dictionaries/api/route.js +4 -0
  608. package/dist/modules/dictionaries/api/route.js.map +2 -2
  609. package/dist/modules/dictionaries/components/DictionariesManager.js +4 -3
  610. package/dist/modules/dictionaries/components/DictionariesManager.js.map +2 -2
  611. package/dist/modules/dictionaries/data/validators.js +3 -1
  612. package/dist/modules/dictionaries/data/validators.js.map +2 -2
  613. package/dist/modules/directory/api/organization-branding/route.js +10 -1
  614. package/dist/modules/directory/api/organization-branding/route.js.map +2 -2
  615. package/dist/modules/directory/api/organizations/route.js +1 -1
  616. package/dist/modules/directory/api/organizations/route.js.map +1 -1
  617. package/dist/modules/directory/backend/directory/branding/page.js +17 -4
  618. package/dist/modules/directory/backend/directory/branding/page.js.map +3 -3
  619. package/dist/modules/directory/commands/organizations.js +136 -74
  620. package/dist/modules/directory/commands/organizations.js.map +2 -2
  621. package/dist/modules/directory/lib/hierarchy.js +19 -1
  622. package/dist/modules/directory/lib/hierarchy.js.map +2 -2
  623. package/dist/modules/directory/utils/organizationScope.js +66 -12
  624. package/dist/modules/directory/utils/organizationScope.js.map +2 -2
  625. package/dist/modules/directory/utils/organizationScopeFilter.js +7 -4
  626. package/dist/modules/directory/utils/organizationScopeFilter.js.map +2 -2
  627. package/dist/modules/directory/utils/organizationScopeGuard.js +6 -2
  628. package/dist/modules/directory/utils/organizationScopeGuard.js.map +2 -2
  629. package/dist/modules/entities/api/encryption.js +68 -25
  630. package/dist/modules/entities/api/encryption.js.map +2 -2
  631. package/dist/modules/entities/api/records.js +9 -8
  632. package/dist/modules/entities/api/records.js.map +2 -2
  633. package/dist/modules/entities/cli.js +33 -22
  634. package/dist/modules/entities/cli.js.map +2 -2
  635. package/dist/modules/entities/data/entities.js +8 -0
  636. package/dist/modules/entities/data/entities.js.map +2 -2
  637. package/dist/modules/entities/lib/definition-scope.js +3 -1
  638. package/dist/modules/entities/lib/definition-scope.js.map +2 -2
  639. package/dist/modules/entities/lib/encryption-maps.js +117 -0
  640. package/dist/modules/entities/lib/encryption-maps.js.map +7 -0
  641. package/dist/modules/entities/lib/helpers.js +30 -6
  642. package/dist/modules/entities/lib/helpers.js.map +2 -2
  643. package/dist/modules/entities/migrations/Migration20260910120000.js +17 -0
  644. package/dist/modules/entities/migrations/Migration20260910120000.js.map +7 -0
  645. package/dist/modules/entities/migrations/Migration20261004120000_encryption_map_scope_uniqueness.js +130 -0
  646. package/dist/modules/entities/migrations/Migration20261004120000_encryption_map_scope_uniqueness.js.map +7 -0
  647. package/dist/modules/eudr/api/dashboard/widgets/compliance-overview/route.js +2 -1
  648. package/dist/modules/eudr/api/dashboard/widgets/compliance-overview/route.js.map +2 -2
  649. package/dist/modules/eudr/api/plots/import/route.js +2 -1
  650. package/dist/modules/eudr/api/plots/import/route.js.map +2 -2
  651. package/dist/modules/eudr/api/product-mappings/suggestions/apply/route.js +2 -1
  652. package/dist/modules/eudr/api/product-mappings/suggestions/apply/route.js.map +2 -2
  653. package/dist/modules/eudr/api/product-mappings/suggestions/route.js +2 -1
  654. package/dist/modules/eudr/api/product-mappings/suggestions/route.js.map +2 -2
  655. package/dist/modules/eudr/api/reports/annual/route.js +2 -1
  656. package/dist/modules/eudr/api/reports/annual/route.js.map +2 -2
  657. package/dist/modules/eudr/api/statements/[id]/export/route.js +2 -1
  658. package/dist/modules/eudr/api/statements/[id]/export/route.js.map +2 -2
  659. package/dist/modules/eudr/api/statements/[id]/readiness/route.js +2 -1
  660. package/dist/modules/eudr/api/statements/[id]/readiness/route.js.map +2 -2
  661. package/dist/modules/eudr/api/suppliers/compliance/route.js +2 -1
  662. package/dist/modules/eudr/api/suppliers/compliance/route.js.map +2 -2
  663. package/dist/modules/feature_toggles/commands/global.js +13 -13
  664. package/dist/modules/feature_toggles/commands/global.js.map +2 -2
  665. package/dist/modules/feature_toggles/lib/feature-flag-check.js +8 -2
  666. package/dist/modules/feature_toggles/lib/feature-flag-check.js.map +2 -2
  667. package/dist/modules/forms/acl.js +14 -0
  668. package/dist/modules/forms/acl.js.map +7 -0
  669. package/dist/modules/forms/api/[id]/analytics/route.js +113 -0
  670. package/dist/modules/forms/api/[id]/analytics/route.js.map +7 -0
  671. package/dist/modules/forms/api/[id]/distributions/route.js +176 -0
  672. package/dist/modules/forms/api/[id]/distributions/route.js.map +7 -0
  673. package/dist/modules/forms/api/[id]/route.js +225 -0
  674. package/dist/modules/forms/api/[id]/route.js.map +7 -0
  675. package/dist/modules/forms/api/[id]/run/context/route.js +115 -0
  676. package/dist/modules/forms/api/[id]/run/context/route.js.map +7 -0
  677. package/dist/modules/forms/api/[id]/run/submissions/route.js +109 -0
  678. package/dist/modules/forms/api/[id]/run/submissions/route.js.map +7 -0
  679. package/dist/modules/forms/api/[id]/submissions/route.js +83 -0
  680. package/dist/modules/forms/api/[id]/submissions/route.js.map +7 -0
  681. package/dist/modules/forms/api/[id]/theme-logo/route.js +117 -0
  682. package/dist/modules/forms/api/[id]/theme-logo/route.js.map +7 -0
  683. package/dist/modules/forms/api/[id]/versions/[versionId]/diff/route.js +125 -0
  684. package/dist/modules/forms/api/[id]/versions/[versionId]/diff/route.js.map +7 -0
  685. package/dist/modules/forms/api/[id]/versions/[versionId]/publish/route.js +99 -0
  686. package/dist/modules/forms/api/[id]/versions/[versionId]/publish/route.js.map +7 -0
  687. package/dist/modules/forms/api/[id]/versions/[versionId]/route.js +176 -0
  688. package/dist/modules/forms/api/[id]/versions/[versionId]/route.js.map +7 -0
  689. package/dist/modules/forms/api/[id]/versions/fork/route.js +92 -0
  690. package/dist/modules/forms/api/[id]/versions/fork/route.js.map +7 -0
  691. package/dist/modules/forms/api/attachment-helpers.js +111 -0
  692. package/dist/modules/forms/api/attachment-helpers.js.map +7 -0
  693. package/dist/modules/forms/api/by-key/[key]/active/route.js +140 -0
  694. package/dist/modules/forms/api/by-key/[key]/active/route.js.map +7 -0
  695. package/dist/modules/forms/api/distributions/[distributionId]/invitations/[invitationId]/route.js +84 -0
  696. package/dist/modules/forms/api/distributions/[distributionId]/invitations/[invitationId]/route.js.map +7 -0
  697. package/dist/modules/forms/api/distributions/[distributionId]/invitations/[invitationId]/send/route.js +88 -0
  698. package/dist/modules/forms/api/distributions/[distributionId]/invitations/[invitationId]/send/route.js.map +7 -0
  699. package/dist/modules/forms/api/distributions/[distributionId]/invitations/route.js +183 -0
  700. package/dist/modules/forms/api/distributions/[distributionId]/invitations/route.js.map +7 -0
  701. package/dist/modules/forms/api/distributions/[distributionId]/route.js +191 -0
  702. package/dist/modules/forms/api/distributions/[distributionId]/route.js.map +7 -0
  703. package/dist/modules/forms/api/form-submissions/[id]/attachments/route.js +91 -0
  704. package/dist/modules/forms/api/form-submissions/[id]/attachments/route.js.map +7 -0
  705. package/dist/modules/forms/api/form-submissions/[id]/resume-token/route.js +110 -0
  706. package/dist/modules/forms/api/form-submissions/[id]/resume-token/route.js.map +7 -0
  707. package/dist/modules/forms/api/form-submissions/[id]/route.js +146 -0
  708. package/dist/modules/forms/api/form-submissions/[id]/route.js.map +7 -0
  709. package/dist/modules/forms/api/form-submissions/[id]/submit/route.js +74 -0
  710. package/dist/modules/forms/api/form-submissions/[id]/submit/route.js.map +7 -0
  711. package/dist/modules/forms/api/form-submissions/by-subject/[subject_type]/[subject_id]/route.js +76 -0
  712. package/dist/modules/forms/api/form-submissions/by-subject/[subject_type]/[subject_id]/route.js.map +7 -0
  713. package/dist/modules/forms/api/form-submissions/route.js +113 -0
  714. package/dist/modules/forms/api/form-submissions/route.js.map +7 -0
  715. package/dist/modules/forms/api/helpers.js +124 -0
  716. package/dist/modules/forms/api/helpers.js.map +7 -0
  717. package/dist/modules/forms/api/public/distributions/[slug]/embed-policy/route.js +47 -0
  718. package/dist/modules/forms/api/public/distributions/[slug]/embed-policy/route.js.map +7 -0
  719. package/dist/modules/forms/api/public/distributions/[slug]/route.js +81 -0
  720. package/dist/modules/forms/api/public/distributions/[slug]/route.js.map +7 -0
  721. package/dist/modules/forms/api/public/embed-loader/route.js +116 -0
  722. package/dist/modules/forms/api/public/embed-loader/route.js.map +7 -0
  723. package/dist/modules/forms/api/public/invitations/[token]/route.js +87 -0
  724. package/dist/modules/forms/api/public/invitations/[token]/route.js.map +7 -0
  725. package/dist/modules/forms/api/public/rate-limit.js +54 -0
  726. package/dist/modules/forms/api/public/rate-limit.js.map +7 -0
  727. package/dist/modules/forms/api/public/start/route.js +142 -0
  728. package/dist/modules/forms/api/public/start/route.js.map +7 -0
  729. package/dist/modules/forms/api/public/submissions/[id]/attachments/[attachmentId]/route.js +67 -0
  730. package/dist/modules/forms/api/public/submissions/[id]/attachments/[attachmentId]/route.js.map +7 -0
  731. package/dist/modules/forms/api/public/submissions/[id]/attachments/route.js +85 -0
  732. package/dist/modules/forms/api/public/submissions/[id]/attachments/route.js.map +7 -0
  733. package/dist/modules/forms/api/public/submissions/[id]/pdf/route.js +72 -0
  734. package/dist/modules/forms/api/public/submissions/[id]/pdf/route.js.map +7 -0
  735. package/dist/modules/forms/api/public/submissions/[id]/route.js +154 -0
  736. package/dist/modules/forms/api/public/submissions/[id]/route.js.map +7 -0
  737. package/dist/modules/forms/api/public/submissions/[id]/submit/route.js +127 -0
  738. package/dist/modules/forms/api/public/submissions/[id]/submit/route.js.map +7 -0
  739. package/dist/modules/forms/api/route.js +216 -0
  740. package/dist/modules/forms/api/route.js.map +7 -0
  741. package/dist/modules/forms/api/runtime-helpers.js +149 -0
  742. package/dist/modules/forms/api/runtime-helpers.js.map +7 -0
  743. package/dist/modules/forms/api/subjects/[subjectType]/[subjectId]/consents/route.js +137 -0
  744. package/dist/modules/forms/api/subjects/[subjectType]/[subjectId]/consents/route.js.map +7 -0
  745. package/dist/modules/forms/api/subjects/[subjectType]/[subjectId]/export/route.js +101 -0
  746. package/dist/modules/forms/api/subjects/[subjectType]/[subjectId]/export/route.js.map +7 -0
  747. package/dist/modules/forms/api/submissions/[submissionId]/access-audit/route.js +76 -0
  748. package/dist/modules/forms/api/submissions/[submissionId]/access-audit/route.js.map +7 -0
  749. package/dist/modules/forms/api/submissions/[submissionId]/actors/[actorId]/route.js +56 -0
  750. package/dist/modules/forms/api/submissions/[submissionId]/actors/[actorId]/route.js.map +7 -0
  751. package/dist/modules/forms/api/submissions/[submissionId]/actors/route.js +76 -0
  752. package/dist/modules/forms/api/submissions/[submissionId]/actors/route.js.map +7 -0
  753. package/dist/modules/forms/api/submissions/[submissionId]/anonymize/route.js +107 -0
  754. package/dist/modules/forms/api/submissions/[submissionId]/anonymize/route.js.map +7 -0
  755. package/dist/modules/forms/api/submissions/[submissionId]/attachments/[attachmentId]/route.js +73 -0
  756. package/dist/modules/forms/api/submissions/[submissionId]/attachments/[attachmentId]/route.js.map +7 -0
  757. package/dist/modules/forms/api/submissions/[submissionId]/export/route.js +90 -0
  758. package/dist/modules/forms/api/submissions/[submissionId]/export/route.js.map +7 -0
  759. package/dist/modules/forms/api/submissions/[submissionId]/pdf/route.js +91 -0
  760. package/dist/modules/forms/api/submissions/[submissionId]/pdf/route.js.map +7 -0
  761. package/dist/modules/forms/api/submissions/[submissionId]/reopen/route.js +55 -0
  762. package/dist/modules/forms/api/submissions/[submissionId]/reopen/route.js.map +7 -0
  763. package/dist/modules/forms/api/submissions/[submissionId]/revisions/route.js +61 -0
  764. package/dist/modules/forms/api/submissions/[submissionId]/revisions/route.js.map +7 -0
  765. package/dist/modules/forms/api/submissions/[submissionId]/route.js +75 -0
  766. package/dist/modules/forms/api/submissions/[submissionId]/route.js.map +7 -0
  767. package/dist/modules/forms/backend/forms/[id]/FormStudio.js +2811 -0
  768. package/dist/modules/forms/backend/forms/[id]/FormStudio.js.map +7 -0
  769. package/dist/modules/forms/backend/forms/[id]/analytics/page.js +214 -0
  770. package/dist/modules/forms/backend/forms/[id]/analytics/page.js.map +7 -0
  771. package/dist/modules/forms/backend/forms/[id]/analytics/page.meta.js +19 -0
  772. package/dist/modules/forms/backend/forms/[id]/analytics/page.meta.js.map +7 -0
  773. package/dist/modules/forms/backend/forms/[id]/distributions/page.js +12 -0
  774. package/dist/modules/forms/backend/forms/[id]/distributions/page.js.map +7 -0
  775. package/dist/modules/forms/backend/forms/[id]/distributions/page.meta.js +19 -0
  776. package/dist/modules/forms/backend/forms/[id]/distributions/page.meta.js.map +7 -0
  777. package/dist/modules/forms/backend/forms/[id]/history/page.js +152 -0
  778. package/dist/modules/forms/backend/forms/[id]/history/page.js.map +7 -0
  779. package/dist/modules/forms/backend/forms/[id]/history/page.meta.js +15 -0
  780. package/dist/modules/forms/backend/forms/[id]/history/page.meta.js.map +7 -0
  781. package/dist/modules/forms/backend/forms/[id]/page.js +13 -0
  782. package/dist/modules/forms/backend/forms/[id]/page.js.map +7 -0
  783. package/dist/modules/forms/backend/forms/[id]/page.meta.js +15 -0
  784. package/dist/modules/forms/backend/forms/[id]/page.meta.js.map +7 -0
  785. package/dist/modules/forms/backend/forms/[id]/studio/YesNoRow.js +51 -0
  786. package/dist/modules/forms/backend/forms/[id]/studio/YesNoRow.js.map +7 -0
  787. package/dist/modules/forms/backend/forms/[id]/studio/autosave-guard.js +21 -0
  788. package/dist/modules/forms/backend/forms/[id]/studio/autosave-guard.js.map +7 -0
  789. package/dist/modules/forms/backend/forms/[id]/studio/canvas/DragOverlayCard.js +18 -0
  790. package/dist/modules/forms/backend/forms/[id]/studio/canvas/DragOverlayCard.js.map +7 -0
  791. package/dist/modules/forms/backend/forms/[id]/studio/canvas/DropIndicator.js +41 -0
  792. package/dist/modules/forms/backend/forms/[id]/studio/canvas/DropIndicator.js.map +7 -0
  793. package/dist/modules/forms/backend/forms/[id]/studio/canvas/FieldRow.js +277 -0
  794. package/dist/modules/forms/backend/forms/[id]/studio/canvas/FieldRow.js.map +7 -0
  795. package/dist/modules/forms/backend/forms/[id]/studio/canvas/FormCanvas.js +196 -0
  796. package/dist/modules/forms/backend/forms/[id]/studio/canvas/FormCanvas.js.map +7 -0
  797. package/dist/modules/forms/backend/forms/[id]/studio/canvas/GridSlot.js +151 -0
  798. package/dist/modules/forms/backend/forms/[id]/studio/canvas/GridSlot.js.map +7 -0
  799. package/dist/modules/forms/backend/forms/[id]/studio/canvas/SectionContainer.js +340 -0
  800. package/dist/modules/forms/backend/forms/[id]/studio/canvas/SectionContainer.js.map +7 -0
  801. package/dist/modules/forms/backend/forms/[id]/studio/canvas/grid-collision.js +24 -0
  802. package/dist/modules/forms/backend/forms/[id]/studio/canvas/grid-collision.js.map +7 -0
  803. package/dist/modules/forms/backend/forms/[id]/studio/canvas/keyboard-coordinates.js +91 -0
  804. package/dist/modules/forms/backend/forms/[id]/studio/canvas/keyboard-coordinates.js.map +7 -0
  805. package/dist/modules/forms/backend/forms/[id]/studio/canvas/overlay-size.js +11 -0
  806. package/dist/modules/forms/backend/forms/[id]/studio/canvas/overlay-size.js.map +7 -0
  807. package/dist/modules/forms/backend/forms/[id]/studio/canvas/resize-math.js +27 -0
  808. package/dist/modules/forms/backend/forms/[id]/studio/canvas/resize-math.js.map +7 -0
  809. package/dist/modules/forms/backend/forms/[id]/studio/canvas/row-layout.js +80 -0
  810. package/dist/modules/forms/backend/forms/[id]/studio/canvas/row-layout.js.map +7 -0
  811. package/dist/modules/forms/backend/forms/[id]/studio/logic/ConditionBuilder.js +210 -0
  812. package/dist/modules/forms/backend/forms/[id]/studio/logic/ConditionBuilder.js.map +7 -0
  813. package/dist/modules/forms/backend/forms/[id]/studio/logic/HiddenFieldsPanel.js +91 -0
  814. package/dist/modules/forms/backend/forms/[id]/studio/logic/HiddenFieldsPanel.js.map +7 -0
  815. package/dist/modules/forms/backend/forms/[id]/studio/logic/JumpsEditor.js +201 -0
  816. package/dist/modules/forms/backend/forms/[id]/studio/logic/JumpsEditor.js.map +7 -0
  817. package/dist/modules/forms/backend/forms/[id]/studio/logic/RecallTokenPicker.js +66 -0
  818. package/dist/modules/forms/backend/forms/[id]/studio/logic/RecallTokenPicker.js.map +7 -0
  819. package/dist/modules/forms/backend/forms/[id]/studio/logic/VariablesPanel.js +223 -0
  820. package/dist/modules/forms/backend/forms/[id]/studio/logic/VariablesPanel.js.map +7 -0
  821. package/dist/modules/forms/backend/forms/[id]/studio/logic/condition-model.js +151 -0
  822. package/dist/modules/forms/backend/forms/[id]/studio/logic/condition-model.js.map +7 -0
  823. package/dist/modules/forms/backend/forms/[id]/studio/lucide-icons.js +88 -0
  824. package/dist/modules/forms/backend/forms/[id]/studio/lucide-icons.js.map +7 -0
  825. package/dist/modules/forms/backend/forms/[id]/studio/palette/FormAppearancePanel.js +493 -0
  826. package/dist/modules/forms/backend/forms/[id]/studio/palette/FormAppearancePanel.js.map +7 -0
  827. package/dist/modules/forms/backend/forms/[id]/studio/palette/FormPalettePanel.js +44 -0
  828. package/dist/modules/forms/backend/forms/[id]/studio/palette/FormPalettePanel.js.map +7 -0
  829. package/dist/modules/forms/backend/forms/[id]/studio/palette/InputParametersTab.js +350 -0
  830. package/dist/modules/forms/backend/forms/[id]/studio/palette/InputParametersTab.js.map +7 -0
  831. package/dist/modules/forms/backend/forms/[id]/studio/palette/PaletteCard.js +40 -0
  832. package/dist/modules/forms/backend/forms/[id]/studio/palette/PaletteCard.js.map +7 -0
  833. package/dist/modules/forms/backend/forms/[id]/studio/palette/RolesEditor.js +202 -0
  834. package/dist/modules/forms/backend/forms/[id]/studio/palette/RolesEditor.js.map +7 -0
  835. package/dist/modules/forms/backend/forms/[id]/studio/palette/entries.js +66 -0
  836. package/dist/modules/forms/backend/forms/[id]/studio/palette/entries.js.map +7 -0
  837. package/dist/modules/forms/backend/forms/[id]/studio/preview/PreviewSurface.js +1200 -0
  838. package/dist/modules/forms/backend/forms/[id]/studio/preview/PreviewSurface.js.map +7 -0
  839. package/dist/modules/forms/backend/forms/[id]/studio/preview/ViewportFrame.js +34 -0
  840. package/dist/modules/forms/backend/forms/[id]/studio/preview/ViewportFrame.js.map +7 -0
  841. package/dist/modules/forms/backend/forms/[id]/studio/recall.js +76 -0
  842. package/dist/modules/forms/backend/forms/[id]/studio/recall.js.map +7 -0
  843. package/dist/modules/forms/backend/forms/[id]/studio/schema-helpers.js +1693 -0
  844. package/dist/modules/forms/backend/forms/[id]/studio/schema-helpers.js.map +7 -0
  845. package/dist/modules/forms/backend/forms/[id]/studio/style/BackgroundControl.js +127 -0
  846. package/dist/modules/forms/backend/forms/[id]/studio/style/BackgroundControl.js.map +7 -0
  847. package/dist/modules/forms/backend/forms/[id]/studio/style/ColorControl.js +181 -0
  848. package/dist/modules/forms/backend/forms/[id]/studio/style/ColorControl.js.map +7 -0
  849. package/dist/modules/forms/backend/forms/[id]/studio/style/contrast.js +75 -0
  850. package/dist/modules/forms/backend/forms/[id]/studio/style/contrast.js.map +7 -0
  851. package/dist/modules/forms/backend/forms/[id]/studio/style/presets.js +91 -0
  852. package/dist/modules/forms/backend/forms/[id]/studio/style/presets.js.map +7 -0
  853. package/dist/modules/forms/backend/forms/[id]/studio/type-label.js +11 -0
  854. package/dist/modules/forms/backend/forms/[id]/studio/type-label.js.map +7 -0
  855. package/dist/modules/forms/backend/forms/[id]/studio/types.js +1 -0
  856. package/dist/modules/forms/backend/forms/[id]/studio/types.js.map +7 -0
  857. package/dist/modules/forms/backend/forms/[id]/studio/undo-controller.js +43 -0
  858. package/dist/modules/forms/backend/forms/[id]/studio/undo-controller.js.map +7 -0
  859. package/dist/modules/forms/backend/forms/[id]/studio/validation/FileConstraintsEditor.js +74 -0
  860. package/dist/modules/forms/backend/forms/[id]/studio/validation/FileConstraintsEditor.js.map +7 -0
  861. package/dist/modules/forms/backend/forms/[id]/studio/validation/GroupConfigEditor.js +134 -0
  862. package/dist/modules/forms/backend/forms/[id]/studio/validation/GroupConfigEditor.js.map +7 -0
  863. package/dist/modules/forms/backend/forms/[id]/studio/validation/LengthRangeEditor.js +61 -0
  864. package/dist/modules/forms/backend/forms/[id]/studio/validation/LengthRangeEditor.js.map +7 -0
  865. package/dist/modules/forms/backend/forms/[id]/studio/validation/MatrixColumnsEditor.js +149 -0
  866. package/dist/modules/forms/backend/forms/[id]/studio/validation/MatrixColumnsEditor.js.map +7 -0
  867. package/dist/modules/forms/backend/forms/[id]/studio/validation/MatrixRowsEditor.js +168 -0
  868. package/dist/modules/forms/backend/forms/[id]/studio/validation/MatrixRowsEditor.js.map +7 -0
  869. package/dist/modules/forms/backend/forms/[id]/studio/validation/MessageOverridesEditor.js +64 -0
  870. package/dist/modules/forms/backend/forms/[id]/studio/validation/MessageOverridesEditor.js.map +7 -0
  871. package/dist/modules/forms/backend/forms/[id]/studio/validation/NpsAnchorsEditor.js +52 -0
  872. package/dist/modules/forms/backend/forms/[id]/studio/validation/NpsAnchorsEditor.js.map +7 -0
  873. package/dist/modules/forms/backend/forms/[id]/studio/validation/NumberRangeEditor.js +59 -0
  874. package/dist/modules/forms/backend/forms/[id]/studio/validation/NumberRangeEditor.js.map +7 -0
  875. package/dist/modules/forms/backend/forms/[id]/studio/validation/OpinionIconSelect.js +31 -0
  876. package/dist/modules/forms/backend/forms/[id]/studio/validation/OpinionIconSelect.js.map +7 -0
  877. package/dist/modules/forms/backend/forms/[id]/studio/validation/PatternEditor.js +105 -0
  878. package/dist/modules/forms/backend/forms/[id]/studio/validation/PatternEditor.js.map +7 -0
  879. package/dist/modules/forms/backend/forms/[id]/studio/validation/RankingExhaustiveSwitch.js +15 -0
  880. package/dist/modules/forms/backend/forms/[id]/studio/validation/RankingExhaustiveSwitch.js.map +7 -0
  881. package/dist/modules/forms/backend/forms/[id]/studio/validation/SignatureConfigEditor.js +75 -0
  882. package/dist/modules/forms/backend/forms/[id]/studio/validation/SignatureConfigEditor.js.map +7 -0
  883. package/dist/modules/forms/backend/forms/[id]/studio/validation/ValidationPanel.js +293 -0
  884. package/dist/modules/forms/backend/forms/[id]/studio/validation/ValidationPanel.js.map +7 -0
  885. package/dist/modules/forms/backend/forms/[id]/submissions/components/RowBadges.js +42 -0
  886. package/dist/modules/forms/backend/forms/[id]/submissions/components/RowBadges.js.map +7 -0
  887. package/dist/modules/forms/backend/forms/[id]/submissions/components/SubmissionDrawer.js +473 -0
  888. package/dist/modules/forms/backend/forms/[id]/submissions/components/SubmissionDrawer.js.map +7 -0
  889. package/dist/modules/forms/backend/forms/[id]/submissions/page.js +208 -0
  890. package/dist/modules/forms/backend/forms/[id]/submissions/page.js.map +7 -0
  891. package/dist/modules/forms/backend/forms/[id]/submissions/page.meta.js +12 -0
  892. package/dist/modules/forms/backend/forms/[id]/submissions/page.meta.js.map +7 -0
  893. package/dist/modules/forms/backend/forms/create/page.js +101 -0
  894. package/dist/modules/forms/backend/forms/create/page.js.map +7 -0
  895. package/dist/modules/forms/backend/forms/create/page.meta.js +15 -0
  896. package/dist/modules/forms/backend/forms/create/page.meta.js.map +7 -0
  897. package/dist/modules/forms/backend/forms/page.js +227 -0
  898. package/dist/modules/forms/backend/forms/page.js.map +7 -0
  899. package/dist/modules/forms/backend/forms/page.meta.js +33 -0
  900. package/dist/modules/forms/backend/forms/page.meta.js.map +7 -0
  901. package/dist/modules/forms/commands/distribution.js +417 -0
  902. package/dist/modules/forms/commands/distribution.js.map +7 -0
  903. package/dist/modules/forms/commands/form-version.js +640 -0
  904. package/dist/modules/forms/commands/form-version.js.map +7 -0
  905. package/dist/modules/forms/commands/form.js +406 -0
  906. package/dist/modules/forms/commands/form.js.map +7 -0
  907. package/dist/modules/forms/commands/index.js +11 -0
  908. package/dist/modules/forms/commands/index.js.map +7 -0
  909. package/dist/modules/forms/commands/invitation.js +329 -0
  910. package/dist/modules/forms/commands/invitation.js.map +7 -0
  911. package/dist/modules/forms/commands/shared.js +151 -0
  912. package/dist/modules/forms/commands/shared.js.map +7 -0
  913. package/dist/modules/forms/commands/submission.js +132 -0
  914. package/dist/modules/forms/commands/submission.js.map +7 -0
  915. package/dist/modules/forms/data/entities.js +654 -0
  916. package/dist/modules/forms/data/entities.js.map +7 -0
  917. package/dist/modules/forms/data/validators.js +254 -0
  918. package/dist/modules/forms/data/validators.js.map +7 -0
  919. package/dist/modules/forms/di.js +199 -0
  920. package/dist/modules/forms/di.js.map +7 -0
  921. package/dist/modules/forms/encryption.js +15 -0
  922. package/dist/modules/forms/encryption.js.map +7 -0
  923. package/dist/modules/forms/events-payloads.js +81 -0
  924. package/dist/modules/forms/events-payloads.js.map +7 -0
  925. package/dist/modules/forms/events.js +33 -0
  926. package/dist/modules/forms/events.js.map +7 -0
  927. package/dist/modules/forms/extension-points.js +36 -0
  928. package/dist/modules/forms/extension-points.js.map +7 -0
  929. package/dist/modules/forms/frontend/[orgSlug]/portal/forms/[key]/page.js +33 -0
  930. package/dist/modules/forms/frontend/[orgSlug]/portal/forms/[key]/page.js.map +7 -0
  931. package/dist/modules/forms/frontend/[orgSlug]/portal/forms/[key]/page.meta.js +11 -0
  932. package/dist/modules/forms/frontend/[orgSlug]/portal/forms/[key]/page.meta.js.map +7 -0
  933. package/dist/modules/forms/frontend/[orgSlug]/portal/submissions/[id]/continue/page.js +41 -0
  934. package/dist/modules/forms/frontend/[orgSlug]/portal/submissions/[id]/continue/page.js.map +7 -0
  935. package/dist/modules/forms/frontend/[orgSlug]/portal/submissions/[id]/continue/page.meta.js +11 -0
  936. package/dist/modules/forms/frontend/[orgSlug]/portal/submissions/[id]/continue/page.meta.js.map +7 -0
  937. package/dist/modules/forms/frontend/embed/[slug]/page.js +105 -0
  938. package/dist/modules/forms/frontend/embed/[slug]/page.js.map +7 -0
  939. package/dist/modules/forms/frontend/embed/[slug]/page.meta.js +11 -0
  940. package/dist/modules/forms/frontend/embed/[slug]/page.meta.js.map +7 -0
  941. package/dist/modules/forms/frontend/f/[slug]/page.js +12 -0
  942. package/dist/modules/forms/frontend/f/[slug]/page.js.map +7 -0
  943. package/dist/modules/forms/frontend/f/[slug]/page.meta.js +11 -0
  944. package/dist/modules/forms/frontend/f/[slug]/page.meta.js.map +7 -0
  945. package/dist/modules/forms/frontend/forms/[id]/run/page.js +62 -0
  946. package/dist/modules/forms/frontend/forms/[id]/run/page.js.map +7 -0
  947. package/dist/modules/forms/frontend/forms/[id]/run/page.meta.js +11 -0
  948. package/dist/modules/forms/frontend/forms/[id]/run/page.meta.js.map +7 -0
  949. package/dist/modules/forms/frontend/i/[token]/page.js +12 -0
  950. package/dist/modules/forms/frontend/i/[token]/page.js.map +7 -0
  951. package/dist/modules/forms/frontend/i/[token]/page.meta.js +11 -0
  952. package/dist/modules/forms/frontend/i/[token]/page.meta.js.map +7 -0
  953. package/dist/modules/forms/index.js +20 -0
  954. package/dist/modules/forms/index.js.map +7 -0
  955. package/dist/modules/forms/lib/embed-frame-policy.js +68 -0
  956. package/dist/modules/forms/lib/embed-frame-policy.js.map +7 -0
  957. package/dist/modules/forms/lib/form-definition-slicing.js +38 -0
  958. package/dist/modules/forms/lib/form-definition-slicing.js.map +7 -0
  959. package/dist/modules/forms/lib/log-redaction.js +38 -0
  960. package/dist/modules/forms/lib/log-redaction.js.map +7 -0
  961. package/dist/modules/forms/lib/navigable-url.js +24 -0
  962. package/dist/modules/forms/lib/navigable-url.js.map +7 -0
  963. package/dist/modules/forms/lib/retention.js +20 -0
  964. package/dist/modules/forms/lib/retention.js.map +7 -0
  965. package/dist/modules/forms/lib/runtime-principal.js +59 -0
  966. package/dist/modules/forms/lib/runtime-principal.js.map +7 -0
  967. package/dist/modules/forms/migrations/Migration20260508135459_forms.js +17 -0
  968. package/dist/modules/forms/migrations/Migration20260508135459_forms.js.map +7 -0
  969. package/dist/modules/forms/migrations/Migration20260508140932_forms.js +23 -0
  970. package/dist/modules/forms/migrations/Migration20260508140932_forms.js.map +7 -0
  971. package/dist/modules/forms/migrations/Migration20260508155737_forms.js +15 -0
  972. package/dist/modules/forms/migrations/Migration20260508155737_forms.js.map +7 -0
  973. package/dist/modules/forms/migrations/Migration20260520120000_forms.js +23 -0
  974. package/dist/modules/forms/migrations/Migration20260520120000_forms.js.map +7 -0
  975. package/dist/modules/forms/migrations/Migration20260521090000_forms.js +13 -0
  976. package/dist/modules/forms/migrations/Migration20260521090000_forms.js.map +7 -0
  977. package/dist/modules/forms/migrations/Migration20260521120000_forms.js +17 -0
  978. package/dist/modules/forms/migrations/Migration20260521120000_forms.js.map +7 -0
  979. package/dist/modules/forms/runner/FormRunner.js +786 -0
  980. package/dist/modules/forms/runner/FormRunner.js.map +7 -0
  981. package/dist/modules/forms/runner/MatrixField.js +150 -0
  982. package/dist/modules/forms/runner/MatrixField.js.map +7 -0
  983. package/dist/modules/forms/runner/RankingField.js +131 -0
  984. package/dist/modules/forms/runner/RankingField.js.map +7 -0
  985. package/dist/modules/forms/runner/ScaleField.js +78 -0
  986. package/dist/modules/forms/runner/ScaleField.js.map +7 -0
  987. package/dist/modules/forms/runner/SignatureField.js +132 -0
  988. package/dist/modules/forms/runner/SignatureField.js.map +7 -0
  989. package/dist/modules/forms/runner/tamper-check.js +85 -0
  990. package/dist/modules/forms/runner/tamper-check.js.map +7 -0
  991. package/dist/modules/forms/schema/address-countries.js +43 -0
  992. package/dist/modules/forms/schema/address-countries.js.map +7 -0
  993. package/dist/modules/forms/schema/field-type-patterns.js +15 -0
  994. package/dist/modules/forms/schema/field-type-patterns.js.map +7 -0
  995. package/dist/modules/forms/schema/field-type-registry-advanced.js +32 -0
  996. package/dist/modules/forms/schema/field-type-registry-advanced.js.map +7 -0
  997. package/dist/modules/forms/schema/field-type-registry.js +625 -0
  998. package/dist/modules/forms/schema/field-type-registry.js.map +7 -0
  999. package/dist/modules/forms/schema/file-field.js +64 -0
  1000. package/dist/modules/forms/schema/file-field.js.map +7 -0
  1001. package/dist/modules/forms/schema/group-field.js +143 -0
  1002. package/dist/modules/forms/schema/group-field.js.map +7 -0
  1003. package/dist/modules/forms/schema/jsonlogic-grammar.js +66 -0
  1004. package/dist/modules/forms/schema/jsonlogic-grammar.js.map +7 -0
  1005. package/dist/modules/forms/schema/jsonschema-extensions.js +739 -0
  1006. package/dist/modules/forms/schema/jsonschema-extensions.js.map +7 -0
  1007. package/dist/modules/forms/schema/layout-catalog.js +38 -0
  1008. package/dist/modules/forms/schema/layout-catalog.js.map +7 -0
  1009. package/dist/modules/forms/schema/signature-field.js +67 -0
  1010. package/dist/modules/forms/schema/signature-field.js.map +7 -0
  1011. package/dist/modules/forms/schema/style-extensions.js +77 -0
  1012. package/dist/modules/forms/schema/style-extensions.js.map +7 -0
  1013. package/dist/modules/forms/schema/style-validators.js +181 -0
  1014. package/dist/modules/forms/schema/style-validators.js.map +7 -0
  1015. package/dist/modules/forms/services/access-audit-logger.js +179 -0
  1016. package/dist/modules/forms/services/access-audit-logger.js.map +7 -0
  1017. package/dist/modules/forms/services/analytics-service.js +306 -0
  1018. package/dist/modules/forms/services/analytics-service.js.map +7 -0
  1019. package/dist/modules/forms/services/anonymize-service.js +123 -0
  1020. package/dist/modules/forms/services/anonymize-service.js.map +7 -0
  1021. package/dist/modules/forms/services/attachment-service.js +123 -0
  1022. package/dist/modules/forms/services/attachment-service.js.map +7 -0
  1023. package/dist/modules/forms/services/captcha-verifier.js +76 -0
  1024. package/dist/modules/forms/services/captcha-verifier.js.map +7 -0
  1025. package/dist/modules/forms/services/consent-record-service.js +96 -0
  1026. package/dist/modules/forms/services/consent-record-service.js.map +7 -0
  1027. package/dist/modules/forms/services/distribution-service.js +366 -0
  1028. package/dist/modules/forms/services/distribution-service.js.map +7 -0
  1029. package/dist/modules/forms/services/distribution-token.js +93 -0
  1030. package/dist/modules/forms/services/distribution-token.js.map +7 -0
  1031. package/dist/modules/forms/services/encryption-service.js +328 -0
  1032. package/dist/modules/forms/services/encryption-service.js.map +7 -0
  1033. package/dist/modules/forms/services/export-service.js +210 -0
  1034. package/dist/modules/forms/services/export-service.js.map +7 -0
  1035. package/dist/modules/forms/services/field-validation-service.js +168 -0
  1036. package/dist/modules/forms/services/field-validation-service.js.map +7 -0
  1037. package/dist/modules/forms/services/form-logic-evaluator.js +517 -0
  1038. package/dist/modules/forms/services/form-logic-evaluator.js.map +7 -0
  1039. package/dist/modules/forms/services/form-version-compiler.js +518 -0
  1040. package/dist/modules/forms/services/form-version-compiler.js.map +7 -0
  1041. package/dist/modules/forms/services/form-version-differ.js +89 -0
  1042. package/dist/modules/forms/services/form-version-differ.js.map +7 -0
  1043. package/dist/modules/forms/services/jsonlogic-evaluator.js +171 -0
  1044. package/dist/modules/forms/services/jsonlogic-evaluator.js.map +7 -0
  1045. package/dist/modules/forms/services/pdf-snapshot-service.js +526 -0
  1046. package/dist/modules/forms/services/pdf-snapshot-service.js.map +7 -0
  1047. package/dist/modules/forms/services/prefill-resolver.js +53 -0
  1048. package/dist/modules/forms/services/prefill-resolver.js.map +7 -0
  1049. package/dist/modules/forms/services/role-policy-service.js +55 -0
  1050. package/dist/modules/forms/services/role-policy-service.js.map +7 -0
  1051. package/dist/modules/forms/services/style-compiler.js +234 -0
  1052. package/dist/modules/forms/services/style-compiler.js.map +7 -0
  1053. package/dist/modules/forms/services/submission-service.js +858 -0
  1054. package/dist/modules/forms/services/submission-service.js.map +7 -0
  1055. package/dist/modules/forms/services/upload-scanner.js +9 -0
  1056. package/dist/modules/forms/services/upload-scanner.js.map +7 -0
  1057. package/dist/modules/forms/services/upload-validation.js +54 -0
  1058. package/dist/modules/forms/services/upload-validation.js.map +7 -0
  1059. package/dist/modules/forms/services/visibility-resolver.js +30 -0
  1060. package/dist/modules/forms/services/visibility-resolver.js.map +7 -0
  1061. package/dist/modules/forms/setup.js +18 -0
  1062. package/dist/modules/forms/setup.js.map +7 -0
  1063. package/dist/modules/forms/subscribers/forms-consent-projector.js +58 -0
  1064. package/dist/modules/forms/subscribers/forms-consent-projector.js.map +7 -0
  1065. package/dist/modules/forms/subscribers/forms-pdf-snapshot.js +68 -0
  1066. package/dist/modules/forms/subscribers/forms-pdf-snapshot.js.map +7 -0
  1067. package/dist/modules/forms/subscribers/forms-webhook-bridge-anonymized.js +29 -0
  1068. package/dist/modules/forms/subscribers/forms-webhook-bridge-anonymized.js.map +7 -0
  1069. package/dist/modules/forms/subscribers/forms-webhook-bridge.js +35 -0
  1070. package/dist/modules/forms/subscribers/forms-webhook-bridge.js.map +7 -0
  1071. package/dist/modules/forms/subscribers/invitation-email.js +100 -0
  1072. package/dist/modules/forms/subscribers/invitation-email.js.map +7 -0
  1073. package/dist/modules/forms/translations.js +10 -0
  1074. package/dist/modules/forms/translations.js.map +7 -0
  1075. package/dist/modules/forms/ui/admin/forms/[id]/distributions/CreateDistributionDialog.js +376 -0
  1076. package/dist/modules/forms/ui/admin/forms/[id]/distributions/CreateDistributionDialog.js.map +7 -0
  1077. package/dist/modules/forms/ui/admin/forms/[id]/distributions/DistributionsPanel.js +313 -0
  1078. package/dist/modules/forms/ui/admin/forms/[id]/distributions/DistributionsPanel.js.map +7 -0
  1079. package/dist/modules/forms/ui/admin/forms/[id]/distributions/EmbedSettingsDialog.js +263 -0
  1080. package/dist/modules/forms/ui/admin/forms/[id]/distributions/EmbedSettingsDialog.js.map +7 -0
  1081. package/dist/modules/forms/ui/admin/forms/[id]/distributions/RecipientsTable.js +373 -0
  1082. package/dist/modules/forms/ui/admin/forms/[id]/distributions/RecipientsTable.js.map +7 -0
  1083. package/dist/modules/forms/ui/public/EmbeddedForm.js +166 -0
  1084. package/dist/modules/forms/ui/public/EmbeddedForm.js.map +7 -0
  1085. package/dist/modules/forms/ui/public/FormRunner.js +359 -0
  1086. package/dist/modules/forms/ui/public/FormRunner.js.map +7 -0
  1087. package/dist/modules/forms/ui/public/FormTrigger.js +45 -0
  1088. package/dist/modules/forms/ui/public/FormTrigger.js.map +7 -0
  1089. package/dist/modules/forms/ui/public/PublicFormRunnerPage.js +14 -0
  1090. package/dist/modules/forms/ui/public/PublicFormRunnerPage.js.map +7 -0
  1091. package/dist/modules/forms/ui/public/components/CompletionScreen.js +55 -0
  1092. package/dist/modules/forms/ui/public/components/CompletionScreen.js.map +7 -0
  1093. package/dist/modules/forms/ui/public/components/LocaleSwitch.js +28 -0
  1094. package/dist/modules/forms/ui/public/components/LocaleSwitch.js.map +7 -0
  1095. package/dist/modules/forms/ui/public/components/ResumeGate.js +52 -0
  1096. package/dist/modules/forms/ui/public/components/ResumeGate.js.map +7 -0
  1097. package/dist/modules/forms/ui/public/components/ReviewStep.js +90 -0
  1098. package/dist/modules/forms/ui/public/components/ReviewStep.js.map +7 -0
  1099. package/dist/modules/forms/ui/public/components/SaveIndicator.js +65 -0
  1100. package/dist/modules/forms/ui/public/components/SaveIndicator.js.map +7 -0
  1101. package/dist/modules/forms/ui/public/components/SectionStepper.js +52 -0
  1102. package/dist/modules/forms/ui/public/components/SectionStepper.js.map +7 -0
  1103. package/dist/modules/forms/ui/public/index.js +38 -0
  1104. package/dist/modules/forms/ui/public/index.js.map +7 -0
  1105. package/dist/modules/forms/ui/public/renderers/index.js +737 -0
  1106. package/dist/modules/forms/ui/public/renderers/index.js.map +7 -0
  1107. package/dist/modules/forms/ui/public/state/logic-derivation.js +42 -0
  1108. package/dist/modules/forms/ui/public/state/logic-derivation.js.map +7 -0
  1109. package/dist/modules/forms/ui/public/state/runtime-client.js +306 -0
  1110. package/dist/modules/forms/ui/public/state/runtime-client.js.map +7 -0
  1111. package/dist/modules/forms/ui/public/state/useAutosave.js +64 -0
  1112. package/dist/modules/forms/ui/public/state/useAutosave.js.map +7 -0
  1113. package/dist/modules/forms/ui/public/state/useFormRunner.js +394 -0
  1114. package/dist/modules/forms/ui/public/state/useFormRunner.js.map +7 -0
  1115. package/dist/modules/forms/ui/public/style/LogoHeader.js +33 -0
  1116. package/dist/modules/forms/ui/public/style/LogoHeader.js.map +7 -0
  1117. package/dist/modules/forms/ui/public/style/applyStyle.js +12 -0
  1118. package/dist/modules/forms/ui/public/style/applyStyle.js.map +7 -0
  1119. package/dist/modules/forms/ui/public/types.js +18 -0
  1120. package/dist/modules/forms/ui/public/types.js.map +7 -0
  1121. package/dist/modules/forms/widgets/injection/access-audit-panel/widget.js +100 -0
  1122. package/dist/modules/forms/widgets/injection/access-audit-panel/widget.js.map +7 -0
  1123. package/dist/modules/forms/widgets/injection/anonymize-button/widget.js +148 -0
  1124. package/dist/modules/forms/widgets/injection/anonymize-button/widget.js.map +7 -0
  1125. package/dist/modules/forms/widgets/injection/audit-format.js +33 -0
  1126. package/dist/modules/forms/widgets/injection/audit-format.js.map +7 -0
  1127. package/dist/modules/forms/widgets/injection/context.js +5 -0
  1128. package/dist/modules/forms/widgets/injection/context.js.map +7 -0
  1129. package/dist/modules/forms/widgets/injection/embedded-form/widget.js +52 -0
  1130. package/dist/modules/forms/widgets/injection/embedded-form/widget.js.map +7 -0
  1131. package/dist/modules/forms/widgets/injection/pdf-download-button/widget.js +83 -0
  1132. package/dist/modules/forms/widgets/injection/pdf-download-button/widget.js.map +7 -0
  1133. package/dist/modules/forms/widgets/injection/self-audit-footer/widget.js +38 -0
  1134. package/dist/modules/forms/widgets/injection/self-audit-footer/widget.js.map +7 -0
  1135. package/dist/modules/forms/widgets/injection-table.js +32 -0
  1136. package/dist/modules/forms/widgets/injection-table.js.map +7 -0
  1137. package/dist/modules/forms/workers/pdf-snapshot.js +60 -0
  1138. package/dist/modules/forms/workers/pdf-snapshot.js.map +7 -0
  1139. package/dist/modules/forms/workers/retention-purge.js +112 -0
  1140. package/dist/modules/forms/workers/retention-purge.js.map +7 -0
  1141. package/dist/modules/inbox_ops/api/proposals/[id]/actions/[actionId]/route.js +7 -1
  1142. package/dist/modules/inbox_ops/api/proposals/[id]/actions/[actionId]/route.js.map +2 -2
  1143. package/dist/modules/inbox_ops/data/validators.js +2 -2
  1144. package/dist/modules/inbox_ops/data/validators.js.map +2 -2
  1145. package/dist/modules/inbox_ops/lib/llmProvider.js +5 -1
  1146. package/dist/modules/inbox_ops/lib/llmProvider.js.map +2 -2
  1147. package/dist/modules/inbox_ops/widgets/notifications/ProposalCreatedRenderer.js +2 -2
  1148. package/dist/modules/inbox_ops/widgets/notifications/ProposalCreatedRenderer.js.map +2 -2
  1149. package/dist/modules/integrations/di.js +3 -1
  1150. package/dist/modules/integrations/di.js.map +2 -2
  1151. package/dist/modules/integrations/lib/credentials-service.js +29 -36
  1152. package/dist/modules/integrations/lib/credentials-service.js.map +2 -2
  1153. package/dist/modules/messages/api/[id]/attachments/route.js +7 -3
  1154. package/dist/modules/messages/api/[id]/attachments/route.js.map +2 -2
  1155. package/dist/modules/messages/api/[id]/forward-preview/route.js +4 -3
  1156. package/dist/modules/messages/api/[id]/forward-preview/route.js.map +2 -2
  1157. package/dist/modules/messages/api/[id]/route.js +29 -3
  1158. package/dist/modules/messages/api/[id]/route.js.map +2 -2
  1159. package/dist/modules/messages/api/route.js +91 -2
  1160. package/dist/modules/messages/api/route.js.map +2 -2
  1161. package/dist/modules/messages/commands/messages.js +40 -6
  1162. package/dist/modules/messages/commands/messages.js.map +2 -2
  1163. package/dist/modules/messages/components/ComposeMessagePageClient.js +24 -1
  1164. package/dist/modules/messages/components/ComposeMessagePageClient.js.map +2 -2
  1165. package/dist/modules/messages/data/validators.js +11 -1
  1166. package/dist/modules/messages/data/validators.js.map +2 -2
  1167. package/dist/modules/messages/lib/channelThreadAccess.js +30 -0
  1168. package/dist/modules/messages/lib/channelThreadAccess.js.map +7 -0
  1169. package/dist/modules/messages/lib/composeSenderDelegation.js +87 -0
  1170. package/dist/modules/messages/lib/composeSenderDelegation.js.map +7 -0
  1171. package/dist/modules/messages/lib/composeSenderOptions.js +24 -0
  1172. package/dist/modules/messages/lib/composeSenderOptions.js.map +7 -0
  1173. package/dist/modules/messages/lib/email-sender.js +1 -11
  1174. package/dist/modules/messages/lib/email-sender.js.map +2 -2
  1175. package/dist/modules/messages/lib/forwarding.js +4 -4
  1176. package/dist/modules/messages/lib/forwarding.js.map +2 -2
  1177. package/dist/modules/messages/lib/markdownEmailBody.js +15 -0
  1178. package/dist/modules/messages/lib/markdownEmailBody.js.map +7 -0
  1179. package/dist/modules/messages/lib/messageSourceEntityTypes.js +7 -0
  1180. package/dist/modules/messages/lib/messageSourceEntityTypes.js.map +7 -0
  1181. package/dist/modules/messages/lib/routeHelpers.js +43 -0
  1182. package/dist/modules/messages/lib/routeHelpers.js.map +2 -2
  1183. package/dist/modules/messages/subscribers/message-notification.js +30 -1
  1184. package/dist/modules/messages/subscribers/message-notification.js.map +2 -2
  1185. package/dist/modules/notifications/api/[id]/action/route.js +2 -1
  1186. package/dist/modules/notifications/api/[id]/action/route.js.map +2 -2
  1187. package/dist/modules/notifications/api/openapi.js +2 -1
  1188. package/dist/modules/notifications/api/openapi.js.map +2 -2
  1189. package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js +47 -28
  1190. package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js.map +2 -2
  1191. package/dist/modules/notifications/lib/deliveryConfig.js +27 -2
  1192. package/dist/modules/notifications/lib/deliveryConfig.js.map +2 -2
  1193. package/dist/modules/notifications/lib/notificationMapper.js +3 -1
  1194. package/dist/modules/notifications/lib/notificationMapper.js.map +2 -2
  1195. package/dist/modules/notifications/lib/safeHref.js +4 -0
  1196. package/dist/modules/notifications/lib/safeHref.js.map +2 -2
  1197. package/dist/modules/planner/api/availability-date-specific.js +2 -1
  1198. package/dist/modules/planner/api/availability-date-specific.js.map +2 -2
  1199. package/dist/modules/planner/api/availability-weekly.js +2 -1
  1200. package/dist/modules/planner/api/availability-weekly.js.map +2 -2
  1201. package/dist/modules/progress/api/active/route.js +14 -2
  1202. package/dist/modules/progress/api/active/route.js.map +2 -2
  1203. package/dist/modules/progress/api/jobs/[id]/route.js +38 -22
  1204. package/dist/modules/progress/api/jobs/[id]/route.js.map +2 -2
  1205. package/dist/modules/progress/api/jobs/route.js +20 -6
  1206. package/dist/modules/progress/api/jobs/route.js.map +2 -2
  1207. package/dist/modules/progress/api/requestScope.js +32 -0
  1208. package/dist/modules/progress/api/requestScope.js.map +7 -0
  1209. package/dist/modules/progress/lib/organizationScope.js +10 -0
  1210. package/dist/modules/progress/lib/organizationScope.js.map +7 -0
  1211. package/dist/modules/progress/lib/progressService.js.map +2 -2
  1212. package/dist/modules/progress/lib/progressServiceImpl.js +48 -15
  1213. package/dist/modules/progress/lib/progressServiceImpl.js.map +2 -2
  1214. package/dist/modules/push_notifications/api/custom-send/route.js +4 -1
  1215. package/dist/modules/push_notifications/api/custom-send/route.js.map +2 -2
  1216. package/dist/modules/query_index/api/status.js +5 -3
  1217. package/dist/modules/query_index/api/status.js.map +2 -2
  1218. package/dist/modules/query_index/di.js +2 -1
  1219. package/dist/modules/query_index/di.js.map +2 -2
  1220. package/dist/modules/query_index/lib/engine.js +2 -1
  1221. package/dist/modules/query_index/lib/engine.js.map +2 -2
  1222. package/dist/modules/query_index/lib/request-encryption.js +16 -0
  1223. package/dist/modules/query_index/lib/request-encryption.js.map +7 -0
  1224. package/dist/modules/query_index/lib/search-tokens.js +31 -1
  1225. package/dist/modules/query_index/lib/search-tokens.js.map +2 -2
  1226. package/dist/modules/resources/api/resources/tags/assign/route.js +2 -1
  1227. package/dist/modules/resources/api/resources/tags/assign/route.js.map +2 -2
  1228. package/dist/modules/resources/api/resources/tags/unassign/route.js +2 -1
  1229. package/dist/modules/resources/api/resources/tags/unassign/route.js.map +2 -2
  1230. package/dist/modules/resources/commands/activities.js +2 -2
  1231. package/dist/modules/resources/commands/activities.js.map +2 -2
  1232. package/dist/modules/sales/api/document-history/route.js +5 -1
  1233. package/dist/modules/sales/api/document-history/route.js.map +2 -2
  1234. package/dist/modules/sales/api/document-numbers/route.js +2 -1
  1235. package/dist/modules/sales/api/document-numbers/route.js.map +2 -2
  1236. package/dist/modules/sales/api/quotes/convert/route.js +2 -1
  1237. package/dist/modules/sales/api/quotes/convert/route.js.map +2 -2
  1238. package/dist/modules/sales/api/quotes/send/route.js +2 -1
  1239. package/dist/modules/sales/api/quotes/send/route.js.map +2 -2
  1240. package/dist/modules/sales/api/settings/document-numbers/route.js +7 -1
  1241. package/dist/modules/sales/api/settings/document-numbers/route.js.map +2 -2
  1242. package/dist/modules/sales/api/settings/order-editing/route.js +7 -1
  1243. package/dist/modules/sales/api/settings/order-editing/route.js.map +2 -2
  1244. package/dist/modules/sales/commands/documents.js +354 -138
  1245. package/dist/modules/sales/commands/documents.js.map +3 -3
  1246. package/dist/modules/sales/commands/payments.js +2 -1
  1247. package/dist/modules/sales/commands/payments.js.map +2 -2
  1248. package/dist/modules/sales/commands/settings.js +25 -5
  1249. package/dist/modules/sales/commands/settings.js.map +2 -2
  1250. package/dist/modules/sales/commands/shipments.js +2 -1
  1251. package/dist/modules/sales/commands/shipments.js.map +2 -2
  1252. package/dist/modules/sales/components/DocumentNumberSettings.js +32 -21
  1253. package/dist/modules/sales/components/DocumentNumberSettings.js.map +2 -2
  1254. package/dist/modules/sales/components/documents/ItemsSection.js +49 -11
  1255. package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
  1256. package/dist/modules/sales/components/documents/LineItemDialog.js +159 -81
  1257. package/dist/modules/sales/components/documents/LineItemDialog.js.map +2 -2
  1258. package/dist/modules/sales/components/documents/lineItemUtils.js +7 -0
  1259. package/dist/modules/sales/components/documents/lineItemUtils.js.map +2 -2
  1260. package/dist/modules/sales/lib/lineSnapshots.js +19 -0
  1261. package/dist/modules/sales/lib/lineSnapshots.js.map +2 -2
  1262. package/dist/modules/sales/setup.js +4 -4
  1263. package/dist/modules/sales/setup.js.map +2 -2
  1264. package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js +2 -2
  1265. package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js.map +2 -2
  1266. package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js +2 -2
  1267. package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js.map +2 -2
  1268. package/dist/modules/staff/api/leave-requests/accept/route.js +2 -1
  1269. package/dist/modules/staff/api/leave-requests/accept/route.js.map +2 -2
  1270. package/dist/modules/staff/api/leave-requests/reject/route.js +2 -1
  1271. package/dist/modules/staff/api/leave-requests/reject/route.js.map +2 -2
  1272. package/dist/modules/staff/api/leave-requests.js +2 -1
  1273. package/dist/modules/staff/api/leave-requests.js.map +2 -2
  1274. package/dist/modules/staff/api/team-members/self/route.js +2 -1
  1275. package/dist/modules/staff/api/team-members/self/route.js.map +2 -2
  1276. package/dist/modules/staff/api/team-members/tags/assign/route.js +2 -1
  1277. package/dist/modules/staff/api/team-members/tags/assign/route.js.map +2 -2
  1278. package/dist/modules/staff/api/team-members/tags/unassign/route.js +2 -1
  1279. package/dist/modules/staff/api/team-members/tags/unassign/route.js.map +2 -2
  1280. package/dist/modules/staff/api/timesheets/_shared/withTimesheetInterceptors.js +12 -11
  1281. package/dist/modules/staff/api/timesheets/_shared/withTimesheetInterceptors.js.map +2 -2
  1282. package/dist/modules/staff/api/timesheets/my-projects/[projectId]/route.js +2 -1
  1283. package/dist/modules/staff/api/timesheets/my-projects/[projectId]/route.js.map +2 -2
  1284. package/dist/modules/staff/api/timesheets/my-projects/route.js +2 -1
  1285. package/dist/modules/staff/api/timesheets/my-projects/route.js.map +2 -2
  1286. package/dist/modules/staff/api/timesheets/my-work/route.js +2 -1
  1287. package/dist/modules/staff/api/timesheets/my-work/route.js.map +2 -2
  1288. package/dist/modules/staff/api/timesheets/projects/kpis/route.js +2 -1
  1289. package/dist/modules/staff/api/timesheets/projects/kpis/route.js.map +2 -2
  1290. package/dist/modules/staff/api/timesheets/reports/[id]/close/route.js +2 -1
  1291. package/dist/modules/staff/api/timesheets/reports/[id]/close/route.js.map +2 -2
  1292. package/dist/modules/staff/api/timesheets/reports/[id]/export/route.js +3 -2
  1293. package/dist/modules/staff/api/timesheets/reports/[id]/export/route.js.map +2 -2
  1294. package/dist/modules/staff/api/timesheets/reports/[id]/sheet/route.js +3 -2
  1295. package/dist/modules/staff/api/timesheets/reports/[id]/sheet/route.js.map +2 -2
  1296. package/dist/modules/staff/api/timesheets/reports/[id]/unlock/route.js +3 -2
  1297. package/dist/modules/staff/api/timesheets/reports/[id]/unlock/route.js.map +2 -2
  1298. package/dist/modules/staff/api/timesheets/reports/preview/route.js +2 -1
  1299. package/dist/modules/staff/api/timesheets/reports/preview/route.js.map +2 -2
  1300. package/dist/modules/staff/api/timesheets/reports/shared.js +2 -1
  1301. package/dist/modules/staff/api/timesheets/reports/shared.js.map +2 -2
  1302. package/dist/modules/staff/api/timesheets/settings/reapply-rounding/route.js +2 -1
  1303. package/dist/modules/staff/api/timesheets/settings/reapply-rounding/route.js.map +2 -2
  1304. package/dist/modules/staff/api/timesheets/tags/entry-assignments/route.js +2 -1
  1305. package/dist/modules/staff/api/timesheets/tags/entry-assignments/route.js.map +2 -2
  1306. package/dist/modules/staff/api/timesheets/tags/task-assignments/route.js +2 -1
  1307. package/dist/modules/staff/api/timesheets/tags/task-assignments/route.js.map +2 -2
  1308. package/dist/modules/staff/api/timesheets/tasks/[id]/comments/route.js +2 -1
  1309. package/dist/modules/staff/api/timesheets/tasks/[id]/comments/route.js.map +2 -2
  1310. package/dist/modules/staff/api/timesheets/tasks/[id]/status/route.js +2 -1
  1311. package/dist/modules/staff/api/timesheets/tasks/[id]/status/route.js.map +2 -2
  1312. package/dist/modules/staff/api/timesheets/time-entries/[id]/duplicate/route.js +3 -2
  1313. package/dist/modules/staff/api/timesheets/time-entries/[id]/duplicate/route.js.map +2 -2
  1314. package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/[segmentId]/route.js +2 -1
  1315. package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/[segmentId]/route.js.map +2 -2
  1316. package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/route.js +2 -1
  1317. package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/route.js.map +2 -2
  1318. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.js +2 -1
  1319. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.js.map +2 -2
  1320. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.js +2 -1
  1321. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.js.map +2 -2
  1322. package/dist/modules/staff/api/timesheets/time-entries/bulk/route.js +2 -1
  1323. package/dist/modules/staff/api/timesheets/time-entries/bulk/route.js.map +2 -2
  1324. package/dist/modules/staff/api/timesheets/time-entries/copy-day/route.js +3 -2
  1325. package/dist/modules/staff/api/timesheets/time-entries/copy-day/route.js.map +2 -2
  1326. package/dist/modules/staff/api/timesheets/time-entries/overlaps/route.js +2 -1
  1327. package/dist/modules/staff/api/timesheets/time-entries/overlaps/route.js.map +2 -2
  1328. package/dist/modules/staff/api/timesheets/time-entries/start-timer/route.js +3 -2
  1329. package/dist/modules/staff/api/timesheets/time-entries/start-timer/route.js.map +2 -2
  1330. package/dist/modules/staff/api/timesheets/time-projects/[id]/change-currency/route.js +3 -2
  1331. package/dist/modules/staff/api/timesheets/time-projects/[id]/change-currency/route.js.map +2 -2
  1332. package/dist/modules/staff/api/timesheets/time-projects/route.js +2 -1
  1333. package/dist/modules/staff/api/timesheets/time-projects/route.js.map +2 -2
  1334. package/dist/modules/staff/commands/activities.js +2 -2
  1335. package/dist/modules/staff/commands/activities.js.map +2 -2
  1336. package/dist/modules/staff/commands/timesheets-entries.js.map +2 -2
  1337. package/dist/modules/staff/commands/timesheets-reports.js +55 -14
  1338. package/dist/modules/staff/commands/timesheets-reports.js.map +2 -2
  1339. package/dist/modules/staff/lib/timesheets-reports/buildReportSheet.js +2 -1
  1340. package/dist/modules/staff/lib/timesheets-reports/buildReportSheet.js.map +2 -2
  1341. package/dist/modules/staff/lib/timesheets-reports/loadReportData.js +32 -3
  1342. package/dist/modules/staff/lib/timesheets-reports/loadReportData.js.map +2 -2
  1343. package/dist/modules/staff/lib/timesheets-reports/reportPeriod.js +16 -0
  1344. package/dist/modules/staff/lib/timesheets-reports/reportPeriod.js.map +7 -0
  1345. package/dist/modules/staff/lib/timesheets-ui/CalendarPicker.js +15 -10
  1346. package/dist/modules/staff/lib/timesheets-ui/CalendarPicker.js.map +2 -2
  1347. package/dist/modules/sync_excel/api/import/route.js +35 -12
  1348. package/dist/modules/sync_excel/api/import/route.js.map +2 -2
  1349. package/dist/modules/sync_excel/api/upload/route.js +29 -4
  1350. package/dist/modules/sync_excel/api/upload/route.js.map +2 -2
  1351. package/dist/modules/translations/api/context.js +2 -1
  1352. package/dist/modules/translations/api/context.js.map +2 -2
  1353. package/dist/modules/warranty_claims/api/ai/assess/route.js +2 -1
  1354. package/dist/modules/warranty_claims/api/ai/assess/route.js.map +2 -2
  1355. package/dist/modules/warranty_claims/api/ai/draft-reply/route.js +2 -1
  1356. package/dist/modules/warranty_claims/api/ai/draft-reply/route.js.map +2 -2
  1357. package/dist/modules/warranty_claims/api/ai/suggest/route.js +2 -1
  1358. package/dist/modules/warranty_claims/api/ai/suggest/route.js.map +2 -2
  1359. package/dist/modules/warranty_claims/api/assign/route.js +2 -1
  1360. package/dist/modules/warranty_claims/api/assign/route.js.map +2 -2
  1361. package/dist/modules/warranty_claims/api/credit-memo/route.js +2 -1
  1362. package/dist/modules/warranty_claims/api/credit-memo/route.js.map +2 -2
  1363. package/dist/modules/warranty_claims/api/entitlement/route.js +2 -1
  1364. package/dist/modules/warranty_claims/api/entitlement/route.js.map +2 -2
  1365. package/dist/modules/warranty_claims/api/events/route.js +2 -1
  1366. package/dist/modules/warranty_claims/api/events/route.js.map +2 -2
  1367. package/dist/modules/warranty_claims/api/external/claims/route.js +2 -1
  1368. package/dist/modules/warranty_claims/api/external/claims/route.js.map +2 -2
  1369. package/dist/modules/warranty_claims/api/receiving/route.js +2 -1
  1370. package/dist/modules/warranty_claims/api/receiving/route.js.map +2 -2
  1371. package/dist/modules/warranty_claims/api/replacement-order/route.js +2 -1
  1372. package/dist/modules/warranty_claims/api/replacement-order/route.js.map +2 -2
  1373. package/dist/modules/warranty_claims/api/return-label/route.js +2 -1
  1374. package/dist/modules/warranty_claims/api/return-label/route.js.map +2 -2
  1375. package/dist/modules/warranty_claims/api/risk/route.js +2 -1
  1376. package/dist/modules/warranty_claims/api/risk/route.js.map +2 -2
  1377. package/dist/modules/warranty_claims/api/sales-return/route.js +2 -1
  1378. package/dist/modules/warranty_claims/api/sales-return/route.js.map +2 -2
  1379. package/dist/modules/warranty_claims/api/settings-general/route.js +2 -1
  1380. package/dist/modules/warranty_claims/api/settings-general/route.js.map +2 -2
  1381. package/dist/modules/warranty_claims/api/stats/route.js +9 -5
  1382. package/dist/modules/warranty_claims/api/stats/route.js.map +2 -2
  1383. package/dist/modules/warranty_claims/api/submit/route.js +2 -1
  1384. package/dist/modules/warranty_claims/api/submit/route.js.map +2 -2
  1385. package/dist/modules/warranty_claims/api/transition/route.js +2 -1
  1386. package/dist/modules/warranty_claims/api/transition/route.js.map +2 -2
  1387. package/dist/modules/warranty_claims/api/vendor-recovery/route.js +2 -1
  1388. package/dist/modules/warranty_claims/api/vendor-recovery/route.js.map +2 -2
  1389. package/dist/modules/warranty_claims/api/vendor-recovery-suggestions/route.js +2 -1
  1390. package/dist/modules/warranty_claims/api/vendor-recovery-suggestions/route.js.map +2 -2
  1391. package/dist/modules/warranty_claims/widgets/notifications/WarrantyClaimNotificationRenderer.js +1 -1
  1392. package/dist/modules/warranty_claims/widgets/notifications/WarrantyClaimNotificationRenderer.js.map +2 -2
  1393. package/dist/modules/wms/api/dashboard/operational/route.js +2 -1
  1394. package/dist/modules/wms/api/dashboard/operational/route.js.map +2 -2
  1395. package/dist/modules/wms/api/inventory/cycle-count/route.js +1 -0
  1396. package/dist/modules/wms/api/inventory/cycle-count/route.js.map +2 -2
  1397. package/dist/modules/wms/api/inventory/helpers.js +2 -1
  1398. package/dist/modules/wms/api/inventory/helpers.js.map +2 -2
  1399. package/dist/modules/wms/api/inventory/import/helpers.js +2 -1
  1400. package/dist/modules/wms/api/inventory/import/helpers.js.map +2 -2
  1401. package/dist/modules/wms/api/sales-orders/[salesOrderId]/warehouse-assignment/route.js +2 -1
  1402. package/dist/modules/wms/api/sales-orders/[salesOrderId]/warehouse-assignment/route.js.map +2 -2
  1403. package/dist/modules/wms/commands/inventory-actions.js +39 -1
  1404. package/dist/modules/wms/commands/inventory-actions.js.map +2 -2
  1405. package/dist/modules/wms/components/backend/CycleCountWizardDialog.js +14 -1
  1406. package/dist/modules/wms/components/backend/CycleCountWizardDialog.js.map +2 -2
  1407. package/dist/modules/wms/di.js +5 -0
  1408. package/dist/modules/wms/di.js.map +2 -2
  1409. package/dist/modules/wms/lib/availabilityCache.js +86 -0
  1410. package/dist/modules/wms/lib/availabilityCache.js.map +7 -0
  1411. package/dist/modules/wms/lib/availabilityCalculation.js +212 -0
  1412. package/dist/modules/wms/lib/availabilityCalculation.js.map +7 -0
  1413. package/dist/modules/wms/lib/availabilityProvider.js +24 -0
  1414. package/dist/modules/wms/lib/availabilityProvider.js.map +7 -0
  1415. package/dist/modules/wms/lib/loadOperationalDashboard.js +42 -5
  1416. package/dist/modules/wms/lib/loadOperationalDashboard.js.map +2 -2
  1417. package/dist/modules/wms/lib/lowStockBalanceFilter.js +23 -10
  1418. package/dist/modules/wms/lib/lowStockBalanceFilter.js.map +2 -2
  1419. package/dist/modules/wms/lib/sqlInClause.js +9 -0
  1420. package/dist/modules/wms/lib/sqlInClause.js.map +7 -0
  1421. package/dist/modules/wms/lib/tryResolve.js +11 -0
  1422. package/dist/modules/wms/lib/tryResolve.js.map +7 -0
  1423. package/dist/modules/wms/subscribers/invalidate-availability-cache-policy.js +14 -0
  1424. package/dist/modules/wms/subscribers/invalidate-availability-cache-policy.js.map +7 -0
  1425. package/dist/modules/wms/subscribers/invalidate-availability-cache-profile.js +14 -0
  1426. package/dist/modules/wms/subscribers/invalidate-availability-cache-profile.js.map +7 -0
  1427. package/dist/modules/wms/subscribers/invalidate-availability-cache.js +16 -0
  1428. package/dist/modules/wms/subscribers/invalidate-availability-cache.js.map +7 -0
  1429. package/dist/modules/wms/widgets/notifications/WmsLowStockRenderer.js +2 -2
  1430. package/dist/modules/wms/widgets/notifications/WmsLowStockRenderer.js.map +2 -2
  1431. package/dist/modules/wms/widgets/notifications/WmsReservationShortfallRenderer.js +4 -3
  1432. package/dist/modules/wms/widgets/notifications/WmsReservationShortfallRenderer.js.map +2 -2
  1433. package/dist/modules/workflows/api/commands/route.js +4 -1
  1434. package/dist/modules/workflows/api/commands/route.js.map +2 -2
  1435. package/dist/modules/workflows/api/definitions/[id]/callers/route.js +4 -1
  1436. package/dist/modules/workflows/api/definitions/[id]/callers/route.js.map +2 -2
  1437. package/dist/modules/workflows/api/definitions/[id]/context-schema/route.js +4 -2
  1438. package/dist/modules/workflows/api/definitions/[id]/context-schema/route.js.map +2 -2
  1439. package/dist/modules/workflows/api/definitions/[id]/customize/route.js +4 -1
  1440. package/dist/modules/workflows/api/definitions/[id]/customize/route.js.map +2 -2
  1441. package/dist/modules/workflows/api/definitions/[id]/draft/route.js +6 -1
  1442. package/dist/modules/workflows/api/definitions/[id]/draft/route.js.map +2 -2
  1443. package/dist/modules/workflows/api/definitions/[id]/publish/route.js +6 -1
  1444. package/dist/modules/workflows/api/definitions/[id]/publish/route.js.map +2 -2
  1445. package/dist/modules/workflows/api/definitions/[id]/reset-to-code/route.js +4 -1
  1446. package/dist/modules/workflows/api/definitions/[id]/reset-to-code/route.js.map +2 -2
  1447. package/dist/modules/workflows/api/definitions/[id]/route.js +5 -3
  1448. package/dist/modules/workflows/api/definitions/[id]/route.js.map +2 -2
  1449. package/dist/modules/workflows/api/definitions/[id]/test-step/route.js +4 -2
  1450. package/dist/modules/workflows/api/definitions/[id]/test-step/route.js.map +2 -2
  1451. package/dist/modules/workflows/api/definitions/generate/route.js +4 -1
  1452. package/dist/modules/workflows/api/definitions/generate/route.js.map +2 -2
  1453. package/dist/modules/workflows/api/definitions/route.js +4 -2
  1454. package/dist/modules/workflows/api/definitions/route.js.map +2 -2
  1455. package/dist/modules/workflows/api/endpoints/route.js +4 -1
  1456. package/dist/modules/workflows/api/endpoints/route.js.map +2 -2
  1457. package/dist/modules/workflows/api/functions/route.js +4 -1
  1458. package/dist/modules/workflows/api/functions/route.js.map +2 -2
  1459. package/dist/modules/workflows/api/grantable-features/route.js +2 -1
  1460. package/dist/modules/workflows/api/grantable-features/route.js.map +2 -2
  1461. package/dist/modules/workflows/api/instances/[id]/advance/route.js +4 -1
  1462. package/dist/modules/workflows/api/instances/[id]/advance/route.js.map +2 -2
  1463. package/dist/modules/workflows/api/instances/[id]/cancel/route.js +4 -1
  1464. package/dist/modules/workflows/api/instances/[id]/cancel/route.js.map +2 -2
  1465. package/dist/modules/workflows/api/instances/[id]/context/route.js +2 -1
  1466. package/dist/modules/workflows/api/instances/[id]/context/route.js.map +2 -2
  1467. package/dist/modules/workflows/api/instances/[id]/rerun-step/route.js +4 -1
  1468. package/dist/modules/workflows/api/instances/[id]/rerun-step/route.js.map +2 -2
  1469. package/dist/modules/workflows/api/instances/[id]/retry/route.js +4 -1
  1470. package/dist/modules/workflows/api/instances/[id]/retry/route.js.map +2 -2
  1471. package/dist/modules/workflows/api/instances/[id]/signal/route.js +4 -1
  1472. package/dist/modules/workflows/api/instances/[id]/signal/route.js.map +2 -2
  1473. package/dist/modules/workflows/api/instances/[id]/step-through/route.js +4 -2
  1474. package/dist/modules/workflows/api/instances/[id]/step-through/route.js.map +2 -2
  1475. package/dist/modules/workflows/api/instances/route.js +4 -2
  1476. package/dist/modules/workflows/api/instances/route.js.map +2 -2
  1477. package/dist/modules/workflows/api/instances/validate-start/route.js +4 -1
  1478. package/dist/modules/workflows/api/instances/validate-start/route.js.map +2 -2
  1479. package/dist/modules/workflows/api/rule-usage/route.js +4 -1
  1480. package/dist/modules/workflows/api/rule-usage/route.js.map +2 -2
  1481. package/dist/modules/workflows/api/signals/route.js +4 -1
  1482. package/dist/modules/workflows/api/signals/route.js.map +2 -2
  1483. package/dist/modules/workflows/api/tasks/[id]/claim/route.js +4 -1
  1484. package/dist/modules/workflows/api/tasks/[id]/claim/route.js.map +2 -2
  1485. package/dist/modules/workflows/api/tasks/[id]/complete/route.js +4 -1
  1486. package/dist/modules/workflows/api/tasks/[id]/complete/route.js.map +2 -2
  1487. package/dist/modules/workflows/api/tasks/[id]/reassign/route.js +2 -1
  1488. package/dist/modules/workflows/api/tasks/[id]/reassign/route.js.map +2 -2
  1489. package/dist/modules/workflows/api/tasks/[id]/unclaim/route.js +4 -1
  1490. package/dist/modules/workflows/api/tasks/[id]/unclaim/route.js.map +2 -2
  1491. package/dist/modules/workflows/api/templates/route.js +4 -1
  1492. package/dist/modules/workflows/api/templates/route.js.map +2 -2
  1493. package/dist/modules/workflows/api/work-inbox/next/route.js +4 -1
  1494. package/dist/modules/workflows/api/work-inbox/next/route.js.map +2 -2
  1495. package/dist/modules/workflows/lib/activity-executor.js +87 -20
  1496. package/dist/modules/workflows/lib/activity-executor.js.map +2 -2
  1497. package/dist/modules/workflows/lib/activity-types.js +4 -4
  1498. package/dist/modules/workflows/lib/activity-types.js.map +2 -2
  1499. package/dist/modules/workflows/lib/activity-worker-handler.js +16 -11
  1500. package/dist/modules/workflows/lib/activity-worker-handler.js.map +2 -2
  1501. package/dist/modules/workflows/lib/event-trigger-service.js +8 -1
  1502. package/dist/modules/workflows/lib/event-trigger-service.js.map +2 -2
  1503. package/dist/modules/workflows/lib/step-handler.js +4 -4
  1504. package/dist/modules/workflows/lib/step-handler.js.map +2 -2
  1505. package/dist/test-utils/transactionalEntityManagerDouble.js +37 -0
  1506. package/dist/test-utils/transactionalEntityManagerDouble.js.map +7 -0
  1507. package/generated/entities/availability_policy/index.ts +19 -0
  1508. package/generated/entities/communication_channel/index.ts +1 -0
  1509. package/generated/entities/customer_email_conversation_share/index.ts +9 -0
  1510. package/generated/entities/customer_group/index.ts +15 -0
  1511. package/generated/entities/customer_group_membership/index.ts +13 -0
  1512. package/generated/entities/customer_group_terms/index.ts +15 -0
  1513. package/generated/entities/customer_interaction/index.ts +1 -0
  1514. package/generated/entities/form/index.ts +16 -0
  1515. package/generated/entities/form_access_audit/index.ts +9 -0
  1516. package/generated/entities/form_attachment/index.ts +13 -0
  1517. package/generated/entities/form_consent_record/index.ts +17 -0
  1518. package/generated/entities/form_distribution/index.ts +22 -0
  1519. package/generated/entities/form_invitation/index.ts +23 -0
  1520. package/generated/entities/form_submission/index.ts +18 -0
  1521. package/generated/entities/form_submission_actor/index.ts +10 -0
  1522. package/generated/entities/form_submission_revision/index.ts +13 -0
  1523. package/generated/entities/form_version/index.ts +17 -0
  1524. package/generated/entities/forms_encryption_key/index.ts +6 -0
  1525. package/generated/entities.ids.generated.ts +27 -2
  1526. package/generated/entity-fields-registry.ts +269 -0
  1527. package/package.json +18 -7
  1528. package/src/helpers/integration/communicationChannelsFixtures.ts +43 -0
  1529. package/src/helpers/integration/customerGroupsFixtures.ts +171 -0
  1530. package/src/helpers/integration/formsFixtures.ts +757 -0
  1531. package/src/modules/api_docs/api/get/version.ts +28 -11
  1532. package/src/modules/api_keys/api/keys/route.ts +89 -199
  1533. package/src/modules/api_keys/backend/api-keys/create/page.tsx +2 -2
  1534. package/src/modules/api_keys/commands/keys.ts +172 -0
  1535. package/src/modules/api_keys/i18n/de.json +1 -0
  1536. package/src/modules/api_keys/i18n/en.json +1 -0
  1537. package/src/modules/api_keys/i18n/es.json +1 -0
  1538. package/src/modules/api_keys/i18n/ko.json +1 -0
  1539. package/src/modules/api_keys/i18n/pl.json +1 -0
  1540. package/src/modules/api_keys/services/apiKeyService.ts +82 -49
  1541. package/src/modules/attachments/api/file/[id]/route.ts +9 -4
  1542. package/src/modules/attachments/api/image/[id]/[[...slug]]/route.ts +6 -4
  1543. package/src/modules/attachments/api/route.ts +10 -4
  1544. package/src/modules/attachments/components/AttachmentLibrary.tsx +16 -5
  1545. package/src/modules/attachments/lib/access.ts +1 -3
  1546. package/src/modules/attachments/lib/requestScope.ts +35 -3
  1547. package/src/modules/audit_logs/api/audit-logs/actions/export/route.ts +6 -1
  1548. package/src/modules/audit_logs/api/audit-logs/actions/redo/route.ts +41 -6
  1549. package/src/modules/audit_logs/api/audit-logs/actions/route.ts +6 -1
  1550. package/src/modules/audit_logs/api/audit-logs/actions/undo/route.ts +39 -4
  1551. package/src/modules/audit_logs/data/validators.ts +1 -0
  1552. package/src/modules/audit_logs/lib/actorSubject.ts +82 -0
  1553. package/src/modules/audit_logs/lib/replayAuthorization.ts +61 -0
  1554. package/src/modules/audit_logs/services/actionLogService.ts +191 -47
  1555. package/src/modules/auth/api/features.ts +1 -1
  1556. package/src/modules/auth/cli.ts +31 -17
  1557. package/src/modules/auth/commands/acl.ts +26 -36
  1558. package/src/modules/auth/commands/interceptors.ts +23 -0
  1559. package/src/modules/auth/commands/roles.ts +475 -148
  1560. package/src/modules/auth/commands/users.ts +693 -81
  1561. package/src/modules/auth/i18n/de.json +22 -0
  1562. package/src/modules/auth/i18n/en.json +22 -0
  1563. package/src/modules/auth/i18n/es.json +22 -0
  1564. package/src/modules/auth/i18n/ko.json +22 -0
  1565. package/src/modules/auth/i18n/pl.json +22 -0
  1566. package/src/modules/auth/lib/authorizationStateLocks.ts +340 -0
  1567. package/src/modules/auth/lib/commandReplay.ts +194 -0
  1568. package/src/modules/auth/lib/executionPrincipal.ts +36 -28
  1569. package/src/modules/auth/lib/grantChecks.ts +10 -2
  1570. package/src/modules/auth/lib/setup-app.ts +97 -50
  1571. package/src/modules/auth/lib/tokenHash.ts +16 -1
  1572. package/src/modules/auth/services/rbacService.ts +578 -6
  1573. package/src/modules/availability/acl.ts +12 -0
  1574. package/src/modules/availability/api/check/route.ts +136 -0
  1575. package/src/modules/availability/api/openapi.ts +28 -0
  1576. package/src/modules/availability/api/policies/resolve-preview/route.ts +83 -0
  1577. package/src/modules/availability/api/policies/route.ts +244 -0
  1578. package/src/modules/availability/backend/availability/check/page.meta.ts +12 -0
  1579. package/src/modules/availability/backend/availability/check/page.tsx +223 -0
  1580. package/src/modules/availability/backend/availability/policies/ResolutionPreviewPanel.tsx +112 -0
  1581. package/src/modules/availability/backend/availability/policies/ScopeFields.tsx +55 -0
  1582. package/src/modules/availability/backend/availability/policies/StockManagedField.tsx +37 -0
  1583. package/src/modules/availability/backend/availability/policies/[id]/page.meta.ts +8 -0
  1584. package/src/modules/availability/backend/availability/policies/[id]/page.tsx +202 -0
  1585. package/src/modules/availability/backend/availability/policies/create/page.meta.ts +8 -0
  1586. package/src/modules/availability/backend/availability/policies/create/page.tsx +131 -0
  1587. package/src/modules/availability/backend/availability/policies/formGroups.ts +83 -0
  1588. package/src/modules/availability/backend/availability/policies/page.meta.ts +12 -0
  1589. package/src/modules/availability/backend/availability/policies/page.tsx +232 -0
  1590. package/src/modules/availability/backend/availability/policies/policyPayload.ts +29 -0
  1591. package/src/modules/availability/commands/policies.ts +430 -0
  1592. package/src/modules/availability/commands/scope.ts +26 -0
  1593. package/src/modules/availability/data/entities.ts +93 -0
  1594. package/src/modules/availability/data/validators.ts +87 -0
  1595. package/src/modules/availability/di.ts +68 -0
  1596. package/src/modules/availability/events.ts +17 -0
  1597. package/src/modules/availability/i18n/de.json +92 -0
  1598. package/src/modules/availability/i18n/en.json +92 -0
  1599. package/src/modules/availability/i18n/es.json +92 -0
  1600. package/src/modules/availability/i18n/ko.json +92 -0
  1601. package/src/modules/availability/i18n/pl.json +92 -0
  1602. package/src/modules/availability/index.ts +13 -0
  1603. package/src/modules/availability/lib/catalogTarget.ts +72 -0
  1604. package/src/modules/availability/lib/organizationScope.ts +18 -0
  1605. package/src/modules/availability/lib/policyResolution.ts +289 -0
  1606. package/src/modules/availability/lib/tryResolve.ts +8 -0
  1607. package/src/modules/availability/migrations/.snapshot-open-mercato.json +375 -0
  1608. package/src/modules/availability/migrations/Migration20260922095844_availability.ts +13 -0
  1609. package/src/modules/availability/migrations/Migration20260930120000_availability.ts +22 -0
  1610. package/src/modules/availability/setup.ts +10 -0
  1611. package/src/modules/catalog/api/categories/bulk-create/route.ts +119 -0
  1612. package/src/modules/catalog/api/categories/route.ts +70 -8
  1613. package/src/modules/catalog/api/products/bulk-create/route.ts +119 -0
  1614. package/src/modules/catalog/api/products/route.ts +55 -24
  1615. package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +8 -16
  1616. package/src/modules/catalog/backend/catalog/products/create/page.tsx +16 -10
  1617. package/src/modules/catalog/commands/categories.ts +1 -0
  1618. package/src/modules/catalog/commands/productDeleteChildren.ts +557 -0
  1619. package/src/modules/catalog/commands/products.ts +69 -24
  1620. package/src/modules/catalog/components/PriceKindSettings.tsx +6 -20
  1621. package/src/modules/catalog/components/products/ProductUomSection.tsx +26 -37
  1622. package/src/modules/catalog/components/products/productForm.ts +6 -4
  1623. package/src/modules/catalog/data/validators.ts +22 -0
  1624. package/src/modules/catalog/di.ts +2 -1
  1625. package/src/modules/catalog/events.ts +9 -3
  1626. package/src/modules/catalog/i18n/de.json +40 -0
  1627. package/src/modules/catalog/i18n/en.json +40 -0
  1628. package/src/modules/catalog/i18n/es.json +40 -0
  1629. package/src/modules/catalog/i18n/ko.json +40 -0
  1630. package/src/modules/catalog/i18n/pl.json +40 -0
  1631. package/src/modules/catalog/lib/bulkCreateCategories.ts +349 -0
  1632. package/src/modules/catalog/lib/bulkCreateCheckpoint.ts +176 -0
  1633. package/src/modules/catalog/lib/bulkCreateMutationGuards.ts +62 -0
  1634. package/src/modules/catalog/lib/bulkCreateProducts.ts +340 -0
  1635. package/src/modules/catalog/lib/bulkDelete.ts +10 -14
  1636. package/src/modules/catalog/lib/catalogQueue.ts +14 -0
  1637. package/src/modules/catalog/lib/currencyOptions.ts +28 -0
  1638. package/src/modules/catalog/lib/productSearch.ts +16 -0
  1639. package/src/modules/catalog/lib/seeds.ts +2 -43
  1640. package/src/modules/catalog/lib/unitLabels.ts +52 -0
  1641. package/src/modules/catalog/migrations/Migration20260914120000.ts +51 -0
  1642. package/src/modules/catalog/migrations/Migration20260914120100.ts +50 -0
  1643. package/src/modules/catalog/workers/catalog-category-bulk-create.ts +48 -0
  1644. package/src/modules/catalog/workers/catalog-product-bulk-create.ts +48 -0
  1645. package/src/modules/communication_channels/acl.ts +8 -0
  1646. package/src/modules/communication_channels/api/get/me/channels/route.ts +4 -0
  1647. package/src/modules/communication_channels/api/get/oauth/[provider]/callback/route.ts +23 -0
  1648. package/src/modules/communication_channels/api/post/channels/[id]/import-history/route.ts +3 -4
  1649. package/src/modules/communication_channels/api/post/channels/[id]/test-send/route.ts +9 -1
  1650. package/src/modules/communication_channels/api/post/channels/connect/credentials/route.ts +4 -6
  1651. package/src/modules/communication_channels/api/post/channels/connect/tenant-credentials/route.ts +4 -6
  1652. package/src/modules/communication_channels/api/post/test-seed/route.ts +109 -24
  1653. package/src/modules/communication_channels/api/put/channels/[id]/visibility/route.ts +165 -0
  1654. package/src/modules/communication_channels/backend/profile/communication-channels/page.tsx +247 -129
  1655. package/src/modules/communication_channels/commands/ingest-inbound-message.ts +2 -1
  1656. package/src/modules/communication_channels/commands/set-channel-visibility.ts +138 -0
  1657. package/src/modules/communication_channels/data/enrichers.ts +42 -19
  1658. package/src/modules/communication_channels/data/entities.ts +21 -0
  1659. package/src/modules/communication_channels/di.ts +9 -0
  1660. package/src/modules/communication_channels/events.ts +7 -0
  1661. package/src/modules/communication_channels/i18n/de.json +16 -3
  1662. package/src/modules/communication_channels/i18n/en.json +16 -3
  1663. package/src/modules/communication_channels/i18n/es.json +16 -3
  1664. package/src/modules/communication_channels/i18n/ko.json +16 -3
  1665. package/src/modules/communication_channels/i18n/pl.json +16 -3
  1666. package/src/modules/communication_channels/index.ts +1 -1
  1667. package/src/modules/communication_channels/lib/access-control.ts +4 -1
  1668. package/src/modules/communication_channels/lib/adapter.ts +16 -6
  1669. package/src/modules/communication_channels/lib/channel-thread-access.ts +133 -0
  1670. package/src/modules/communication_channels/lib/credential-refresh.ts +27 -5
  1671. package/src/modules/communication_channels/lib/inbound-message-origin.ts +62 -0
  1672. package/src/modules/communication_channels/lib/oauth-state.ts +96 -1
  1673. package/src/modules/communication_channels/lib/outbound-delivery-intent.ts +57 -0
  1674. package/src/modules/communication_channels/lib/send-as-user.ts +2 -2
  1675. package/src/modules/communication_channels/migrations/.snapshot-open-mercato.json +18 -1
  1676. package/src/modules/communication_channels/migrations/Migration20260825141000_communication_channels.ts +22 -0
  1677. package/src/modules/communication_channels/setup.ts +4 -0
  1678. package/src/modules/communication_channels/subscribers/outbound-bridge.ts +34 -9
  1679. package/src/modules/communication_channels/workers/gmail-history-sync.ts +1 -1
  1680. package/src/modules/communication_channels/workers/poll-channel.ts +1 -1
  1681. package/src/modules/communication_channels/workers/reaction-processor.ts +2 -2
  1682. package/src/modules/configs/api/upgrade-actions/route.ts +2 -1
  1683. package/src/modules/configs/cli.ts +2 -2
  1684. package/src/modules/configs/i18n/de.json +2 -0
  1685. package/src/modules/configs/i18n/en.json +2 -0
  1686. package/src/modules/configs/i18n/es.json +2 -0
  1687. package/src/modules/configs/i18n/ko.json +2 -0
  1688. package/src/modules/configs/i18n/pl.json +2 -0
  1689. package/src/modules/configs/lib/upgrade-actions.ts +29 -6
  1690. package/src/modules/configs/services/upgradeActionsService.ts +45 -30
  1691. package/src/modules/currencies/api/currencies/route.ts +11 -5
  1692. package/src/modules/currencies/api/exchange-rates/route.ts +11 -5
  1693. package/src/modules/customer_groups/acl.ts +10 -0
  1694. package/src/modules/customer_groups/api/customer-groups/[id]/terms/route.ts +355 -0
  1695. package/src/modules/customer_groups/api/customer-groups/crud.ts +627 -0
  1696. package/src/modules/customer_groups/api/customer-groups/explain-terms/route.ts +195 -0
  1697. package/src/modules/customer_groups/api/customer-groups/memberships/crud.ts +525 -0
  1698. package/src/modules/customer_groups/api/customer-groups/memberships/route.ts +65 -0
  1699. package/src/modules/customer_groups/api/customer-groups/reconcile/adopt/route.ts +150 -0
  1700. package/src/modules/customer_groups/api/customer-groups/reconcile/route.ts +90 -0
  1701. package/src/modules/customer_groups/api/customer-groups/reorder/route.ts +147 -0
  1702. package/src/modules/customer_groups/api/customer-groups/route.ts +65 -0
  1703. package/src/modules/customer_groups/api/openapi.ts +28 -0
  1704. package/src/modules/customer_groups/backend/customer-groups/[id]/edit/page.meta.ts +12 -0
  1705. package/src/modules/customer_groups/backend/customer-groups/[id]/edit/page.tsx +392 -0
  1706. package/src/modules/customer_groups/backend/customer-groups/create/page.meta.ts +25 -0
  1707. package/src/modules/customer_groups/backend/customer-groups/create/page.tsx +279 -0
  1708. package/src/modules/customer_groups/backend/customer-groups/orphans/page.meta.ts +12 -0
  1709. package/src/modules/customer_groups/backend/customer-groups/orphans/page.tsx +216 -0
  1710. package/src/modules/customer_groups/backend/customer-groups/page.meta.ts +11 -0
  1711. package/src/modules/customer_groups/backend/customer-groups/page.tsx +478 -0
  1712. package/src/modules/customer_groups/cli.ts +87 -0
  1713. package/src/modules/customer_groups/commands/reorderGroups.ts +163 -0
  1714. package/src/modules/customer_groups/components/CustomerGroupDefaultField.tsx +55 -0
  1715. package/src/modules/customer_groups/components/CustomerGroupParentField.tsx +194 -0
  1716. package/src/modules/customer_groups/components/CustomerGroupTermsPriceKindField.tsx +111 -0
  1717. package/src/modules/customer_groups/components/CustomerGroupTermsSection.tsx +273 -0
  1718. package/src/modules/customer_groups/components/GroupPickerField.tsx +142 -0
  1719. package/src/modules/customer_groups/components/OrphanBanner.tsx +92 -0
  1720. package/src/modules/customer_groups/components/customerGroupTree.ts +84 -0
  1721. package/src/modules/customer_groups/data/entities.ts +244 -0
  1722. package/src/modules/customer_groups/data/validators.ts +232 -0
  1723. package/src/modules/customer_groups/di.ts +25 -0
  1724. package/src/modules/customer_groups/events.ts +22 -0
  1725. package/src/modules/customer_groups/i18n/de.json +199 -0
  1726. package/src/modules/customer_groups/i18n/en.json +199 -0
  1727. package/src/modules/customer_groups/i18n/es.json +199 -0
  1728. package/src/modules/customer_groups/i18n/ko.json +199 -0
  1729. package/src/modules/customer_groups/i18n/pl.json +199 -0
  1730. package/src/modules/customer_groups/index.ts +13 -0
  1731. package/src/modules/customer_groups/lib/createConflictRecheck.ts +39 -0
  1732. package/src/modules/customer_groups/lib/customerScope.ts +145 -0
  1733. package/src/modules/customer_groups/lib/groupEvents.ts +50 -0
  1734. package/src/modules/customer_groups/lib/priceKindScope.ts +22 -0
  1735. package/src/modules/customer_groups/lib/reconcile.ts +299 -0
  1736. package/src/modules/customer_groups/migrations/.snapshot-open-mercato.json +905 -0
  1737. package/src/modules/customer_groups/migrations/Migration20260922095316_customer_groups.ts +26 -0
  1738. package/src/modules/customer_groups/migrations/Migration20260922103033_customer_groups.ts +22 -0
  1739. package/src/modules/customer_groups/migrations/Migration20260922105444_customer_groups.ts +17 -0
  1740. package/src/modules/customer_groups/migrations/Migration20260923193330_customer_groups.ts +20 -0
  1741. package/src/modules/customer_groups/migrations/Migration20260929083000_customer_groups.ts +21 -0
  1742. package/src/modules/customer_groups/services/customerGroupsService.ts +358 -0
  1743. package/src/modules/customer_groups/setup.ts +11 -0
  1744. package/src/modules/customer_groups/widgets/injection/group-picker-field/widget.ts +41 -0
  1745. package/src/modules/customer_groups/widgets/injection/person-groups-explain-terms.tsx +227 -0
  1746. package/src/modules/customer_groups/widgets/injection/person-groups-tab/widget.ts +21 -0
  1747. package/src/modules/customer_groups/widgets/injection/person-groups-tab.tsx +573 -0
  1748. package/src/modules/customer_groups/widgets/injection-table.ts +35 -0
  1749. package/src/modules/customers/acl.ts +13 -0
  1750. package/src/modules/customers/api/activities/route.ts +10 -0
  1751. package/src/modules/customers/api/companies/[id]/people/route.ts +2 -1
  1752. package/src/modules/customers/api/companies/[id]/route.ts +20 -6
  1753. package/src/modules/customers/api/deals/[id]/companies/route.ts +2 -1
  1754. package/src/modules/customers/api/deals/[id]/people/route.ts +84 -4
  1755. package/src/modules/customers/api/deals/map/route.ts +11 -10
  1756. package/src/modules/customers/api/dictionaries/context.ts +2 -1
  1757. package/src/modules/customers/api/entity-roles-factory.ts +3 -2
  1758. package/src/modules/customers/api/interactions/[id]/visibility/route.ts +2 -1
  1759. package/src/modules/customers/api/interactions/cancel/route.ts +2 -1
  1760. package/src/modules/customers/api/interactions/complete/route.ts +2 -1
  1761. package/src/modules/customers/api/interactions/conflicts/route.ts +10 -10
  1762. package/src/modules/customers/api/interactions/counts/route.ts +25 -7
  1763. package/src/modules/customers/api/interactions/route.ts +34 -10
  1764. package/src/modules/customers/api/labels/assign/route.ts +2 -1
  1765. package/src/modules/customers/api/labels/route.ts +3 -2
  1766. package/src/modules/customers/api/labels/unassign/route.ts +2 -1
  1767. package/src/modules/customers/api/people/[id]/companies/context.ts +11 -2
  1768. package/src/modules/customers/api/people/[id]/email-share/route.ts +276 -0
  1769. package/src/modules/customers/api/people/[id]/email-threads/route.ts +14 -1
  1770. package/src/modules/customers/api/people/[id]/emails/route.ts +2 -1
  1771. package/src/modules/customers/api/people/[id]/route.ts +31 -22
  1772. package/src/modules/customers/api/people/check-phone/route.ts +2 -1
  1773. package/src/modules/customers/api/pipeline-stages/reorder/route.ts +3 -2
  1774. package/src/modules/customers/api/pipeline-stages/route.ts +3 -3
  1775. package/src/modules/customers/api/pipelines/route.ts +3 -3
  1776. package/src/modules/customers/api/settings/address-format/route.ts +2 -1
  1777. package/src/modules/customers/api/settings/dictionary-sort-modes/route.ts +2 -1
  1778. package/src/modules/customers/api/settings/stuck-threshold/route.ts +2 -1
  1779. package/src/modules/customers/api/tags/assign/route.ts +2 -1
  1780. package/src/modules/customers/api/tags/unassign/route.ts +2 -1
  1781. package/src/modules/customers/backend/customers/companies/[id]/page.tsx +4 -2
  1782. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealAssociations.ts +10 -35
  1783. package/src/modules/customers/backend/customers/deals/[id]/page.tsx +21 -18
  1784. package/src/modules/customers/backend/customers/deals/components/ReassignOwnerDialog.tsx +115 -0
  1785. package/src/modules/customers/backend/customers/deals/page.tsx +121 -1
  1786. package/src/modules/customers/backend/customers/people/[id]/page.tsx +4 -2
  1787. package/src/modules/customers/commands/addresses.ts +117 -15
  1788. package/src/modules/customers/commands/companies.ts +10 -4
  1789. package/src/modules/customers/commands/emailConversationShares.ts +261 -0
  1790. package/src/modules/customers/commands/index.ts +1 -0
  1791. package/src/modules/customers/commands/interactions.ts +61 -21
  1792. package/src/modules/customers/commands/people.ts +3 -2
  1793. package/src/modules/customers/commands/shared.ts +4 -0
  1794. package/src/modules/customers/components/calendar/types.ts +1 -1
  1795. package/src/modules/customers/components/detail/CompanyPeopleSection.tsx +97 -399
  1796. package/src/modules/customers/components/detail/CreatePersonDialog.tsx +39 -19
  1797. package/src/modules/customers/components/detail/DealForm.tsx +118 -5
  1798. package/src/modules/customers/components/detail/DealOwnerSelect.tsx +161 -0
  1799. package/src/modules/customers/components/detail/DealPeopleSection.tsx +256 -0
  1800. package/src/modules/customers/components/detail/DealsSection.tsx +8 -14
  1801. package/src/modules/customers/components/detail/LinkedPeopleSection.tsx +474 -0
  1802. package/src/modules/customers/components/detail/PersonCard.tsx +12 -4
  1803. package/src/modules/customers/components/detail/PersonEmailShareControl.tsx +273 -0
  1804. package/src/modules/customers/components/detail/PersonEmailThreadsTab.tsx +26 -0
  1805. package/src/modules/customers/components/detail/ScheduleActivityDialog.tsx +10 -2
  1806. package/src/modules/customers/components/detail/create/CreateDealForm.tsx +30 -0
  1807. package/src/modules/customers/components/detail/create/DealDetailsFields.tsx +12 -0
  1808. package/src/modules/customers/components/detail/create/DealSectionCard.tsx +7 -2
  1809. package/src/modules/customers/components/detail/create/dealFormTypes.ts +3 -0
  1810. package/src/modules/customers/components/detail/schedule/useScheduleFormState.ts +16 -4
  1811. package/src/modules/customers/components/formConfig.tsx +3 -0
  1812. package/src/modules/customers/components/linking/LinkEntityDialog.tsx +8 -0
  1813. package/src/modules/customers/components/linking/adapters/personAdapter.tsx +4 -0
  1814. package/src/modules/customers/data/enrichers.ts +64 -5
  1815. package/src/modules/customers/data/entities.ts +105 -1
  1816. package/src/modules/customers/data/validators.ts +22 -0
  1817. package/src/modules/customers/events.ts +5 -0
  1818. package/src/modules/customers/i18n/de.json +49 -13
  1819. package/src/modules/customers/i18n/en.json +44 -8
  1820. package/src/modules/customers/i18n/es.json +44 -8
  1821. package/src/modules/customers/i18n/ko.json +44 -8
  1822. package/src/modules/customers/i18n/pl.json +44 -8
  1823. package/src/modules/customers/lib/assignableStaff.ts +17 -0
  1824. package/src/modules/customers/lib/calendar/editorPayload.ts +20 -13
  1825. package/src/modules/customers/lib/calendar/mapItem.ts +1 -0
  1826. package/src/modules/customers/lib/conversationShares.ts +250 -0
  1827. package/src/modules/customers/lib/dealsOrganizationScope.ts +5 -3
  1828. package/src/modules/customers/lib/interactionRequestContext.ts +2 -1
  1829. package/src/modules/customers/lib/link-channel-message-handler.ts +27 -4
  1830. package/src/modules/customers/lib/personDetailCacheTags.ts +68 -0
  1831. package/src/modules/customers/lib/personEmailThreads.ts +61 -6
  1832. package/src/modules/customers/lib/reassignDealOwner.ts +51 -0
  1833. package/src/modules/customers/lib/userNames.ts +39 -0
  1834. package/src/modules/customers/lib/visibilityFilter.ts +170 -3
  1835. package/src/modules/customers/migrations/.snapshot-open-mercato.json +240 -0
  1836. package/src/modules/customers/migrations/Migration20260825120000_customers.ts +19 -0
  1837. package/src/modules/customers/migrations/Migration20260825140000_customers.ts +41 -0
  1838. package/src/modules/customers/setup.ts +1 -0
  1839. package/src/modules/customers/subscribers/channel-visibility-changed.ts +50 -0
  1840. package/src/modules/dashboards/api/widgets/data/batch/route.ts +3 -8
  1841. package/src/modules/dashboards/api/widgets/data/route.ts +12 -18
  1842. package/src/modules/dashboards/lib/aggregations.ts +1 -1
  1843. package/src/modules/dashboards/lib/widgetScope.ts +2 -7
  1844. package/src/modules/data_sync/AGENTS.md +35 -1
  1845. package/src/modules/data_sync/api/runs/[id]/cancel.ts +5 -1
  1846. package/src/modules/data_sync/backend/data-sync/page.tsx +292 -19
  1847. package/src/modules/data_sync/backend/data-sync/runs/[id]/page.tsx +205 -21
  1848. package/src/modules/data_sync/components/useDataSyncRunAccess.ts +27 -0
  1849. package/src/modules/data_sync/i18n/de.json +24 -0
  1850. package/src/modules/data_sync/i18n/en.json +24 -0
  1851. package/src/modules/data_sync/i18n/es.json +24 -0
  1852. package/src/modules/data_sync/i18n/ko.json +24 -0
  1853. package/src/modules/data_sync/i18n/pl.json +24 -0
  1854. package/src/modules/data_sync/lib/adapter.ts +37 -0
  1855. package/src/modules/data_sync/lib/resume-point.ts +63 -0
  1856. package/src/modules/data_sync/lib/start-run.ts +61 -2
  1857. package/src/modules/data_sync/lib/sync-run-service.ts +27 -34
  1858. package/src/modules/devices/api/[id]/route.ts +3 -2
  1859. package/src/modules/devices/api/admin/devices/route.ts +2 -1
  1860. package/src/modules/devices/api/route.ts +2 -1
  1861. package/src/modules/dictionaries/api/[dictionaryId]/route.ts +3 -5
  1862. package/src/modules/dictionaries/api/context.ts +2 -1
  1863. package/src/modules/dictionaries/api/route.ts +4 -0
  1864. package/src/modules/dictionaries/components/DictionariesManager.tsx +4 -3
  1865. package/src/modules/dictionaries/data/validators.ts +9 -1
  1866. package/src/modules/dictionaries/i18n/de.json +3 -3
  1867. package/src/modules/dictionaries/i18n/en.json +3 -3
  1868. package/src/modules/dictionaries/i18n/es.json +3 -3
  1869. package/src/modules/dictionaries/i18n/ko.json +3 -3
  1870. package/src/modules/dictionaries/i18n/pl.json +3 -3
  1871. package/src/modules/directory/api/organization-branding/route.ts +10 -1
  1872. package/src/modules/directory/api/organizations/route.ts +1 -1
  1873. package/src/modules/directory/backend/directory/branding/page.tsx +24 -2
  1874. package/src/modules/directory/commands/organizations.ts +173 -80
  1875. package/src/modules/directory/i18n/de.json +1 -0
  1876. package/src/modules/directory/i18n/en.json +1 -0
  1877. package/src/modules/directory/i18n/es.json +1 -0
  1878. package/src/modules/directory/i18n/ko.json +1 -0
  1879. package/src/modules/directory/i18n/pl.json +1 -0
  1880. package/src/modules/directory/lib/hierarchy.ts +22 -1
  1881. package/src/modules/directory/utils/organizationScope.ts +102 -15
  1882. package/src/modules/directory/utils/organizationScopeFilter.ts +6 -3
  1883. package/src/modules/directory/utils/organizationScopeGuard.ts +9 -5
  1884. package/src/modules/entities/api/encryption.ts +73 -27
  1885. package/src/modules/entities/api/records.ts +9 -8
  1886. package/src/modules/entities/cli.ts +46 -24
  1887. package/src/modules/entities/data/entities.ts +15 -0
  1888. package/src/modules/entities/lib/definition-scope.ts +5 -1
  1889. package/src/modules/entities/lib/encryption-maps.ts +164 -0
  1890. package/src/modules/entities/lib/helpers.ts +95 -8
  1891. package/src/modules/entities/migrations/.snapshot-open-mercato.json +21 -0
  1892. package/src/modules/entities/migrations/.snapshot-openmercato.json +12 -0
  1893. package/src/modules/entities/migrations/Migration20260910120000.ts +42 -0
  1894. package/src/modules/entities/migrations/Migration20261004120000_encryption_map_scope_uniqueness.ts +130 -0
  1895. package/src/modules/eudr/api/dashboard/widgets/compliance-overview/route.ts +2 -1
  1896. package/src/modules/eudr/api/plots/import/route.ts +2 -1
  1897. package/src/modules/eudr/api/product-mappings/suggestions/apply/route.ts +2 -1
  1898. package/src/modules/eudr/api/product-mappings/suggestions/route.ts +2 -1
  1899. package/src/modules/eudr/api/reports/annual/route.ts +2 -1
  1900. package/src/modules/eudr/api/statements/[id]/export/route.ts +2 -1
  1901. package/src/modules/eudr/api/statements/[id]/readiness/route.ts +2 -1
  1902. package/src/modules/eudr/api/suppliers/compliance/route.ts +2 -1
  1903. package/src/modules/feature_toggles/commands/global.ts +18 -15
  1904. package/src/modules/feature_toggles/lib/feature-flag-check.ts +8 -3
  1905. package/src/modules/forms/acl.ts +10 -0
  1906. package/src/modules/forms/api/[id]/analytics/route.ts +137 -0
  1907. package/src/modules/forms/api/[id]/distributions/route.ts +192 -0
  1908. package/src/modules/forms/api/[id]/route.ts +245 -0
  1909. package/src/modules/forms/api/[id]/run/context/route.ts +142 -0
  1910. package/src/modules/forms/api/[id]/run/submissions/route.ts +147 -0
  1911. package/src/modules/forms/api/[id]/submissions/route.ts +100 -0
  1912. package/src/modules/forms/api/[id]/theme-logo/route.ts +147 -0
  1913. package/src/modules/forms/api/[id]/versions/[versionId]/diff/route.ts +137 -0
  1914. package/src/modules/forms/api/[id]/versions/[versionId]/publish/route.ts +108 -0
  1915. package/src/modules/forms/api/[id]/versions/[versionId]/route.ts +200 -0
  1916. package/src/modules/forms/api/[id]/versions/fork/route.ts +98 -0
  1917. package/src/modules/forms/api/attachment-helpers.ts +160 -0
  1918. package/src/modules/forms/api/by-key/[key]/active/route.ts +165 -0
  1919. package/src/modules/forms/api/distributions/[distributionId]/invitations/[invitationId]/route.ts +92 -0
  1920. package/src/modules/forms/api/distributions/[distributionId]/invitations/[invitationId]/send/route.ts +96 -0
  1921. package/src/modules/forms/api/distributions/[distributionId]/invitations/route.ts +207 -0
  1922. package/src/modules/forms/api/distributions/[distributionId]/route.ts +213 -0
  1923. package/src/modules/forms/api/form-submissions/[id]/attachments/route.ts +114 -0
  1924. package/src/modules/forms/api/form-submissions/[id]/resume-token/route.ts +140 -0
  1925. package/src/modules/forms/api/form-submissions/[id]/route.ts +176 -0
  1926. package/src/modules/forms/api/form-submissions/[id]/submit/route.ts +91 -0
  1927. package/src/modules/forms/api/form-submissions/by-subject/[subject_type]/[subject_id]/route.ts +93 -0
  1928. package/src/modules/forms/api/form-submissions/route.ts +133 -0
  1929. package/src/modules/forms/api/helpers.ts +175 -0
  1930. package/src/modules/forms/api/public/distributions/[slug]/embed-policy/route.ts +74 -0
  1931. package/src/modules/forms/api/public/distributions/[slug]/route.ts +101 -0
  1932. package/src/modules/forms/api/public/embed-loader/route.ts +136 -0
  1933. package/src/modules/forms/api/public/invitations/[token]/route.ts +107 -0
  1934. package/src/modules/forms/api/public/rate-limit.ts +69 -0
  1935. package/src/modules/forms/api/public/start/route.ts +195 -0
  1936. package/src/modules/forms/api/public/submissions/[id]/attachments/[attachmentId]/route.ts +86 -0
  1937. package/src/modules/forms/api/public/submissions/[id]/attachments/route.ts +108 -0
  1938. package/src/modules/forms/api/public/submissions/[id]/pdf/route.ts +96 -0
  1939. package/src/modules/forms/api/public/submissions/[id]/route.ts +189 -0
  1940. package/src/modules/forms/api/public/submissions/[id]/submit/route.ts +159 -0
  1941. package/src/modules/forms/api/route.ts +240 -0
  1942. package/src/modules/forms/api/runtime-helpers.ts +208 -0
  1943. package/src/modules/forms/api/subjects/[subjectType]/[subjectId]/consents/route.ts +178 -0
  1944. package/src/modules/forms/api/subjects/[subjectType]/[subjectId]/export/route.ts +135 -0
  1945. package/src/modules/forms/api/submissions/[submissionId]/access-audit/route.ts +100 -0
  1946. package/src/modules/forms/api/submissions/[submissionId]/actors/[actorId]/route.ts +70 -0
  1947. package/src/modules/forms/api/submissions/[submissionId]/actors/route.ts +92 -0
  1948. package/src/modules/forms/api/submissions/[submissionId]/anonymize/route.ts +134 -0
  1949. package/src/modules/forms/api/submissions/[submissionId]/attachments/[attachmentId]/route.ts +90 -0
  1950. package/src/modules/forms/api/submissions/[submissionId]/export/route.ts +111 -0
  1951. package/src/modules/forms/api/submissions/[submissionId]/pdf/route.ts +118 -0
  1952. package/src/modules/forms/api/submissions/[submissionId]/reopen/route.ts +69 -0
  1953. package/src/modules/forms/api/submissions/[submissionId]/revisions/route.ts +75 -0
  1954. package/src/modules/forms/api/submissions/[submissionId]/route.ts +90 -0
  1955. package/src/modules/forms/backend/forms/[id]/FormStudio.tsx +3269 -0
  1956. package/src/modules/forms/backend/forms/[id]/analytics/page.meta.ts +15 -0
  1957. package/src/modules/forms/backend/forms/[id]/analytics/page.tsx +289 -0
  1958. package/src/modules/forms/backend/forms/[id]/distributions/page.meta.ts +15 -0
  1959. package/src/modules/forms/backend/forms/[id]/distributions/page.tsx +16 -0
  1960. package/src/modules/forms/backend/forms/[id]/history/page.meta.ts +11 -0
  1961. package/src/modules/forms/backend/forms/[id]/history/page.tsx +229 -0
  1962. package/src/modules/forms/backend/forms/[id]/page.meta.ts +11 -0
  1963. package/src/modules/forms/backend/forms/[id]/page.tsx +17 -0
  1964. package/src/modules/forms/backend/forms/[id]/studio/YesNoRow.tsx +65 -0
  1965. package/src/modules/forms/backend/forms/[id]/studio/autosave-guard.ts +25 -0
  1966. package/src/modules/forms/backend/forms/[id]/studio/canvas/DragOverlayCard.tsx +24 -0
  1967. package/src/modules/forms/backend/forms/[id]/studio/canvas/DropIndicator.tsx +36 -0
  1968. package/src/modules/forms/backend/forms/[id]/studio/canvas/FieldRow.tsx +308 -0
  1969. package/src/modules/forms/backend/forms/[id]/studio/canvas/FormCanvas.tsx +265 -0
  1970. package/src/modules/forms/backend/forms/[id]/studio/canvas/GridSlot.tsx +176 -0
  1971. package/src/modules/forms/backend/forms/[id]/studio/canvas/SectionContainer.tsx +473 -0
  1972. package/src/modules/forms/backend/forms/[id]/studio/canvas/grid-collision.ts +25 -0
  1973. package/src/modules/forms/backend/forms/[id]/studio/canvas/keyboard-coordinates.ts +128 -0
  1974. package/src/modules/forms/backend/forms/[id]/studio/canvas/overlay-size.ts +15 -0
  1975. package/src/modules/forms/backend/forms/[id]/studio/canvas/resize-math.ts +36 -0
  1976. package/src/modules/forms/backend/forms/[id]/studio/canvas/row-layout.ts +110 -0
  1977. package/src/modules/forms/backend/forms/[id]/studio/logic/ConditionBuilder.tsx +264 -0
  1978. package/src/modules/forms/backend/forms/[id]/studio/logic/HiddenFieldsPanel.tsx +121 -0
  1979. package/src/modules/forms/backend/forms/[id]/studio/logic/JumpsEditor.tsx +237 -0
  1980. package/src/modules/forms/backend/forms/[id]/studio/logic/RecallTokenPicker.tsx +87 -0
  1981. package/src/modules/forms/backend/forms/[id]/studio/logic/VariablesPanel.tsx +260 -0
  1982. package/src/modules/forms/backend/forms/[id]/studio/logic/condition-model.ts +207 -0
  1983. package/src/modules/forms/backend/forms/[id]/studio/lucide-icons.ts +87 -0
  1984. package/src/modules/forms/backend/forms/[id]/studio/palette/FormAppearancePanel.tsx +561 -0
  1985. package/src/modules/forms/backend/forms/[id]/studio/palette/FormPalettePanel.tsx +52 -0
  1986. package/src/modules/forms/backend/forms/[id]/studio/palette/InputParametersTab.tsx +378 -0
  1987. package/src/modules/forms/backend/forms/[id]/studio/palette/PaletteCard.tsx +40 -0
  1988. package/src/modules/forms/backend/forms/[id]/studio/palette/RolesEditor.tsx +225 -0
  1989. package/src/modules/forms/backend/forms/[id]/studio/palette/entries.ts +102 -0
  1990. package/src/modules/forms/backend/forms/[id]/studio/preview/PreviewSurface.tsx +1459 -0
  1991. package/src/modules/forms/backend/forms/[id]/studio/preview/ViewportFrame.tsx +49 -0
  1992. package/src/modules/forms/backend/forms/[id]/studio/recall.ts +0 -0
  1993. package/src/modules/forms/backend/forms/[id]/studio/schema-helpers.ts +2525 -0
  1994. package/src/modules/forms/backend/forms/[id]/studio/style/BackgroundControl.tsx +137 -0
  1995. package/src/modules/forms/backend/forms/[id]/studio/style/ColorControl.tsx +257 -0
  1996. package/src/modules/forms/backend/forms/[id]/studio/style/contrast.ts +114 -0
  1997. package/src/modules/forms/backend/forms/[id]/studio/style/presets.ts +104 -0
  1998. package/src/modules/forms/backend/forms/[id]/studio/type-label.ts +13 -0
  1999. package/src/modules/forms/backend/forms/[id]/studio/types.ts +31 -0
  2000. package/src/modules/forms/backend/forms/[id]/studio/undo-controller.ts +52 -0
  2001. package/src/modules/forms/backend/forms/[id]/studio/validation/FileConstraintsEditor.tsx +89 -0
  2002. package/src/modules/forms/backend/forms/[id]/studio/validation/GroupConfigEditor.tsx +167 -0
  2003. package/src/modules/forms/backend/forms/[id]/studio/validation/LengthRangeEditor.tsx +67 -0
  2004. package/src/modules/forms/backend/forms/[id]/studio/validation/MatrixColumnsEditor.tsx +166 -0
  2005. package/src/modules/forms/backend/forms/[id]/studio/validation/MatrixRowsEditor.tsx +184 -0
  2006. package/src/modules/forms/backend/forms/[id]/studio/validation/MessageOverridesEditor.tsx +83 -0
  2007. package/src/modules/forms/backend/forms/[id]/studio/validation/NpsAnchorsEditor.tsx +60 -0
  2008. package/src/modules/forms/backend/forms/[id]/studio/validation/NumberRangeEditor.tsx +65 -0
  2009. package/src/modules/forms/backend/forms/[id]/studio/validation/OpinionIconSelect.tsx +46 -0
  2010. package/src/modules/forms/backend/forms/[id]/studio/validation/PatternEditor.tsx +122 -0
  2011. package/src/modules/forms/backend/forms/[id]/studio/validation/RankingExhaustiveSwitch.tsx +28 -0
  2012. package/src/modules/forms/backend/forms/[id]/studio/validation/SignatureConfigEditor.tsx +84 -0
  2013. package/src/modules/forms/backend/forms/[id]/studio/validation/ValidationPanel.tsx +369 -0
  2014. package/src/modules/forms/backend/forms/[id]/submissions/components/RowBadges.ts +56 -0
  2015. package/src/modules/forms/backend/forms/[id]/submissions/components/SubmissionDrawer.tsx +604 -0
  2016. package/src/modules/forms/backend/forms/[id]/submissions/page.meta.ts +10 -0
  2017. package/src/modules/forms/backend/forms/[id]/submissions/page.tsx +264 -0
  2018. package/src/modules/forms/backend/forms/create/page.meta.ts +11 -0
  2019. package/src/modules/forms/backend/forms/create/page.tsx +113 -0
  2020. package/src/modules/forms/backend/forms/page.meta.ts +31 -0
  2021. package/src/modules/forms/backend/forms/page.tsx +269 -0
  2022. package/src/modules/forms/commands/distribution.ts +502 -0
  2023. package/src/modules/forms/commands/form-version.ts +806 -0
  2024. package/src/modules/forms/commands/form.ts +472 -0
  2025. package/src/modules/forms/commands/index.ts +18 -0
  2026. package/src/modules/forms/commands/invitation.ts +424 -0
  2027. package/src/modules/forms/commands/shared.ts +261 -0
  2028. package/src/modules/forms/commands/submission.ts +209 -0
  2029. package/src/modules/forms/data/entities.ts +686 -0
  2030. package/src/modules/forms/data/validators.ts +483 -0
  2031. package/src/modules/forms/di.ts +246 -0
  2032. package/src/modules/forms/encryption.ts +31 -0
  2033. package/src/modules/forms/events-payloads.ts +103 -0
  2034. package/src/modules/forms/events.ts +50 -0
  2035. package/src/modules/forms/extension-points.ts +41 -0
  2036. package/src/modules/forms/frontend/[orgSlug]/portal/forms/[key]/page.meta.ts +9 -0
  2037. package/src/modules/forms/frontend/[orgSlug]/portal/forms/[key]/page.tsx +45 -0
  2038. package/src/modules/forms/frontend/[orgSlug]/portal/submissions/[id]/continue/page.meta.ts +9 -0
  2039. package/src/modules/forms/frontend/[orgSlug]/portal/submissions/[id]/continue/page.tsx +56 -0
  2040. package/src/modules/forms/frontend/embed/[slug]/page.meta.ts +42 -0
  2041. package/src/modules/forms/frontend/embed/[slug]/page.tsx +171 -0
  2042. package/src/modules/forms/frontend/f/[slug]/page.meta.ts +9 -0
  2043. package/src/modules/forms/frontend/f/[slug]/page.tsx +10 -0
  2044. package/src/modules/forms/frontend/forms/[id]/run/page.meta.ts +17 -0
  2045. package/src/modules/forms/frontend/forms/[id]/run/page.tsx +83 -0
  2046. package/src/modules/forms/frontend/i/[token]/page.meta.ts +9 -0
  2047. package/src/modules/forms/frontend/i/[token]/page.tsx +10 -0
  2048. package/src/modules/forms/i18n/de.json +800 -0
  2049. package/src/modules/forms/i18n/en.json +800 -0
  2050. package/src/modules/forms/i18n/es.json +800 -0
  2051. package/src/modules/forms/i18n/ko.json +800 -0
  2052. package/src/modules/forms/i18n/pl.json +800 -0
  2053. package/src/modules/forms/index.ts +18 -0
  2054. package/src/modules/forms/lib/embed-frame-policy.ts +144 -0
  2055. package/src/modules/forms/lib/form-definition-slicing.ts +54 -0
  2056. package/src/modules/forms/lib/log-redaction.ts +91 -0
  2057. package/src/modules/forms/lib/navigable-url.ts +57 -0
  2058. package/src/modules/forms/lib/retention.ts +73 -0
  2059. package/src/modules/forms/lib/runtime-principal.ts +101 -0
  2060. package/src/modules/forms/migrations/.snapshot-open-mercato.json +3185 -0
  2061. package/src/modules/forms/migrations/Migration20260508135459_forms.ts +17 -0
  2062. package/src/modules/forms/migrations/Migration20260508140932_forms.ts +26 -0
  2063. package/src/modules/forms/migrations/Migration20260508155737_forms.ts +15 -0
  2064. package/src/modules/forms/migrations/Migration20260520120000_forms.ts +26 -0
  2065. package/src/modules/forms/migrations/Migration20260521090000_forms.ts +15 -0
  2066. package/src/modules/forms/migrations/Migration20260521120000_forms.ts +21 -0
  2067. package/src/modules/forms/runner/FormRunner.tsx +924 -0
  2068. package/src/modules/forms/runner/MatrixField.tsx +210 -0
  2069. package/src/modules/forms/runner/RankingField.tsx +207 -0
  2070. package/src/modules/forms/runner/ScaleField.tsx +102 -0
  2071. package/src/modules/forms/runner/SignatureField.tsx +158 -0
  2072. package/src/modules/forms/runner/tamper-check.ts +131 -0
  2073. package/src/modules/forms/schema/address-countries.ts +60 -0
  2074. package/src/modules/forms/schema/field-type-patterns.ts +21 -0
  2075. package/src/modules/forms/schema/field-type-registry-advanced.ts +58 -0
  2076. package/src/modules/forms/schema/field-type-registry.ts +819 -0
  2077. package/src/modules/forms/schema/file-field.ts +102 -0
  2078. package/src/modules/forms/schema/group-field.ts +235 -0
  2079. package/src/modules/forms/schema/jsonlogic-grammar.ts +95 -0
  2080. package/src/modules/forms/schema/jsonschema-extensions.ts +1060 -0
  2081. package/src/modules/forms/schema/layout-catalog.ts +68 -0
  2082. package/src/modules/forms/schema/signature-field.ts +120 -0
  2083. package/src/modules/forms/schema/style-extensions.ts +194 -0
  2084. package/src/modules/forms/schema/style-validators.ts +252 -0
  2085. package/src/modules/forms/services/access-audit-logger.ts +275 -0
  2086. package/src/modules/forms/services/analytics-service.ts +498 -0
  2087. package/src/modules/forms/services/anonymize-service.ts +177 -0
  2088. package/src/modules/forms/services/attachment-service.ts +223 -0
  2089. package/src/modules/forms/services/captcha-verifier.ts +156 -0
  2090. package/src/modules/forms/services/consent-record-service.ts +162 -0
  2091. package/src/modules/forms/services/distribution-service.ts +509 -0
  2092. package/src/modules/forms/services/distribution-token.ts +153 -0
  2093. package/src/modules/forms/services/encryption-service.ts +500 -0
  2094. package/src/modules/forms/services/export-service.ts +360 -0
  2095. package/src/modules/forms/services/field-validation-service.ts +300 -0
  2096. package/src/modules/forms/services/form-logic-evaluator.ts +718 -0
  2097. package/src/modules/forms/services/form-version-compiler.ts +829 -0
  2098. package/src/modules/forms/services/form-version-differ.ts +143 -0
  2099. package/src/modules/forms/services/jsonlogic-evaluator.ts +228 -0
  2100. package/src/modules/forms/services/pdf-snapshot-service.ts +782 -0
  2101. package/src/modules/forms/services/prefill-resolver.ts +125 -0
  2102. package/src/modules/forms/services/role-policy-service.ts +90 -0
  2103. package/src/modules/forms/services/style-compiler.ts +378 -0
  2104. package/src/modules/forms/services/submission-service.ts +1259 -0
  2105. package/src/modules/forms/services/upload-scanner.ts +36 -0
  2106. package/src/modules/forms/services/upload-validation.ts +94 -0
  2107. package/src/modules/forms/services/visibility-resolver.ts +63 -0
  2108. package/src/modules/forms/setup.ts +16 -0
  2109. package/src/modules/forms/subscribers/forms-consent-projector.ts +100 -0
  2110. package/src/modules/forms/subscribers/forms-pdf-snapshot.ts +112 -0
  2111. package/src/modules/forms/subscribers/forms-webhook-bridge-anonymized.ts +36 -0
  2112. package/src/modules/forms/subscribers/forms-webhook-bridge.ts +56 -0
  2113. package/src/modules/forms/subscribers/invitation-email.ts +180 -0
  2114. package/src/modules/forms/translations.ts +14 -0
  2115. package/src/modules/forms/ui/admin/forms/[id]/distributions/CreateDistributionDialog.tsx +401 -0
  2116. package/src/modules/forms/ui/admin/forms/[id]/distributions/DistributionsPanel.tsx +381 -0
  2117. package/src/modules/forms/ui/admin/forms/[id]/distributions/EmbedSettingsDialog.tsx +332 -0
  2118. package/src/modules/forms/ui/admin/forms/[id]/distributions/RecipientsTable.tsx +460 -0
  2119. package/src/modules/forms/ui/public/EmbeddedForm.tsx +248 -0
  2120. package/src/modules/forms/ui/public/FormRunner.tsx +491 -0
  2121. package/src/modules/forms/ui/public/FormTrigger.tsx +80 -0
  2122. package/src/modules/forms/ui/public/PublicFormRunnerPage.tsx +34 -0
  2123. package/src/modules/forms/ui/public/components/CompletionScreen.tsx +97 -0
  2124. package/src/modules/forms/ui/public/components/LocaleSwitch.tsx +42 -0
  2125. package/src/modules/forms/ui/public/components/ResumeGate.tsx +61 -0
  2126. package/src/modules/forms/ui/public/components/ReviewStep.tsx +153 -0
  2127. package/src/modules/forms/ui/public/components/SaveIndicator.tsx +69 -0
  2128. package/src/modules/forms/ui/public/components/SectionStepper.tsx +60 -0
  2129. package/src/modules/forms/ui/public/index.ts +48 -0
  2130. package/src/modules/forms/ui/public/renderers/index.tsx +889 -0
  2131. package/src/modules/forms/ui/public/state/logic-derivation.ts +91 -0
  2132. package/src/modules/forms/ui/public/state/runtime-client.ts +495 -0
  2133. package/src/modules/forms/ui/public/state/useAutosave.ts +97 -0
  2134. package/src/modules/forms/ui/public/state/useFormRunner.ts +547 -0
  2135. package/src/modules/forms/ui/public/style/LogoHeader.tsx +43 -0
  2136. package/src/modules/forms/ui/public/style/applyStyle.ts +26 -0
  2137. package/src/modules/forms/ui/public/types.ts +228 -0
  2138. package/src/modules/forms/widgets/injection/access-audit-panel/widget.tsx +144 -0
  2139. package/src/modules/forms/widgets/injection/anonymize-button/widget.tsx +177 -0
  2140. package/src/modules/forms/widgets/injection/audit-format.ts +60 -0
  2141. package/src/modules/forms/widgets/injection/context.ts +24 -0
  2142. package/src/modules/forms/widgets/injection/embedded-form/widget.tsx +102 -0
  2143. package/src/modules/forms/widgets/injection/pdf-download-button/widget.tsx +111 -0
  2144. package/src/modules/forms/widgets/injection/self-audit-footer/widget.tsx +56 -0
  2145. package/src/modules/forms/widgets/injection-table.ts +54 -0
  2146. package/src/modules/forms/workers/pdf-snapshot.ts +110 -0
  2147. package/src/modules/forms/workers/retention-purge.ts +169 -0
  2148. package/src/modules/inbox_ops/api/proposals/[id]/actions/[actionId]/route.ts +7 -1
  2149. package/src/modules/inbox_ops/data/validators.ts +2 -1
  2150. package/src/modules/inbox_ops/lib/llmProvider.ts +11 -0
  2151. package/src/modules/inbox_ops/widgets/notifications/ProposalCreatedRenderer.tsx +2 -2
  2152. package/src/modules/integrations/di.ts +5 -1
  2153. package/src/modules/integrations/lib/credentials-service.ts +45 -36
  2154. package/src/modules/messages/api/[id]/attachments/route.ts +12 -3
  2155. package/src/modules/messages/api/[id]/forward-preview/route.ts +9 -3
  2156. package/src/modules/messages/api/[id]/route.ts +83 -4
  2157. package/src/modules/messages/api/route.ts +123 -2
  2158. package/src/modules/messages/commands/messages.ts +81 -7
  2159. package/src/modules/messages/components/ComposeMessagePageClient.tsx +29 -1
  2160. package/src/modules/messages/data/validators.ts +10 -0
  2161. package/src/modules/messages/i18n/de.json +8 -0
  2162. package/src/modules/messages/i18n/en.json +8 -0
  2163. package/src/modules/messages/i18n/es.json +8 -0
  2164. package/src/modules/messages/i18n/ko.json +8 -0
  2165. package/src/modules/messages/i18n/pl.json +8 -0
  2166. package/src/modules/messages/lib/channelThreadAccess.ts +101 -0
  2167. package/src/modules/messages/lib/composeSenderDelegation.ts +182 -0
  2168. package/src/modules/messages/lib/composeSenderOptions.ts +56 -0
  2169. package/src/modules/messages/lib/email-sender.ts +1 -17
  2170. package/src/modules/messages/lib/forwarding.ts +17 -2
  2171. package/src/modules/messages/lib/markdownEmailBody.ts +25 -0
  2172. package/src/modules/messages/lib/messageSourceEntityTypes.ts +12 -0
  2173. package/src/modules/messages/lib/routeHelpers.ts +92 -0
  2174. package/src/modules/messages/subscribers/message-notification.ts +47 -1
  2175. package/src/modules/notifications/api/[id]/action/route.ts +2 -1
  2176. package/src/modules/notifications/api/openapi.ts +1 -0
  2177. package/src/modules/notifications/frontend/NotificationSettingsPageClient.tsx +77 -48
  2178. package/src/modules/notifications/i18n/de.json +1 -0
  2179. package/src/modules/notifications/i18n/en.json +1 -0
  2180. package/src/modules/notifications/i18n/es.json +1 -0
  2181. package/src/modules/notifications/i18n/ko.json +1 -0
  2182. package/src/modules/notifications/i18n/pl.json +1 -0
  2183. package/src/modules/notifications/lib/deliveryConfig.ts +31 -2
  2184. package/src/modules/notifications/lib/notificationMapper.ts +2 -0
  2185. package/src/modules/notifications/lib/safeHref.ts +7 -0
  2186. package/src/modules/planner/api/availability-date-specific.ts +2 -1
  2187. package/src/modules/planner/api/availability-weekly.ts +2 -1
  2188. package/src/modules/progress/AGENTS.md +2 -0
  2189. package/src/modules/progress/api/active/route.ts +14 -2
  2190. package/src/modules/progress/api/jobs/[id]/route.ts +44 -27
  2191. package/src/modules/progress/api/jobs/route.ts +22 -8
  2192. package/src/modules/progress/api/requestScope.ts +43 -0
  2193. package/src/modules/progress/lib/organizationScope.ts +17 -0
  2194. package/src/modules/progress/lib/progressService.ts +3 -2
  2195. package/src/modules/progress/lib/progressServiceImpl.ts +63 -14
  2196. package/src/modules/push_notifications/api/custom-send/route.ts +4 -1
  2197. package/src/modules/query_index/api/status.ts +4 -9
  2198. package/src/modules/query_index/di.ts +2 -1
  2199. package/src/modules/query_index/lib/engine.ts +2 -0
  2200. package/src/modules/query_index/lib/request-encryption.ts +31 -0
  2201. package/src/modules/query_index/lib/search-tokens.ts +42 -1
  2202. package/src/modules/resources/api/resources/tags/assign/route.ts +2 -1
  2203. package/src/modules/resources/api/resources/tags/unassign/route.ts +2 -1
  2204. package/src/modules/resources/commands/activities.ts +2 -2
  2205. package/src/modules/sales/api/document-history/route.ts +5 -1
  2206. package/src/modules/sales/api/document-numbers/route.ts +2 -1
  2207. package/src/modules/sales/api/quotes/convert/route.ts +2 -1
  2208. package/src/modules/sales/api/quotes/send/route.ts +2 -1
  2209. package/src/modules/sales/api/settings/document-numbers/route.ts +7 -1
  2210. package/src/modules/sales/api/settings/order-editing/route.ts +7 -1
  2211. package/src/modules/sales/commands/documents.ts +451 -131
  2212. package/src/modules/sales/commands/payments.ts +2 -1
  2213. package/src/modules/sales/commands/settings.ts +34 -6
  2214. package/src/modules/sales/commands/shipments.ts +2 -1
  2215. package/src/modules/sales/components/DocumentNumberSettings.tsx +41 -28
  2216. package/src/modules/sales/components/documents/ItemsSection.tsx +58 -13
  2217. package/src/modules/sales/components/documents/LineItemDialog.tsx +194 -111
  2218. package/src/modules/sales/components/documents/lineItemUtils.ts +18 -0
  2219. package/src/modules/sales/i18n/de.json +2 -0
  2220. package/src/modules/sales/i18n/en.json +2 -0
  2221. package/src/modules/sales/i18n/es.json +2 -0
  2222. package/src/modules/sales/i18n/ko.json +2 -0
  2223. package/src/modules/sales/i18n/pl.json +2 -0
  2224. package/src/modules/sales/lib/lineSnapshots.ts +36 -0
  2225. package/src/modules/sales/setup.ts +4 -4
  2226. package/src/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.tsx +2 -2
  2227. package/src/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.tsx +2 -2
  2228. package/src/modules/staff/api/leave-requests/accept/route.ts +2 -1
  2229. package/src/modules/staff/api/leave-requests/reject/route.ts +2 -1
  2230. package/src/modules/staff/api/leave-requests.ts +2 -1
  2231. package/src/modules/staff/api/team-members/self/route.ts +2 -1
  2232. package/src/modules/staff/api/team-members/tags/assign/route.ts +2 -1
  2233. package/src/modules/staff/api/team-members/tags/unassign/route.ts +2 -1
  2234. package/src/modules/staff/api/timesheets/_shared/withTimesheetInterceptors.ts +16 -16
  2235. package/src/modules/staff/api/timesheets/my-projects/[projectId]/route.ts +2 -1
  2236. package/src/modules/staff/api/timesheets/my-projects/route.ts +2 -1
  2237. package/src/modules/staff/api/timesheets/my-work/route.ts +2 -1
  2238. package/src/modules/staff/api/timesheets/projects/kpis/route.ts +2 -1
  2239. package/src/modules/staff/api/timesheets/reports/[id]/close/route.ts +2 -1
  2240. package/src/modules/staff/api/timesheets/reports/[id]/export/route.ts +3 -2
  2241. package/src/modules/staff/api/timesheets/reports/[id]/sheet/route.ts +3 -2
  2242. package/src/modules/staff/api/timesheets/reports/[id]/unlock/route.ts +3 -2
  2243. package/src/modules/staff/api/timesheets/reports/preview/route.ts +2 -1
  2244. package/src/modules/staff/api/timesheets/reports/shared.ts +2 -1
  2245. package/src/modules/staff/api/timesheets/settings/reapply-rounding/route.ts +2 -1
  2246. package/src/modules/staff/api/timesheets/tags/entry-assignments/route.ts +2 -1
  2247. package/src/modules/staff/api/timesheets/tags/task-assignments/route.ts +2 -1
  2248. package/src/modules/staff/api/timesheets/tasks/[id]/comments/route.ts +2 -1
  2249. package/src/modules/staff/api/timesheets/tasks/[id]/status/route.ts +2 -1
  2250. package/src/modules/staff/api/timesheets/time-entries/[id]/duplicate/route.ts +3 -2
  2251. package/src/modules/staff/api/timesheets/time-entries/[id]/segments/[segmentId]/route.ts +2 -1
  2252. package/src/modules/staff/api/timesheets/time-entries/[id]/segments/route.ts +2 -1
  2253. package/src/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.ts +2 -1
  2254. package/src/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.ts +2 -1
  2255. package/src/modules/staff/api/timesheets/time-entries/bulk/route.ts +2 -1
  2256. package/src/modules/staff/api/timesheets/time-entries/copy-day/route.ts +3 -2
  2257. package/src/modules/staff/api/timesheets/time-entries/overlaps/route.ts +2 -1
  2258. package/src/modules/staff/api/timesheets/time-entries/start-timer/route.ts +3 -2
  2259. package/src/modules/staff/api/timesheets/time-projects/[id]/change-currency/route.ts +3 -2
  2260. package/src/modules/staff/api/timesheets/time-projects/route.ts +2 -1
  2261. package/src/modules/staff/commands/activities.ts +2 -2
  2262. package/src/modules/staff/commands/timesheets-entries.ts +3 -2
  2263. package/src/modules/staff/commands/timesheets-reports.ts +88 -15
  2264. package/src/modules/staff/lib/timesheets-reports/buildReportSheet.ts +1 -0
  2265. package/src/modules/staff/lib/timesheets-reports/loadReportData.ts +69 -8
  2266. package/src/modules/staff/lib/timesheets-reports/reportPeriod.ts +18 -0
  2267. package/src/modules/staff/lib/timesheets-ui/CalendarPicker.tsx +21 -10
  2268. package/src/modules/sync_excel/api/import/route.ts +40 -12
  2269. package/src/modules/sync_excel/api/upload/route.ts +34 -4
  2270. package/src/modules/translations/api/context.ts +2 -1
  2271. package/src/modules/warranty_claims/api/ai/assess/route.ts +2 -1
  2272. package/src/modules/warranty_claims/api/ai/draft-reply/route.ts +2 -1
  2273. package/src/modules/warranty_claims/api/ai/suggest/route.ts +2 -1
  2274. package/src/modules/warranty_claims/api/assign/route.ts +2 -1
  2275. package/src/modules/warranty_claims/api/credit-memo/route.ts +2 -1
  2276. package/src/modules/warranty_claims/api/entitlement/route.ts +2 -1
  2277. package/src/modules/warranty_claims/api/events/route.ts +2 -1
  2278. package/src/modules/warranty_claims/api/external/claims/route.ts +2 -1
  2279. package/src/modules/warranty_claims/api/receiving/route.ts +2 -1
  2280. package/src/modules/warranty_claims/api/replacement-order/route.ts +2 -1
  2281. package/src/modules/warranty_claims/api/return-label/route.ts +2 -1
  2282. package/src/modules/warranty_claims/api/risk/route.ts +2 -1
  2283. package/src/modules/warranty_claims/api/sales-return/route.ts +2 -1
  2284. package/src/modules/warranty_claims/api/settings-general/route.ts +2 -1
  2285. package/src/modules/warranty_claims/api/stats/route.ts +11 -11
  2286. package/src/modules/warranty_claims/api/submit/route.ts +2 -1
  2287. package/src/modules/warranty_claims/api/transition/route.ts +2 -1
  2288. package/src/modules/warranty_claims/api/vendor-recovery/route.ts +2 -1
  2289. package/src/modules/warranty_claims/api/vendor-recovery-suggestions/route.ts +2 -1
  2290. package/src/modules/warranty_claims/widgets/notifications/WarrantyClaimNotificationRenderer.tsx +1 -1
  2291. package/src/modules/wms/api/dashboard/operational/route.ts +2 -1
  2292. package/src/modules/wms/api/inventory/cycle-count/route.ts +1 -0
  2293. package/src/modules/wms/api/inventory/helpers.ts +2 -1
  2294. package/src/modules/wms/api/inventory/import/helpers.ts +2 -1
  2295. package/src/modules/wms/api/sales-orders/[salesOrderId]/warehouse-assignment/route.ts +2 -1
  2296. package/src/modules/wms/commands/inventory-actions.ts +45 -1
  2297. package/src/modules/wms/components/backend/CycleCountWizardDialog.tsx +14 -1
  2298. package/src/modules/wms/di.ts +6 -0
  2299. package/src/modules/wms/i18n/de.json +1 -0
  2300. package/src/modules/wms/i18n/en.json +1 -0
  2301. package/src/modules/wms/i18n/es.json +1 -0
  2302. package/src/modules/wms/i18n/ko.json +1 -0
  2303. package/src/modules/wms/i18n/pl.json +1 -0
  2304. package/src/modules/wms/lib/availabilityCache.ts +137 -0
  2305. package/src/modules/wms/lib/availabilityCalculation.ts +351 -0
  2306. package/src/modules/wms/lib/availabilityProvider.ts +47 -0
  2307. package/src/modules/wms/lib/loadOperationalDashboard.ts +51 -3
  2308. package/src/modules/wms/lib/lowStockBalanceFilter.ts +23 -10
  2309. package/src/modules/wms/lib/sqlInClause.ts +21 -0
  2310. package/src/modules/wms/lib/tryResolve.ts +8 -0
  2311. package/src/modules/wms/subscribers/invalidate-availability-cache-policy.ts +18 -0
  2312. package/src/modules/wms/subscribers/invalidate-availability-cache-profile.ts +18 -0
  2313. package/src/modules/wms/subscribers/invalidate-availability-cache.ts +30 -0
  2314. package/src/modules/wms/widgets/notifications/WmsLowStockRenderer.tsx +2 -2
  2315. package/src/modules/wms/widgets/notifications/WmsReservationShortfallRenderer.tsx +4 -3
  2316. package/src/modules/workflows/AGENTS.md +7 -5
  2317. package/src/modules/workflows/api/commands/route.ts +4 -1
  2318. package/src/modules/workflows/api/definitions/[id]/callers/route.ts +4 -1
  2319. package/src/modules/workflows/api/definitions/[id]/context-schema/route.ts +4 -2
  2320. package/src/modules/workflows/api/definitions/[id]/customize/route.ts +4 -1
  2321. package/src/modules/workflows/api/definitions/[id]/draft/route.ts +6 -1
  2322. package/src/modules/workflows/api/definitions/[id]/publish/route.ts +10 -1
  2323. package/src/modules/workflows/api/definitions/[id]/reset-to-code/route.ts +4 -1
  2324. package/src/modules/workflows/api/definitions/[id]/route.ts +5 -3
  2325. package/src/modules/workflows/api/definitions/[id]/test-step/route.ts +4 -2
  2326. package/src/modules/workflows/api/definitions/generate/route.ts +4 -1
  2327. package/src/modules/workflows/api/definitions/route.ts +4 -2
  2328. package/src/modules/workflows/api/endpoints/route.ts +4 -1
  2329. package/src/modules/workflows/api/functions/route.ts +4 -1
  2330. package/src/modules/workflows/api/grantable-features/route.ts +2 -1
  2331. package/src/modules/workflows/api/instances/[id]/advance/route.ts +4 -1
  2332. package/src/modules/workflows/api/instances/[id]/cancel/route.ts +4 -1
  2333. package/src/modules/workflows/api/instances/[id]/context/route.ts +2 -1
  2334. package/src/modules/workflows/api/instances/[id]/rerun-step/route.ts +4 -1
  2335. package/src/modules/workflows/api/instances/[id]/retry/route.ts +4 -1
  2336. package/src/modules/workflows/api/instances/[id]/signal/route.ts +4 -1
  2337. package/src/modules/workflows/api/instances/[id]/step-through/route.ts +4 -2
  2338. package/src/modules/workflows/api/instances/route.ts +4 -2
  2339. package/src/modules/workflows/api/instances/validate-start/route.ts +4 -1
  2340. package/src/modules/workflows/api/rule-usage/route.ts +4 -1
  2341. package/src/modules/workflows/api/signals/route.ts +4 -1
  2342. package/src/modules/workflows/api/tasks/[id]/claim/route.ts +4 -1
  2343. package/src/modules/workflows/api/tasks/[id]/complete/route.ts +4 -1
  2344. package/src/modules/workflows/api/tasks/[id]/reassign/route.ts +2 -1
  2345. package/src/modules/workflows/api/tasks/[id]/unclaim/route.ts +4 -1
  2346. package/src/modules/workflows/api/templates/route.ts +4 -1
  2347. package/src/modules/workflows/api/work-inbox/next/route.ts +4 -1
  2348. package/src/modules/workflows/lib/activity-executor.ts +125 -28
  2349. package/src/modules/workflows/lib/activity-types.ts +8 -4
  2350. package/src/modules/workflows/lib/activity-worker-handler.ts +16 -12
  2351. package/src/modules/workflows/lib/event-trigger-service.ts +18 -2
  2352. package/src/modules/workflows/lib/step-handler.ts +13 -8
  2353. package/src/test-utils/transactionalEntityManagerDouble.ts +51 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/staff/commands/timesheets-reports.ts"],
4
- "sourcesContent": ["/**\n * Customer report commands \u2014 screens 13, 14 and 15.\n *\n * A report is the one artefact in this module a client can dispute, so the rules\n * it enforces are financial rather than cosmetic:\n *\n * 1. **One customer, one currency (risk R2).** Every selected project must carry\n * the report's `customerId` and they must all agree on a currency code. A\n * mismatch is refused with the offending project names rather than silently\n * averaging two currencies into one number.\n * 2. **The reference is allocated once and never reused** \u2014 see\n * `lib/timesheets-reports/reportReference.ts`. It is printed on a PDF the\n * client keeps.\n * 3. **A closed report is immutable.** Editing or deleting one is refused with\n * `409 report_closed`; the way back is the unlock command, which is gated on\n * its own feature (`staff.timesheets.reports.unlock`) precisely so \"who may\n * restate billed time\" is answerable without inventing an admin role.\n *\n * Money is never computed here. `lib/timesheets-reports/reportTotals.ts` owns\n * D-7 (round at the entry, then sum upward) and the close command below feeds\n * its per-entry results straight into the freeze records.\n */\n\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport type { CommandHandler, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport { registerCommand } from '@open-mercato/shared/lib/commands'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { buildChanges, emitCrudSideEffects, emitCrudUndoSideEffects } from '@open-mercato/shared/lib/commands/helpers'\nimport { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'\nimport type { CrudEventsConfig, CrudIndexerConfig } from '@open-mercato/shared/lib/crud/types'\nimport type { ModuleConfigService } from '@open-mercato/core/modules/configs/lib/module-config-service'\nimport {\n StaffTimeEntry,\n StaffTimeProject,\n StaffTimeReport,\n StaffTimeReportEntry,\n StaffTimeReportEvent,\n StaffTimeReportProject,\n} from '../data/entities'\nimport {\n staffTimeReportCloseSchema,\n staffTimeReportCreateSchema,\n staffTimeReportUnlockSchema,\n staffTimeReportUpdateSchema,\n type StaffTimeReportCloseInput,\n type StaffTimeReportCreateInput,\n type StaffTimeReportUnlockInput,\n type StaffTimeReportUpdateInput,\n} from '../data/validators'\nimport { readTimeTrackingSettings } from '../lib/time-tracking/settings'\nimport {\n allocateReportReference,\n highestReportSequenceNumber,\n isReportReferenceConflict,\n reportReferencePrefix,\n reportReferenceYear,\n withReportReferenceRetry,\n} from '../lib/timesheets-reports/reportReference'\nimport { loadReportData } from '../lib/timesheets-reports/loadReportData'\nimport { reportSheetLabels } from '../lib/timesheets-reports/reportLabels'\nimport {\n computeReportTotals,\n resolveEntryValues,\n resolveReportCurrency,\n selectIncludedEntries,\n} from '../lib/timesheets-reports/reportTotals'\nimport { emitStaffEvent } from '../events'\nimport {\n applyScopeToWhere,\n commandActorScope,\n commandInputScope,\n ensureOrganizationScope,\n ensureTenantScope,\n extractUndoPayload,\n scopedStaffSnapshotWhere,\n staffSnapshotScopeFromContext,\n staffSnapshotScopeFromSnapshot,\n type StaffCommandScope,\n type StaffSnapshotScope,\n} from './shared'\n\nexport const staffTimeReportCommandIds = {\n create: 'staff.timesheets.reports.create',\n update: 'staff.timesheets.reports.update',\n delete: 'staff.timesheets.reports.delete',\n close: 'staff.timesheets.reports.close',\n unlock: 'staff.timesheets.reports.unlock',\n} as const\n\nexport const STAFF_TIME_REPORT_RESOURCE_KIND = 'staff.timesheets.time_report'\n\nexport const REPORT_CURRENCY_CONFLICT_CODE = 'report_currency_conflict'\nexport const REPORT_PROJECT_CUSTOMER_MISMATCH_CODE = 'report_project_customer_mismatch'\nexport const REPORT_PROJECT_NOT_FOUND_CODE = 'report_project_not_found'\nexport const REPORT_CLOSED_CODE = 'report_closed'\nexport const REPORT_NOT_CLOSED_CODE = 'report_not_closed'\nexport const REPORT_REFERENCE_CONFLICT_CODE = 'report_reference_conflict'\nexport const REPORT_EMPTY_CODE = 'report_empty'\n\nconst logger = createLogger('staff').child({ component: 'commands/timesheets-reports' })\n\nconst reportCrudIndexer: CrudIndexerConfig<StaffTimeReport> = {\n entityType: 'staff:staff_time_report',\n}\n\nconst reportCrudEvents: CrudEventsConfig<StaffTimeReport> = {\n module: 'staff',\n entity: 'timesheets.time_report',\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 Translate = (key: string, fallback: string) => string\n\nexport type ReportSnapshot = {\n id: string\n tenantId: string\n organizationId: string\n customerId: string\n customerSnapshot: Record<string, unknown> | null\n reference: string\n title: string\n periodKind: string\n periodFrom: string | null\n periodTo: string | null\n currencyCode: string\n grouping: string\n nonbillableMode: string\n includeAlreadyReported: boolean\n showRates: boolean\n roundingUnitMinutes: number\n roundingDirection: string\n status: string\n totalBillableMinutes: number | null\n totalNonbillableMinutes: number | null\n totalAmount: string | null\n closedAt: string | null\n closedByUserId: string | null\n timeProjectIds: string[]\n deletedAt: string | null\n}\n\ntype ReportUndoPayload = {\n before?: ReportSnapshot | null\n after?: ReportSnapshot | null\n}\n\nconst DIFFED_FIELDS = [\n 'title',\n 'periodKind',\n 'periodFrom',\n 'periodTo',\n 'currencyCode',\n 'grouping',\n 'nonbillableMode',\n 'includeAlreadyReported',\n 'showRates',\n 'status',\n 'totalBillableMinutes',\n 'totalNonbillableMinutes',\n 'totalAmount',\n] as const\n\nfunction toIsoDate(value: Date | string | null | undefined): string | null {\n if (!value) return null\n if (value instanceof Date) {\n if (Number.isNaN(value.getTime())) return null\n const year = value.getFullYear()\n const month = String(value.getMonth() + 1).padStart(2, '0')\n const day = String(value.getDate()).padStart(2, '0')\n return `${year}-${month}-${day}`\n }\n const text = String(value)\n return text.length >= 10 ? text.slice(0, 10) : text\n}\n\nfunction snapshotScopeWhere(scope?: StaffSnapshotScope | null): { tenantId?: string; organizationId?: string } {\n const where: { tenantId?: string; organizationId?: string } = {}\n if (scope?.tenantId) where.tenantId = scope.tenantId\n if (scope?.organizationId) where.organizationId = scope.organizationId\n return where\n}\n\nexport async function loadReportProjectIds(\n em: EntityManager,\n reportId: string,\n scope?: StaffSnapshotScope | null,\n): Promise<string[]> {\n const rows = await em.find(StaffTimeReportProject, { reportId, ...snapshotScopeWhere(scope) })\n return rows.map((row) => row.timeProjectId)\n}\n\nfunction toSnapshot(report: StaffTimeReport, timeProjectIds: string[]): ReportSnapshot {\n return {\n id: report.id,\n tenantId: report.tenantId,\n organizationId: report.organizationId,\n customerId: report.customerId,\n customerSnapshot: report.customerSnapshot ?? null,\n reference: report.reference,\n title: report.title,\n periodKind: report.periodKind,\n periodFrom: toIsoDate(report.periodFrom),\n periodTo: toIsoDate(report.periodTo),\n currencyCode: report.currencyCode,\n grouping: report.grouping,\n nonbillableMode: report.nonbillableMode,\n includeAlreadyReported: report.includeAlreadyReported ?? false,\n showRates: report.showRates ?? true,\n roundingUnitMinutes: report.roundingUnitMinutes ?? 0,\n roundingDirection: report.roundingDirection ?? 'up',\n status: report.status,\n totalBillableMinutes: report.totalBillableMinutes ?? null,\n totalNonbillableMinutes: report.totalNonbillableMinutes ?? null,\n totalAmount: report.totalAmount ?? null,\n closedAt: report.closedAt ? report.closedAt.toISOString() : null,\n closedByUserId: report.closedByUserId ?? null,\n timeProjectIds,\n deletedAt: report.deletedAt ? report.deletedAt.toISOString() : null,\n }\n}\n\nexport async function loadReportSnapshot(\n em: EntityManager,\n id: string,\n scope?: StaffSnapshotScope | null,\n): Promise<ReportSnapshot | null> {\n const report = await em.findOne(StaffTimeReport, scopedStaffSnapshotWhere(id, scope))\n if (!report) return null\n const projectIds = await loadReportProjectIds(em, report.id, scope)\n return toSnapshot(report, projectIds)\n}\n\nexport function reportNotFoundError(translate: Translate): CrudHttpError {\n return new CrudHttpError(404, {\n error: translate('staff.time_tracking.reports.errors.notFound', 'Report not found or not accessible.'),\n })\n}\n\nexport function reportClosedError(translate: Translate, reference: string | null): CrudHttpError {\n return new CrudHttpError(409, {\n code: REPORT_CLOSED_CODE,\n error: translate(\n 'staff.time_tracking.reports.errors.closed',\n 'This report is closed. Unlock it before changing anything.',\n ),\n reference: reference ?? null,\n })\n}\n\nfunction projectsRequiredError(translate: Translate): CrudHttpError {\n const message = translate(\n 'staff.time_tracking.reports.errors.projectsRequired',\n 'Pick at least one project for this report.',\n )\n return new CrudHttpError(422, { error: message, fieldErrors: { timeProjectIds: message } })\n}\n\nfunction projectNotFoundError(translate: Translate, missingIds: string[]): CrudHttpError {\n const message = translate(\n 'staff.time_tracking.reports.errors.projectNotFound',\n 'Some of the selected projects are not available.',\n )\n return new CrudHttpError(422, {\n code: REPORT_PROJECT_NOT_FOUND_CODE,\n error: message,\n fieldErrors: { timeProjectIds: message },\n missingProjectIds: missingIds,\n })\n}\n\nfunction customerMismatchError(translate: Translate, offenders: string[]): CrudHttpError {\n const message = translate(\n 'staff.time_tracking.reports.errors.customerMismatch',\n 'A report always covers one customer. These projects belong to someone else: {projects}.',\n ).replace('{projects}', offenders.join(', '))\n return new CrudHttpError(422, {\n code: REPORT_PROJECT_CUSTOMER_MISMATCH_CODE,\n error: message,\n fieldErrors: { timeProjectIds: message },\n offenders,\n })\n}\n\n/**\n * Risk R2 refused at the cheapest point. The body names both the currencies and\n * the projects carrying them, because \"pick one currency\" is unactionable\n * without knowing which project is the odd one out.\n */\nexport function currencyConflictError(\n translate: Translate,\n currencies: string[],\n offenders: Array<{ id: string; name: string; currencyCode: string | null }>,\n): CrudHttpError {\n const message = translate(\n 'staff.time_tracking.reports.errors.currencyConflict',\n 'A report always covers one currency. Selected projects use {currencies}.',\n ).replace('{currencies}', currencies.join(', '))\n return new CrudHttpError(422, {\n code: REPORT_CURRENCY_CONFLICT_CODE,\n error: message,\n fieldErrors: { timeProjectIds: message },\n currencies,\n offenders: offenders.map((project) => ({\n id: project.id,\n name: project.name,\n currencyCode: project.currencyCode ?? null,\n })),\n })\n}\n\nfunction referenceConflictError(translate: Translate): CrudHttpError {\n return new CrudHttpError(409, {\n code: REPORT_REFERENCE_CONFLICT_CODE,\n error: translate(\n 'staff.time_tracking.reports.errors.referenceConflict',\n 'Could not allocate a report number right now. Try again.',\n ),\n })\n}\n\nexport type ResolvedReportProjects = {\n projects: StaffTimeProject[]\n currencyCode: string\n}\n\n/**\n * The single validation gate every write shares: the projects exist in scope,\n * they all belong to the report's customer, and they agree on a currency.\n */\nexport async function resolveReportProjects(\n em: EntityManager,\n timeProjectIds: readonly string[],\n customerId: string,\n scope: StaffCommandScope,\n translate: Translate,\n): Promise<ResolvedReportProjects> {\n const ids = Array.from(new Set(timeProjectIds.filter((id) => typeof id === 'string' && id.length > 0)))\n if (ids.length === 0) throw projectsRequiredError(translate)\n\n const projects = await em.find(\n StaffTimeProject,\n applyScopeToWhere<StaffTimeProject>({ id: { $in: ids }, deletedAt: null }, scope),\n )\n if (projects.length !== ids.length) {\n const found = new Set(projects.map((project) => project.id))\n throw projectNotFoundError(\n translate,\n ids.filter((id) => !found.has(id)),\n )\n }\n\n const mismatched = projects.filter((project) => (project.customerId ?? null) !== customerId)\n if (mismatched.length > 0) {\n throw customerMismatchError(\n translate,\n mismatched.map((project) => project.name),\n )\n }\n\n const resolution = resolveReportCurrency(\n projects.map((project) => ({\n id: project.id,\n name: project.name,\n currencyCode: project.currencyCode ?? null,\n })),\n )\n if (!resolution.ok) {\n throw currencyConflictError(translate, resolution.currencies, resolution.offenders)\n }\n\n return { projects, currencyCode: resolution.currencyCode ?? '' }\n}\n\n/**\n * D-9: the report carries the customer as an FK id plus a denormalized snapshot,\n * so the sheet header resolves a client name without joining the customers\n * module \u2014 and keeps resolving it if that customer is later removed. The\n * snapshot is taken from the selected projects, which already carry one, rather\n * than reaching across the module boundary a second time.\n */\nexport function deriveCustomerSnapshot(projects: readonly StaffTimeProject[]): Record<string, unknown> | null {\n for (const project of projects) {\n const snapshot = project.customerSnapshot\n if (snapshot && typeof snapshot === 'object' && Object.keys(snapshot).length > 0) {\n return snapshot as Record<string, unknown>\n }\n }\n return null\n}\n\nasync function readRoundingSnapshot(\n ctx: CommandRuntimeContext,\n tenantId: string,\n): Promise<{ unitMinutes: number; direction: string }> {\n try {\n const configService = ctx.container.resolve('moduleConfigService') as ModuleConfigService\n const settings = await readTimeTrackingSettings(configService, { tenantId })\n return { unitMinutes: settings.rounding.unitMinutes, direction: settings.rounding.direction }\n } catch (err) {\n // A draft that cannot read the rule still has to exist; close re-stamps it.\n logger.warn('staff.timesheets.reports rounding snapshot unavailable', { err })\n return { unitMinutes: 0, direction: 'up' }\n }\n}\n\nasync function replaceReportProjects(\n em: EntityManager,\n report: StaffTimeReport,\n projects: readonly StaffTimeProject[],\n): Promise<void> {\n const existing = await em.find(StaffTimeReportProject, { reportId: report.id })\n for (const row of existing) em.remove(row)\n for (const project of projects) {\n em.persist(\n em.create(StaffTimeReportProject, {\n tenantId: report.tenantId,\n organizationId: report.organizationId,\n reportId: report.id,\n timeProjectId: project.id,\n createdAt: new Date(),\n }),\n )\n }\n}\n\nfunction actorUserId(ctx: CommandRuntimeContext): string | null {\n return typeof ctx.auth?.sub === 'string' ? ctx.auth.sub : null\n}\n\n/**\n * The highest report number the organization has EVER handed out this year,\n * soft-deleted rows included. The unique index covers live rows only, so a\n * deleted `RAP-2026-0042` would otherwise be reissued behind a PDF a client\n * already holds.\n */\nasync function readHighestReportSequence(\n em: EntityManager,\n year: number,\n scope: StaffCommandScope,\n): Promise<number> {\n const rows = await em.find(\n StaffTimeReport,\n applyScopeToWhere<StaffTimeReport>({ reference: { $like: `${reportReferencePrefix(year)}%` } }, scope),\n )\n return highestReportSequenceNumber(\n rows.map((row) => row.reference),\n year,\n )\n}\n\nconst createReportCommand: CommandHandler<StaffTimeReportCreateInput, { reportId: string }> = {\n id: staffTimeReportCommandIds.create,\n async execute(rawInput, ctx) {\n const parsed = staffTimeReportCreateSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n const scope = commandInputScope(ctx, parsed.tenantId, parsed.organizationId)\n const { translate } = await resolveTranslations()\n const baseEm = ctx.container.resolve('em') as EntityManager\n const createdByUserId = actorUserId(ctx)\n const rounding = await readRoundingSnapshot(ctx, parsed.tenantId)\n const issuedAt = new Date()\n const year = reportReferenceYear(issuedAt)\n\n let record: StaffTimeReport\n try {\n record = await withReportReferenceRetry(async () => {\n // A fresh fork per attempt: a lost race aborts the transaction, so the\n // retry re-reads the highest reference rather than reusing a stale max.\n const em = baseEm.fork()\n let created: StaffTimeReport | null = null\n let plan: { projects: StaffTimeProject[]; currencyCode: string; highest: number } | null = null\n\n await withAtomicFlush(\n em,\n [\n async () => {\n const resolved = await resolveReportProjects(\n em,\n parsed.timeProjectIds,\n parsed.customerId,\n scope,\n translate,\n )\n plan = {\n projects: resolved.projects,\n currencyCode: resolved.currencyCode,\n highest: await readHighestReportSequence(em, year, scope),\n }\n },\n () => {\n if (!plan) throw reportNotFoundError(translate)\n const allocation = allocateReportReference(year, plan.highest)\n const now = new Date()\n created = em.create(StaffTimeReport, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n customerId: parsed.customerId,\n customerSnapshot: deriveCustomerSnapshot(plan.projects),\n reference: allocation.reference,\n title: parsed.title,\n periodKind: parsed.periodKind,\n periodFrom: parsed.periodFrom,\n periodTo: parsed.periodTo,\n currencyCode: plan.currencyCode,\n grouping: parsed.grouping,\n nonbillableMode: parsed.nonbillableMode,\n includeAlreadyReported: parsed.includeAlreadyReported,\n showRates: parsed.showRates,\n roundingUnitMinutes: rounding.unitMinutes,\n roundingDirection: rounding.direction,\n status: 'draft',\n createdByUserId,\n createdAt: now,\n updatedAt: now,\n deletedAt: null,\n })\n em.persist(created)\n },\n async () => {\n if (!created || !plan) return\n await replaceReportProjects(em, created, plan.projects)\n },\n ],\n { transaction: true, label: staffTimeReportCommandIds.create },\n )\n\n if (!created) throw reportNotFoundError(translate)\n return created as StaffTimeReport\n })\n } catch (err) {\n if (isReportReferenceConflict(err)) throw referenceConflictError(translate)\n throw err\n }\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'created',\n entity: record,\n identifiers: { id: record.id, organizationId: record.organizationId, tenantId: record.tenantId },\n events: reportCrudEvents,\n indexer: reportCrudIndexer,\n })\n\n return { reportId: record.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadReportSnapshot(em, result.reportId, staffSnapshotScopeFromContext(ctx))\n if (!snapshot) return null\n return { snapshot }\n },\n buildLog: async ({ result, ctx }) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadReportSnapshot(em, result.reportId, staffSnapshotScopeFromContext(ctx))\n if (!snapshot) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.reports.create', 'Create report'),\n resourceKind: STAFF_TIME_REPORT_RESOURCE_KIND,\n resourceId: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n snapshotAfter: snapshot,\n payload: { undo: { after: snapshot } satisfies ReportUndoPayload },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<ReportUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const report = await em.findOne(\n StaffTimeReport,\n scopedStaffSnapshotWhere(after.id, staffSnapshotScopeFromSnapshot(after)),\n )\n if (!report) return\n // A report that has since been closed froze entries; undoing its creation\n // would strand those locks, so the undo declines rather than half-unwinding.\n if (report.status === 'closed') return\n report.deletedAt = new Date()\n report.updatedAt = new Date()\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'deleted',\n entity: report,\n identifiers: { id: report.id, organizationId: report.organizationId, tenantId: report.tenantId },\n events: reportCrudEvents,\n indexer: reportCrudIndexer,\n })\n },\n}\n\nconst updateReportCommand: CommandHandler<StaffTimeReportUpdateInput, { reportId: string }> = {\n id: staffTimeReportCommandIds.update,\n async prepare(rawInput, ctx) {\n const parsed = staffTimeReportUpdateSchema.safeParse(rawInput)\n if (!parsed.success) return {}\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const before = await loadReportSnapshot(em, parsed.data.id, staffSnapshotScopeFromContext(ctx))\n if (!before) return {}\n return { before: { snapshot: before } }\n },\n async execute(rawInput, ctx) {\n const parsed = staffTimeReportUpdateSchema.parse(rawInput)\n const { translate } = await resolveTranslations()\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n\n const report = await em.findOne(\n StaffTimeReport,\n applyScopeToWhere<StaffTimeReport>({ id: parsed.id, deletedAt: null }, scope),\n )\n if (!report) throw reportNotFoundError(translate)\n ensureTenantScope(ctx, report.tenantId)\n ensureOrganizationScope(ctx, report.organizationId)\n if (report.status === 'closed') throw reportClosedError(translate, report.reference)\n\n const targetCustomerId = parsed.customerId ?? report.customerId\n let resolved: ResolvedReportProjects | null = null\n\n await withAtomicFlush(\n em,\n [\n async () => {\n const needsProjectCheck =\n parsed.timeProjectIds !== undefined || (parsed.customerId !== undefined && parsed.customerId !== report.customerId)\n if (!needsProjectCheck) return\n const ids = parsed.timeProjectIds ?? (await loadReportProjectIds(em, report.id, scope))\n resolved = await resolveReportProjects(em, ids, targetCustomerId, scope, translate)\n },\n () => {\n const now = new Date()\n if (parsed.title !== undefined) report.title = parsed.title\n if (parsed.periodKind !== undefined) report.periodKind = parsed.periodKind\n if (parsed.periodFrom !== undefined) report.periodFrom = parsed.periodFrom\n if (parsed.periodTo !== undefined) report.periodTo = parsed.periodTo\n if (parsed.grouping !== undefined) report.grouping = parsed.grouping\n if (parsed.nonbillableMode !== undefined) report.nonbillableMode = parsed.nonbillableMode\n if (parsed.includeAlreadyReported !== undefined) {\n report.includeAlreadyReported = parsed.includeAlreadyReported\n }\n if (parsed.showRates !== undefined) report.showRates = parsed.showRates\n if (parsed.customerId !== undefined) report.customerId = parsed.customerId\n if (resolved) {\n report.currencyCode = resolved.currencyCode\n report.customerSnapshot = deriveCustomerSnapshot(resolved.projects) ?? report.customerSnapshot ?? null\n }\n report.updatedAt = now\n },\n async () => {\n if (!resolved || parsed.timeProjectIds === undefined) return\n await replaceReportProjects(em, report, resolved.projects)\n },\n ],\n { transaction: true, label: staffTimeReportCommandIds.update },\n )\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'updated',\n entity: report,\n identifiers: { id: report.id, organizationId: report.organizationId, tenantId: report.tenantId },\n events: reportCrudEvents,\n indexer: reportCrudIndexer,\n })\n\n return { reportId: report.id }\n },\n buildLog: async ({ snapshots, ctx }) => {\n const before = (snapshots.before as { snapshot?: ReportSnapshot } | undefined)?.snapshot\n if (!before) return null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const after = await loadReportSnapshot(em, before.id, staffSnapshotScopeFromSnapshot(before))\n if (!after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.reports.update', 'Update report'),\n resourceKind: STAFF_TIME_REPORT_RESOURCE_KIND,\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes: buildChanges(\n before as unknown as Record<string, unknown>,\n after as unknown as Record<string, unknown>,\n [...DIFFED_FIELDS],\n ),\n payload: { undo: { before, after } satisfies ReportUndoPayload },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<ReportUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const report = await em.findOne(\n StaffTimeReport,\n scopedStaffSnapshotWhere(before.id, staffSnapshotScopeFromSnapshot(before)),\n )\n if (!report) return\n if (report.status === 'closed') return\n\n const projects = await em.find(StaffTimeProject, {\n id: { $in: before.timeProjectIds },\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n })\n\n await withAtomicFlush(\n em,\n [\n () => {\n report.customerId = before.customerId\n report.customerSnapshot = before.customerSnapshot\n report.title = before.title\n report.periodKind = before.periodKind as StaffTimeReport['periodKind']\n if (before.periodFrom) report.periodFrom = new Date(before.periodFrom)\n if (before.periodTo) report.periodTo = new Date(before.periodTo)\n report.currencyCode = before.currencyCode\n report.grouping = before.grouping as StaffTimeReport['grouping']\n report.nonbillableMode = before.nonbillableMode as StaffTimeReport['nonbillableMode']\n report.includeAlreadyReported = before.includeAlreadyReported\n report.showRates = before.showRates\n report.updatedAt = new Date()\n },\n async () => {\n if (projects.length !== before.timeProjectIds.length) return\n await replaceReportProjects(em, report, projects)\n },\n ],\n { transaction: true, label: `${staffTimeReportCommandIds.update}.undo` },\n )\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'updated',\n entity: report,\n identifiers: { id: report.id, organizationId: report.organizationId, tenantId: report.tenantId },\n events: reportCrudEvents,\n indexer: reportCrudIndexer,\n })\n },\n}\n\nconst deleteReportCommand: CommandHandler<{ id?: string }, { reportId: string }> = {\n id: staffTimeReportCommandIds.delete,\n async prepare(input, ctx) {\n const id = input?.id\n if (!id) return {}\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const before = await loadReportSnapshot(em, id, staffSnapshotScopeFromContext(ctx))\n if (!before) return {}\n return { before: { snapshot: before } }\n },\n async execute(input, ctx) {\n const { translate } = await resolveTranslations()\n const id = input?.id\n if (!id) {\n throw new CrudHttpError(400, {\n error: translate('staff.time_tracking.reports.errors.idRequired', 'Report id is required.'),\n })\n }\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n const report = await em.findOne(\n StaffTimeReport,\n applyScopeToWhere<StaffTimeReport>({ id, deletedAt: null }, scope),\n )\n if (!report) throw reportNotFoundError(translate)\n ensureTenantScope(ctx, report.tenantId)\n ensureOrganizationScope(ctx, report.organizationId)\n // Deleting a closed report would strand every entry it froze: their\n // `locked_report_id` would point at a row nothing can unlock.\n if (report.status === 'closed') throw reportClosedError(translate, report.reference)\n\n const now = new Date()\n report.deletedAt = now\n report.updatedAt = now\n await em.flush()\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'deleted',\n entity: report,\n identifiers: { id: report.id, organizationId: report.organizationId, tenantId: report.tenantId },\n events: reportCrudEvents,\n indexer: reportCrudIndexer,\n })\n\n return { reportId: report.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = (snapshots.before as { snapshot?: ReportSnapshot } | undefined)?.snapshot\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.reports.delete', 'Delete report'),\n resourceKind: STAFF_TIME_REPORT_RESOURCE_KIND,\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: { undo: { before } satisfies ReportUndoPayload },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<ReportUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const report = await em.findOne(\n StaffTimeReport,\n scopedStaffSnapshotWhere(before.id, staffSnapshotScopeFromSnapshot(before)),\n )\n if (!report) return\n report.deletedAt = null\n report.updatedAt = new Date()\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'created',\n entity: report,\n identifiers: { id: report.id, organizationId: report.organizationId, tenantId: report.tenantId },\n events: reportCrudEvents,\n indexer: reportCrudIndexer,\n })\n },\n}\n\nregisterCommand(createReportCommand)\nregisterCommand(updateReportCommand)\nregisterCommand(deleteReportCommand)\n\n/**\n * US-G3 \u2014 close & lock. This is the only place a lock is created: exporting a\n * PDF freezes nothing (screen 14 note 5), because \"in a generated/sent report\"\n * (\u00A79) is ambiguous and a download that silently locks a team's timesheet is the\n * worse reading of it.\n *\n * Everything the close writes happens inside ONE `withAtomicFlush({ transaction:\n * true })`: the per-entry freeze records, the `locked_report_id` stamps, the\n * frozen report totals and the `closed` audit event. A partial close would leave\n * entries frozen against a report that never closed \u2014 unlockable by nobody,\n * because the unlock command refuses a draft.\n *\n * Two rules that are easy to get wrong:\n *\n * - **The freeze records come from the same `selectIncludedEntries` /\n * `resolveEntryValues` pair the sheet printed**, so what is frozen is by\n * construction what the client was shown. The amounts are already rounded at\n * the entry (D-7), which is what lets `total_amount` be an exact sum.\n * - **An entry already locked by another report keeps that lock.** When the\n * D-5 opt-in pulls a previously billed hour into a second report, this report\n * records what it billed, but ownership of the lock stays with the report\n * that froze it first \u2014 otherwise unlocking the earlier report would leave\n * the hour editable while a later closed report still quotes it.\n */\nexport type StaffTimeReportCloseResult = {\n reportId: string\n lockedEntryCount: number\n totalAmount: number\n totalBillableMinutes: number\n totalNonbillableMinutes: number\n}\n\nfunction reportNotClosedError(translate: Translate): CrudHttpError {\n return new CrudHttpError(409, {\n code: REPORT_NOT_CLOSED_CODE,\n error: translate(\n 'staff.time_tracking.reports.errors.notClosed',\n 'This report is not closed, so there is nothing to unlock.',\n ),\n })\n}\n\nfunction reportEmptyError(translate: Translate): CrudHttpError {\n return new CrudHttpError(422, {\n code: REPORT_EMPTY_CODE,\n error: translate(\n 'staff.time_tracking.reports.errors.empty',\n 'This report covers no time entries, so there is nothing to freeze. Adjust the period or the project selection first.',\n ),\n })\n}\n\nconst closeReportCommand: CommandHandler<StaffTimeReportCloseInput, StaffTimeReportCloseResult> = {\n id: staffTimeReportCommandIds.close,\n async prepare(rawInput, ctx) {\n const parsed = staffTimeReportCloseSchema.safeParse(rawInput)\n if (!parsed.success) return {}\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const before = await loadReportSnapshot(em, parsed.data.id, staffSnapshotScopeFromContext(ctx))\n if (!before) return {}\n return { before: { snapshot: before } }\n },\n async execute(rawInput, ctx) {\n const parsed = staffTimeReportCloseSchema.parse(rawInput)\n const { translate } = await resolveTranslations()\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n\n const report = await em.findOne(\n StaffTimeReport,\n applyScopeToWhere<StaffTimeReport>({ id: parsed.id, deletedAt: null }, scope),\n )\n if (!report) throw reportNotFoundError(translate)\n ensureTenantScope(ctx, report.tenantId)\n ensureOrganizationScope(ctx, report.organizationId)\n if (report.status === 'closed') throw reportClosedError(translate, report.reference)\n\n const dataScope = { tenantId: report.tenantId, organizationId: report.organizationId }\n const rounding = await readRoundingSnapshot(ctx, report.tenantId)\n const actorId = actorUserId(ctx)\n const labels = reportSheetLabels(translate)\n\n type ClosePlanItem = {\n entry: ReturnType<typeof selectIncludedEntries>[number]\n row: StaffTimeEntry | null\n values: ReturnType<typeof resolveEntryValues>\n currencyCode: string\n }\n\n let lockedEntryCount = 0\n let totals: ReturnType<typeof computeReportTotals> | null = null\n let closePlan: ClosePlanItem[] = []\n\n await withAtomicFlush(\n em,\n [\n async () => {\n const timeProjectIds = await loadReportProjectIds(em, report.id, dataScope)\n const data = await loadReportData({\n em,\n scope: dataScope,\n timeProjectIds,\n periodFrom: report.periodFrom,\n periodTo: report.periodTo,\n })\n const options = {\n grouping: report.grouping,\n nonbillableMode: report.nonbillableMode,\n includeAlreadyReported: report.includeAlreadyReported ?? false,\n } as const\n const included = selectIncludedEntries(data.entries, options, report.id)\n if (included.length === 0) throw reportEmptyError(translate)\n\n totals = computeReportTotals({\n entries: data.entries,\n projects: data.projects,\n directory: data.directory,\n options,\n currentReportId: report.id,\n labels,\n })\n\n const projectById = new Map(data.projects.map((project) => [project.id, project]))\n const entryRows = await em.find(StaffTimeEntry, {\n id: { $in: included.map((entry) => entry.id) },\n tenantId: report.tenantId,\n organizationId: report.organizationId,\n })\n const entryById = new Map(entryRows.map((row) => [row.id, row]))\n\n closePlan = included.map((entry) => ({\n entry,\n row: entryById.get(entry.id) ?? null,\n values: resolveEntryValues(entry, projectById.get(entry.timeProjectId) ?? null),\n currencyCode:\n projectById.get(entry.timeProjectId)?.currencyCode ?? report.currencyCode ?? '',\n }))\n },\n () => {\n if (!totals) throw reportEmptyError(translate)\n const now = new Date()\n for (const item of closePlan) {\n em.persist(\n em.create(StaffTimeReportEntry, {\n tenantId: report.tenantId,\n organizationId: report.organizationId,\n reportId: report.id,\n timeEntryId: item.entry.id,\n frozenRawMinutes: item.values.rawMinutes,\n frozenRoundedMinutes: item.values.minutes,\n frozenRateAmount: item.values.rate === null ? null : String(item.values.rate),\n frozenCurrencyCode: item.currencyCode,\n frozenAmount: item.values.amount === null ? null : item.values.amount.toFixed(2),\n frozenIsBillable: item.values.isBillable,\n createdAt: now,\n }),\n )\n const row = item.row\n if (!row) continue\n // Ownership of an existing lock is never transferred \u2014 see the note\n // on this command.\n if (row.lockedReportId) continue\n row.lockedReportId = report.id\n row.lockedAt = now\n row.updatedAt = now\n lockedEntryCount += 1\n }\n\n report.status = 'closed'\n report.closedAt = now\n report.closedByUserId = actorId\n report.roundingUnitMinutes = rounding.unitMinutes\n report.roundingDirection = rounding.direction\n report.totalBillableMinutes = totals.billableMinutes\n report.totalNonbillableMinutes = totals.nonbillableMinutes\n report.totalAmount = totals.totalAmount.toFixed(2)\n report.updatedAt = now\n\n em.persist(\n em.create(StaffTimeReportEvent, {\n tenantId: report.tenantId,\n organizationId: report.organizationId,\n reportId: report.id,\n eventType: 'closed',\n reason: null,\n actorUserId: actorId,\n metadata: {\n frozenEntryCount: closePlan.length,\n lockedEntryCount,\n totalAmount: totals.totalAmount,\n currencyCode: report.currencyCode,\n roundingUnitMinutes: rounding.unitMinutes,\n roundingDirection: rounding.direction,\n },\n createdAt: now,\n }),\n )\n },\n ],\n { transaction: true, label: staffTimeReportCommandIds.close },\n )\n\n const resolved = totals as ReturnType<typeof computeReportTotals> | null\n const result: StaffTimeReportCloseResult = {\n reportId: report.id,\n lockedEntryCount,\n totalAmount: resolved?.totalAmount ?? 0,\n totalBillableMinutes: resolved?.billableMinutes ?? 0,\n totalNonbillableMinutes: resolved?.nonbillableMinutes ?? 0,\n }\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'updated',\n entity: report,\n identifiers: { id: report.id, organizationId: report.organizationId, tenantId: report.tenantId },\n events: reportCrudEvents,\n indexer: reportCrudIndexer,\n })\n\n // A failed broadcast must never fail a committed close.\n //\n // The payload is spelled out rather than spreading `result` because this event is\n // `clientBroadcast: true`: the DOM Event Bridge delivers it to every user of the\n // organization with no feature check, and `result.totalAmount` is money, which is\n // gated on `staff.timesheets.rates.view`. The minute totals and the locked-entry\n // count are not money and are what a live report screen needs; the amount is read\n // back from the report itself by a caller entitled to it.\n //\n // What else that unfiltered audience decides, field by field:\n //\n // - `customerId` is DROPPED. It is the one field that links a report to a named\n // client, and one organization serves many; a tenant's whole staff learning\n // which client was billed this week is a disclosure with no consumer asking\n // for it. The schema always declared it optional, both in-repo subscribers\n // re-read the report from the database, and the portal mirror\n // (`time_report.portal_published`) resolves the customer itself.\n // - `reference` and the two minute totals STAY. They are stable identifiers and\n // non-money aggregates, they are the published webhook contract an external\n // billing system codes against, and they are what a live reports screen needs\n // to refresh a row. Narrowing them further is not expressible here: the DOM\n // bridge can only pin an audience by user or ROLE id, and this module\n // deliberately gates on immutable feature ids rather than mutable roles.\n void emitStaffEvent('staff.timesheets.time_report.closed', {\n id: report.id,\n tenantId: report.tenantId,\n organizationId: report.organizationId,\n reference: report.reference,\n reportId: result.reportId,\n lockedEntryCount: result.lockedEntryCount,\n totalBillableMinutes: result.totalBillableMinutes,\n totalNonbillableMinutes: result.totalNonbillableMinutes,\n }).catch((err) => {\n logger.error('staff.timesheets emit time_report.closed failed', { err })\n })\n\n // The close froze `lockedEntryCount` entries. The entry-scoped subscribers key\n // off a single record id, so this batch-level notice carries none and reaches\n // only the ones that care about a period being frozen.\n if (lockedEntryCount > 0) {\n void emitStaffEvent('staff.timesheets.time_entry.locked', {\n tenantId: report.tenantId,\n organizationId: report.organizationId,\n reportId: report.id,\n lockedEntryCount,\n }).catch((err) => {\n logger.error('staff.timesheets emit time_entry.locked failed', { err })\n })\n }\n\n return result\n },\n buildLog: async ({ snapshots, ctx }) => {\n const before = (snapshots.before as { snapshot?: ReportSnapshot } | undefined)?.snapshot\n if (!before) return null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const after = await loadReportSnapshot(em, before.id, staffSnapshotScopeFromSnapshot(before))\n if (!after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.reports.close', 'Close and lock report'),\n resourceKind: STAFF_TIME_REPORT_RESOURCE_KIND,\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes: buildChanges(\n before as unknown as Record<string, unknown>,\n after as unknown as Record<string, unknown>,\n [...DIFFED_FIELDS],\n ),\n // Deliberately no `undo` payload: unwinding a close is the unlock command,\n // which requires a reason and its own feature. A silent undo of a billing\n // freeze is exactly what US-G3 forbids.\n }\n },\n}\n\n/**\n * US-G3's other half \u2014 unlock, screen 15.\n *\n * Three things make it an \"explicit, audited action\" rather than a confirm\n * dialog: it takes a mandatory reason, it appends an `unlocked` event carrying\n * that reason and the actor, and it is gated on `staff.timesheets.reports.unlock`\n * \u2014 a feature distinct from `staff.timesheets.lock`, so \"who may restate billed\n * time\" can be answered by withholding it from a Team Leader without inventing\n * the admin role \u00A710 rejects.\n *\n * The freeze records are DELETED rather than kept. Two reasons: `staff_time_\n * report_entries` is what makes D-5 answerable (\"is this hour already billed?\"),\n * so leaving stale rows behind after the report reopened would keep hours out of\n * the next invoice for no reason; and the unique `(report_id, time_entry_id)`\n * index would otherwise refuse the re-close. The numbers they held are copied\n * into the `unlocked` event's metadata, so the audit trail keeps what was\n * frozen.\n */\nexport type StaffTimeReportUnlockResult = {\n reportId: string\n unlockedEntryCount: number\n}\n\nconst unlockReportCommand: CommandHandler<StaffTimeReportUnlockInput, StaffTimeReportUnlockResult> = {\n id: staffTimeReportCommandIds.unlock,\n async prepare(rawInput, ctx) {\n const parsed = staffTimeReportUnlockSchema.safeParse(rawInput)\n if (!parsed.success) return {}\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const before = await loadReportSnapshot(em, parsed.data.id, staffSnapshotScopeFromContext(ctx))\n if (!before) return {}\n return { before: { snapshot: before } }\n },\n async execute(rawInput, ctx) {\n const parsed = staffTimeReportUnlockSchema.parse(rawInput)\n const { translate } = await resolveTranslations()\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n\n const report = await em.findOne(\n StaffTimeReport,\n applyScopeToWhere<StaffTimeReport>({ id: parsed.id, deletedAt: null }, scope),\n )\n if (!report) throw reportNotFoundError(translate)\n ensureTenantScope(ctx, report.tenantId)\n ensureOrganizationScope(ctx, report.organizationId)\n if (report.status !== 'closed') throw reportNotClosedError(translate)\n\n const actorId = actorUserId(ctx)\n let unlockedEntryCount = 0\n let frozenEntries: StaffTimeReportEntry[] = []\n let lockedRows: StaffTimeEntry[] = []\n const frozenTotals = {\n totalAmount: report.totalAmount,\n totalBillableMinutes: report.totalBillableMinutes ?? null,\n totalNonbillableMinutes: report.totalNonbillableMinutes ?? null,\n }\n\n await withAtomicFlush(\n em,\n [\n async () => {\n frozenEntries = await em.find(StaffTimeReportEntry, {\n reportId: report.id,\n tenantId: report.tenantId,\n organizationId: report.organizationId,\n })\n lockedRows = await em.find(StaffTimeEntry, {\n lockedReportId: report.id,\n tenantId: report.tenantId,\n organizationId: report.organizationId,\n })\n },\n () => {\n const now = new Date()\n for (const row of lockedRows) {\n row.lockedReportId = null\n row.lockedAt = null\n row.updatedAt = now\n unlockedEntryCount += 1\n }\n for (const frozen of frozenEntries) em.remove(frozen)\n\n report.status = 'draft'\n report.closedAt = null\n report.closedByUserId = null\n report.totalAmount = null\n report.totalBillableMinutes = null\n report.totalNonbillableMinutes = null\n report.updatedAt = now\n\n em.persist(\n em.create(StaffTimeReportEvent, {\n tenantId: report.tenantId,\n organizationId: report.organizationId,\n reportId: report.id,\n eventType: 'unlocked',\n reason: parsed.reason,\n actorUserId: actorId,\n metadata: {\n unlockedEntryCount,\n frozenEntryCount: frozenEntries.length,\n frozenTotalAmount: frozenTotals.totalAmount,\n frozenBillableMinutes: frozenTotals.totalBillableMinutes,\n frozenNonbillableMinutes: frozenTotals.totalNonbillableMinutes,\n currencyCode: report.currencyCode,\n },\n createdAt: now,\n }),\n )\n },\n ],\n { transaction: true, label: staffTimeReportCommandIds.unlock },\n )\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'updated',\n entity: report,\n identifiers: { id: report.id, organizationId: report.organizationId, tenantId: report.tenantId },\n events: reportCrudEvents,\n indexer: reportCrudIndexer,\n })\n\n // `reason` is deliberately NOT on the wire.\n //\n // This event is `clientBroadcast: true`, and the DOM Event Bridge filters a\n // broadcast by tenant + organization only \u2014 no feature check \u2014 so every\n // signed-in user of the organization receives whatever the payload carries.\n // `reason` is mandatory operator prose of up to 2000 characters explaining why\n // a client's billing was reopened; broadcasting it organization-wide is a\n // disclosure the screen it comes from (`staff.timesheets.reports.unlock`) does\n // not make. It is already persisted verbatim on the `StaffTimeReportEvent`\n // audit row above, which is read behind the ACL, so nothing is lost.\n void emitStaffEvent('staff.timesheets.time_report.unlocked', {\n id: report.id,\n tenantId: report.tenantId,\n organizationId: report.organizationId,\n reference: report.reference,\n actorUserId: actorId,\n unlockedEntryCount,\n }).catch((err) => {\n logger.error('staff.timesheets emit time_report.unlocked failed', { err })\n })\n\n if (unlockedEntryCount > 0) {\n void emitStaffEvent('staff.timesheets.time_entry.unlocked', {\n tenantId: report.tenantId,\n organizationId: report.organizationId,\n reportId: report.id,\n unlockedEntryCount,\n }).catch((err) => {\n logger.error('staff.timesheets emit time_entry.unlocked failed', { err })\n })\n }\n\n return { reportId: report.id, unlockedEntryCount }\n },\n buildLog: async ({ snapshots, ctx, input }) => {\n const before = (snapshots.before as { snapshot?: ReportSnapshot } | undefined)?.snapshot\n if (!before) return null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const after = await loadReportSnapshot(em, before.id, staffSnapshotScopeFromSnapshot(before))\n if (!after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.reports.unlock', 'Unlock report entries'),\n resourceKind: STAFF_TIME_REPORT_RESOURCE_KIND,\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes: buildChanges(\n before as unknown as Record<string, unknown>,\n after as unknown as Record<string, unknown>,\n [...DIFFED_FIELDS],\n ),\n payload: { reason: input?.reason ?? null },\n }\n },\n}\n\nregisterCommand(closeReportCommand)\nregisterCommand(unlockReportCommand)\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Customer report commands \u2014 screens 13, 14 and 15.\n *\n * A report is the one artefact in this module a client can dispute, so the rules\n * it enforces are financial rather than cosmetic:\n *\n * 1. **One customer, one currency (risk R2).** Every selected project must carry\n * the report's `customerId` and they must all agree on a currency code. A\n * mismatch is refused with the offending project names rather than silently\n * averaging two currencies into one number.\n * 2. **The reference is allocated once and never reused** \u2014 see\n * `lib/timesheets-reports/reportReference.ts`. It is printed on a PDF the\n * client keeps.\n * 3. **A closed report is immutable.** Editing or deleting one is refused with\n * `409 report_closed`; the way back is the unlock command, which is gated on\n * its own feature (`staff.timesheets.reports.unlock`) precisely so \"who may\n * restate billed time\" is answerable without inventing an admin role.\n *\n * Money is never computed here. `lib/timesheets-reports/reportTotals.ts` owns\n * D-7 (round at the entry, then sum upward) and the close command below feeds\n * its per-entry results straight into the freeze records.\n */\n\nimport { LockMode } from '@mikro-orm/core'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport type { CommandHandler, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport { registerCommand } from '@open-mercato/shared/lib/commands'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { buildChanges, emitCrudSideEffects, emitCrudUndoSideEffects } from '@open-mercato/shared/lib/commands/helpers'\nimport { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'\nimport type { CrudEventsConfig, CrudIndexerConfig } from '@open-mercato/shared/lib/crud/types'\nimport type { ModuleConfigService } from '@open-mercato/core/modules/configs/lib/module-config-service'\nimport {\n StaffTimeEntry,\n StaffTimeProject,\n StaffTimeReport,\n StaffTimeReportEntry,\n StaffTimeReportEvent,\n StaffTimeReportProject,\n} from '../data/entities'\nimport {\n staffTimeReportCloseSchema,\n staffTimeReportCreateSchema,\n staffTimeReportUnlockSchema,\n staffTimeReportUpdateSchema,\n type StaffTimeReportCloseInput,\n type StaffTimeReportCreateInput,\n type StaffTimeReportUnlockInput,\n type StaffTimeReportUpdateInput,\n} from '../data/validators'\nimport { readTimeTrackingSettings } from '../lib/time-tracking/settings'\nimport {\n allocateReportReference,\n highestReportSequenceNumber,\n isReportReferenceConflict,\n reportReferencePrefix,\n reportReferenceYear,\n withReportReferenceRetry,\n} from '../lib/timesheets-reports/reportReference'\nimport { loadClosedReportFreezes, loadReportData } from '../lib/timesheets-reports/loadReportData'\nimport { reportSheetLabels } from '../lib/timesheets-reports/reportLabels'\nimport {\n computeReportTotals,\n resolveEntryValues,\n resolveReportCurrency,\n selectIncludedEntries,\n} from '../lib/timesheets-reports/reportTotals'\nimport { emitStaffEvent } from '../events'\nimport {\n applyScopeToWhere,\n commandActorScope,\n commandInputScope,\n ensureOrganizationScope,\n ensureTenantScope,\n extractUndoPayload,\n scopedStaffSnapshotWhere,\n staffSnapshotScopeFromContext,\n staffSnapshotScopeFromSnapshot,\n type StaffCommandScope,\n type StaffSnapshotScope,\n} from './shared'\n\nexport const staffTimeReportCommandIds = {\n create: 'staff.timesheets.reports.create',\n update: 'staff.timesheets.reports.update',\n delete: 'staff.timesheets.reports.delete',\n close: 'staff.timesheets.reports.close',\n unlock: 'staff.timesheets.reports.unlock',\n} as const\n\nexport const STAFF_TIME_REPORT_RESOURCE_KIND = 'staff.timesheets.time_report'\n\nexport const REPORT_CURRENCY_CONFLICT_CODE = 'report_currency_conflict'\nexport const REPORT_PROJECT_CUSTOMER_MISMATCH_CODE = 'report_project_customer_mismatch'\nexport const REPORT_PROJECT_NOT_FOUND_CODE = 'report_project_not_found'\nexport const REPORT_CLOSED_CODE = 'report_closed'\nexport const REPORT_NOT_CLOSED_CODE = 'report_not_closed'\nexport const REPORT_REFERENCE_CONFLICT_CODE = 'report_reference_conflict'\nexport const REPORT_EMPTY_CODE = 'report_empty'\n\nconst logger = createLogger('staff').child({ component: 'commands/timesheets-reports' })\n\nconst reportCrudIndexer: CrudIndexerConfig<StaffTimeReport> = {\n entityType: 'staff:staff_time_report',\n}\n\nconst reportCrudEvents: CrudEventsConfig<StaffTimeReport> = {\n module: 'staff',\n entity: 'timesheets.time_report',\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 Translate = (key: string, fallback: string) => string\n\nexport type ReportSnapshot = {\n id: string\n tenantId: string\n organizationId: string\n customerId: string\n customerSnapshot: Record<string, unknown> | null\n reference: string\n title: string\n periodKind: string\n periodFrom: string | null\n periodTo: string | null\n currencyCode: string\n grouping: string\n nonbillableMode: string\n includeAlreadyReported: boolean\n showRates: boolean\n roundingUnitMinutes: number\n roundingDirection: string\n status: string\n totalBillableMinutes: number | null\n totalNonbillableMinutes: number | null\n totalAmount: string | null\n closedAt: string | null\n closedByUserId: string | null\n timeProjectIds: string[]\n deletedAt: string | null\n}\n\ntype ReportUndoPayload = {\n before?: ReportSnapshot | null\n after?: ReportSnapshot | null\n}\n\nconst DIFFED_FIELDS = [\n 'title',\n 'periodKind',\n 'periodFrom',\n 'periodTo',\n 'currencyCode',\n 'grouping',\n 'nonbillableMode',\n 'includeAlreadyReported',\n 'showRates',\n 'status',\n 'totalBillableMinutes',\n 'totalNonbillableMinutes',\n 'totalAmount',\n] as const\n\nfunction toIsoDate(value: Date | string | null | undefined): string | null {\n if (!value) return null\n if (value instanceof Date) {\n if (Number.isNaN(value.getTime())) return null\n const year = value.getFullYear()\n const month = String(value.getMonth() + 1).padStart(2, '0')\n const day = String(value.getDate()).padStart(2, '0')\n return `${year}-${month}-${day}`\n }\n const text = String(value)\n return text.length >= 10 ? text.slice(0, 10) : text\n}\n\nfunction snapshotScopeWhere(scope?: StaffSnapshotScope | null): { tenantId?: string; organizationId?: string } {\n const where: { tenantId?: string; organizationId?: string } = {}\n if (scope?.tenantId) where.tenantId = scope.tenantId\n if (scope?.organizationId) where.organizationId = scope.organizationId\n return where\n}\n\nexport async function loadReportProjectIds(\n em: EntityManager,\n reportId: string,\n scope?: StaffSnapshotScope | null,\n): Promise<string[]> {\n const rows = await em.find(StaffTimeReportProject, { reportId, ...snapshotScopeWhere(scope) })\n return rows.map((row) => row.timeProjectId)\n}\n\nfunction toSnapshot(report: StaffTimeReport, timeProjectIds: string[]): ReportSnapshot {\n return {\n id: report.id,\n tenantId: report.tenantId,\n organizationId: report.organizationId,\n customerId: report.customerId,\n customerSnapshot: report.customerSnapshot ?? null,\n reference: report.reference,\n title: report.title,\n periodKind: report.periodKind,\n periodFrom: toIsoDate(report.periodFrom),\n periodTo: toIsoDate(report.periodTo),\n currencyCode: report.currencyCode,\n grouping: report.grouping,\n nonbillableMode: report.nonbillableMode,\n includeAlreadyReported: report.includeAlreadyReported ?? false,\n showRates: report.showRates ?? true,\n roundingUnitMinutes: report.roundingUnitMinutes ?? 0,\n roundingDirection: report.roundingDirection ?? 'up',\n status: report.status,\n totalBillableMinutes: report.totalBillableMinutes ?? null,\n totalNonbillableMinutes: report.totalNonbillableMinutes ?? null,\n totalAmount: report.totalAmount ?? null,\n closedAt: report.closedAt ? report.closedAt.toISOString() : null,\n closedByUserId: report.closedByUserId ?? null,\n timeProjectIds,\n deletedAt: report.deletedAt ? report.deletedAt.toISOString() : null,\n }\n}\n\nexport async function loadReportSnapshot(\n em: EntityManager,\n id: string,\n scope?: StaffSnapshotScope | null,\n): Promise<ReportSnapshot | null> {\n const report = await em.findOne(StaffTimeReport, scopedStaffSnapshotWhere(id, scope))\n if (!report) return null\n const projectIds = await loadReportProjectIds(em, report.id, scope)\n return toSnapshot(report, projectIds)\n}\n\nexport function reportNotFoundError(translate: Translate): CrudHttpError {\n return new CrudHttpError(404, {\n error: translate('staff.time_tracking.reports.errors.notFound', 'Report not found or not accessible.'),\n })\n}\n\nexport function reportClosedError(translate: Translate, reference: string | null): CrudHttpError {\n return new CrudHttpError(409, {\n code: REPORT_CLOSED_CODE,\n error: translate(\n 'staff.time_tracking.reports.errors.closed',\n 'This report is closed. Unlock it before changing anything.',\n ),\n reference: reference ?? null,\n })\n}\n\nfunction projectsRequiredError(translate: Translate): CrudHttpError {\n const message = translate(\n 'staff.time_tracking.reports.errors.projectsRequired',\n 'Pick at least one project for this report.',\n )\n return new CrudHttpError(422, { error: message, fieldErrors: { timeProjectIds: message } })\n}\n\nfunction projectNotFoundError(translate: Translate, missingIds: string[]): CrudHttpError {\n const message = translate(\n 'staff.time_tracking.reports.errors.projectNotFound',\n 'Some of the selected projects are not available.',\n )\n return new CrudHttpError(422, {\n code: REPORT_PROJECT_NOT_FOUND_CODE,\n error: message,\n fieldErrors: { timeProjectIds: message },\n missingProjectIds: missingIds,\n })\n}\n\nfunction customerMismatchError(translate: Translate, offenders: string[]): CrudHttpError {\n const message = translate(\n 'staff.time_tracking.reports.errors.customerMismatch',\n 'A report always covers one customer. These projects belong to someone else: {projects}.',\n ).replace('{projects}', offenders.join(', '))\n return new CrudHttpError(422, {\n code: REPORT_PROJECT_CUSTOMER_MISMATCH_CODE,\n error: message,\n fieldErrors: { timeProjectIds: message },\n offenders,\n })\n}\n\n/**\n * Risk R2 refused at the cheapest point. The body names both the currencies and\n * the projects carrying them, because \"pick one currency\" is unactionable\n * without knowing which project is the odd one out.\n */\nexport function currencyConflictError(\n translate: Translate,\n currencies: string[],\n offenders: Array<{ id: string; name: string; currencyCode: string | null }>,\n): CrudHttpError {\n const message = translate(\n 'staff.time_tracking.reports.errors.currencyConflict',\n 'A report always covers one currency. Selected projects use {currencies}.',\n ).replace('{currencies}', currencies.join(', '))\n return new CrudHttpError(422, {\n code: REPORT_CURRENCY_CONFLICT_CODE,\n error: message,\n fieldErrors: { timeProjectIds: message },\n currencies,\n offenders: offenders.map((project) => ({\n id: project.id,\n name: project.name,\n currencyCode: project.currencyCode ?? null,\n })),\n })\n}\n\nfunction referenceConflictError(translate: Translate): CrudHttpError {\n return new CrudHttpError(409, {\n code: REPORT_REFERENCE_CONFLICT_CODE,\n error: translate(\n 'staff.time_tracking.reports.errors.referenceConflict',\n 'Could not allocate a report number right now. Try again.',\n ),\n })\n}\n\nexport type ResolvedReportProjects = {\n projects: StaffTimeProject[]\n currencyCode: string\n}\n\n/**\n * The single validation gate every write shares: the projects exist in scope,\n * they all belong to the report's customer, and they agree on a currency.\n */\nexport async function resolveReportProjects(\n em: EntityManager,\n timeProjectIds: readonly string[],\n customerId: string,\n scope: StaffCommandScope,\n translate: Translate,\n): Promise<ResolvedReportProjects> {\n const ids = Array.from(new Set(timeProjectIds.filter((id) => typeof id === 'string' && id.length > 0)))\n if (ids.length === 0) throw projectsRequiredError(translate)\n\n const projects = await em.find(\n StaffTimeProject,\n applyScopeToWhere<StaffTimeProject>({ id: { $in: ids }, deletedAt: null }, scope),\n )\n if (projects.length !== ids.length) {\n const found = new Set(projects.map((project) => project.id))\n throw projectNotFoundError(\n translate,\n ids.filter((id) => !found.has(id)),\n )\n }\n\n const mismatched = projects.filter((project) => (project.customerId ?? null) !== customerId)\n if (mismatched.length > 0) {\n throw customerMismatchError(\n translate,\n mismatched.map((project) => project.name),\n )\n }\n\n const resolution = resolveReportCurrency(\n projects.map((project) => ({\n id: project.id,\n name: project.name,\n currencyCode: project.currencyCode ?? null,\n })),\n )\n if (!resolution.ok) {\n throw currencyConflictError(translate, resolution.currencies, resolution.offenders)\n }\n\n return { projects, currencyCode: resolution.currencyCode ?? '' }\n}\n\n/**\n * D-9: the report carries the customer as an FK id plus a denormalized snapshot,\n * so the sheet header resolves a client name without joining the customers\n * module \u2014 and keeps resolving it if that customer is later removed. The\n * snapshot is taken from the selected projects, which already carry one, rather\n * than reaching across the module boundary a second time.\n */\nexport function deriveCustomerSnapshot(projects: readonly StaffTimeProject[]): Record<string, unknown> | null {\n for (const project of projects) {\n const snapshot = project.customerSnapshot\n if (snapshot && typeof snapshot === 'object' && Object.keys(snapshot).length > 0) {\n return snapshot as Record<string, unknown>\n }\n }\n return null\n}\n\nasync function readRoundingSnapshot(\n ctx: CommandRuntimeContext,\n tenantId: string,\n): Promise<{ unitMinutes: number; direction: string }> {\n try {\n const configService = ctx.container.resolve('moduleConfigService') as ModuleConfigService\n const settings = await readTimeTrackingSettings(configService, { tenantId })\n return { unitMinutes: settings.rounding.unitMinutes, direction: settings.rounding.direction }\n } catch (err) {\n // A draft that cannot read the rule still has to exist; close re-stamps it.\n logger.warn('staff.timesheets.reports rounding snapshot unavailable', { err })\n return { unitMinutes: 0, direction: 'up' }\n }\n}\n\nasync function replaceReportProjects(\n em: EntityManager,\n report: StaffTimeReport,\n projects: readonly StaffTimeProject[],\n): Promise<void> {\n const existing = await em.find(StaffTimeReportProject, { reportId: report.id })\n for (const row of existing) em.remove(row)\n for (const project of projects) {\n em.persist(\n em.create(StaffTimeReportProject, {\n tenantId: report.tenantId,\n organizationId: report.organizationId,\n reportId: report.id,\n timeProjectId: project.id,\n createdAt: new Date(),\n }),\n )\n }\n}\n\nfunction actorUserId(ctx: CommandRuntimeContext): string | null {\n return typeof ctx.auth?.sub === 'string' ? ctx.auth.sub : null\n}\n\n/**\n * The highest report number the organization has EVER handed out this year,\n * soft-deleted rows included. The unique index covers live rows only, so a\n * deleted `RAP-2026-0042` would otherwise be reissued behind a PDF a client\n * already holds.\n */\nasync function readHighestReportSequence(\n em: EntityManager,\n year: number,\n scope: StaffCommandScope,\n): Promise<number> {\n const rows = await em.find(\n StaffTimeReport,\n applyScopeToWhere<StaffTimeReport>({ reference: { $like: `${reportReferencePrefix(year)}%` } }, scope),\n )\n return highestReportSequenceNumber(\n rows.map((row) => row.reference),\n year,\n )\n}\n\nconst createReportCommand: CommandHandler<StaffTimeReportCreateInput, { reportId: string }> = {\n id: staffTimeReportCommandIds.create,\n async execute(rawInput, ctx) {\n const parsed = staffTimeReportCreateSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n const scope = commandInputScope(ctx, parsed.tenantId, parsed.organizationId)\n const { translate } = await resolveTranslations()\n const baseEm = ctx.container.resolve('em') as EntityManager\n const createdByUserId = actorUserId(ctx)\n const rounding = await readRoundingSnapshot(ctx, parsed.tenantId)\n const issuedAt = new Date()\n const year = reportReferenceYear(issuedAt)\n\n let record: StaffTimeReport\n try {\n record = await withReportReferenceRetry(async () => {\n // A fresh fork per attempt: a lost race aborts the transaction, so the\n // retry re-reads the highest reference rather than reusing a stale max.\n const em = baseEm.fork()\n let created: StaffTimeReport | null = null\n let plan: { projects: StaffTimeProject[]; currencyCode: string; highest: number } | null = null\n\n await withAtomicFlush(\n em,\n [\n async () => {\n const resolved = await resolveReportProjects(\n em,\n parsed.timeProjectIds,\n parsed.customerId,\n scope,\n translate,\n )\n plan = {\n projects: resolved.projects,\n currencyCode: resolved.currencyCode,\n highest: await readHighestReportSequence(em, year, scope),\n }\n },\n () => {\n if (!plan) throw reportNotFoundError(translate)\n const allocation = allocateReportReference(year, plan.highest)\n const now = new Date()\n created = em.create(StaffTimeReport, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n customerId: parsed.customerId,\n customerSnapshot: deriveCustomerSnapshot(plan.projects),\n reference: allocation.reference,\n title: parsed.title,\n periodKind: parsed.periodKind,\n periodFrom: parsed.periodFrom,\n periodTo: parsed.periodTo,\n currencyCode: plan.currencyCode,\n grouping: parsed.grouping,\n nonbillableMode: parsed.nonbillableMode,\n includeAlreadyReported: parsed.includeAlreadyReported,\n showRates: parsed.showRates,\n roundingUnitMinutes: rounding.unitMinutes,\n roundingDirection: rounding.direction,\n status: 'draft',\n createdByUserId,\n createdAt: now,\n updatedAt: now,\n deletedAt: null,\n })\n em.persist(created)\n },\n async () => {\n if (!created || !plan) return\n await replaceReportProjects(em, created, plan.projects)\n },\n ],\n { transaction: true, label: staffTimeReportCommandIds.create },\n )\n\n if (!created) throw reportNotFoundError(translate)\n return created as StaffTimeReport\n })\n } catch (err) {\n if (isReportReferenceConflict(err)) throw referenceConflictError(translate)\n throw err\n }\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'created',\n entity: record,\n identifiers: { id: record.id, organizationId: record.organizationId, tenantId: record.tenantId },\n events: reportCrudEvents,\n indexer: reportCrudIndexer,\n })\n\n return { reportId: record.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadReportSnapshot(em, result.reportId, staffSnapshotScopeFromContext(ctx))\n if (!snapshot) return null\n return { snapshot }\n },\n buildLog: async ({ result, ctx }) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadReportSnapshot(em, result.reportId, staffSnapshotScopeFromContext(ctx))\n if (!snapshot) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.reports.create', 'Create report'),\n resourceKind: STAFF_TIME_REPORT_RESOURCE_KIND,\n resourceId: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n snapshotAfter: snapshot,\n payload: { undo: { after: snapshot } satisfies ReportUndoPayload },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<ReportUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const report = await em.findOne(\n StaffTimeReport,\n scopedStaffSnapshotWhere(after.id, staffSnapshotScopeFromSnapshot(after)),\n )\n if (!report) return\n // A report that has since been closed froze entries; undoing its creation\n // would strand those locks, so the undo declines rather than half-unwinding.\n if (report.status === 'closed') return\n report.deletedAt = new Date()\n report.updatedAt = new Date()\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'deleted',\n entity: report,\n identifiers: { id: report.id, organizationId: report.organizationId, tenantId: report.tenantId },\n events: reportCrudEvents,\n indexer: reportCrudIndexer,\n })\n },\n}\n\nconst updateReportCommand: CommandHandler<StaffTimeReportUpdateInput, { reportId: string }> = {\n id: staffTimeReportCommandIds.update,\n async prepare(rawInput, ctx) {\n const parsed = staffTimeReportUpdateSchema.safeParse(rawInput)\n if (!parsed.success) return {}\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const before = await loadReportSnapshot(em, parsed.data.id, staffSnapshotScopeFromContext(ctx))\n if (!before) return {}\n return { before: { snapshot: before } }\n },\n async execute(rawInput, ctx) {\n const parsed = staffTimeReportUpdateSchema.parse(rawInput)\n const { translate } = await resolveTranslations()\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n\n const report = await em.findOne(\n StaffTimeReport,\n applyScopeToWhere<StaffTimeReport>({ id: parsed.id, deletedAt: null }, scope),\n )\n if (!report) throw reportNotFoundError(translate)\n ensureTenantScope(ctx, report.tenantId)\n ensureOrganizationScope(ctx, report.organizationId)\n if (report.status === 'closed') throw reportClosedError(translate, report.reference)\n\n const targetCustomerId = parsed.customerId ?? report.customerId\n let resolved: ResolvedReportProjects | null = null\n\n await withAtomicFlush(\n em,\n [\n async () => {\n const needsProjectCheck =\n parsed.timeProjectIds !== undefined || (parsed.customerId !== undefined && parsed.customerId !== report.customerId)\n if (!needsProjectCheck) return\n const ids = parsed.timeProjectIds ?? (await loadReportProjectIds(em, report.id, scope))\n resolved = await resolveReportProjects(em, ids, targetCustomerId, scope, translate)\n },\n () => {\n const now = new Date()\n if (parsed.title !== undefined) report.title = parsed.title\n if (parsed.periodKind !== undefined) report.periodKind = parsed.periodKind\n if (parsed.periodFrom !== undefined) report.periodFrom = parsed.periodFrom\n if (parsed.periodTo !== undefined) report.periodTo = parsed.periodTo\n if (parsed.grouping !== undefined) report.grouping = parsed.grouping\n if (parsed.nonbillableMode !== undefined) report.nonbillableMode = parsed.nonbillableMode\n if (parsed.includeAlreadyReported !== undefined) {\n report.includeAlreadyReported = parsed.includeAlreadyReported\n }\n if (parsed.showRates !== undefined) report.showRates = parsed.showRates\n if (parsed.customerId !== undefined) report.customerId = parsed.customerId\n if (resolved) {\n report.currencyCode = resolved.currencyCode\n report.customerSnapshot = deriveCustomerSnapshot(resolved.projects) ?? report.customerSnapshot ?? null\n }\n report.updatedAt = now\n },\n async () => {\n if (!resolved || parsed.timeProjectIds === undefined) return\n await replaceReportProjects(em, report, resolved.projects)\n },\n ],\n { transaction: true, label: staffTimeReportCommandIds.update },\n )\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'updated',\n entity: report,\n identifiers: { id: report.id, organizationId: report.organizationId, tenantId: report.tenantId },\n events: reportCrudEvents,\n indexer: reportCrudIndexer,\n })\n\n return { reportId: report.id }\n },\n buildLog: async ({ snapshots, ctx }) => {\n const before = (snapshots.before as { snapshot?: ReportSnapshot } | undefined)?.snapshot\n if (!before) return null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const after = await loadReportSnapshot(em, before.id, staffSnapshotScopeFromSnapshot(before))\n if (!after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.reports.update', 'Update report'),\n resourceKind: STAFF_TIME_REPORT_RESOURCE_KIND,\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes: buildChanges(\n before as unknown as Record<string, unknown>,\n after as unknown as Record<string, unknown>,\n [...DIFFED_FIELDS],\n ),\n payload: { undo: { before, after } satisfies ReportUndoPayload },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<ReportUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const report = await em.findOne(\n StaffTimeReport,\n scopedStaffSnapshotWhere(before.id, staffSnapshotScopeFromSnapshot(before)),\n )\n if (!report) return\n if (report.status === 'closed') return\n\n const projects = await em.find(StaffTimeProject, {\n id: { $in: before.timeProjectIds },\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n })\n\n await withAtomicFlush(\n em,\n [\n () => {\n report.customerId = before.customerId\n report.customerSnapshot = before.customerSnapshot\n report.title = before.title\n report.periodKind = before.periodKind as StaffTimeReport['periodKind']\n if (before.periodFrom) report.periodFrom = new Date(before.periodFrom)\n if (before.periodTo) report.periodTo = new Date(before.periodTo)\n report.currencyCode = before.currencyCode\n report.grouping = before.grouping as StaffTimeReport['grouping']\n report.nonbillableMode = before.nonbillableMode as StaffTimeReport['nonbillableMode']\n report.includeAlreadyReported = before.includeAlreadyReported\n report.showRates = before.showRates\n report.updatedAt = new Date()\n },\n async () => {\n if (projects.length !== before.timeProjectIds.length) return\n await replaceReportProjects(em, report, projects)\n },\n ],\n { transaction: true, label: `${staffTimeReportCommandIds.update}.undo` },\n )\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'updated',\n entity: report,\n identifiers: { id: report.id, organizationId: report.organizationId, tenantId: report.tenantId },\n events: reportCrudEvents,\n indexer: reportCrudIndexer,\n })\n },\n}\n\nconst deleteReportCommand: CommandHandler<{ id?: string }, { reportId: string }> = {\n id: staffTimeReportCommandIds.delete,\n async prepare(input, ctx) {\n const id = input?.id\n if (!id) return {}\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const before = await loadReportSnapshot(em, id, staffSnapshotScopeFromContext(ctx))\n if (!before) return {}\n return { before: { snapshot: before } }\n },\n async execute(input, ctx) {\n const { translate } = await resolveTranslations()\n const id = input?.id\n if (!id) {\n throw new CrudHttpError(400, {\n error: translate('staff.time_tracking.reports.errors.idRequired', 'Report id is required.'),\n })\n }\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n const report = await em.findOne(\n StaffTimeReport,\n applyScopeToWhere<StaffTimeReport>({ id, deletedAt: null }, scope),\n )\n if (!report) throw reportNotFoundError(translate)\n ensureTenantScope(ctx, report.tenantId)\n ensureOrganizationScope(ctx, report.organizationId)\n // Deleting a closed report would strand every entry it froze: their\n // `locked_report_id` would point at a row nothing can unlock.\n if (report.status === 'closed') throw reportClosedError(translate, report.reference)\n\n const now = new Date()\n report.deletedAt = now\n report.updatedAt = now\n await em.flush()\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'deleted',\n entity: report,\n identifiers: { id: report.id, organizationId: report.organizationId, tenantId: report.tenantId },\n events: reportCrudEvents,\n indexer: reportCrudIndexer,\n })\n\n return { reportId: report.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = (snapshots.before as { snapshot?: ReportSnapshot } | undefined)?.snapshot\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.reports.delete', 'Delete report'),\n resourceKind: STAFF_TIME_REPORT_RESOURCE_KIND,\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: { undo: { before } satisfies ReportUndoPayload },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<ReportUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const report = await em.findOne(\n StaffTimeReport,\n scopedStaffSnapshotWhere(before.id, staffSnapshotScopeFromSnapshot(before)),\n )\n if (!report) return\n report.deletedAt = null\n report.updatedAt = new Date()\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'created',\n entity: report,\n identifiers: { id: report.id, organizationId: report.organizationId, tenantId: report.tenantId },\n events: reportCrudEvents,\n indexer: reportCrudIndexer,\n })\n },\n}\n\nregisterCommand(createReportCommand)\nregisterCommand(updateReportCommand)\nregisterCommand(deleteReportCommand)\n\n/**\n * US-G3 \u2014 close & lock. This is the only place a lock is created: exporting a\n * PDF freezes nothing (screen 14 note 5), because \"in a generated/sent report\"\n * (\u00A79) is ambiguous and a download that silently locks a team's timesheet is the\n * worse reading of it.\n *\n * Everything the close writes happens inside ONE `withAtomicFlush({ transaction:\n * true })`: the per-entry freeze records, the `locked_report_id` stamps, the\n * frozen report totals and the `closed` audit event. A partial close would leave\n * entries frozen against a report that never closed \u2014 unlockable by nobody,\n * because the unlock command refuses a draft.\n *\n * Two rules that are easy to get wrong:\n *\n * - **The freeze records come from the same `selectIncludedEntries` /\n * `resolveEntryValues` pair the sheet printed**, so what is frozen is by\n * construction what the client was shown. The amounts are already rounded at\n * the entry (D-7), which is what lets `total_amount` be an exact sum.\n * - **An entry already locked by another report keeps that lock.** When the\n * D-5 opt-in pulls a previously billed hour into a second report, this report\n * records what it billed, but ownership of the lock stays with the report\n * that froze it first. The lock is a denormalized \"some closed report quotes\n * this hour\", so it must outlive whichever of them is unlocked first: the\n * unlock command hands it to a remaining closed report instead of clearing\n * it.\n */\nexport type StaffTimeReportCloseResult = {\n reportId: string\n lockedEntryCount: number\n totalAmount: number\n totalBillableMinutes: number\n totalNonbillableMinutes: number\n}\n\nfunction reportNotClosedError(translate: Translate): CrudHttpError {\n return new CrudHttpError(409, {\n code: REPORT_NOT_CLOSED_CODE,\n error: translate(\n 'staff.time_tracking.reports.errors.notClosed',\n 'This report is not closed, so there is nothing to unlock.',\n ),\n })\n}\n\nfunction reportEmptyError(translate: Translate): CrudHttpError {\n return new CrudHttpError(422, {\n code: REPORT_EMPTY_CODE,\n error: translate(\n 'staff.time_tracking.reports.errors.empty',\n 'This report covers no time entries, so there is nothing to freeze. Adjust the period or the project selection first.',\n ),\n })\n}\n\nconst closeReportCommand: CommandHandler<StaffTimeReportCloseInput, StaffTimeReportCloseResult> = {\n id: staffTimeReportCommandIds.close,\n async prepare(rawInput, ctx) {\n const parsed = staffTimeReportCloseSchema.safeParse(rawInput)\n if (!parsed.success) return {}\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const before = await loadReportSnapshot(em, parsed.data.id, staffSnapshotScopeFromContext(ctx))\n if (!before) return {}\n return { before: { snapshot: before } }\n },\n async execute(rawInput, ctx) {\n const parsed = staffTimeReportCloseSchema.parse(rawInput)\n const { translate } = await resolveTranslations()\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n\n const report = await em.findOne(\n StaffTimeReport,\n applyScopeToWhere<StaffTimeReport>({ id: parsed.id, deletedAt: null }, scope),\n )\n if (!report) throw reportNotFoundError(translate)\n ensureTenantScope(ctx, report.tenantId)\n ensureOrganizationScope(ctx, report.organizationId)\n if (report.status === 'closed') throw reportClosedError(translate, report.reference)\n\n const dataScope = { tenantId: report.tenantId, organizationId: report.organizationId }\n const rounding = await readRoundingSnapshot(ctx, report.tenantId)\n const actorId = actorUserId(ctx)\n const labels = reportSheetLabels(translate)\n\n type ClosePlanItem = {\n entry: ReturnType<typeof selectIncludedEntries>[number]\n row: StaffTimeEntry | null\n values: ReturnType<typeof resolveEntryValues>\n currencyCode: string\n }\n\n let lockedEntryCount = 0\n let totals: ReturnType<typeof computeReportTotals> | null = null\n let closePlan: ClosePlanItem[] = []\n\n await withAtomicFlush(\n em,\n [\n async () => {\n const timeProjectIds = await loadReportProjectIds(em, report.id, dataScope)\n const data = await loadReportData({\n em,\n scope: dataScope,\n timeProjectIds,\n periodFrom: report.periodFrom,\n periodTo: report.periodTo,\n currentReportId: report.id,\n })\n const options = {\n grouping: report.grouping,\n nonbillableMode: report.nonbillableMode,\n includeAlreadyReported: report.includeAlreadyReported ?? false,\n } as const\n const included = selectIncludedEntries(data.entries, options, report.id)\n if (included.length === 0) throw reportEmptyError(translate)\n\n totals = computeReportTotals({\n entries: data.entries,\n projects: data.projects,\n directory: data.directory,\n options,\n currentReportId: report.id,\n labels,\n })\n\n const projectById = new Map(data.projects.map((project) => [project.id, project]))\n const entryRows = await em.find(StaffTimeEntry, {\n id: { $in: included.map((entry) => entry.id) },\n tenantId: report.tenantId,\n organizationId: report.organizationId,\n })\n const entryById = new Map(entryRows.map((row) => [row.id, row]))\n\n closePlan = included.map((entry) => ({\n entry,\n row: entryById.get(entry.id) ?? null,\n values: resolveEntryValues(entry, projectById.get(entry.timeProjectId) ?? null),\n currencyCode:\n projectById.get(entry.timeProjectId)?.currencyCode ?? report.currencyCode ?? '',\n }))\n },\n () => {\n if (!totals) throw reportEmptyError(translate)\n const now = new Date()\n for (const item of closePlan) {\n em.persist(\n em.create(StaffTimeReportEntry, {\n tenantId: report.tenantId,\n organizationId: report.organizationId,\n reportId: report.id,\n timeEntryId: item.entry.id,\n frozenRawMinutes: item.values.rawMinutes,\n frozenRoundedMinutes: item.values.minutes,\n frozenRateAmount: item.values.rate === null ? null : String(item.values.rate),\n frozenCurrencyCode: item.currencyCode,\n frozenAmount: item.values.amount === null ? null : item.values.amount.toFixed(2),\n frozenIsBillable: item.values.isBillable,\n createdAt: now,\n }),\n )\n const row = item.row\n if (!row) continue\n // Ownership of an existing lock is never transferred \u2014 see the note\n // on this command.\n if (row.lockedReportId) continue\n row.lockedReportId = report.id\n row.lockedAt = now\n row.updatedAt = now\n lockedEntryCount += 1\n }\n\n report.status = 'closed'\n report.closedAt = now\n report.closedByUserId = actorId\n report.roundingUnitMinutes = rounding.unitMinutes\n report.roundingDirection = rounding.direction\n report.totalBillableMinutes = totals.billableMinutes\n report.totalNonbillableMinutes = totals.nonbillableMinutes\n report.totalAmount = totals.totalAmount.toFixed(2)\n report.updatedAt = now\n\n em.persist(\n em.create(StaffTimeReportEvent, {\n tenantId: report.tenantId,\n organizationId: report.organizationId,\n reportId: report.id,\n eventType: 'closed',\n reason: null,\n actorUserId: actorId,\n metadata: {\n frozenEntryCount: closePlan.length,\n lockedEntryCount,\n totalAmount: totals.totalAmount,\n currencyCode: report.currencyCode,\n roundingUnitMinutes: rounding.unitMinutes,\n roundingDirection: rounding.direction,\n },\n createdAt: now,\n }),\n )\n },\n ],\n { transaction: true, label: staffTimeReportCommandIds.close },\n )\n\n const resolved = totals as ReturnType<typeof computeReportTotals> | null\n const result: StaffTimeReportCloseResult = {\n reportId: report.id,\n lockedEntryCount,\n totalAmount: resolved?.totalAmount ?? 0,\n totalBillableMinutes: resolved?.billableMinutes ?? 0,\n totalNonbillableMinutes: resolved?.nonbillableMinutes ?? 0,\n }\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'updated',\n entity: report,\n identifiers: { id: report.id, organizationId: report.organizationId, tenantId: report.tenantId },\n events: reportCrudEvents,\n indexer: reportCrudIndexer,\n })\n\n // A failed broadcast must never fail a committed close.\n //\n // The payload is spelled out rather than spreading `result` because this event is\n // `clientBroadcast: true`: the DOM Event Bridge delivers it to every user of the\n // organization with no feature check, and `result.totalAmount` is money, which is\n // gated on `staff.timesheets.rates.view`. The minute totals and the locked-entry\n // count are not money and are what a live report screen needs; the amount is read\n // back from the report itself by a caller entitled to it.\n //\n // What else that unfiltered audience decides, field by field:\n //\n // - `customerId` is DROPPED. It is the one field that links a report to a named\n // client, and one organization serves many; a tenant's whole staff learning\n // which client was billed this week is a disclosure with no consumer asking\n // for it. The schema always declared it optional, both in-repo subscribers\n // re-read the report from the database, and the portal mirror\n // (`time_report.portal_published`) resolves the customer itself.\n // - `reference` and the two minute totals STAY. They are stable identifiers and\n // non-money aggregates, they are the published webhook contract an external\n // billing system codes against, and they are what a live reports screen needs\n // to refresh a row. Narrowing them further is not expressible here: the DOM\n // bridge can only pin an audience by user or ROLE id, and this module\n // deliberately gates on immutable feature ids rather than mutable roles.\n void emitStaffEvent('staff.timesheets.time_report.closed', {\n id: report.id,\n tenantId: report.tenantId,\n organizationId: report.organizationId,\n reference: report.reference,\n reportId: result.reportId,\n lockedEntryCount: result.lockedEntryCount,\n totalBillableMinutes: result.totalBillableMinutes,\n totalNonbillableMinutes: result.totalNonbillableMinutes,\n }).catch((err) => {\n logger.error('staff.timesheets emit time_report.closed failed', { err })\n })\n\n // The close froze `lockedEntryCount` entries. The entry-scoped subscribers key\n // off a single record id, so this batch-level notice carries none and reaches\n // only the ones that care about a period being frozen.\n if (lockedEntryCount > 0) {\n void emitStaffEvent('staff.timesheets.time_entry.locked', {\n tenantId: report.tenantId,\n organizationId: report.organizationId,\n reportId: report.id,\n lockedEntryCount,\n }).catch((err) => {\n logger.error('staff.timesheets emit time_entry.locked failed', { err })\n })\n }\n\n return result\n },\n buildLog: async ({ snapshots, ctx }) => {\n const before = (snapshots.before as { snapshot?: ReportSnapshot } | undefined)?.snapshot\n if (!before) return null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const after = await loadReportSnapshot(em, before.id, staffSnapshotScopeFromSnapshot(before))\n if (!after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.reports.close', 'Close and lock report'),\n resourceKind: STAFF_TIME_REPORT_RESOURCE_KIND,\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes: buildChanges(\n before as unknown as Record<string, unknown>,\n after as unknown as Record<string, unknown>,\n [...DIFFED_FIELDS],\n ),\n // Deliberately no `undo` payload: unwinding a close is the unlock command,\n // which requires a reason and its own feature. A silent undo of a billing\n // freeze is exactly what US-G3 forbids.\n }\n },\n}\n\n/**\n * US-G3's other half \u2014 unlock, screen 15.\n *\n * Three things make it an \"explicit, audited action\" rather than a confirm\n * dialog: it takes a mandatory reason, it appends an `unlocked` event carrying\n * that reason and the actor, and it is gated on `staff.timesheets.reports.unlock`\n * \u2014 a feature distinct from `staff.timesheets.lock`, so \"who may restate billed\n * time\" can be answered by withholding it from a Team Leader without inventing\n * the admin role \u00A710 rejects.\n *\n * The freeze records are DELETED rather than kept. Two reasons: `staff_time_\n * report_entries` is what makes D-5 answerable (\"is this hour already billed?\"),\n * so leaving stale rows behind after the report reopened would keep hours out of\n * the next invoice for no reason; and the unique `(report_id, time_entry_id)`\n * index would otherwise refuse the re-close. The numbers they held are copied\n * into the `unlocked` event's metadata, so the audit trail keeps what was\n * frozen.\n *\n * An entry is freed only when no other closed report quotes it. The D-5 opt-in\n * lets a later report re-include an hour this one froze; `locked_report_id` is\n * the denormalized form of \"a closed report quotes this hour\", so for such an\n * entry the lock moves to the earliest remaining closed report rather than\n * being cleared \u2014 clearing it would let the hour be edited, moved or deleted\n * underneath a closed report that still prints it.\n *\n * Unlocks of reports that share an entry must not interleave: one of them\n * could hand the lock to the other while that other is on its way back to\n * draft, leaving the entry locked by a report nobody can unlock. Every entry\n * this report quotes is therefore row-locked, in id order, BEFORE the other\n * reports are read.\n */\nexport type StaffTimeReportUnlockResult = {\n reportId: string\n /** Entries no closed report quotes any more, so they are editable again. */\n unlockedEntryCount: number\n /** Entries still quoted by another closed report, which now owns their lock. */\n transferredLockCount: number\n}\n\nconst unlockReportCommand: CommandHandler<StaffTimeReportUnlockInput, StaffTimeReportUnlockResult> = {\n id: staffTimeReportCommandIds.unlock,\n async prepare(rawInput, ctx) {\n const parsed = staffTimeReportUnlockSchema.safeParse(rawInput)\n if (!parsed.success) return {}\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const before = await loadReportSnapshot(em, parsed.data.id, staffSnapshotScopeFromContext(ctx))\n if (!before) return {}\n return { before: { snapshot: before } }\n },\n async execute(rawInput, ctx) {\n const parsed = staffTimeReportUnlockSchema.parse(rawInput)\n const { translate } = await resolveTranslations()\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n\n const report = await em.findOne(\n StaffTimeReport,\n applyScopeToWhere<StaffTimeReport>({ id: parsed.id, deletedAt: null }, scope),\n )\n if (!report) throw reportNotFoundError(translate)\n ensureTenantScope(ctx, report.tenantId)\n ensureOrganizationScope(ctx, report.organizationId)\n if (report.status !== 'closed') throw reportNotClosedError(translate)\n\n const actorId = actorUserId(ctx)\n let unlockedEntryCount = 0\n let transferredLockCount = 0\n let frozenEntries: StaffTimeReportEntry[] = []\n let lockedRows: StaffTimeEntry[] = []\n const nextLockOwnerByEntryId = new Map<string, StaffTimeReport>()\n let frozenTotals: {\n totalAmount: string | null\n totalBillableMinutes: number | null\n totalNonbillableMinutes: number | null\n } = { totalAmount: null, totalBillableMinutes: null, totalNonbillableMinutes: null }\n\n await withAtomicFlush(\n em,\n [\n async () => {\n // The status was checked before the transaction opened; a concurrent\n // unlock of this same report may have won since.\n const stillClosed = await em.find(\n StaffTimeReport,\n {\n id: report.id,\n tenantId: report.tenantId,\n organizationId: report.organizationId,\n status: 'closed',\n deletedAt: null,\n },\n { lockMode: LockMode.PESSIMISTIC_WRITE },\n )\n const [lockedReport] = stillClosed\n if (!lockedReport) throw reportNotClosedError(translate)\n // Read under the row lock, copied before the report goes back to draft.\n frozenTotals = {\n totalAmount: lockedReport.totalAmount ?? null,\n totalBillableMinutes: lockedReport.totalBillableMinutes ?? null,\n totalNonbillableMinutes: lockedReport.totalNonbillableMinutes ?? null,\n }\n\n frozenEntries = await em.find(StaffTimeReportEntry, {\n reportId: report.id,\n tenantId: report.tenantId,\n organizationId: report.organizationId,\n })\n const quotedEntryIds = Array.from(new Set(frozenEntries.map((frozen) => frozen.timeEntryId)))\n const quotedRows = await em.find(\n StaffTimeEntry,\n {\n $or:\n quotedEntryIds.length > 0\n ? [{ id: { $in: quotedEntryIds } }, { lockedReportId: report.id }]\n : [{ lockedReportId: report.id }],\n tenantId: report.tenantId,\n organizationId: report.organizationId,\n },\n { lockMode: LockMode.PESSIMISTIC_WRITE, orderBy: { id: 'asc' } },\n )\n lockedRows = quotedRows.filter((row) => row.lockedReportId === report.id)\n\n // Read only now that the rows are locked, so a report sharing one of\n // these entries has either finished its own unlock or waits for this one.\n const freezesByEntryId = await loadClosedReportFreezes(\n em,\n { tenantId: report.tenantId, organizationId: report.organizationId },\n lockedRows.map((row) => row.id),\n )\n for (const [timeEntryId, freezes] of freezesByEntryId) {\n const nextOwner = freezes.find((freeze) => freeze.report.id !== report.id)\n if (nextOwner) nextLockOwnerByEntryId.set(timeEntryId, nextOwner.report)\n }\n },\n () => {\n const now = new Date()\n for (const row of lockedRows) {\n const nextOwner = nextLockOwnerByEntryId.get(row.id)\n row.updatedAt = now\n if (nextOwner) {\n row.lockedReportId = nextOwner.id\n row.lockedAt = nextOwner.closedAt ?? now\n transferredLockCount += 1\n continue\n }\n row.lockedReportId = null\n row.lockedAt = null\n unlockedEntryCount += 1\n }\n for (const frozen of frozenEntries) em.remove(frozen)\n\n report.status = 'draft'\n report.closedAt = null\n report.closedByUserId = null\n report.totalAmount = null\n report.totalBillableMinutes = null\n report.totalNonbillableMinutes = null\n report.updatedAt = now\n\n em.persist(\n em.create(StaffTimeReportEvent, {\n tenantId: report.tenantId,\n organizationId: report.organizationId,\n reportId: report.id,\n eventType: 'unlocked',\n reason: parsed.reason,\n actorUserId: actorId,\n metadata: {\n unlockedEntryCount,\n transferredLockCount,\n frozenEntryCount: frozenEntries.length,\n frozenTotalAmount: frozenTotals.totalAmount,\n frozenBillableMinutes: frozenTotals.totalBillableMinutes,\n frozenNonbillableMinutes: frozenTotals.totalNonbillableMinutes,\n currencyCode: report.currencyCode,\n },\n createdAt: now,\n }),\n )\n },\n ],\n { transaction: true, label: staffTimeReportCommandIds.unlock },\n )\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'updated',\n entity: report,\n identifiers: { id: report.id, organizationId: report.organizationId, tenantId: report.tenantId },\n events: reportCrudEvents,\n indexer: reportCrudIndexer,\n })\n\n // `reason` is deliberately NOT on the wire.\n //\n // This event is `clientBroadcast: true`, and the DOM Event Bridge filters a\n // broadcast by tenant + organization only \u2014 no feature check \u2014 so every\n // signed-in user of the organization receives whatever the payload carries.\n // `reason` is mandatory operator prose of up to 2000 characters explaining why\n // a client's billing was reopened; broadcasting it organization-wide is a\n // disclosure the screen it comes from (`staff.timesheets.reports.unlock`) does\n // not make. It is already persisted verbatim on the `StaffTimeReportEvent`\n // audit row above, which is read behind the ACL, so nothing is lost.\n void emitStaffEvent('staff.timesheets.time_report.unlocked', {\n id: report.id,\n tenantId: report.tenantId,\n organizationId: report.organizationId,\n reference: report.reference,\n actorUserId: actorId,\n unlockedEntryCount,\n }).catch((err) => {\n logger.error('staff.timesheets emit time_report.unlocked failed', { err })\n })\n\n if (unlockedEntryCount > 0) {\n void emitStaffEvent('staff.timesheets.time_entry.unlocked', {\n tenantId: report.tenantId,\n organizationId: report.organizationId,\n reportId: report.id,\n unlockedEntryCount,\n }).catch((err) => {\n logger.error('staff.timesheets emit time_entry.unlocked failed', { err })\n })\n }\n\n return { reportId: report.id, unlockedEntryCount, transferredLockCount }\n },\n buildLog: async ({ snapshots, ctx, input }) => {\n const before = (snapshots.before as { snapshot?: ReportSnapshot } | undefined)?.snapshot\n if (!before) return null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const after = await loadReportSnapshot(em, before.id, staffSnapshotScopeFromSnapshot(before))\n if (!after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.reports.unlock', 'Unlock report entries'),\n resourceKind: STAFF_TIME_REPORT_RESOURCE_KIND,\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes: buildChanges(\n before as unknown as Record<string, unknown>,\n after as unknown as Record<string, unknown>,\n [...DIFFED_FIELDS],\n ),\n payload: { reason: input?.reason ?? null },\n }\n },\n}\n\nregisterCommand(closeReportCommand)\nregisterCommand(unlockReportCommand)\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -22,7 +22,8 @@ async function buildReportSheet(input) {
22
22
  scope,
23
23
  timeProjectIds: input.timeProjectIds,
24
24
  periodFrom: toDate(report.periodFrom, /* @__PURE__ */ new Date(0)),
25
- periodTo: toDate(report.periodTo, /* @__PURE__ */ new Date())
25
+ periodTo: toDate(report.periodTo, /* @__PURE__ */ new Date()),
26
+ currentReportId: report.id
26
27
  });
27
28
  const entries = isClosed ? data.entries.filter((entry) => entry.frozen?.reportId === report.id) : data.entries;
28
29
  const totals = computeReportTotals({
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/staff/lib/timesheets-reports/buildReportSheet.ts"],
4
- "sourcesContent": ["/**\n * The sheet of screen 14, built once and reused by the detail page, the exports\n * and the close command.\n *\n * The one rule that matters here is the difference between a draft and a closed\n * report:\n *\n * - a **draft** is computed live, so it moves when an entry is edited or the\n * rounding rule changes \u2014 by design, and screen 16 says so;\n * - a **closed** report renders exactly what it froze. Its lines come from the\n * `staff_time_report_entries` snapshots, so a later rounding change, a rate\n * change or an unlocked-and-edited entry cannot restate an invoice a client\n * already holds (risk R1).\n *\n * Both paths go through the same `computeReportTotals`, which is what keeps the\n * preview, the sheet and the freeze records arithmetically identical.\n */\n\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport type { StaffTimeReport } from '../../data/entities'\nimport { loadReportData, type ReportDataScope } from './loadReportData'\nimport { normalizeReportGrouping } from './reportGroupings'\nimport {\n computeReportTotals,\n resolveReportCurrency,\n type ReportDirectory,\n type ReportGrouping,\n type ReportInputEntry,\n type ReportInputProject,\n type ReportNonBillableMode,\n type ReportTotals,\n} from './reportTotals'\n\nexport type ReportSheetLabels = {\n unassignedTask: string\n unassignedPerson: string\n nonbillableGroup: string\n}\n\nexport type BuildReportSheetInput = {\n em: EntityManager\n scope: ReportDataScope\n report: StaffTimeReport\n timeProjectIds: readonly string[]\n labels: ReportSheetLabels\n /** Overrides the report's stored grouping, for an export that re-groups. */\n grouping?: ReportGrouping\n}\n\nexport type ReportSheet = {\n totals: ReportTotals\n entries: ReportInputEntry[]\n projects: ReportInputProject[]\n directory: ReportDirectory\n currencyCode: string | null\n grouping: ReportGrouping\n nonbillableMode: ReportNonBillableMode\n isClosed: boolean\n}\n\nfunction toDate(value: Date | string | null | undefined, fallback: Date): Date {\n if (value instanceof Date && !Number.isNaN(value.getTime())) return value\n if (typeof value === 'string') {\n const parsed = new Date(value)\n if (!Number.isNaN(parsed.getTime())) return parsed\n }\n return fallback\n}\n\nexport async function buildReportSheet(input: BuildReportSheetInput): Promise<ReportSheet> {\n const { em, scope, report, labels } = input\n const isClosed = report.status === 'closed'\n const grouping = normalizeReportGrouping(input.grouping ?? report.grouping)\n const nonbillableMode = report.nonbillableMode as ReportNonBillableMode\n\n const data = await loadReportData({\n em,\n scope,\n timeProjectIds: input.timeProjectIds,\n periodFrom: toDate(report.periodFrom, new Date(0)),\n periodTo: toDate(report.periodTo, new Date()),\n })\n\n // A closed report shows only what it froze. An entry logged into the period\n // AFTER the report closed is genuinely new work and belongs to the next\n // report \u2014 screen 15 note 2 is explicit that the lock covers entries, not\n // tasks, so logging more time on the same task must stay possible.\n const entries = isClosed\n ? data.entries.filter((entry) => entry.frozen?.reportId === report.id)\n : data.entries\n\n const totals = computeReportTotals({\n entries,\n projects: data.projects,\n directory: data.directory,\n options: {\n grouping,\n nonbillableMode,\n includeAlreadyReported: report.includeAlreadyReported ?? false,\n },\n currentReportId: report.id,\n labels,\n })\n\n const currency = resolveReportCurrency(\n data.projects.map((project) => ({\n id: project.id,\n name: project.name,\n currencyCode: project.currencyCode,\n })),\n )\n\n return {\n totals,\n entries,\n projects: data.projects,\n directory: data.directory,\n // A closed report keeps the currency it was closed with, even if a project\n // has since been relabelled (risk R11).\n currencyCode: isClosed ? report.currencyCode : currency.ok ? currency.currencyCode : report.currencyCode,\n grouping,\n nonbillableMode,\n isClosed,\n }\n}\n"],
5
- "mappings": "AAoBA,SAAS,sBAA4C;AACrD,SAAS,+BAA+B;AACxC;AAAA,EACE;AAAA,EACA;AAAA,OAOK;AA6BP,SAAS,OAAO,OAAyC,UAAsB;AAC7E,MAAI,iBAAiB,QAAQ,CAAC,OAAO,MAAM,MAAM,QAAQ,CAAC,EAAG,QAAO;AACpE,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,SAAS,IAAI,KAAK,KAAK;AAC7B,QAAI,CAAC,OAAO,MAAM,OAAO,QAAQ,CAAC,EAAG,QAAO;AAAA,EAC9C;AACA,SAAO;AACT;AAEA,eAAsB,iBAAiB,OAAoD;AACzF,QAAM,EAAE,IAAI,OAAO,QAAQ,OAAO,IAAI;AACtC,QAAM,WAAW,OAAO,WAAW;AACnC,QAAM,WAAW,wBAAwB,MAAM,YAAY,OAAO,QAAQ;AAC1E,QAAM,kBAAkB,OAAO;AAE/B,QAAM,OAAO,MAAM,eAAe;AAAA,IAChC;AAAA,IACA;AAAA,IACA,gBAAgB,MAAM;AAAA,IACtB,YAAY,OAAO,OAAO,YAAY,oBAAI,KAAK,CAAC,CAAC;AAAA,IACjD,UAAU,OAAO,OAAO,UAAU,oBAAI,KAAK,CAAC;AAAA,EAC9C,CAAC;AAMD,QAAM,UAAU,WACZ,KAAK,QAAQ,OAAO,CAAC,UAAU,MAAM,QAAQ,aAAa,OAAO,EAAE,IACnE,KAAK;AAET,QAAM,SAAS,oBAAoB;AAAA,IACjC;AAAA,IACA,UAAU,KAAK;AAAA,IACf,WAAW,KAAK;AAAA,IAChB,SAAS;AAAA,MACP;AAAA,MACA;AAAA,MACA,wBAAwB,OAAO,0BAA0B;AAAA,IAC3D;AAAA,IACA,iBAAiB,OAAO;AAAA,IACxB;AAAA,EACF,CAAC;AAED,QAAM,WAAW;AAAA,IACf,KAAK,SAAS,IAAI,CAAC,aAAa;AAAA,MAC9B,IAAI,QAAQ;AAAA,MACZ,MAAM,QAAQ;AAAA,MACd,cAAc,QAAQ;AAAA,IACxB,EAAE;AAAA,EACJ;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,UAAU,KAAK;AAAA,IACf,WAAW,KAAK;AAAA;AAAA;AAAA,IAGhB,cAAc,WAAW,OAAO,eAAe,SAAS,KAAK,SAAS,eAAe,OAAO;AAAA,IAC5F;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;",
4
+ "sourcesContent": ["/**\n * The sheet of screen 14, built once and reused by the detail page, the exports\n * and the close command.\n *\n * The one rule that matters here is the difference between a draft and a closed\n * report:\n *\n * - a **draft** is computed live, so it moves when an entry is edited or the\n * rounding rule changes \u2014 by design, and screen 16 says so;\n * - a **closed** report renders exactly what it froze. Its lines come from the\n * `staff_time_report_entries` snapshots, so a later rounding change, a rate\n * change or an unlocked-and-edited entry cannot restate an invoice a client\n * already holds (risk R1).\n *\n * Both paths go through the same `computeReportTotals`, which is what keeps the\n * preview, the sheet and the freeze records arithmetically identical.\n */\n\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport type { StaffTimeReport } from '../../data/entities'\nimport { loadReportData, type ReportDataScope } from './loadReportData'\nimport { normalizeReportGrouping } from './reportGroupings'\nimport {\n computeReportTotals,\n resolveReportCurrency,\n type ReportDirectory,\n type ReportGrouping,\n type ReportInputEntry,\n type ReportInputProject,\n type ReportNonBillableMode,\n type ReportTotals,\n} from './reportTotals'\n\nexport type ReportSheetLabels = {\n unassignedTask: string\n unassignedPerson: string\n nonbillableGroup: string\n}\n\nexport type BuildReportSheetInput = {\n em: EntityManager\n scope: ReportDataScope\n report: StaffTimeReport\n timeProjectIds: readonly string[]\n labels: ReportSheetLabels\n /** Overrides the report's stored grouping, for an export that re-groups. */\n grouping?: ReportGrouping\n}\n\nexport type ReportSheet = {\n totals: ReportTotals\n entries: ReportInputEntry[]\n projects: ReportInputProject[]\n directory: ReportDirectory\n currencyCode: string | null\n grouping: ReportGrouping\n nonbillableMode: ReportNonBillableMode\n isClosed: boolean\n}\n\nfunction toDate(value: Date | string | null | undefined, fallback: Date): Date {\n if (value instanceof Date && !Number.isNaN(value.getTime())) return value\n if (typeof value === 'string') {\n const parsed = new Date(value)\n if (!Number.isNaN(parsed.getTime())) return parsed\n }\n return fallback\n}\n\nexport async function buildReportSheet(input: BuildReportSheetInput): Promise<ReportSheet> {\n const { em, scope, report, labels } = input\n const isClosed = report.status === 'closed'\n const grouping = normalizeReportGrouping(input.grouping ?? report.grouping)\n const nonbillableMode = report.nonbillableMode as ReportNonBillableMode\n\n const data = await loadReportData({\n em,\n scope,\n timeProjectIds: input.timeProjectIds,\n periodFrom: toDate(report.periodFrom, new Date(0)),\n periodTo: toDate(report.periodTo, new Date()),\n currentReportId: report.id,\n })\n\n // A closed report shows only what it froze. An entry logged into the period\n // AFTER the report closed is genuinely new work and belongs to the next\n // report \u2014 screen 15 note 2 is explicit that the lock covers entries, not\n // tasks, so logging more time on the same task must stay possible.\n const entries = isClosed\n ? data.entries.filter((entry) => entry.frozen?.reportId === report.id)\n : data.entries\n\n const totals = computeReportTotals({\n entries,\n projects: data.projects,\n directory: data.directory,\n options: {\n grouping,\n nonbillableMode,\n includeAlreadyReported: report.includeAlreadyReported ?? false,\n },\n currentReportId: report.id,\n labels,\n })\n\n const currency = resolveReportCurrency(\n data.projects.map((project) => ({\n id: project.id,\n name: project.name,\n currencyCode: project.currencyCode,\n })),\n )\n\n return {\n totals,\n entries,\n projects: data.projects,\n directory: data.directory,\n // A closed report keeps the currency it was closed with, even if a project\n // has since been relabelled (risk R11).\n currencyCode: isClosed ? report.currencyCode : currency.ok ? currency.currencyCode : report.currencyCode,\n grouping,\n nonbillableMode,\n isClosed,\n }\n}\n"],
5
+ "mappings": "AAoBA,SAAS,sBAA4C;AACrD,SAAS,+BAA+B;AACxC;AAAA,EACE;AAAA,EACA;AAAA,OAOK;AA6BP,SAAS,OAAO,OAAyC,UAAsB;AAC7E,MAAI,iBAAiB,QAAQ,CAAC,OAAO,MAAM,MAAM,QAAQ,CAAC,EAAG,QAAO;AACpE,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,SAAS,IAAI,KAAK,KAAK;AAC7B,QAAI,CAAC,OAAO,MAAM,OAAO,QAAQ,CAAC,EAAG,QAAO;AAAA,EAC9C;AACA,SAAO;AACT;AAEA,eAAsB,iBAAiB,OAAoD;AACzF,QAAM,EAAE,IAAI,OAAO,QAAQ,OAAO,IAAI;AACtC,QAAM,WAAW,OAAO,WAAW;AACnC,QAAM,WAAW,wBAAwB,MAAM,YAAY,OAAO,QAAQ;AAC1E,QAAM,kBAAkB,OAAO;AAE/B,QAAM,OAAO,MAAM,eAAe;AAAA,IAChC;AAAA,IACA;AAAA,IACA,gBAAgB,MAAM;AAAA,IACtB,YAAY,OAAO,OAAO,YAAY,oBAAI,KAAK,CAAC,CAAC;AAAA,IACjD,UAAU,OAAO,OAAO,UAAU,oBAAI,KAAK,CAAC;AAAA,IAC5C,iBAAiB,OAAO;AAAA,EAC1B,CAAC;AAMD,QAAM,UAAU,WACZ,KAAK,QAAQ,OAAO,CAAC,UAAU,MAAM,QAAQ,aAAa,OAAO,EAAE,IACnE,KAAK;AAET,QAAM,SAAS,oBAAoB;AAAA,IACjC;AAAA,IACA,UAAU,KAAK;AAAA,IACf,WAAW,KAAK;AAAA,IAChB,SAAS;AAAA,MACP;AAAA,MACA;AAAA,MACA,wBAAwB,OAAO,0BAA0B;AAAA,IAC3D;AAAA,IACA,iBAAiB,OAAO;AAAA,IACxB;AAAA,EACF,CAAC;AAED,QAAM,WAAW;AAAA,IACf,KAAK,SAAS,IAAI,CAAC,aAAa;AAAA,MAC9B,IAAI,QAAQ;AAAA,MACZ,MAAM,QAAQ;AAAA,MACd,cAAc,QAAQ;AAAA,IACxB,EAAE;AAAA,EACJ;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,UAAU,KAAK;AAAA,IACf,WAAW,KAAK;AAAA;AAAA;AAAA,IAGhB,cAAc,WAAW,OAAO,eAAe,SAAS,KAAK,SAAS,eAAe,OAAO;AAAA,IAC5F;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
@@ -98,7 +98,8 @@ async function loadReportData(input) {
98
98
  const frozenByEntryId = await loadFrozenValues(
99
99
  em,
100
100
  scope,
101
- entryRows.map((entry) => entry.id)
101
+ entryRows.map((entry) => entry.id),
102
+ { preferReportId: input.currentReportId ?? null }
102
103
  );
103
104
  const entries = entryRows.map((entry) => ({
104
105
  id: entry.id,
@@ -127,7 +128,19 @@ async function loadReportData(input) {
127
128
  projectRows
128
129
  };
129
130
  }
130
- async function loadFrozenValues(em, scope, timeEntryIds) {
131
+ function closedAtTime(report) {
132
+ const closedAt = report.closedAt;
133
+ if (closedAt instanceof Date && !Number.isNaN(closedAt.getTime())) return closedAt.getTime();
134
+ return Number.POSITIVE_INFINITY;
135
+ }
136
+ function compareClosedReportFreezes(left, right) {
137
+ const leftTime = closedAtTime(left.report);
138
+ const rightTime = closedAtTime(right.report);
139
+ if (leftTime !== rightTime) return leftTime < rightTime ? -1 : 1;
140
+ if (left.report.id === right.report.id) return 0;
141
+ return left.report.id < right.report.id ? -1 : 1;
142
+ }
143
+ async function loadClosedReportFreezes(em, scope, timeEntryIds) {
131
144
  const ids = Array.from(new Set(timeEntryIds.filter((id) => typeof id === "string" && id.length > 0)));
132
145
  const result = /* @__PURE__ */ new Map();
133
146
  if (ids.length === 0) return result;
@@ -149,7 +162,22 @@ async function loadFrozenValues(em, scope, timeEntryIds) {
149
162
  for (const row of rows) {
150
163
  const report = reportById.get(row.reportId);
151
164
  if (!report) continue;
152
- result.set(row.timeEntryId, {
165
+ const bucket = result.get(row.timeEntryId);
166
+ if (bucket) bucket.push({ report, row });
167
+ else result.set(row.timeEntryId, [{ report, row }]);
168
+ }
169
+ for (const bucket of result.values()) bucket.sort(compareClosedReportFreezes);
170
+ return result;
171
+ }
172
+ async function loadFrozenValues(em, scope, timeEntryIds, options = {}) {
173
+ const result = /* @__PURE__ */ new Map();
174
+ const freezesByEntryId = await loadClosedReportFreezes(em, scope, timeEntryIds);
175
+ const preferReportId = options.preferReportId ?? null;
176
+ for (const [timeEntryId, freezes] of freezesByEntryId) {
177
+ const chosen = (preferReportId ? freezes.find((freeze) => freeze.report.id === preferReportId) : void 0) ?? freezes[0];
178
+ if (!chosen) continue;
179
+ const { report, row } = chosen;
180
+ result.set(timeEntryId, {
153
181
  reportId: report.id,
154
182
  reference: report.reference ?? null,
155
183
  title: report.title ?? null,
@@ -164,6 +192,7 @@ async function loadFrozenValues(em, scope, timeEntryIds) {
164
192
  return result;
165
193
  }
166
194
  export {
195
+ loadClosedReportFreezes,
167
196
  loadFrozenValues,
168
197
  loadReportData
169
198
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/staff/lib/timesheets-reports/loadReportData.ts"],
4
- "sourcesContent": ["/**\n * The one read that feeds every report surface: the live preview of screen 13,\n * the sheet of screen 14, the close command's freeze records and the exports.\n *\n * It is deliberately a single loader rather than one query per surface, because\n * a preview that counts different hours from the sheet it generates \u2014 or from\n * the snapshot the close writes \u2014 is the failure mode this whole phase exists to\n * prevent. Everything downstream consumes the same `ReportInputEntry[]`.\n *\n * Scoping is not optional here: every query carries `tenantId` and\n * `organizationId`, and the project ids are expected to have been narrowed by\n * `resolveProjectAccess` before they arrive.\n */\n\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport {\n StaffTeamMember,\n StaffTimeEntry,\n StaffTimeProject,\n StaffTimeReport,\n StaffTimeReportEntry,\n StaffTimeTask,\n} from '../../data/entities'\nimport type { FrozenEntryValues, ReportDirectory, ReportInputEntry, ReportInputProject } from './reportTotals'\n\nexport type ReportDataScope = {\n tenantId: string\n organizationId: string\n}\n\nexport type LoadReportDataInput = {\n em: EntityManager\n scope: ReportDataScope\n timeProjectIds: readonly string[]\n periodFrom: Date\n periodTo: Date\n}\n\nexport type ReportData = {\n projects: ReportInputProject[]\n entries: ReportInputEntry[]\n directory: ReportDirectory\n /** Raw project rows, kept so callers can assert currency without a second read. */\n projectRows: StaffTimeProject[]\n}\n\nfunction toNumberOrNull(value: unknown): number | null {\n if (value === null || value === undefined) return null\n const parsed = typeof value === 'number' ? value : Number.parseFloat(String(value))\n return Number.isFinite(parsed) ? parsed : null\n}\n\nfunction toIsoDate(value: Date | string | null | undefined): string {\n if (!value) return ''\n if (value instanceof Date) {\n if (Number.isNaN(value.getTime())) return ''\n const year = value.getFullYear()\n const month = String(value.getMonth() + 1).padStart(2, '0')\n const day = String(value.getDate()).padStart(2, '0')\n return `${year}-${month}-${day}`\n }\n return String(value).slice(0, 10)\n}\n\n/**\n * D-2 caps nesting at one level, so a task's root is either itself or its\n * parent. The fallback to the task's own id keeps a line visible even if a\n * parent row has since been hard-removed.\n */\nfunction resolveRootTaskId(taskId: string | null, parentById: ReadonlyMap<string, string | null>): string | null {\n if (!taskId) return null\n const parent = parentById.get(taskId)\n if (!parent) return taskId\n return parent\n}\n\nexport async function loadReportData(input: LoadReportDataInput): Promise<ReportData> {\n const { em, scope, periodFrom, periodTo } = input\n const projectIds = Array.from(new Set(input.timeProjectIds.filter((id) => typeof id === 'string' && id.length > 0)))\n if (projectIds.length === 0) {\n return {\n projects: [],\n entries: [],\n directory: { taskLabelById: {}, personLabelById: {} },\n projectRows: [],\n }\n }\n\n const projectRows = await em.find(StaffTimeProject, {\n id: { $in: projectIds },\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n })\n\n const entryRows = await em.find(StaffTimeEntry, {\n timeProjectId: { $in: projectIds },\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n date: { $gte: periodFrom, $lte: periodTo },\n })\n\n const taskIds = Array.from(\n new Set(entryRows.map((entry) => entry.taskId).filter((id): id is string => typeof id === 'string' && id.length > 0)),\n )\n const taskRows =\n taskIds.length > 0\n ? await em.find(StaffTimeTask, {\n id: { $in: taskIds },\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n })\n : []\n\n // A child task's parent is not necessarily among the entries' tasks, so the\n // parents are fetched in a second pass to give the rolled-up line its label.\n const parentIds = Array.from(\n new Set(\n taskRows\n .map((task) => task.parentTaskId)\n .filter((id): id is string => typeof id === 'string' && id.length > 0 && !taskIds.includes(id)),\n ),\n )\n const parentRows =\n parentIds.length > 0\n ? await em.find(StaffTimeTask, {\n id: { $in: parentIds },\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n })\n : []\n\n const parentById = new Map<string, string | null>()\n const taskLabelById: Record<string, string> = {}\n for (const task of [...taskRows, ...parentRows]) {\n parentById.set(task.id, task.parentTaskId ?? null)\n taskLabelById[task.id] = task.title\n }\n\n const staffMemberIds = Array.from(\n new Set(\n entryRows\n .map((entry) => entry.staffMemberId)\n .filter((id): id is string => typeof id === 'string' && id.length > 0),\n ),\n )\n const memberRows =\n staffMemberIds.length > 0\n ? await findWithDecryption(\n em,\n StaffTeamMember,\n {\n id: { $in: staffMemberIds },\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n },\n {},\n scope,\n )\n : []\n const personLabelById: Record<string, string> = {}\n for (const member of memberRows) personLabelById[member.id] = member.displayName\n\n const frozenByEntryId = await loadFrozenValues(\n em,\n scope,\n entryRows.map((entry) => entry.id),\n )\n\n const entries: ReportInputEntry[] = entryRows.map((entry) => ({\n id: entry.id,\n timeProjectId: entry.timeProjectId ?? '',\n taskId: entry.taskId ?? null,\n rootTaskId: resolveRootTaskId(entry.taskId ?? null, parentById),\n staffMemberId: entry.staffMemberId ?? null,\n date: toIsoDate(entry.date),\n durationMinutes: entry.durationMinutes ?? 0,\n roundedMinutes: entry.roundedMinutes ?? null,\n isBillable: entry.isBillable ?? true,\n rateOverrideAmount: toNumberOrNull(entry.rateOverrideAmount),\n description: entry.notes ?? null,\n frozen: frozenByEntryId.get(entry.id) ?? null,\n }))\n\n const projects: ReportInputProject[] = projectRows.map((project) => ({\n id: project.id,\n name: project.name,\n hourlyRate: toNumberOrNull(project.hourlyRate),\n currencyCode: project.currencyCode ?? null,\n }))\n\n return {\n projects,\n entries,\n directory: { taskLabelById, personLabelById },\n projectRows,\n }\n}\n\n/**\n * D-5's indexed lookup. `staff_time_report_entries` is authoritative for \"has\n * this hour been billed already?\", and only rows belonging to a **closed**\n * report count: a freeze record left behind by a report that has since been\n * unlocked must not keep an hour out of the next invoice.\n */\nexport async function loadFrozenValues(\n em: EntityManager,\n scope: ReportDataScope,\n timeEntryIds: readonly string[],\n): Promise<Map<string, FrozenEntryValues>> {\n const ids = Array.from(new Set(timeEntryIds.filter((id) => typeof id === 'string' && id.length > 0)))\n const result = new Map<string, FrozenEntryValues>()\n if (ids.length === 0) return result\n\n const rows = await em.find(StaffTimeReportEntry, {\n timeEntryId: { $in: ids },\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n })\n if (rows.length === 0) return result\n\n const reportIds = Array.from(new Set(rows.map((row) => row.reportId)))\n const reports = await em.find(StaffTimeReport, {\n id: { $in: reportIds },\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n status: 'closed',\n deletedAt: null,\n })\n const reportById = new Map(reports.map((report) => [report.id, report]))\n\n for (const row of rows) {\n const report = reportById.get(row.reportId)\n if (!report) continue\n result.set(row.timeEntryId, {\n reportId: report.id,\n reference: report.reference ?? null,\n title: report.title ?? null,\n rawMinutes: row.frozenRawMinutes ?? 0,\n roundedMinutes: row.frozenRoundedMinutes ?? 0,\n rateAmount: toNumberOrNull(row.frozenRateAmount),\n currencyCode: row.frozenCurrencyCode ?? null,\n amount: toNumberOrNull(row.frozenAmount),\n isBillable: row.frozenIsBillable ?? true,\n })\n }\n\n return result\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * The one read that feeds every report surface: the live preview of screen 13,\n * the sheet of screen 14, the close command's freeze records and the exports.\n *\n * It is deliberately a single loader rather than one query per surface, because\n * a preview that counts different hours from the sheet it generates \u2014 or from\n * the snapshot the close writes \u2014 is the failure mode this whole phase exists to\n * prevent. Everything downstream consumes the same `ReportInputEntry[]`.\n *\n * Scoping is not optional here: every query carries `tenantId` and\n * `organizationId`, and the project ids are expected to have been narrowed by\n * `resolveProjectAccess` before they arrive.\n */\n\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport {\n StaffTeamMember,\n StaffTimeEntry,\n StaffTimeProject,\n StaffTimeReport,\n StaffTimeReportEntry,\n StaffTimeTask,\n} from '../../data/entities'\nimport type { FrozenEntryValues, ReportDirectory, ReportInputEntry, ReportInputProject } from './reportTotals'\n\nexport type ReportDataScope = {\n tenantId: string\n organizationId: string\n}\n\nexport type LoadReportDataInput = {\n em: EntityManager\n scope: ReportDataScope\n timeProjectIds: readonly string[]\n periodFrom: Date\n periodTo: Date\n /**\n * The report the data is being loaded for. An entry several closed reports\n * quote resolves to THIS report's freeze record when it has one.\n */\n currentReportId?: string | null\n}\n\nexport type ReportData = {\n projects: ReportInputProject[]\n entries: ReportInputEntry[]\n directory: ReportDirectory\n /** Raw project rows, kept so callers can assert currency without a second read. */\n projectRows: StaffTimeProject[]\n}\n\nfunction toNumberOrNull(value: unknown): number | null {\n if (value === null || value === undefined) return null\n const parsed = typeof value === 'number' ? value : Number.parseFloat(String(value))\n return Number.isFinite(parsed) ? parsed : null\n}\n\nfunction toIsoDate(value: Date | string | null | undefined): string {\n if (!value) return ''\n if (value instanceof Date) {\n if (Number.isNaN(value.getTime())) return ''\n const year = value.getFullYear()\n const month = String(value.getMonth() + 1).padStart(2, '0')\n const day = String(value.getDate()).padStart(2, '0')\n return `${year}-${month}-${day}`\n }\n return String(value).slice(0, 10)\n}\n\n/**\n * D-2 caps nesting at one level, so a task's root is either itself or its\n * parent. The fallback to the task's own id keeps a line visible even if a\n * parent row has since been hard-removed.\n */\nfunction resolveRootTaskId(taskId: string | null, parentById: ReadonlyMap<string, string | null>): string | null {\n if (!taskId) return null\n const parent = parentById.get(taskId)\n if (!parent) return taskId\n return parent\n}\n\nexport async function loadReportData(input: LoadReportDataInput): Promise<ReportData> {\n const { em, scope, periodFrom, periodTo } = input\n const projectIds = Array.from(new Set(input.timeProjectIds.filter((id) => typeof id === 'string' && id.length > 0)))\n if (projectIds.length === 0) {\n return {\n projects: [],\n entries: [],\n directory: { taskLabelById: {}, personLabelById: {} },\n projectRows: [],\n }\n }\n\n const projectRows = await em.find(StaffTimeProject, {\n id: { $in: projectIds },\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n })\n\n const entryRows = await em.find(StaffTimeEntry, {\n timeProjectId: { $in: projectIds },\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n date: { $gte: periodFrom, $lte: periodTo },\n })\n\n const taskIds = Array.from(\n new Set(entryRows.map((entry) => entry.taskId).filter((id): id is string => typeof id === 'string' && id.length > 0)),\n )\n const taskRows =\n taskIds.length > 0\n ? await em.find(StaffTimeTask, {\n id: { $in: taskIds },\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n })\n : []\n\n // A child task's parent is not necessarily among the entries' tasks, so the\n // parents are fetched in a second pass to give the rolled-up line its label.\n const parentIds = Array.from(\n new Set(\n taskRows\n .map((task) => task.parentTaskId)\n .filter((id): id is string => typeof id === 'string' && id.length > 0 && !taskIds.includes(id)),\n ),\n )\n const parentRows =\n parentIds.length > 0\n ? await em.find(StaffTimeTask, {\n id: { $in: parentIds },\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n })\n : []\n\n const parentById = new Map<string, string | null>()\n const taskLabelById: Record<string, string> = {}\n for (const task of [...taskRows, ...parentRows]) {\n parentById.set(task.id, task.parentTaskId ?? null)\n taskLabelById[task.id] = task.title\n }\n\n const staffMemberIds = Array.from(\n new Set(\n entryRows\n .map((entry) => entry.staffMemberId)\n .filter((id): id is string => typeof id === 'string' && id.length > 0),\n ),\n )\n const memberRows =\n staffMemberIds.length > 0\n ? await findWithDecryption(\n em,\n StaffTeamMember,\n {\n id: { $in: staffMemberIds },\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n },\n {},\n scope,\n )\n : []\n const personLabelById: Record<string, string> = {}\n for (const member of memberRows) personLabelById[member.id] = member.displayName\n\n const frozenByEntryId = await loadFrozenValues(\n em,\n scope,\n entryRows.map((entry) => entry.id),\n { preferReportId: input.currentReportId ?? null },\n )\n\n const entries: ReportInputEntry[] = entryRows.map((entry) => ({\n id: entry.id,\n timeProjectId: entry.timeProjectId ?? '',\n taskId: entry.taskId ?? null,\n rootTaskId: resolveRootTaskId(entry.taskId ?? null, parentById),\n staffMemberId: entry.staffMemberId ?? null,\n date: toIsoDate(entry.date),\n durationMinutes: entry.durationMinutes ?? 0,\n roundedMinutes: entry.roundedMinutes ?? null,\n isBillable: entry.isBillable ?? true,\n rateOverrideAmount: toNumberOrNull(entry.rateOverrideAmount),\n description: entry.notes ?? null,\n frozen: frozenByEntryId.get(entry.id) ?? null,\n }))\n\n const projects: ReportInputProject[] = projectRows.map((project) => ({\n id: project.id,\n name: project.name,\n hourlyRate: toNumberOrNull(project.hourlyRate),\n currencyCode: project.currencyCode ?? null,\n }))\n\n return {\n projects,\n entries,\n directory: { taskLabelById, personLabelById },\n projectRows,\n }\n}\n\nexport type ClosedReportFreeze = {\n report: StaffTimeReport\n row: StaffTimeReportEntry\n}\n\nfunction closedAtTime(report: StaffTimeReport): number {\n const closedAt = report.closedAt\n if (closedAt instanceof Date && !Number.isNaN(closedAt.getTime())) return closedAt.getTime()\n return Number.POSITIVE_INFINITY\n}\n\nfunction compareClosedReportFreezes(left: ClosedReportFreeze, right: ClosedReportFreeze): number {\n const leftTime = closedAtTime(left.report)\n const rightTime = closedAtTime(right.report)\n if (leftTime !== rightTime) return leftTime < rightTime ? -1 : 1\n if (left.report.id === right.report.id) return 0\n return left.report.id < right.report.id ? -1 : 1\n}\n\n/**\n * Every freeze record a **closed** report holds for the given entries. The D-5\n * opt-in lets a later report re-include an hour an earlier one already froze,\n * so one entry can be quoted by several closed reports; each list is ordered by\n * the moment its report closed (report id as the tie-break), which makes the\n * first item the report that billed the hour first.\n */\nexport async function loadClosedReportFreezes(\n em: EntityManager,\n scope: ReportDataScope,\n timeEntryIds: readonly string[],\n): Promise<Map<string, ClosedReportFreeze[]>> {\n const ids = Array.from(new Set(timeEntryIds.filter((id) => typeof id === 'string' && id.length > 0)))\n const result = new Map<string, ClosedReportFreeze[]>()\n if (ids.length === 0) return result\n\n const rows = await em.find(StaffTimeReportEntry, {\n timeEntryId: { $in: ids },\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n })\n if (rows.length === 0) return result\n\n const reportIds = Array.from(new Set(rows.map((row) => row.reportId)))\n const reports = await em.find(StaffTimeReport, {\n id: { $in: reportIds },\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n status: 'closed',\n deletedAt: null,\n })\n const reportById = new Map(reports.map((report) => [report.id, report]))\n\n for (const row of rows) {\n const report = reportById.get(row.reportId)\n if (!report) continue\n const bucket = result.get(row.timeEntryId)\n if (bucket) bucket.push({ report, row })\n else result.set(row.timeEntryId, [{ report, row }])\n }\n for (const bucket of result.values()) bucket.sort(compareClosedReportFreezes)\n\n return result\n}\n\n/**\n * D-5's indexed lookup. `staff_time_report_entries` is authoritative for \"has\n * this hour been billed already?\", and only rows belonging to a **closed**\n * report count: a freeze record left behind by a report that has since been\n * unlocked must not keep an hour out of the next invoice.\n *\n * When several closed reports quote one entry, `preferReportId` picks that\n * report's own record \u2014 a closed report must be able to find what it froze no\n * matter who else re-included the hour. Without a preferred report the earliest\n * closed one answers, so the already-reported source named is stable.\n */\nexport async function loadFrozenValues(\n em: EntityManager,\n scope: ReportDataScope,\n timeEntryIds: readonly string[],\n options: { preferReportId?: string | null } = {},\n): Promise<Map<string, FrozenEntryValues>> {\n const result = new Map<string, FrozenEntryValues>()\n const freezesByEntryId = await loadClosedReportFreezes(em, scope, timeEntryIds)\n const preferReportId = options.preferReportId ?? null\n\n for (const [timeEntryId, freezes] of freezesByEntryId) {\n const chosen =\n (preferReportId ? freezes.find((freeze) => freeze.report.id === preferReportId) : undefined) ?? freezes[0]\n if (!chosen) continue\n const { report, row } = chosen\n result.set(timeEntryId, {\n reportId: report.id,\n reference: report.reference ?? null,\n title: report.title ?? null,\n rawMinutes: row.frozenRawMinutes ?? 0,\n roundedMinutes: row.frozenRoundedMinutes ?? 0,\n rateAmount: toNumberOrNull(row.frozenRateAmount),\n currencyCode: row.frozenCurrencyCode ?? null,\n amount: toNumberOrNull(row.frozenAmount),\n isBillable: row.frozenIsBillable ?? true,\n })\n }\n\n return result\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,16 @@
1
+ function formatReportPeriodDate(value) {
2
+ if (value instanceof Date) {
3
+ if (Number.isNaN(value.getTime())) return null;
4
+ return value.toISOString().slice(0, 10);
5
+ }
6
+ if (typeof value !== "string") return null;
7
+ const text = value.trim();
8
+ if (/^\d{4}-\d{2}-\d{2}/.test(text)) return text.slice(0, 10);
9
+ const parsed = new Date(text);
10
+ if (Number.isNaN(parsed.getTime())) return null;
11
+ return parsed.toISOString().slice(0, 10);
12
+ }
13
+ export {
14
+ formatReportPeriodDate
15
+ };
16
+ //# sourceMappingURL=reportPeriod.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/staff/lib/timesheets-reports/reportPeriod.ts"],
4
+ "sourcesContent": ["/**\n * `period_from` / `period_to` are `date` columns, and MikroORM hydrates a `date`\n * column as a `YYYY-MM-DD` string even though the entity declares `Date`. A\n * reader that only accepts `instanceof Date` therefore drops the period on every\n * loaded report, so the sheet and its exports read the value through here.\n */\nexport function formatReportPeriodDate(value: Date | string | null | undefined): string | null {\n if (value instanceof Date) {\n if (Number.isNaN(value.getTime())) return null\n return value.toISOString().slice(0, 10)\n }\n if (typeof value !== 'string') return null\n const text = value.trim()\n if (/^\\d{4}-\\d{2}-\\d{2}/.test(text)) return text.slice(0, 10)\n const parsed = new Date(text)\n if (Number.isNaN(parsed.getTime())) return null\n return parsed.toISOString().slice(0, 10)\n}\n"],
5
+ "mappings": "AAMO,SAAS,uBAAuB,OAAwD;AAC7F,MAAI,iBAAiB,MAAM;AACzB,QAAI,OAAO,MAAM,MAAM,QAAQ,CAAC,EAAG,QAAO;AAC1C,WAAO,MAAM,YAAY,EAAE,MAAM,GAAG,EAAE;AAAA,EACxC;AACA,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAM,OAAO,MAAM,KAAK;AACxB,MAAI,qBAAqB,KAAK,IAAI,EAAG,QAAO,KAAK,MAAM,GAAG,EAAE;AAC5D,QAAM,SAAS,IAAI,KAAK,IAAI;AAC5B,MAAI,OAAO,MAAM,OAAO,QAAQ,CAAC,EAAG,QAAO;AAC3C,SAAO,OAAO,YAAY,EAAE,MAAM,GAAG,EAAE;AACzC;",
6
+ "names": []
7
+ }