@open-mercato/core 0.6.5-develop.4534.1.b459babe6d → 0.6.5-develop.4559.1.839e136509

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 (644) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/AGENTS.md +5 -0
  3. package/dist/generated/entities/role/index.js +3 -1
  4. package/dist/generated/entities/role/index.js.map +2 -2
  5. package/dist/generated/entities/user/index.js +3 -1
  6. package/dist/generated/entities/user/index.js.map +2 -2
  7. package/dist/generated/entity-fields-registry.js +2 -0
  8. package/dist/generated/entity-fields-registry.js.map +2 -2
  9. package/dist/helpers/integration/communicationChannelsFixtures.js.map +2 -2
  10. package/dist/helpers/integration/dbFixtures.js +2 -1
  11. package/dist/helpers/integration/dbFixtures.js.map +2 -2
  12. package/dist/helpers/integration/optimisticLockUi.js +104 -0
  13. package/dist/helpers/integration/optimisticLockUi.js.map +7 -0
  14. package/dist/helpers/integration/salesFixtures.js +17 -0
  15. package/dist/helpers/integration/salesFixtures.js.map +2 -2
  16. package/dist/modules/api_keys/backend/api-keys/page.js +9 -5
  17. package/dist/modules/api_keys/backend/api-keys/page.js.map +2 -2
  18. package/dist/modules/attachments/components/AttachmentPartitionSettings.js +17 -9
  19. package/dist/modules/attachments/components/AttachmentPartitionSettings.js.map +2 -2
  20. package/dist/modules/auth/api/roles/acl/route.js +32 -13
  21. package/dist/modules/auth/api/roles/acl/route.js.map +2 -2
  22. package/dist/modules/auth/api/roles/route.js +3 -1
  23. package/dist/modules/auth/api/roles/route.js.map +2 -2
  24. package/dist/modules/auth/api/sidebar/preferences/route.js +71 -3
  25. package/dist/modules/auth/api/sidebar/preferences/route.js.map +2 -2
  26. package/dist/modules/auth/api/users/acl/route.js +42 -19
  27. package/dist/modules/auth/api/users/acl/route.js.map +2 -2
  28. package/dist/modules/auth/api/users/route.js +3 -1
  29. package/dist/modules/auth/api/users/route.js.map +2 -2
  30. package/dist/modules/auth/backend/roles/[id]/edit/page.js +24 -4
  31. package/dist/modules/auth/backend/roles/[id]/edit/page.js.map +2 -2
  32. package/dist/modules/auth/backend/roles/page.js +8 -4
  33. package/dist/modules/auth/backend/roles/page.js.map +2 -2
  34. package/dist/modules/auth/backend/users/[id]/edit/page.js +27 -5
  35. package/dist/modules/auth/backend/users/[id]/edit/page.js.map +2 -2
  36. package/dist/modules/auth/backend/users/page.js +6 -2
  37. package/dist/modules/auth/backend/users/page.js.map +2 -2
  38. package/dist/modules/auth/components/AclEditor.js +3 -1
  39. package/dist/modules/auth/components/AclEditor.js.map +2 -2
  40. package/dist/modules/auth/data/entities.js +6 -0
  41. package/dist/modules/auth/data/entities.js.map +2 -2
  42. package/dist/modules/auth/services/sidebarPreferencesService.js +32 -4
  43. package/dist/modules/auth/services/sidebarPreferencesService.js.map +2 -2
  44. package/dist/modules/business_rules/api/rules/route.js +28 -0
  45. package/dist/modules/business_rules/api/rules/route.js.map +2 -2
  46. package/dist/modules/business_rules/api/sets/route.js +28 -0
  47. package/dist/modules/business_rules/api/sets/route.js.map +2 -2
  48. package/dist/modules/business_rules/backend/rules/[id]/page.js +11 -4
  49. package/dist/modules/business_rules/backend/rules/[id]/page.js.map +3 -3
  50. package/dist/modules/business_rules/backend/rules/page.js +20 -11
  51. package/dist/modules/business_rules/backend/rules/page.js.map +2 -2
  52. package/dist/modules/business_rules/backend/sets/[id]/page.js +11 -4
  53. package/dist/modules/business_rules/backend/sets/[id]/page.js.map +2 -2
  54. package/dist/modules/business_rules/backend/sets/page.js +20 -11
  55. package/dist/modules/business_rules/backend/sets/page.js.map +2 -2
  56. package/dist/modules/catalog/api/categories/route.js +2 -0
  57. package/dist/modules/catalog/api/categories/route.js.map +2 -2
  58. package/dist/modules/catalog/api/products/route.js +2 -1
  59. package/dist/modules/catalog/api/products/route.js.map +2 -2
  60. package/dist/modules/catalog/backend/catalog/categories/[id]/edit/page.js +2 -0
  61. package/dist/modules/catalog/backend/catalog/categories/[id]/edit/page.js.map +2 -2
  62. package/dist/modules/catalog/backend/catalog/products/[id]/page.js +94 -40
  63. package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
  64. package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js +37 -8
  65. package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js.map +2 -2
  66. package/dist/modules/catalog/backend/catalog/products/optionSchemaClient.js.map +2 -2
  67. package/dist/modules/catalog/commands/variants.js +32 -31
  68. package/dist/modules/catalog/commands/variants.js.map +2 -2
  69. package/dist/modules/catalog/components/PriceKindSettings.js +12 -5
  70. package/dist/modules/catalog/components/PriceKindSettings.js.map +2 -2
  71. package/dist/modules/catalog/components/categories/CategoriesDataTable.js.map +2 -2
  72. package/dist/modules/catalog/components/products/ProductMediaManager.js.map +2 -2
  73. package/dist/modules/catalog/components/products/ProductsDataTable.js +5 -3
  74. package/dist/modules/catalog/components/products/ProductsDataTable.js.map +2 -2
  75. package/dist/modules/catalog/components/products/productForm.js.map +2 -2
  76. package/dist/modules/catalog/components/products/variantForm.js +2 -1
  77. package/dist/modules/catalog/components/products/variantForm.js.map +2 -2
  78. package/dist/modules/communication_channels/api/post/test-seed/route.js +23 -2
  79. package/dist/modules/communication_channels/api/post/test-seed/route.js.map +2 -2
  80. package/dist/modules/communication_channels/backend/profile/communication-channels/page.js +5 -0
  81. package/dist/modules/communication_channels/backend/profile/communication-channels/page.js.map +2 -2
  82. package/dist/modules/communication_channels/commands/set-primary-channel.js +2 -1
  83. package/dist/modules/communication_channels/commands/set-primary-channel.js.map +2 -2
  84. package/dist/modules/currencies/backend/currencies/[id]/page.js +6 -3
  85. package/dist/modules/currencies/backend/currencies/[id]/page.js.map +2 -2
  86. package/dist/modules/currencies/backend/currencies/page.js +18 -11
  87. package/dist/modules/currencies/backend/currencies/page.js.map +2 -2
  88. package/dist/modules/currencies/backend/exchange-rates/[id]/page.js +1 -0
  89. package/dist/modules/currencies/backend/exchange-rates/[id]/page.js.map +2 -2
  90. package/dist/modules/currencies/backend/exchange-rates/page.js +10 -6
  91. package/dist/modules/currencies/backend/exchange-rates/page.js.map +2 -2
  92. package/dist/modules/currencies/commands/currencies.js +7 -5
  93. package/dist/modules/currencies/commands/currencies.js.map +2 -2
  94. package/dist/modules/currencies/components/CurrencyFetchingConfig.js +26 -19
  95. package/dist/modules/currencies/components/CurrencyFetchingConfig.js.map +2 -2
  96. package/dist/modules/customer_accounts/api/admin/roles/[id].js +28 -5
  97. package/dist/modules/customer_accounts/api/admin/roles/[id].js.map +2 -2
  98. package/dist/modules/customer_accounts/api/admin/roles.js +4 -2
  99. package/dist/modules/customer_accounts/api/admin/roles.js.map +2 -2
  100. package/dist/modules/customer_accounts/api/admin/users/[id].js +28 -5
  101. package/dist/modules/customer_accounts/api/admin/users/[id].js.map +2 -2
  102. package/dist/modules/customer_accounts/api/admin/users.js +2 -0
  103. package/dist/modules/customer_accounts/api/admin/users.js.map +2 -2
  104. package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js +16 -8
  105. package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js.map +2 -2
  106. package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js +8 -4
  107. package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js.map +2 -2
  108. package/dist/modules/customer_accounts/backend/customer_accounts/settings/domain/page.js +8 -4
  109. package/dist/modules/customer_accounts/backend/customer_accounts/settings/domain/page.js.map +2 -2
  110. package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js +29 -18
  111. package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js.map +2 -2
  112. package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js +18 -11
  113. package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js.map +2 -2
  114. package/dist/modules/customers/api/companies/route.js +13 -2
  115. package/dist/modules/customers/api/companies/route.js.map +2 -2
  116. package/dist/modules/customers/api/deals/route.js +2 -0
  117. package/dist/modules/customers/api/deals/route.js.map +2 -2
  118. package/dist/modules/customers/api/people/route.js +11 -2
  119. package/dist/modules/customers/api/people/route.js.map +2 -2
  120. package/dist/modules/customers/api/todos/route.js +1 -0
  121. package/dist/modules/customers/api/todos/route.js.map +2 -2
  122. package/dist/modules/customers/backend/config/customers/deals/page.js.map +2 -2
  123. package/dist/modules/customers/backend/config/customers/pipeline-stages/page.js +34 -21
  124. package/dist/modules/customers/backend/config/customers/pipeline-stages/page.js.map +2 -2
  125. package/dist/modules/customers/backend/customers/companies/[id]/page.js +45 -27
  126. package/dist/modules/customers/backend/customers/companies/[id]/page.js.map +2 -2
  127. package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
  128. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +22 -5
  129. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
  130. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealFormHandlers.js +30 -8
  131. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealFormHandlers.js.map +2 -2
  132. package/dist/modules/customers/backend/customers/deals/[id]/page.js +1 -0
  133. package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
  134. package/dist/modules/customers/backend/customers/deals/page.js +16 -6
  135. package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
  136. package/dist/modules/customers/backend/customers/deals/pipeline/page.js +62 -39
  137. package/dist/modules/customers/backend/customers/deals/pipeline/page.js.map +2 -2
  138. package/dist/modules/customers/backend/customers/people/[id]/page.js +41 -26
  139. package/dist/modules/customers/backend/customers/people/[id]/page.js.map +2 -2
  140. package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
  141. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +50 -23
  142. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
  143. package/dist/modules/customers/commands/addresses.js +16 -14
  144. package/dist/modules/customers/commands/addresses.js.map +2 -2
  145. package/dist/modules/customers/commands/companies.js +1 -1
  146. package/dist/modules/customers/commands/companies.js.map +2 -2
  147. package/dist/modules/customers/commands/interactions.js +41 -4
  148. package/dist/modules/customers/commands/interactions.js.map +2 -2
  149. package/dist/modules/customers/commands/people.js +1 -1
  150. package/dist/modules/customers/commands/people.js.map +2 -2
  151. package/dist/modules/customers/commands/personCompanyLinks.js +8 -5
  152. package/dist/modules/customers/commands/personCompanyLinks.js.map +2 -2
  153. package/dist/modules/customers/commands/pipeline-stages.js +13 -11
  154. package/dist/modules/customers/commands/pipeline-stages.js.map +3 -3
  155. package/dist/modules/customers/components/AddressFormatSettings.js.map +2 -2
  156. package/dist/modules/customers/components/DictionarySettings.js +20 -13
  157. package/dist/modules/customers/components/DictionarySettings.js.map +2 -2
  158. package/dist/modules/customers/components/DictionarySortSettings.js +4 -0
  159. package/dist/modules/customers/components/DictionarySortSettings.js.map +2 -2
  160. package/dist/modules/customers/components/PipelineSettings.js +38 -23
  161. package/dist/modules/customers/components/PipelineSettings.js.map +2 -2
  162. package/dist/modules/customers/components/detail/ActivityTimeline.js +1 -1
  163. package/dist/modules/customers/components/detail/ActivityTimeline.js.map +2 -2
  164. package/dist/modules/customers/components/detail/AddressesSection.js +4 -0
  165. package/dist/modules/customers/components/detail/AddressesSection.js.map +2 -2
  166. package/dist/modules/customers/components/detail/CompanyPeopleSection.js +28 -22
  167. package/dist/modules/customers/components/detail/CompanyPeopleSection.js.map +2 -2
  168. package/dist/modules/customers/components/detail/DealsSection.js +36 -24
  169. package/dist/modules/customers/components/detail/DealsSection.js.map +2 -2
  170. package/dist/modules/customers/components/detail/EmailCardActions.js +5 -0
  171. package/dist/modules/customers/components/detail/EmailCardActions.js.map +2 -2
  172. package/dist/modules/customers/components/detail/EntityTagsDialog.js +7 -0
  173. package/dist/modules/customers/components/detail/EntityTagsDialog.js.map +2 -2
  174. package/dist/modules/customers/components/detail/ManageTagsDialog.js +34 -22
  175. package/dist/modules/customers/components/detail/ManageTagsDialog.js.map +2 -2
  176. package/dist/modules/customers/components/detail/PersonCompaniesSection.js +41 -29
  177. package/dist/modules/customers/components/detail/PersonCompaniesSection.js.map +2 -2
  178. package/dist/modules/customers/components/detail/RoleAssignmentRow.js +14 -8
  179. package/dist/modules/customers/components/detail/RoleAssignmentRow.js.map +2 -2
  180. package/dist/modules/customers/components/detail/ScheduleActivityDialog.js +14 -6
  181. package/dist/modules/customers/components/detail/ScheduleActivityDialog.js.map +2 -2
  182. package/dist/modules/customers/components/detail/hooks/useInteractionMutations.js +29 -13
  183. package/dist/modules/customers/components/detail/hooks/useInteractionMutations.js.map +2 -2
  184. package/dist/modules/customers/components/detail/hooks/useInteractions.js +77 -35
  185. package/dist/modules/customers/components/detail/hooks/useInteractions.js.map +2 -2
  186. package/dist/modules/customers/components/detail/hooks/usePersonTasks.js +25 -17
  187. package/dist/modules/customers/components/detail/hooks/usePersonTasks.js.map +2 -2
  188. package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js.map +2 -2
  189. package/dist/modules/customers/components/formConfig.js.map +2 -2
  190. package/dist/modules/customers/data/guards.js +66 -0
  191. package/dist/modules/customers/data/guards.js.map +7 -0
  192. package/dist/modules/customers/di.js +37 -0
  193. package/dist/modules/customers/di.js.map +2 -2
  194. package/dist/modules/customers/lib/todoCompatibility.js +11 -0
  195. package/dist/modules/customers/lib/todoCompatibility.js.map +2 -2
  196. package/dist/modules/dashboards/components/WidgetVisibilityEditor.js.map +2 -2
  197. package/dist/modules/data_sync/api/options.js +4 -4
  198. package/dist/modules/data_sync/api/options.js.map +2 -2
  199. package/dist/modules/data_sync/api/schedules/route.js +9 -1
  200. package/dist/modules/data_sync/api/schedules/route.js.map +2 -2
  201. package/dist/modules/data_sync/backend/data-sync/page.js +17 -8
  202. package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
  203. package/dist/modules/data_sync/components/IntegrationScheduleTab.js +43 -22
  204. package/dist/modules/data_sync/components/IntegrationScheduleTab.js.map +2 -2
  205. package/dist/modules/data_sync/lib/sync-schedule-service.js +9 -0
  206. package/dist/modules/data_sync/lib/sync-schedule-service.js.map +2 -2
  207. package/dist/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.js +8 -1
  208. package/dist/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.js.map +2 -2
  209. package/dist/modules/dictionaries/api/[dictionaryId]/route.js +17 -1
  210. package/dist/modules/dictionaries/api/[dictionaryId]/route.js.map +2 -2
  211. package/dist/modules/dictionaries/components/DictionariesManager.js +31 -10
  212. package/dist/modules/dictionaries/components/DictionariesManager.js.map +2 -2
  213. package/dist/modules/dictionaries/components/DictionaryEntriesEditor.js +28 -15
  214. package/dist/modules/dictionaries/components/DictionaryEntriesEditor.js.map +2 -2
  215. package/dist/modules/directory/api/organizations/route.js +3 -0
  216. package/dist/modules/directory/api/organizations/route.js.map +2 -2
  217. package/dist/modules/directory/backend/directory/organizations/[id]/edit/page.js +2 -0
  218. package/dist/modules/directory/backend/directory/organizations/[id]/edit/page.js.map +2 -2
  219. package/dist/modules/directory/backend/directory/organizations/page.js +9 -5
  220. package/dist/modules/directory/backend/directory/organizations/page.js.map +2 -2
  221. package/dist/modules/directory/backend/directory/tenants/[id]/edit/page.js +7 -3
  222. package/dist/modules/directory/backend/directory/tenants/[id]/edit/page.js.map +2 -2
  223. package/dist/modules/directory/backend/directory/tenants/page.js +8 -4
  224. package/dist/modules/directory/backend/directory/tenants/page.js.map +2 -2
  225. package/dist/modules/directory/commands/organizations.js +7 -2
  226. package/dist/modules/directory/commands/organizations.js.map +2 -2
  227. package/dist/modules/entities/api/records.js +66 -0
  228. package/dist/modules/entities/api/records.js.map +2 -2
  229. package/dist/modules/entities/backend/entities/user/[entityId]/records/[recordId]/page.js +1 -0
  230. package/dist/modules/entities/backend/entities/user/[entityId]/records/[recordId]/page.js.map +2 -2
  231. package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js +8 -4
  232. package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js.map +2 -2
  233. package/dist/modules/entities/lib/helpers.js +17 -0
  234. package/dist/modules/entities/lib/helpers.js.map +2 -2
  235. package/dist/modules/feature_toggles/api/global/[id]/override/route.js +2 -1
  236. package/dist/modules/feature_toggles/api/global/[id]/override/route.js.map +2 -2
  237. package/dist/modules/feature_toggles/api/overrides/route.js +15 -0
  238. package/dist/modules/feature_toggles/api/overrides/route.js.map +2 -2
  239. package/dist/modules/feature_toggles/backend/feature-toggles/global/[id]/edit/page.js +15 -14
  240. package/dist/modules/feature_toggles/backend/feature-toggles/global/[id]/edit/page.js.map +2 -2
  241. package/dist/modules/feature_toggles/components/FeatureToggleOverrideCard.js +20 -12
  242. package/dist/modules/feature_toggles/components/FeatureToggleOverrideCard.js.map +2 -2
  243. package/dist/modules/feature_toggles/components/FeatureTogglesTable.js +6 -2
  244. package/dist/modules/feature_toggles/components/FeatureTogglesTable.js.map +2 -2
  245. package/dist/modules/feature_toggles/components/formConfig.js +2 -1
  246. package/dist/modules/feature_toggles/components/formConfig.js.map +2 -2
  247. package/dist/modules/feature_toggles/components/overrideFormConfig.js +5 -1
  248. package/dist/modules/feature_toggles/components/overrideFormConfig.js.map +2 -2
  249. package/dist/modules/feature_toggles/data/validators.js +7 -4
  250. package/dist/modules/feature_toggles/data/validators.js.map +2 -2
  251. package/dist/modules/inbox_ops/api/settings/route.js +17 -2
  252. package/dist/modules/inbox_ops/api/settings/route.js.map +2 -2
  253. package/dist/modules/inbox_ops/backend/inbox-ops/settings/page.js +13 -8
  254. package/dist/modules/inbox_ops/backend/inbox-ops/settings/page.js.map +2 -2
  255. package/dist/modules/inbox_ops/components/proposals/EditActionDialog.js +9 -4
  256. package/dist/modules/inbox_ops/components/proposals/EditActionDialog.js.map +2 -2
  257. package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js +18 -11
  258. package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js.map +2 -2
  259. package/dist/modules/integrations/backend/integrations/page.js +12 -8
  260. package/dist/modules/integrations/backend/integrations/page.js.map +2 -2
  261. package/dist/modules/messages/commands/messages.js +13 -10
  262. package/dist/modules/messages/commands/messages.js.map +2 -2
  263. package/dist/modules/perspectives/api/[tableId]/route.js +39 -30
  264. package/dist/modules/perspectives/api/[tableId]/route.js.map +2 -2
  265. package/dist/modules/perspectives/services/perspectiveService.js +7 -0
  266. package/dist/modules/perspectives/services/perspectiveService.js.map +2 -2
  267. package/dist/modules/planner/backend/planner/availability-rulesets/[id]/page.js +6 -14
  268. package/dist/modules/planner/backend/planner/availability-rulesets/[id]/page.js.map +3 -3
  269. package/dist/modules/planner/backend/planner/availability-rulesets/page.js +4 -2
  270. package/dist/modules/planner/backend/planner/availability-rulesets/page.js.map +2 -2
  271. package/dist/modules/planner/components/AvailabilityRuleSetForm.js +2 -0
  272. package/dist/modules/planner/components/AvailabilityRuleSetForm.js.map +2 -2
  273. package/dist/modules/planner/components/AvailabilityRulesEditor.js +36 -11
  274. package/dist/modules/planner/components/AvailabilityRulesEditor.js.map +2 -2
  275. package/dist/modules/planner/components/AvailabilitySchedule.js +9 -5
  276. package/dist/modules/planner/components/AvailabilitySchedule.js.map +2 -2
  277. package/dist/modules/query_index/lib/engine.js +19 -0
  278. package/dist/modules/query_index/lib/engine.js.map +2 -2
  279. package/dist/modules/resources/backend/resources/resource-types/[id]/edit/page.js +1 -0
  280. package/dist/modules/resources/backend/resources/resource-types/[id]/edit/page.js.map +2 -2
  281. package/dist/modules/resources/backend/resources/resource-types/page.js +4 -2
  282. package/dist/modules/resources/backend/resources/resource-types/page.js.map +2 -2
  283. package/dist/modules/resources/backend/resources/resources/[id]/page.js +14 -3
  284. package/dist/modules/resources/backend/resources/resources/[id]/page.js.map +2 -2
  285. package/dist/modules/resources/backend/resources/resources/page.js +8 -4
  286. package/dist/modules/resources/backend/resources/resources/page.js.map +2 -2
  287. package/dist/modules/resources/components/ResourceCrudForm.js +2 -0
  288. package/dist/modules/resources/components/ResourceCrudForm.js.map +2 -2
  289. package/dist/modules/resources/components/ResourceTypeCrudForm.js +1 -0
  290. package/dist/modules/resources/components/ResourceTypeCrudForm.js.map +2 -2
  291. package/dist/modules/sales/api/documents/factory.js +7 -2
  292. package/dist/modules/sales/api/documents/factory.js.map +2 -2
  293. package/dist/modules/sales/backend/sales/channels/[channelId]/edit/page.js +3 -1
  294. package/dist/modules/sales/backend/sales/channels/[channelId]/edit/page.js.map +2 -2
  295. package/dist/modules/sales/backend/sales/channels/offers/page.js +13 -4
  296. package/dist/modules/sales/backend/sales/channels/offers/page.js.map +2 -2
  297. package/dist/modules/sales/backend/sales/channels/page.js +16 -4
  298. package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
  299. package/dist/modules/sales/backend/sales/documents/[id]/page.js +68 -22
  300. package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
  301. package/dist/modules/sales/backend/sales/documents/create/page.js.map +2 -2
  302. package/dist/modules/sales/commands/documentAddresses.js +181 -2
  303. package/dist/modules/sales/commands/documentAddresses.js.map +2 -2
  304. package/dist/modules/sales/commands/documents.js +29 -1
  305. package/dist/modules/sales/commands/documents.js.map +2 -2
  306. package/dist/modules/sales/commands/returns.js +12 -2
  307. package/dist/modules/sales/commands/returns.js.map +2 -2
  308. package/dist/modules/sales/commands/shared.js +15 -0
  309. package/dist/modules/sales/commands/shared.js.map +2 -2
  310. package/dist/modules/sales/commands/shipments.js +4 -1
  311. package/dist/modules/sales/commands/shipments.js.map +2 -2
  312. package/dist/modules/sales/components/AdjustmentKindSettings.js +19 -11
  313. package/dist/modules/sales/components/AdjustmentKindSettings.js.map +2 -2
  314. package/dist/modules/sales/components/DocumentNumberSettings.js.map +2 -2
  315. package/dist/modules/sales/components/OrderEditingSettings.js.map +2 -2
  316. package/dist/modules/sales/components/PaymentMethodsSettings.js +12 -4
  317. package/dist/modules/sales/components/PaymentMethodsSettings.js.map +2 -2
  318. package/dist/modules/sales/components/ShippingMethodsSettings.js +12 -4
  319. package/dist/modules/sales/components/ShippingMethodsSettings.js.map +2 -2
  320. package/dist/modules/sales/components/StatusSettings.js +18 -11
  321. package/dist/modules/sales/components/StatusSettings.js.map +2 -2
  322. package/dist/modules/sales/components/TaxRatesSettings.js +12 -4
  323. package/dist/modules/sales/components/TaxRatesSettings.js.map +2 -2
  324. package/dist/modules/sales/components/channels/ChannelOfferForm.js +47 -16
  325. package/dist/modules/sales/components/channels/ChannelOfferForm.js.map +2 -2
  326. package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js +8 -4
  327. package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js.map +2 -2
  328. package/dist/modules/sales/components/documents/AddressesSection.js +44 -25
  329. package/dist/modules/sales/components/documents/AddressesSection.js.map +2 -2
  330. package/dist/modules/sales/components/documents/AdjustmentsSection.js +43 -23
  331. package/dist/modules/sales/components/documents/AdjustmentsSection.js.map +2 -2
  332. package/dist/modules/sales/components/documents/ItemsSection.js +22 -13
  333. package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
  334. package/dist/modules/sales/components/documents/LineItemDialog.js +23 -10
  335. package/dist/modules/sales/components/documents/LineItemDialog.js.map +2 -2
  336. package/dist/modules/sales/components/documents/PaymentDialog.js +29 -14
  337. package/dist/modules/sales/components/documents/PaymentDialog.js.map +2 -2
  338. package/dist/modules/sales/components/documents/PaymentsSection.js +20 -10
  339. package/dist/modules/sales/components/documents/PaymentsSection.js.map +2 -2
  340. package/dist/modules/sales/components/documents/ReturnDialog.js +26 -17
  341. package/dist/modules/sales/components/documents/ReturnDialog.js.map +2 -2
  342. package/dist/modules/sales/components/documents/ReturnsSection.js +3 -1
  343. package/dist/modules/sales/components/documents/ReturnsSection.js.map +2 -2
  344. package/dist/modules/sales/components/documents/SalesDocumentsTable.js +10 -5
  345. package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
  346. package/dist/modules/sales/components/documents/ShipmentDialog.js +21 -7
  347. package/dist/modules/sales/components/documents/ShipmentDialog.js.map +2 -2
  348. package/dist/modules/sales/components/documents/ShipmentsSection.js +19 -10
  349. package/dist/modules/sales/components/documents/ShipmentsSection.js.map +2 -2
  350. package/dist/modules/sales/components/documents/optimisticLock.js +27 -0
  351. package/dist/modules/sales/components/documents/optimisticLock.js.map +7 -0
  352. package/dist/modules/sales/di.js +18 -0
  353. package/dist/modules/sales/di.js.map +2 -2
  354. package/dist/modules/staff/api/job-histories.js +11 -2
  355. package/dist/modules/staff/api/job-histories.js.map +2 -2
  356. package/dist/modules/staff/api/timesheets/time-entries/route.js +11 -4
  357. package/dist/modules/staff/api/timesheets/time-entries/route.js.map +2 -2
  358. package/dist/modules/staff/backend/staff/leave-requests/[id]/page.js +13 -8
  359. package/dist/modules/staff/backend/staff/leave-requests/[id]/page.js.map +2 -2
  360. package/dist/modules/staff/backend/staff/my-leave-requests/[id]/page.js +2 -1
  361. package/dist/modules/staff/backend/staff/my-leave-requests/[id]/page.js.map +2 -2
  362. package/dist/modules/staff/backend/staff/team-members/[id]/page.js +7 -4
  363. package/dist/modules/staff/backend/staff/team-members/[id]/page.js.map +2 -2
  364. package/dist/modules/staff/backend/staff/team-members/page.js +4 -2
  365. package/dist/modules/staff/backend/staff/team-members/page.js.map +2 -2
  366. package/dist/modules/staff/backend/staff/team-roles/[id]/edit/page.js +1 -0
  367. package/dist/modules/staff/backend/staff/team-roles/[id]/edit/page.js.map +2 -2
  368. package/dist/modules/staff/backend/staff/team-roles/page.js +4 -2
  369. package/dist/modules/staff/backend/staff/team-roles/page.js.map +2 -2
  370. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +5 -2
  371. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
  372. package/dist/modules/staff/backend/staff/teams/page.js +12 -3
  373. package/dist/modules/staff/backend/staff/teams/page.js.map +2 -2
  374. package/dist/modules/staff/backend/staff/timesheets/page.js +4 -1
  375. package/dist/modules/staff/backend/staff/timesheets/page.js.map +2 -2
  376. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.js.map +2 -2
  377. package/dist/modules/staff/backend/staff/timesheets/projects/page.js +12 -3
  378. package/dist/modules/staff/backend/staff/timesheets/projects/page.js.map +2 -2
  379. package/dist/modules/staff/commands/job-histories.js +40 -3
  380. package/dist/modules/staff/commands/job-histories.js.map +2 -2
  381. package/dist/modules/staff/components/LeaveRequestForm.js +1 -0
  382. package/dist/modules/staff/components/LeaveRequestForm.js.map +2 -2
  383. package/dist/modules/staff/components/TeamForm.js +1 -0
  384. package/dist/modules/staff/components/TeamForm.js.map +2 -2
  385. package/dist/modules/staff/components/TeamMemberForm.js +1 -0
  386. package/dist/modules/staff/components/TeamMemberForm.js.map +2 -2
  387. package/dist/modules/staff/components/TeamRoleForm.js +1 -0
  388. package/dist/modules/staff/components/TeamRoleForm.js.map +2 -2
  389. package/dist/modules/staff/components/detail/JobHistorySection.js +20 -7
  390. package/dist/modules/staff/components/detail/JobHistorySection.js.map +2 -2
  391. package/dist/modules/staff/data/validators.js +7 -1
  392. package/dist/modules/staff/data/validators.js.map +2 -2
  393. package/dist/modules/staff/lib/leaveRequestHelpers.js +2 -1
  394. package/dist/modules/staff/lib/leaveRequestHelpers.js.map +2 -2
  395. package/dist/modules/translations/components/TranslationManager.js +12 -8
  396. package/dist/modules/translations/components/TranslationManager.js.map +2 -2
  397. package/dist/modules/workflows/api/definitions/[id]/route.js +106 -0
  398. package/dist/modules/workflows/api/definitions/[id]/route.js.map +2 -2
  399. package/dist/modules/workflows/backend/definitions/[id]/page.js +11 -3
  400. package/dist/modules/workflows/backend/definitions/[id]/page.js.map +2 -2
  401. package/dist/modules/workflows/backend/definitions/page.js +19 -8
  402. package/dist/modules/workflows/backend/definitions/page.js.map +2 -2
  403. package/dist/modules/workflows/backend/definitions/visual-editor/page.js +29 -16
  404. package/dist/modules/workflows/backend/definitions/visual-editor/page.js.map +2 -2
  405. package/dist/modules/workflows/components/formConfig.js +4 -1
  406. package/dist/modules/workflows/components/formConfig.js.map +2 -2
  407. package/dist/modules/workflows/di.js +12 -0
  408. package/dist/modules/workflows/di.js.map +2 -2
  409. package/generated/entities/role/index.ts +1 -0
  410. package/generated/entities/user/index.ts +1 -0
  411. package/generated/entity-fields-registry.ts +2 -0
  412. package/jest.setup.ts +17 -0
  413. package/package.json +8 -7
  414. package/src/helpers/integration/communicationChannelsFixtures.ts +6 -0
  415. package/src/helpers/integration/dbFixtures.ts +1 -1
  416. package/src/helpers/integration/optimisticLockUi.ts +172 -0
  417. package/src/helpers/integration/salesFixtures.ts +29 -0
  418. package/src/modules/api_keys/backend/api-keys/page.tsx +10 -5
  419. package/src/modules/attachments/components/AttachmentPartitionSettings.tsx +19 -9
  420. package/src/modules/auth/api/roles/acl/route.ts +37 -11
  421. package/src/modules/auth/api/roles/route.ts +2 -0
  422. package/src/modules/auth/api/sidebar/preferences/route.ts +73 -0
  423. package/src/modules/auth/api/users/acl/route.ts +46 -18
  424. package/src/modules/auth/api/users/route.ts +2 -0
  425. package/src/modules/auth/backend/roles/[id]/edit/page.tsx +29 -4
  426. package/src/modules/auth/backend/roles/page.tsx +9 -4
  427. package/src/modules/auth/backend/users/[id]/edit/page.tsx +37 -4
  428. package/src/modules/auth/backend/users/page.tsx +7 -2
  429. package/src/modules/auth/components/AclEditor.tsx +10 -1
  430. package/src/modules/auth/data/entities.ts +7 -1
  431. package/src/modules/auth/services/sidebarPreferencesService.ts +38 -4
  432. package/src/modules/business_rules/api/rules/route.ts +30 -0
  433. package/src/modules/business_rules/api/sets/route.ts +30 -0
  434. package/src/modules/business_rules/backend/rules/[id]/page.tsx +16 -4
  435. package/src/modules/business_rules/backend/rules/page.tsx +20 -11
  436. package/src/modules/business_rules/backend/sets/[id]/page.tsx +16 -4
  437. package/src/modules/business_rules/backend/sets/page.tsx +20 -11
  438. package/src/modules/catalog/api/categories/route.ts +3 -0
  439. package/src/modules/catalog/api/products/route.ts +4 -0
  440. package/src/modules/catalog/backend/catalog/categories/[id]/edit/page.tsx +5 -0
  441. package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +112 -35
  442. package/src/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.tsx +56 -7
  443. package/src/modules/catalog/backend/catalog/products/optionSchemaClient.ts +2 -0
  444. package/src/modules/catalog/commands/variants.ts +32 -32
  445. package/src/modules/catalog/components/PriceKindSettings.tsx +20 -7
  446. package/src/modules/catalog/components/categories/CategoriesDataTable.tsx +1 -0
  447. package/src/modules/catalog/components/products/ProductMediaManager.tsx +2 -0
  448. package/src/modules/catalog/components/products/ProductsDataTable.tsx +8 -4
  449. package/src/modules/catalog/components/products/productForm.ts +3 -0
  450. package/src/modules/catalog/components/products/variantForm.ts +9 -0
  451. package/src/modules/communication_channels/api/post/test-seed/route.ts +28 -1
  452. package/src/modules/communication_channels/backend/profile/communication-channels/page.tsx +5 -0
  453. package/src/modules/communication_channels/commands/set-primary-channel.ts +10 -7
  454. package/src/modules/currencies/backend/currencies/[id]/page.tsx +13 -6
  455. package/src/modules/currencies/backend/currencies/page.tsx +18 -11
  456. package/src/modules/currencies/backend/exchange-rates/[id]/page.tsx +3 -0
  457. package/src/modules/currencies/backend/exchange-rates/page.tsx +10 -6
  458. package/src/modules/currencies/commands/currencies.ts +10 -5
  459. package/src/modules/currencies/components/CurrencyFetchingConfig.tsx +31 -21
  460. package/src/modules/customer_accounts/api/admin/roles/[id].ts +35 -5
  461. package/src/modules/customer_accounts/api/admin/roles.ts +2 -0
  462. package/src/modules/customer_accounts/api/admin/users/[id].ts +38 -5
  463. package/src/modules/customer_accounts/api/admin/users.ts +2 -0
  464. package/src/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.tsx +34 -20
  465. package/src/modules/customer_accounts/backend/customer_accounts/roles/page.tsx +9 -4
  466. package/src/modules/customer_accounts/backend/customer_accounts/settings/domain/page.tsx +11 -4
  467. package/src/modules/customer_accounts/backend/customer_accounts/users/[id]/page.tsx +28 -17
  468. package/src/modules/customer_accounts/backend/customer_accounts/users/page.tsx +19 -11
  469. package/src/modules/customers/AGENTS.md +2 -2
  470. package/src/modules/customers/api/companies/route.ts +14 -1
  471. package/src/modules/customers/api/deals/route.ts +3 -0
  472. package/src/modules/customers/api/people/route.ts +12 -1
  473. package/src/modules/customers/api/todos/route.ts +1 -0
  474. package/src/modules/customers/backend/config/customers/deals/page.tsx +1 -0
  475. package/src/modules/customers/backend/config/customers/pipeline-stages/page.tsx +36 -21
  476. package/src/modules/customers/backend/customers/companies/[id]/page.tsx +52 -27
  477. package/src/modules/customers/backend/customers/companies/page.tsx +2 -0
  478. package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +27 -5
  479. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealFormHandlers.ts +39 -7
  480. package/src/modules/customers/backend/customers/deals/[id]/page.tsx +1 -0
  481. package/src/modules/customers/backend/customers/deals/page.tsx +18 -6
  482. package/src/modules/customers/backend/customers/deals/pipeline/page.tsx +64 -39
  483. package/src/modules/customers/backend/customers/people/[id]/page.tsx +46 -26
  484. package/src/modules/customers/backend/customers/people/page.tsx +2 -0
  485. package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +84 -24
  486. package/src/modules/customers/commands/addresses.ts +16 -14
  487. package/src/modules/customers/commands/companies.ts +3 -1
  488. package/src/modules/customers/commands/interactions.ts +50 -4
  489. package/src/modules/customers/commands/people.ts +2 -1
  490. package/src/modules/customers/commands/personCompanyLinks.ts +8 -5
  491. package/src/modules/customers/commands/pipeline-stages.ts +16 -16
  492. package/src/modules/customers/components/AddressFormatSettings.tsx +1 -0
  493. package/src/modules/customers/components/DictionarySettings.tsx +18 -13
  494. package/src/modules/customers/components/DictionarySortSettings.tsx +4 -0
  495. package/src/modules/customers/components/PipelineSettings.tsx +42 -21
  496. package/src/modules/customers/components/detail/ActivityTimeline.tsx +3 -3
  497. package/src/modules/customers/components/detail/AddressesSection.tsx +4 -0
  498. package/src/modules/customers/components/detail/CompanyPeopleSection.tsx +2 -0
  499. package/src/modules/customers/components/detail/DealsSection.tsx +4 -0
  500. package/src/modules/customers/components/detail/EmailCardActions.tsx +5 -0
  501. package/src/modules/customers/components/detail/EntityTagsDialog.tsx +7 -0
  502. package/src/modules/customers/components/detail/ManageTagsDialog.tsx +4 -0
  503. package/src/modules/customers/components/detail/PersonCompaniesSection.tsx +4 -0
  504. package/src/modules/customers/components/detail/RoleAssignmentRow.tsx +2 -0
  505. package/src/modules/customers/components/detail/ScheduleActivityDialog.tsx +23 -7
  506. package/src/modules/customers/components/detail/hooks/useInteractionMutations.ts +25 -15
  507. package/src/modules/customers/components/detail/hooks/useInteractions.ts +76 -35
  508. package/src/modules/customers/components/detail/hooks/usePersonTasks.ts +30 -17
  509. package/src/modules/customers/components/detail/schedule/useScheduleFormState.ts +2 -0
  510. package/src/modules/customers/components/detail/types.ts +1 -0
  511. package/src/modules/customers/components/formConfig.tsx +2 -0
  512. package/src/modules/customers/data/guards.ts +67 -0
  513. package/src/modules/customers/di.ts +66 -0
  514. package/src/modules/customers/i18n/de.json +2 -0
  515. package/src/modules/customers/i18n/en.json +2 -0
  516. package/src/modules/customers/i18n/es.json +2 -0
  517. package/src/modules/customers/i18n/pl.json +2 -0
  518. package/src/modules/customers/lib/todoCompatibility.ts +14 -0
  519. package/src/modules/dashboards/components/WidgetVisibilityEditor.tsx +2 -0
  520. package/src/modules/data_sync/api/options.ts +7 -4
  521. package/src/modules/data_sync/api/schedules/route.ts +9 -1
  522. package/src/modules/data_sync/backend/data-sync/page.tsx +18 -5
  523. package/src/modules/data_sync/components/IntegrationScheduleTab.tsx +46 -19
  524. package/src/modules/data_sync/lib/sync-schedule-service.ts +11 -0
  525. package/src/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.ts +8 -1
  526. package/src/modules/dictionaries/api/[dictionaryId]/route.ts +23 -0
  527. package/src/modules/dictionaries/components/DictionariesManager.tsx +32 -9
  528. package/src/modules/dictionaries/components/DictionaryEntriesEditor.tsx +30 -14
  529. package/src/modules/dictionaries/i18n/de.json +1 -0
  530. package/src/modules/dictionaries/i18n/en.json +1 -0
  531. package/src/modules/dictionaries/i18n/es.json +1 -0
  532. package/src/modules/dictionaries/i18n/pl.json +1 -0
  533. package/src/modules/directory/api/organizations/route.ts +3 -0
  534. package/src/modules/directory/backend/directory/organizations/[id]/edit/page.tsx +8 -0
  535. package/src/modules/directory/backend/directory/organizations/page.tsx +10 -5
  536. package/src/modules/directory/backend/directory/tenants/[id]/edit/page.tsx +16 -5
  537. package/src/modules/directory/backend/directory/tenants/page.tsx +8 -4
  538. package/src/modules/directory/commands/organizations.ts +7 -4
  539. package/src/modules/entities/api/records.ts +99 -0
  540. package/src/modules/entities/backend/entities/user/[entityId]/records/[recordId]/page.tsx +7 -0
  541. package/src/modules/entities/backend/entities/user/[entityId]/records/page.tsx +8 -4
  542. package/src/modules/entities/lib/helpers.ts +17 -0
  543. package/src/modules/feature_toggles/api/global/[id]/override/route.ts +1 -0
  544. package/src/modules/feature_toggles/api/overrides/route.ts +19 -0
  545. package/src/modules/feature_toggles/backend/feature-toggles/global/[id]/edit/page.tsx +19 -13
  546. package/src/modules/feature_toggles/components/FeatureToggleOverrideCard.tsx +22 -12
  547. package/src/modules/feature_toggles/components/FeatureTogglesTable.tsx +7 -2
  548. package/src/modules/feature_toggles/components/formConfig.tsx +2 -1
  549. package/src/modules/feature_toggles/components/overrideFormConfig.tsx +10 -1
  550. package/src/modules/feature_toggles/data/validators.ts +11 -3
  551. package/src/modules/inbox_ops/api/settings/route.ts +18 -0
  552. package/src/modules/inbox_ops/backend/inbox-ops/settings/page.tsx +15 -10
  553. package/src/modules/inbox_ops/components/proposals/EditActionDialog.tsx +9 -4
  554. package/src/modules/integrations/backend/integrations/bundle/[id]/page.tsx +20 -11
  555. package/src/modules/integrations/backend/integrations/page.tsx +13 -8
  556. package/src/modules/messages/commands/messages.ts +27 -15
  557. package/src/modules/perspectives/api/[tableId]/route.ts +11 -2
  558. package/src/modules/perspectives/services/perspectiveService.ts +13 -1
  559. package/src/modules/planner/backend/planner/availability-rulesets/[id]/page.tsx +16 -14
  560. package/src/modules/planner/backend/planner/availability-rulesets/page.tsx +6 -3
  561. package/src/modules/planner/components/AvailabilityRuleSetForm.tsx +3 -0
  562. package/src/modules/planner/components/AvailabilityRulesEditor.tsx +58 -15
  563. package/src/modules/planner/components/AvailabilitySchedule.tsx +22 -7
  564. package/src/modules/query_index/lib/engine.ts +34 -0
  565. package/src/modules/resources/backend/resources/resource-types/[id]/edit/page.tsx +7 -1
  566. package/src/modules/resources/backend/resources/resource-types/page.tsx +6 -3
  567. package/src/modules/resources/backend/resources/resources/[id]/page.tsx +23 -3
  568. package/src/modules/resources/backend/resources/resources/page.tsx +15 -4
  569. package/src/modules/resources/components/ResourceCrudForm.tsx +3 -0
  570. package/src/modules/resources/components/ResourceTypeCrudForm.tsx +2 -0
  571. package/src/modules/sales/api/documents/factory.ts +13 -1
  572. package/src/modules/sales/backend/sales/channels/[channelId]/edit/page.tsx +6 -0
  573. package/src/modules/sales/backend/sales/channels/offers/page.tsx +10 -4
  574. package/src/modules/sales/backend/sales/channels/page.tsx +19 -4
  575. package/src/modules/sales/backend/sales/documents/[id]/page.tsx +73 -20
  576. package/src/modules/sales/backend/sales/documents/create/page.tsx +2 -0
  577. package/src/modules/sales/commands/documentAddresses.ts +226 -4
  578. package/src/modules/sales/commands/documents.ts +28 -0
  579. package/src/modules/sales/commands/returns.ts +12 -3
  580. package/src/modules/sales/commands/shared.ts +36 -0
  581. package/src/modules/sales/commands/shipments.ts +17 -1
  582. package/src/modules/sales/components/AdjustmentKindSettings.tsx +20 -11
  583. package/src/modules/sales/components/DocumentNumberSettings.tsx +1 -0
  584. package/src/modules/sales/components/OrderEditingSettings.tsx +1 -0
  585. package/src/modules/sales/components/PaymentMethodsSettings.tsx +12 -4
  586. package/src/modules/sales/components/ShippingMethodsSettings.tsx +12 -4
  587. package/src/modules/sales/components/StatusSettings.tsx +20 -11
  588. package/src/modules/sales/components/TaxRatesSettings.tsx +12 -5
  589. package/src/modules/sales/components/channels/ChannelOfferForm.tsx +67 -14
  590. package/src/modules/sales/components/channels/SalesChannelOffersPanel.tsx +7 -4
  591. package/src/modules/sales/components/documents/AddressesSection.tsx +35 -25
  592. package/src/modules/sales/components/documents/AdjustmentsSection.tsx +50 -25
  593. package/src/modules/sales/components/documents/ItemsSection.tsx +24 -13
  594. package/src/modules/sales/components/documents/LineItemDialog.tsx +26 -9
  595. package/src/modules/sales/components/documents/PaymentDialog.tsx +33 -14
  596. package/src/modules/sales/components/documents/PaymentsSection.tsx +22 -10
  597. package/src/modules/sales/components/documents/ReturnDialog.tsx +28 -17
  598. package/src/modules/sales/components/documents/ReturnsSection.tsx +4 -1
  599. package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +11 -4
  600. package/src/modules/sales/components/documents/ShipmentDialog.tsx +23 -8
  601. package/src/modules/sales/components/documents/ShipmentsSection.tsx +20 -10
  602. package/src/modules/sales/components/documents/optimisticLock.ts +34 -0
  603. package/src/modules/sales/components/documents/shipmentTypes.ts +1 -0
  604. package/src/modules/sales/di.ts +35 -0
  605. package/src/modules/sales/i18n/de.json +3 -0
  606. package/src/modules/sales/i18n/en.json +3 -0
  607. package/src/modules/sales/i18n/es.json +3 -0
  608. package/src/modules/sales/i18n/pl.json +3 -0
  609. package/src/modules/staff/api/job-histories.ts +12 -2
  610. package/src/modules/staff/api/timesheets/time-entries/route.ts +16 -4
  611. package/src/modules/staff/backend/staff/leave-requests/[id]/page.tsx +12 -7
  612. package/src/modules/staff/backend/staff/my-leave-requests/[id]/page.tsx +2 -0
  613. package/src/modules/staff/backend/staff/team-members/[id]/page.tsx +16 -5
  614. package/src/modules/staff/backend/staff/team-members/page.tsx +6 -2
  615. package/src/modules/staff/backend/staff/team-roles/[id]/edit/page.tsx +8 -0
  616. package/src/modules/staff/backend/staff/team-roles/page.tsx +6 -2
  617. package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +13 -3
  618. package/src/modules/staff/backend/staff/teams/page.tsx +9 -3
  619. package/src/modules/staff/backend/staff/timesheets/page.tsx +10 -1
  620. package/src/modules/staff/backend/staff/timesheets/projects/[id]/page.tsx +4 -0
  621. package/src/modules/staff/backend/staff/timesheets/projects/page.tsx +9 -3
  622. package/src/modules/staff/commands/job-histories.ts +42 -3
  623. package/src/modules/staff/components/LeaveRequestForm.tsx +2 -0
  624. package/src/modules/staff/components/TeamForm.tsx +2 -0
  625. package/src/modules/staff/components/TeamMemberForm.tsx +2 -0
  626. package/src/modules/staff/components/TeamRoleForm.tsx +2 -0
  627. package/src/modules/staff/components/detail/JobHistorySection.tsx +28 -6
  628. package/src/modules/staff/data/validators.ts +6 -0
  629. package/src/modules/staff/i18n/de.json +1 -0
  630. package/src/modules/staff/i18n/en.json +1 -0
  631. package/src/modules/staff/i18n/es.json +1 -0
  632. package/src/modules/staff/i18n/pl.json +1 -0
  633. package/src/modules/staff/lib/leaveRequestHelpers.ts +4 -0
  634. package/src/modules/translations/components/TranslationManager.tsx +13 -8
  635. package/src/modules/workflows/api/definitions/[id]/route.ts +112 -0
  636. package/src/modules/workflows/backend/definitions/[id]/page.tsx +20 -4
  637. package/src/modules/workflows/backend/definitions/page.tsx +20 -9
  638. package/src/modules/workflows/backend/definitions/visual-editor/page.tsx +29 -16
  639. package/src/modules/workflows/components/formConfig.tsx +5 -0
  640. package/src/modules/workflows/di.ts +20 -0
  641. package/src/modules/workflows/i18n/de.json +1 -0
  642. package/src/modules/workflows/i18n/en.json +1 -0
  643. package/src/modules/workflows/i18n/es.json +1 -0
  644. package/src/modules/workflows/i18n/pl.json +1 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/customers/api/deals/route.ts"],
4
- "sourcesContent": ["import { z } from 'zod'\nimport { makeCrudRoute } from '@open-mercato/shared/lib/crud/factory'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { CustomerDeal, CustomerDealPersonLink, CustomerDealCompanyLink } from '../../data/entities'\nimport { dealCreateSchema, dealUpdateSchema } from '../../data/validators'\nimport { E } from '#generated/entities.ids.generated'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { parseBooleanFromUnknown } from '@open-mercato/shared/lib/boolean'\nimport {\n applyEntityIdRestriction,\n findMatchingEntityIdsWithQueryEngine,\n findMatchingEntityIdsBySearchTokensAcrossSources,\n parseScopedCommandInput,\n} from '../utils'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport {\n createCustomersCrudOpenApi,\n createPagedListResponseSchema,\n defaultOkResponseSchema,\n} from '../openapi'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { isTenantDataEncryptionEnabled } from '@open-mercato/shared/lib/encryption/toggles'\nimport { escapeLikePattern } from '@open-mercato/shared/lib/db/escapeLikePattern'\nimport { consumeAdvancedFilterState, mergeAdvancedFilterTree } from '@open-mercato/shared/lib/crud/advanced-filter-integration'\nimport { fetchStuckDealIds } from '../../lib/stuckDeals'\n\nconst rawBodySchema = z.object({}).passthrough()\n\nconst stringOrStringArray = z.union([z.string(), z.array(z.string())])\nconst booleanQueryParam = z.preprocess((value) => {\n const parsed = parseBooleanFromUnknown(value)\n return parsed === null ? value : parsed\n}, z.boolean()).optional()\n\nexport const dealListQuerySchema = z\n .object({\n page: z.coerce.number().min(1).default(1),\n pageSize: z.coerce.number().min(1).max(100).default(50),\n search: z.string().optional(),\n status: stringOrStringArray.optional(),\n pipelineStage: z.string().optional(),\n pipelineId: stringOrStringArray.optional(),\n pipelineStageId: z.union([z.string().uuid(), z.literal('__unassigned')]).optional(),\n ownerUserId: stringOrStringArray.optional(),\n expectedCloseAtFrom: z.string().optional(),\n expectedCloseAtTo: z.string().optional(),\n isStuck: booleanQueryParam,\n isOverdue: booleanQueryParam,\n valueCurrency: stringOrStringArray.optional(),\n sortField: z.string().optional(),\n sortDir: z.enum(['asc', 'desc']).optional(),\n /**\n * @deprecated Use `personId` instead. The `personEntityId` alias is kept for backward\n * compatibility with older clients and will be removed in a future minor release.\n */\n personEntityId: z.string().uuid().optional().describe('Deprecated; use personId'),\n /**\n * @deprecated Use `companyId` instead. The `companyEntityId` alias is kept for backward\n * compatibility with older clients and will be removed in a future minor release.\n */\n companyEntityId: z.string().uuid().optional().describe('Deprecated; use companyId'),\n personId: stringOrStringArray.optional(),\n companyId: stringOrStringArray.optional(),\n })\n .passthrough()\n\nconst routeMetadata = {\n GET: { requireAuth: true, requireFeatures: ['customers.deals.view'] },\n POST: { requireAuth: true, requireFeatures: ['customers.deals.manage'] },\n PUT: { requireAuth: true, requireFeatures: ['customers.deals.manage'] },\n DELETE: { requireAuth: true, requireFeatures: ['customers.deals.manage'] },\n}\n\nexport const metadata = routeMetadata\n\nexport type DealListQuery = z.infer<typeof dealListQuerySchema>\n\nfunction parseUuid(value: unknown): string | null {\n if (typeof value !== 'string') return null\n const trimmed = value.trim()\n if (!trimmed.length) return null\n const result = z.string().uuid().safeParse(trimmed)\n return result.success ? trimmed : null\n}\n\nfunction normalizeStringList(value: unknown): string[] {\n const set = new Set<string>()\n const visit = (entry: unknown) => {\n if (entry == null) return\n if (Array.isArray(entry)) {\n entry.forEach(visit)\n return\n }\n if (typeof entry !== 'string') return\n entry\n .split(',')\n .map((token) => token.trim())\n .filter((token) => token.length > 0)\n .forEach((token) => set.add(token))\n }\n visit(value)\n return Array.from(set)\n}\n\nfunction parseDateInput(value: unknown): Date | null {\n if (!(typeof value === 'string') || value.trim().length === 0) return null\n const date = new Date(value)\n return Number.isNaN(date.getTime()) ? null : date\n}\n\n/**\n * Pre-pagination ID narrowing for person/company filters.\n *\n * Mirrors the SQL the aggregate route uses (`EXISTS ... IN (...)`) so the list endpoint\n * and the lane-header aggregate return a consistent set of deals for the same filters.\n * Semantics: OR within a category (any selected person/company matches), AND across\n * categories (deal must match at least one person AND at least one company when both\n * filter lists are provided).\n *\n * Returns the matched deal IDs (UUIDs). An empty array means \"no deals match\" \u2014 callers\n * must intersect with `restrictedIds` (which will collapse the list to zero).\n */\nasync function fetchDealIdsMatchingAssociations(\n em: EntityManager,\n organizationId: string,\n tenantId: string,\n personIds: string[],\n companyIds: string[],\n): Promise<string[]> {\n if (!personIds.length && !companyIds.length) return []\n const where: string[] = [\n 'organization_id = ?',\n 'tenant_id = ?',\n 'deleted_at IS NULL',\n ]\n const values: Array<string | number> = [organizationId, tenantId]\n if (personIds.length) {\n const placeholders = personIds.map(() => '?').join(',')\n where.push(\n `EXISTS (SELECT 1 FROM customer_deal_people dp WHERE dp.deal_id = customer_deals.id AND dp.person_entity_id IN (${placeholders}))`,\n )\n values.push(...personIds)\n }\n if (companyIds.length) {\n const placeholders = companyIds.map(() => '?').join(',')\n where.push(\n `EXISTS (SELECT 1 FROM customer_deal_companies dc WHERE dc.deal_id = customer_deals.id AND dc.company_entity_id IN (${placeholders}))`,\n )\n values.push(...companyIds)\n }\n const rows = await em.getConnection().execute<Array<{ id: string }>>(\n `SELECT id FROM customer_deals WHERE ${where.join(' AND ')}`,\n values,\n )\n return rows.map((row) => row.id)\n}\n\nfunction normalizeCurrencyList(value: unknown): string[] {\n const set = new Set<string>()\n const visit = (entry: unknown) => {\n if (entry == null) return\n if (Array.isArray(entry)) {\n entry.forEach(visit)\n return\n }\n if (typeof entry !== 'string') return\n entry\n .split(',')\n .map((token) => token.trim().toUpperCase())\n .filter((token) => /^[A-Z]{3}$/.test(token))\n .forEach((token) => set.add(token))\n }\n visit(value)\n return Array.from(set)\n}\n\nfunction normalizeUuidList(values: Array<unknown>): string[] {\n const set = new Set<string>()\n values.forEach((candidate) => {\n if (Array.isArray(candidate)) {\n candidate.forEach((entry) => {\n const parsed = parseUuid(entry)\n if (parsed) set.add(parsed)\n })\n return\n }\n if (typeof candidate === 'string' && candidate.includes(',')) {\n candidate\n .split(',')\n .map((entry) => entry.trim())\n .forEach((entry) => {\n const parsed = parseUuid(entry)\n if (parsed) set.add(parsed)\n })\n return\n }\n const parsed = parseUuid(candidate)\n if (parsed) set.add(parsed)\n })\n return Array.from(set)\n}\n\nexport async function buildDealListFilters(query: DealListQuery, ctx?: import('@open-mercato/shared/lib/crud/factory').CrudCtx) {\n const advancedFilterTree = consumeAdvancedFilterState(query)\n const filters: Record<string, unknown> = {}\n let restrictedIds: string[] | null = null\n\n const intersectIds = (ids: string[]) => {\n if (restrictedIds === null) {\n restrictedIds = ids\n return\n }\n const lookup = new Set(ids)\n restrictedIds = restrictedIds.filter((id) => lookup.has(id))\n }\n\n if (query.search) {\n const matchingIds = ctx\n ? await findMatchingEntityIdsBySearchTokensAcrossSources({\n ctx,\n query: query.search,\n sources: [\n {\n entityType: E.customers.customer_deal,\n fields: [\n 'title',\n 'description',\n 'status',\n 'pipeline_stage',\n 'source',\n 'value_amount',\n 'value_currency',\n 'cf:competitive_risk',\n 'cf:implementation_complexity',\n ],\n },\n ],\n })\n : null\n if (matchingIds !== null && matchingIds.length > 0) {\n intersectIds(matchingIds)\n } else if (isTenantDataEncryptionEnabled()) {\n // `customers:customer_deal.title` and `.description` are encrypted at rest\n // (see `encryption.ts`). The `$ilike` fallback below would silently match\n // nothing on the ciphertext and produce empty pages without disclosing why \u2014\n // collapse the result to \"no matches\" instead so the kanban + list views\n // agree, and lane aggregates stay consistent with the list endpoint.\n intersectIds([])\n } else {\n const searchPattern = `%${escapeLikePattern(query.search)}%`\n filters.$or = [\n { title: { $ilike: searchPattern } },\n { description: { $ilike: searchPattern } },\n ]\n }\n }\n\n const statusList = query.status ? normalizeStringList(query.status) : []\n if (statusList.length > 0) {\n filters.status = statusList.length === 1 ? { $eq: statusList[0] } : { $in: statusList }\n }\n\n if (query.pipelineStage) {\n filters.pipeline_stage = { $eq: query.pipelineStage }\n }\n\n const pipelineIds = query.pipelineId ? normalizeUuidList([query.pipelineId]) : []\n if (pipelineIds.length > 0) {\n filters.pipeline_id = pipelineIds.length === 1 ? { $eq: pipelineIds[0] } : { $in: pipelineIds }\n }\n\n if (query.pipelineStageId === '__unassigned') {\n filters.pipeline_stage_id = { $eq: null }\n } else if (query.pipelineStageId) {\n filters.pipeline_stage_id = { $eq: query.pipelineStageId }\n }\n\n const ownerUserIds = query.ownerUserId ? normalizeUuidList([query.ownerUserId]) : []\n if (ownerUserIds.length > 0) {\n filters.owner_user_id =\n ownerUserIds.length === 1 ? { $eq: ownerUserIds[0] } : { $in: ownerUserIds }\n }\n\n // Currency filter (additive; sourced by the kanban Currency popover). Codes are\n // normalised to upper-case so `usd` / `USD` / mixed-case query params all hit the same\n // stored value (the deals API persists `value_currency` upper-case already).\n const currencyCodes = query.valueCurrency ? normalizeCurrencyList(query.valueCurrency) : []\n if (currencyCodes.length > 0) {\n filters.value_currency =\n currencyCodes.length === 1 ? { $eq: currencyCodes[0] } : { $in: currencyCodes }\n }\n\n const expectedCloseFrom = parseDateInput(query.expectedCloseAtFrom)\n const expectedCloseTo = parseDateInput(query.expectedCloseAtTo)\n if (expectedCloseFrom || expectedCloseTo) {\n const range: Record<string, Date> = {}\n if (expectedCloseFrom) range.$gte = expectedCloseFrom\n if (expectedCloseTo) range.$lte = expectedCloseTo\n filters.expected_close_at = range\n }\n\n if (query.isOverdue) {\n const today = new Date()\n today.setHours(0, 0, 0, 0)\n if (statusList.length === 0) {\n filters.status = { $eq: 'open' }\n }\n const existingRange =\n filters.expected_close_at && typeof filters.expected_close_at === 'object'\n ? (filters.expected_close_at as Record<string, Date>)\n : {}\n existingRange.$lt = today\n filters.expected_close_at = existingRange\n }\n\n if (query.isStuck && ctx) {\n const tenantId = ctx.auth?.tenantId\n // CrudCtx.auth carries `orgId` (not `organizationId`). The previous code referenced\n // `organizationId` which is always `undefined`, so the typeof check below silently\n // skipped the entire isStuck branch \u2014 `?isStuck=true` was a no-op on this endpoint.\n const organizationId = ctx.auth?.orgId\n if (typeof tenantId === 'string' && typeof organizationId === 'string') {\n const em = ctx.container.resolve<EntityManager>('em')\n const stuckIds = await fetchStuckDealIds(em, organizationId, tenantId)\n intersectIds(stuckIds)\n }\n }\n\n // Pre-pagination association filter. Must run on the FULL dataset (before pagination),\n // otherwise matching deals on later pages disappear and `total` would be wrong. Read the\n // raw URL too so legacy `?personEntityId=` / `?companyEntityId=` keep working alongside the\n // canonical `?personId=` / `?companyId=`.\n const url = ctx?.request ? new URL(ctx.request.url) : null\n const personCandidates: unknown[] = [query.personId, query.personEntityId]\n const companyCandidates: unknown[] = [query.companyId, query.companyEntityId]\n if (url) {\n personCandidates.push(url.searchParams.getAll('personId'))\n personCandidates.push(url.searchParams.getAll('personEntityId'))\n companyCandidates.push(url.searchParams.getAll('companyId'))\n companyCandidates.push(url.searchParams.getAll('companyEntityId'))\n }\n const selectedPersonIds = normalizeUuidList(personCandidates)\n const selectedCompanyIds = normalizeUuidList(companyCandidates)\n if ((selectedPersonIds.length > 0 || selectedCompanyIds.length > 0) && ctx) {\n const tenantId = ctx.auth?.tenantId\n // `ctx.auth` exposes `orgId` (see AuthContext in @open-mercato/shared/lib/auth/server).\n // Read it under the correct key \u2014 the previous code's `organizationId` would always be\n // `undefined`, silently disabling association filtering on the deals list endpoint.\n const organizationId = ctx.auth?.orgId\n if (typeof tenantId === 'string' && typeof organizationId === 'string') {\n const em = ctx.container.resolve<EntityManager>('em')\n const matchedIds = await fetchDealIdsMatchingAssociations(\n em,\n organizationId,\n tenantId,\n selectedPersonIds,\n selectedCompanyIds,\n )\n // intersectIds with empty array \u2192 no rows; collapses the page to zero, total stays correct.\n intersectIds(matchedIds)\n }\n }\n\n if (ctx && advancedFilterTree) {\n const advancedFilters = mergeAdvancedFilterTree({ ...filters }, advancedFilterTree)\n const matchedIds = await findMatchingEntityIdsWithQueryEngine({\n ctx,\n entityId: E.customers.customer_deal,\n filters: advancedFilters,\n })\n if (matchedIds !== null) {\n intersectIds(matchedIds)\n }\n }\n\n if (restrictedIds !== null) {\n applyEntityIdRestriction(filters, restrictedIds)\n }\n\n return filters\n}\n\nconst crud = makeCrudRoute<unknown, unknown, DealListQuery>({\n metadata: routeMetadata,\n orm: {\n entity: CustomerDeal,\n idField: 'id',\n orgField: 'organizationId',\n tenantField: 'tenantId',\n softDeleteField: 'deletedAt',\n },\n indexer: {\n entityType: E.customers.customer_deal,\n },\n enrichers: { entityId: 'customers.deal' },\n list: {\n schema: dealListQuerySchema,\n entityId: E.customers.customer_deal,\n fields: [\n 'id',\n 'title',\n 'description',\n 'status',\n 'pipeline_stage',\n 'pipeline_id',\n 'pipeline_stage_id',\n 'value_amount',\n 'value_currency',\n 'probability',\n 'expected_close_at',\n 'owner_user_id',\n 'source',\n 'closure_outcome',\n 'loss_reason_id',\n 'loss_notes',\n 'organization_id',\n 'tenant_id',\n 'created_at',\n 'updated_at',\n ],\n decorateCustomFields: {\n entityIds: E.customers.customer_deal,\n },\n sortFieldMap: {\n createdAt: 'created_at',\n updatedAt: 'updated_at',\n title: 'title',\n value: 'value_amount',\n probability: 'probability',\n expectedCloseAt: 'expected_close_at',\n },\n buildFilters: buildDealListFilters,\n },\n actions: {\n create: {\n commandId: 'customers.deals.create',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n return parseScopedCommandInput(dealCreateSchema, raw ?? {}, ctx, translate)\n },\n response: ({ result }) => ({ id: result?.dealId ?? result?.id ?? null }),\n status: 201,\n },\n update: {\n commandId: 'customers.deals.update',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n return parseScopedCommandInput(dealUpdateSchema, raw ?? {}, ctx, translate)\n },\n response: () => ({ ok: true }),\n },\n delete: {\n commandId: 'customers.deals.delete',\n schema: rawBodySchema,\n mapInput: async ({ parsed, ctx }) => {\n const { translate } = await resolveTranslations()\n const id =\n parsed?.body?.id ??\n parsed?.id ??\n parsed?.query?.id ??\n (ctx.request ? new URL(ctx.request.url).searchParams.get('id') : null)\n if (!id) throw new CrudHttpError(400, { error: translate('customers.errors.deal_required', 'Deal id is required') })\n return { id }\n },\n response: () => ({ ok: true }),\n },\n },\n hooks: {\n // afterList only DECORATES results with `people`/`companies` arrays \u2014 it must not filter,\n // because filtering after pagination would drop deals on later pages and rewrite `total`\n // to a misleading value. Association filtering happens pre-pagination in `buildFilters`\n // via `fetchDealIdsMatchingAssociations`.\n afterList: async (payload, ctx) => {\n const items = Array.isArray(payload.items) ? payload.items : []\n if (!items.length) return\n const scopeSource = (items[0] ?? {}) as Record<string, unknown>\n const tenantIdRaw = scopeSource.tenantId ?? scopeSource.tenant_id\n const fallbackTenantId = (typeof tenantIdRaw === 'string' && tenantIdRaw.trim().length ? tenantIdRaw : null) ?? ctx.auth?.tenantId ?? null\n const orgIdRaw = scopeSource.organizationId ?? scopeSource.organization_id\n const fallbackOrganizationId = (typeof orgIdRaw === 'string' && orgIdRaw.trim().length ? orgIdRaw : null) ?? ctx.auth?.orgId ?? null\n const ids = items\n .map((item: unknown) => {\n if (!item || typeof item !== 'object') return null\n const candidate = (item as Record<string, unknown>).id\n return typeof candidate === 'string' && candidate.trim().length ? candidate : null\n })\n .filter((value: string | null): value is string => typeof value === 'string' && value.length > 0)\n if (!ids.length) {\n payload.items = []\n payload.total = 0\n return\n }\n try {\n const em = (ctx.container.resolve('em') as EntityManager)\n const [allPersonLinks, allCompanyLinks] = await Promise.all([\n findWithDecryption(\n em,\n CustomerDealPersonLink,\n { deal: { $in: ids } },\n { populate: ['person'] },\n { tenantId: fallbackTenantId, organizationId: fallbackOrganizationId },\n ),\n findWithDecryption(\n em,\n CustomerDealCompanyLink,\n { deal: { $in: ids } },\n { populate: ['company'] },\n { tenantId: fallbackTenantId, organizationId: fallbackOrganizationId },\n ),\n ])\n\n const personAssignments = new Map<string, { id: string; label: string }[]>()\n allPersonLinks.forEach((link) => {\n const deal = link.deal\n const dealRecord = deal && typeof deal === 'object' ? deal as unknown as Record<string, unknown> : null\n const dealId = typeof deal === 'string' ? deal\n : dealRecord && typeof dealRecord.id === 'string' ? dealRecord.id\n : null\n if (!dealId) return\n const personRef = link.person\n const personRecord = personRef && typeof personRef === 'object' ? personRef as unknown as Record<string, unknown> : null\n const personId = typeof personRef === 'string' ? personRef\n : personRecord && typeof personRecord.id === 'string' ? personRecord.id\n : null\n if (!personId) return\n const label = personRecord && typeof personRecord.displayName === 'string'\n ? personRecord.displayName\n : ''\n const bucket = personAssignments.get(dealId) ?? []\n if (!bucket.some((entry) => entry.id === personId)) {\n bucket.push({ id: personId, label })\n personAssignments.set(dealId, bucket)\n }\n })\n\n const companyAssignments = new Map<string, { id: string; label: string }[]>()\n allCompanyLinks.forEach((link) => {\n const deal = link.deal\n const dealRecord = deal && typeof deal === 'object' ? deal as unknown as Record<string, unknown> : null\n const dealId = typeof deal === 'string' ? deal\n : dealRecord && typeof dealRecord.id === 'string' ? dealRecord.id\n : null\n if (!dealId) return\n const companyRef = link.company\n const companyRecord = companyRef && typeof companyRef === 'object' ? companyRef as unknown as Record<string, unknown> : null\n const companyId = typeof companyRef === 'string' ? companyRef\n : companyRecord && typeof companyRecord.id === 'string' ? companyRecord.id\n : null\n if (!companyId) return\n const label = companyRecord && typeof companyRecord.displayName === 'string'\n ? companyRecord.displayName\n : ''\n const bucket = companyAssignments.get(dealId) ?? []\n if (!bucket.some((entry) => entry.id === companyId)) {\n bucket.push({ id: companyId, label })\n companyAssignments.set(dealId, bucket)\n }\n })\n\n const enhancedItems = items\n .map((item: unknown) => {\n if (!item || typeof item !== 'object') return null\n const data = item as Record<string, unknown>\n const candidate = typeof data.id === 'string' ? data.id : null\n if (!candidate || !candidate.trim().length) return null\n const people = personAssignments.get(candidate) ?? []\n const companies = companyAssignments.get(candidate) ?? []\n const tenantIdRaw =\n typeof data.tenantId === 'string'\n ? data.tenantId\n : typeof data.tenant_id === 'string'\n ? data.tenant_id\n : null\n const organizationIdRaw =\n typeof data.organizationId === 'string'\n ? data.organizationId\n : typeof data.organization_id === 'string'\n ? data.organization_id\n : null\n const tenantId = tenantIdRaw && tenantIdRaw.trim().length ? tenantIdRaw.trim() : null\n const organizationId = organizationIdRaw && organizationIdRaw.trim().length ? organizationIdRaw.trim() : null\n return {\n ...data,\n personIds: people.map((entry) => entry.id),\n people,\n companyIds: companies.map((entry) => entry.id),\n companies,\n tenantId,\n organizationId,\n }\n })\n .filter(\n (item: Record<string, unknown> | null): item is Record<string, unknown> => item !== null,\n )\n\n payload.items = enhancedItems\n } catch (err) {\n // We swallow rather than fail the request because the kanban is still useful without\n // people/companies labels (cards just lose their company pill). Tag every item with\n // `_associations: { ok: false }` so a future surface can render a degraded-state hint\n // instead of silently showing cards without company badges.\n console.warn('[customers.deals] failed to decorate items with person/company links', err)\n payload.items = items.map((item: unknown) => {\n if (!item || typeof item !== 'object') return item\n return {\n ...(item as Record<string, unknown>),\n _associations: {\n ok: false,\n reason: err instanceof Error ? err.message : 'unknown',\n },\n }\n })\n }\n },\n },\n})\n\nconst { POST, PUT, DELETE } = crud\n\nexport { POST, PUT, DELETE }\nexport const GET = crud.GET\n\nconst dealAssociationSchema = z.object({\n id: z.string().uuid(),\n label: z.string().nullable(),\n})\n\nconst dealListItemSchema = z\n .object({\n id: z.string().uuid(),\n title: z.string().nullable(),\n description: z.string().nullable().optional(),\n status: z.string().nullable().optional(),\n pipeline_stage: z.string().nullable().optional(),\n pipeline_id: z.string().uuid().nullable().optional(),\n pipeline_stage_id: z.string().uuid().nullable().optional(),\n value_amount: z.number().nullable().optional(),\n value_currency: z.string().nullable().optional(),\n probability: z.number().nullable().optional(),\n expected_close_at: z.string().nullable().optional(),\n owner_user_id: z.string().uuid().nullable().optional(),\n source: z.string().nullable().optional(),\n organization_id: z.string().uuid().nullable().optional(),\n tenant_id: z.string().uuid().nullable().optional(),\n created_at: z.string().nullable().optional(),\n updated_at: z.string().nullable().optional(),\n personIds: z.array(z.string().uuid()).optional(),\n people: z.array(dealAssociationSchema).optional(),\n companyIds: z.array(z.string().uuid()).optional(),\n companies: z.array(dealAssociationSchema).optional(),\n organizationId: z.string().uuid().nullable().optional(),\n tenantId: z.string().uuid().nullable().optional(),\n })\n .passthrough()\n\nconst dealCreateResponseSchema = z.object({\n id: z.string().uuid().nullable(),\n})\n\nexport const openApi = createCustomersCrudOpenApi({\n resourceName: 'Deal',\n querySchema: dealListQuerySchema,\n listResponseSchema: createPagedListResponseSchema(dealListItemSchema),\n create: {\n schema: dealCreateSchema,\n responseSchema: dealCreateResponseSchema,\n description: 'Creates a sales deal, optionally associating people and companies.',\n },\n update: {\n schema: dealUpdateSchema,\n responseSchema: defaultOkResponseSchema,\n description: 'Updates pipeline position, metadata, or associations for an existing deal.',\n },\n del: {\n schema: z.object({ id: z.string().uuid() }),\n responseSchema: defaultOkResponseSchema,\n description: 'Deletes a deal by `id`. The identifier may be provided in the body or query parameters.',\n },\n})\n"],
5
- "mappings": "AAAA,SAAS,SAAS;AAClB,SAAS,qBAAqB;AAC9B,SAAS,qBAAqB;AAC9B,SAAS,cAAc,wBAAwB,+BAA+B;AAC9E,SAAS,kBAAkB,wBAAwB;AACnD,SAAS,SAAS;AAClB,SAAS,2BAA2B;AACpC,SAAS,+BAA+B;AACxC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,0BAA0B;AACnC,SAAS,qCAAqC;AAC9C,SAAS,yBAAyB;AAClC,SAAS,4BAA4B,+BAA+B;AACpE,SAAS,yBAAyB;AAElC,MAAM,gBAAgB,EAAE,OAAO,CAAC,CAAC,EAAE,YAAY;AAE/C,MAAM,sBAAsB,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AACrE,MAAM,oBAAoB,EAAE,WAAW,CAAC,UAAU;AAChD,QAAM,SAAS,wBAAwB,KAAK;AAC5C,SAAO,WAAW,OAAO,QAAQ;AACnC,GAAG,EAAE,QAAQ,CAAC,EAAE,SAAS;AAElB,MAAM,sBAAsB,EAChC,OAAO;AAAA,EACN,MAAM,EAAE,OAAO,OAAO,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC;AAAA,EACxC,UAAU,EAAE,OAAO,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,EAAE;AAAA,EACtD,QAAQ,EAAE,OAAO,EAAE,SAAS;AAAA,EAC5B,QAAQ,oBAAoB,SAAS;AAAA,EACrC,eAAe,EAAE,OAAO,EAAE,SAAS;AAAA,EACnC,YAAY,oBAAoB,SAAS;AAAA,EACzC,iBAAiB,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,GAAG,EAAE,QAAQ,cAAc,CAAC,CAAC,EAAE,SAAS;AAAA,EAClF,aAAa,oBAAoB,SAAS;AAAA,EAC1C,qBAAqB,EAAE,OAAO,EAAE,SAAS;AAAA,EACzC,mBAAmB,EAAE,OAAO,EAAE,SAAS;AAAA,EACvC,SAAS;AAAA,EACT,WAAW;AAAA,EACX,eAAe,oBAAoB,SAAS;AAAA,EAC5C,WAAW,EAAE,OAAO,EAAE,SAAS;AAAA,EAC/B,SAAS,EAAE,KAAK,CAAC,OAAO,MAAM,CAAC,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,EAK1C,gBAAgB,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,0BAA0B;AAAA;AAAA;AAAA;AAAA;AAAA,EAKhF,iBAAiB,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,2BAA2B;AAAA,EAClF,UAAU,oBAAoB,SAAS;AAAA,EACvC,WAAW,oBAAoB,SAAS;AAC1C,CAAC,EACA,YAAY;AAEf,MAAM,gBAAgB;AAAA,EACpB,KAAK,EAAE,aAAa,MAAM,iBAAiB,CAAC,sBAAsB,EAAE;AAAA,EACpE,MAAM,EAAE,aAAa,MAAM,iBAAiB,CAAC,wBAAwB,EAAE;AAAA,EACvE,KAAK,EAAE,aAAa,MAAM,iBAAiB,CAAC,wBAAwB,EAAE;AAAA,EACtE,QAAQ,EAAE,aAAa,MAAM,iBAAiB,CAAC,wBAAwB,EAAE;AAC3E;AAEO,MAAM,WAAW;AAIxB,SAAS,UAAU,OAA+B;AAChD,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAM,UAAU,MAAM,KAAK;AAC3B,MAAI,CAAC,QAAQ,OAAQ,QAAO;AAC5B,QAAM,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,OAAO;AAClD,SAAO,OAAO,UAAU,UAAU;AACpC;AAEA,SAAS,oBAAoB,OAA0B;AACrD,QAAM,MAAM,oBAAI,IAAY;AAC5B,QAAM,QAAQ,CAAC,UAAmB;AAChC,QAAI,SAAS,KAAM;AACnB,QAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,YAAM,QAAQ,KAAK;AACnB;AAAA,IACF;AACA,QAAI,OAAO,UAAU,SAAU;AAC/B,UACG,MAAM,GAAG,EACT,IAAI,CAAC,UAAU,MAAM,KAAK,CAAC,EAC3B,OAAO,CAAC,UAAU,MAAM,SAAS,CAAC,EAClC,QAAQ,CAAC,UAAU,IAAI,IAAI,KAAK,CAAC;AAAA,EACtC;AACA,QAAM,KAAK;AACX,SAAO,MAAM,KAAK,GAAG;AACvB;AAEA,SAAS,eAAe,OAA6B;AACnD,MAAI,EAAE,OAAO,UAAU,aAAa,MAAM,KAAK,EAAE,WAAW,EAAG,QAAO;AACtE,QAAM,OAAO,IAAI,KAAK,KAAK;AAC3B,SAAO,OAAO,MAAM,KAAK,QAAQ,CAAC,IAAI,OAAO;AAC/C;AAcA,eAAe,iCACb,IACA,gBACA,UACA,WACA,YACmB;AACnB,MAAI,CAAC,UAAU,UAAU,CAAC,WAAW,OAAQ,QAAO,CAAC;AACrD,QAAM,QAAkB;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,QAAM,SAAiC,CAAC,gBAAgB,QAAQ;AAChE,MAAI,UAAU,QAAQ;AACpB,UAAM,eAAe,UAAU,IAAI,MAAM,GAAG,EAAE,KAAK,GAAG;AACtD,UAAM;AAAA,MACJ,kHAAkH,YAAY;AAAA,IAChI;AACA,WAAO,KAAK,GAAG,SAAS;AAAA,EAC1B;AACA,MAAI,WAAW,QAAQ;AACrB,UAAM,eAAe,WAAW,IAAI,MAAM,GAAG,EAAE,KAAK,GAAG;AACvD,UAAM;AAAA,MACJ,sHAAsH,YAAY;AAAA,IACpI;AACA,WAAO,KAAK,GAAG,UAAU;AAAA,EAC3B;AACA,QAAM,OAAO,MAAM,GAAG,cAAc,EAAE;AAAA,IACpC,uCAAuC,MAAM,KAAK,OAAO,CAAC;AAAA,IAC1D;AAAA,EACF;AACA,SAAO,KAAK,IAAI,CAAC,QAAQ,IAAI,EAAE;AACjC;AAEA,SAAS,sBAAsB,OAA0B;AACvD,QAAM,MAAM,oBAAI,IAAY;AAC5B,QAAM,QAAQ,CAAC,UAAmB;AAChC,QAAI,SAAS,KAAM;AACnB,QAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,YAAM,QAAQ,KAAK;AACnB;AAAA,IACF;AACA,QAAI,OAAO,UAAU,SAAU;AAC/B,UACG,MAAM,GAAG,EACT,IAAI,CAAC,UAAU,MAAM,KAAK,EAAE,YAAY,CAAC,EACzC,OAAO,CAAC,UAAU,aAAa,KAAK,KAAK,CAAC,EAC1C,QAAQ,CAAC,UAAU,IAAI,IAAI,KAAK,CAAC;AAAA,EACtC;AACA,QAAM,KAAK;AACX,SAAO,MAAM,KAAK,GAAG;AACvB;AAEA,SAAS,kBAAkB,QAAkC;AAC3D,QAAM,MAAM,oBAAI,IAAY;AAC5B,SAAO,QAAQ,CAAC,cAAc;AAC5B,QAAI,MAAM,QAAQ,SAAS,GAAG;AAC5B,gBAAU,QAAQ,CAAC,UAAU;AAC3B,cAAMA,UAAS,UAAU,KAAK;AAC9B,YAAIA,QAAQ,KAAI,IAAIA,OAAM;AAAA,MAC5B,CAAC;AACD;AAAA,IACF;AACA,QAAI,OAAO,cAAc,YAAY,UAAU,SAAS,GAAG,GAAG;AAC5D,gBACG,MAAM,GAAG,EACT,IAAI,CAAC,UAAU,MAAM,KAAK,CAAC,EAC3B,QAAQ,CAAC,UAAU;AAClB,cAAMA,UAAS,UAAU,KAAK;AAC9B,YAAIA,QAAQ,KAAI,IAAIA,OAAM;AAAA,MAC5B,CAAC;AACH;AAAA,IACF;AACA,UAAM,SAAS,UAAU,SAAS;AAClC,QAAI,OAAQ,KAAI,IAAI,MAAM;AAAA,EAC5B,CAAC;AACD,SAAO,MAAM,KAAK,GAAG;AACvB;AAEA,eAAsB,qBAAqB,OAAsB,KAA+D;AAC9H,QAAM,qBAAqB,2BAA2B,KAAK;AAC3D,QAAM,UAAmC,CAAC;AAC1C,MAAI,gBAAiC;AAErC,QAAM,eAAe,CAAC,QAAkB;AACtC,QAAI,kBAAkB,MAAM;AAC1B,sBAAgB;AAChB;AAAA,IACF;AACA,UAAM,SAAS,IAAI,IAAI,GAAG;AAC1B,oBAAgB,cAAc,OAAO,CAAC,OAAO,OAAO,IAAI,EAAE,CAAC;AAAA,EAC7D;AAEA,MAAI,MAAM,QAAQ;AAChB,UAAM,cAAc,MAChB,MAAM,iDAAiD;AAAA,MACrD;AAAA,MACA,OAAO,MAAM;AAAA,MACb,SAAS;AAAA,QACP;AAAA,UACE,YAAY,EAAE,UAAU;AAAA,UACxB,QAAQ;AAAA,YACN;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC,IACD;AACJ,QAAI,gBAAgB,QAAQ,YAAY,SAAS,GAAG;AAClD,mBAAa,WAAW;AAAA,IAC1B,WAAW,8BAA8B,GAAG;AAM1C,mBAAa,CAAC,CAAC;AAAA,IACjB,OAAO;AACL,YAAM,gBAAgB,IAAI,kBAAkB,MAAM,MAAM,CAAC;AACzD,cAAQ,MAAM;AAAA,QACZ,EAAE,OAAO,EAAE,QAAQ,cAAc,EAAE;AAAA,QACnC,EAAE,aAAa,EAAE,QAAQ,cAAc,EAAE;AAAA,MAC3C;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAAa,MAAM,SAAS,oBAAoB,MAAM,MAAM,IAAI,CAAC;AACvE,MAAI,WAAW,SAAS,GAAG;AACzB,YAAQ,SAAS,WAAW,WAAW,IAAI,EAAE,KAAK,WAAW,CAAC,EAAE,IAAI,EAAE,KAAK,WAAW;AAAA,EACxF;AAEA,MAAI,MAAM,eAAe;AACvB,YAAQ,iBAAiB,EAAE,KAAK,MAAM,cAAc;AAAA,EACtD;AAEA,QAAM,cAAc,MAAM,aAAa,kBAAkB,CAAC,MAAM,UAAU,CAAC,IAAI,CAAC;AAChF,MAAI,YAAY,SAAS,GAAG;AAC1B,YAAQ,cAAc,YAAY,WAAW,IAAI,EAAE,KAAK,YAAY,CAAC,EAAE,IAAI,EAAE,KAAK,YAAY;AAAA,EAChG;AAEA,MAAI,MAAM,oBAAoB,gBAAgB;AAC5C,YAAQ,oBAAoB,EAAE,KAAK,KAAK;AAAA,EAC1C,WAAW,MAAM,iBAAiB;AAChC,YAAQ,oBAAoB,EAAE,KAAK,MAAM,gBAAgB;AAAA,EAC3D;AAEA,QAAM,eAAe,MAAM,cAAc,kBAAkB,CAAC,MAAM,WAAW,CAAC,IAAI,CAAC;AACnF,MAAI,aAAa,SAAS,GAAG;AAC3B,YAAQ,gBACN,aAAa,WAAW,IAAI,EAAE,KAAK,aAAa,CAAC,EAAE,IAAI,EAAE,KAAK,aAAa;AAAA,EAC/E;AAKA,QAAM,gBAAgB,MAAM,gBAAgB,sBAAsB,MAAM,aAAa,IAAI,CAAC;AAC1F,MAAI,cAAc,SAAS,GAAG;AAC5B,YAAQ,iBACN,cAAc,WAAW,IAAI,EAAE,KAAK,cAAc,CAAC,EAAE,IAAI,EAAE,KAAK,cAAc;AAAA,EAClF;AAEA,QAAM,oBAAoB,eAAe,MAAM,mBAAmB;AAClE,QAAM,kBAAkB,eAAe,MAAM,iBAAiB;AAC9D,MAAI,qBAAqB,iBAAiB;AACxC,UAAM,QAA8B,CAAC;AACrC,QAAI,kBAAmB,OAAM,OAAO;AACpC,QAAI,gBAAiB,OAAM,OAAO;AAClC,YAAQ,oBAAoB;AAAA,EAC9B;AAEA,MAAI,MAAM,WAAW;AACnB,UAAM,QAAQ,oBAAI,KAAK;AACvB,UAAM,SAAS,GAAG,GAAG,GAAG,CAAC;AACzB,QAAI,WAAW,WAAW,GAAG;AAC3B,cAAQ,SAAS,EAAE,KAAK,OAAO;AAAA,IACjC;AACA,UAAM,gBACJ,QAAQ,qBAAqB,OAAO,QAAQ,sBAAsB,WAC7D,QAAQ,oBACT,CAAC;AACP,kBAAc,MAAM;AACpB,YAAQ,oBAAoB;AAAA,EAC9B;AAEA,MAAI,MAAM,WAAW,KAAK;AACxB,UAAM,WAAW,IAAI,MAAM;AAI3B,UAAM,iBAAiB,IAAI,MAAM;AACjC,QAAI,OAAO,aAAa,YAAY,OAAO,mBAAmB,UAAU;AACtE,YAAM,KAAK,IAAI,UAAU,QAAuB,IAAI;AACpD,YAAM,WAAW,MAAM,kBAAkB,IAAI,gBAAgB,QAAQ;AACrE,mBAAa,QAAQ;AAAA,IACvB;AAAA,EACF;AAMA,QAAM,MAAM,KAAK,UAAU,IAAI,IAAI,IAAI,QAAQ,GAAG,IAAI;AACtD,QAAM,mBAA8B,CAAC,MAAM,UAAU,MAAM,cAAc;AACzE,QAAM,oBAA+B,CAAC,MAAM,WAAW,MAAM,eAAe;AAC5E,MAAI,KAAK;AACP,qBAAiB,KAAK,IAAI,aAAa,OAAO,UAAU,CAAC;AACzD,qBAAiB,KAAK,IAAI,aAAa,OAAO,gBAAgB,CAAC;AAC/D,sBAAkB,KAAK,IAAI,aAAa,OAAO,WAAW,CAAC;AAC3D,sBAAkB,KAAK,IAAI,aAAa,OAAO,iBAAiB,CAAC;AAAA,EACnE;AACA,QAAM,oBAAoB,kBAAkB,gBAAgB;AAC5D,QAAM,qBAAqB,kBAAkB,iBAAiB;AAC9D,OAAK,kBAAkB,SAAS,KAAK,mBAAmB,SAAS,MAAM,KAAK;AAC1E,UAAM,WAAW,IAAI,MAAM;AAI3B,UAAM,iBAAiB,IAAI,MAAM;AACjC,QAAI,OAAO,aAAa,YAAY,OAAO,mBAAmB,UAAU;AACtE,YAAM,KAAK,IAAI,UAAU,QAAuB,IAAI;AACpD,YAAM,aAAa,MAAM;AAAA,QACvB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEA,mBAAa,UAAU;AAAA,IACzB;AAAA,EACF;AAEA,MAAI,OAAO,oBAAoB;AAC7B,UAAM,kBAAkB,wBAAwB,EAAE,GAAG,QAAQ,GAAG,kBAAkB;AAClF,UAAM,aAAa,MAAM,qCAAqC;AAAA,MAC5D;AAAA,MACA,UAAU,EAAE,UAAU;AAAA,MACtB,SAAS;AAAA,IACX,CAAC;AACD,QAAI,eAAe,MAAM;AACvB,mBAAa,UAAU;AAAA,IACzB;AAAA,EACF;AAEA,MAAI,kBAAkB,MAAM;AAC1B,6BAAyB,SAAS,aAAa;AAAA,EACjD;AAEA,SAAO;AACT;AAEA,MAAM,OAAO,cAA+C;AAAA,EAC1D,UAAU;AAAA,EACV,KAAK;AAAA,IACH,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,UAAU;AAAA,IACV,aAAa;AAAA,IACb,iBAAiB;AAAA,EACnB;AAAA,EACA,SAAS;AAAA,IACP,YAAY,EAAE,UAAU;AAAA,EAC1B;AAAA,EACA,WAAW,EAAE,UAAU,iBAAiB;AAAA,EACxC,MAAM;AAAA,IACJ,QAAQ;AAAA,IACR,UAAU,EAAE,UAAU;AAAA,IACtB,QAAQ;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,sBAAsB;AAAA,MACpB,WAAW,EAAE,UAAU;AAAA,IACzB;AAAA,IACA,cAAc;AAAA,MACZ,WAAW;AAAA,MACX,WAAW;AAAA,MACX,OAAO;AAAA,MACP,OAAO;AAAA,MACP,aAAa;AAAA,MACb,iBAAiB;AAAA,IACnB;AAAA,IACA,cAAc;AAAA,EAChB;AAAA,EACA,SAAS;AAAA,IACP,QAAQ;AAAA,MACN,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,UAAU,OAAO,EAAE,KAAK,IAAI,MAAM;AAChC,cAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAChD,eAAO,wBAAwB,kBAAkB,OAAO,CAAC,GAAG,KAAK,SAAS;AAAA,MAC5E;AAAA,MACA,UAAU,CAAC,EAAE,OAAO,OAAO,EAAE,IAAI,QAAQ,UAAU,QAAQ,MAAM,KAAK;AAAA,MACtE,QAAQ;AAAA,IACV;AAAA,IACA,QAAQ;AAAA,MACN,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,UAAU,OAAO,EAAE,KAAK,IAAI,MAAM;AAChC,cAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAChD,eAAO,wBAAwB,kBAAkB,OAAO,CAAC,GAAG,KAAK,SAAS;AAAA,MAC5E;AAAA,MACA,UAAU,OAAO,EAAE,IAAI,KAAK;AAAA,IAC9B;AAAA,IACA,QAAQ;AAAA,MACN,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,UAAU,OAAO,EAAE,QAAQ,IAAI,MAAM;AACnC,cAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAChD,cAAM,KACJ,QAAQ,MAAM,MACd,QAAQ,MACR,QAAQ,OAAO,OACd,IAAI,UAAU,IAAI,IAAI,IAAI,QAAQ,GAAG,EAAE,aAAa,IAAI,IAAI,IAAI;AACnE,YAAI,CAAC,GAAI,OAAM,IAAI,cAAc,KAAK,EAAE,OAAO,UAAU,kCAAkC,qBAAqB,EAAE,CAAC;AACnH,eAAO,EAAE,GAAG;AAAA,MACd;AAAA,MACA,UAAU,OAAO,EAAE,IAAI,KAAK;AAAA,IAC9B;AAAA,EACF;AAAA,EACA,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA,IAKL,WAAW,OAAO,SAAS,QAAQ;AACjC,YAAM,QAAQ,MAAM,QAAQ,QAAQ,KAAK,IAAI,QAAQ,QAAQ,CAAC;AAC9D,UAAI,CAAC,MAAM,OAAQ;AACnB,YAAM,cAAe,MAAM,CAAC,KAAK,CAAC;AAClC,YAAM,cAAc,YAAY,YAAY,YAAY;AACxD,YAAM,oBAAoB,OAAO,gBAAgB,YAAY,YAAY,KAAK,EAAE,SAAS,cAAc,SAAS,IAAI,MAAM,YAAY;AACtI,YAAM,WAAW,YAAY,kBAAkB,YAAY;AAC3D,YAAM,0BAA0B,OAAO,aAAa,YAAY,SAAS,KAAK,EAAE,SAAS,WAAW,SAAS,IAAI,MAAM,SAAS;AAChI,YAAM,MAAM,MACT,IAAI,CAAC,SAAkB;AACtB,YAAI,CAAC,QAAQ,OAAO,SAAS,SAAU,QAAO;AAC9C,cAAM,YAAa,KAAiC;AACpD,eAAO,OAAO,cAAc,YAAY,UAAU,KAAK,EAAE,SAAS,YAAY;AAAA,MAChF,CAAC,EACA,OAAO,CAAC,UAA0C,OAAO,UAAU,YAAY,MAAM,SAAS,CAAC;AAClG,UAAI,CAAC,IAAI,QAAQ;AACf,gBAAQ,QAAQ,CAAC;AACjB,gBAAQ,QAAQ;AAChB;AAAA,MACF;AACA,UAAI;AACF,cAAM,KAAM,IAAI,UAAU,QAAQ,IAAI;AACtC,cAAM,CAAC,gBAAgB,eAAe,IAAI,MAAM,QAAQ,IAAI;AAAA,UAC1D;AAAA,YACE;AAAA,YACA;AAAA,YACA,EAAE,MAAM,EAAE,KAAK,IAAI,EAAE;AAAA,YACrB,EAAE,UAAU,CAAC,QAAQ,EAAE;AAAA,YACvB,EAAE,UAAU,kBAAkB,gBAAgB,uBAAuB;AAAA,UACvE;AAAA,UACA;AAAA,YACE;AAAA,YACA;AAAA,YACA,EAAE,MAAM,EAAE,KAAK,IAAI,EAAE;AAAA,YACrB,EAAE,UAAU,CAAC,SAAS,EAAE;AAAA,YACxB,EAAE,UAAU,kBAAkB,gBAAgB,uBAAuB;AAAA,UACvE;AAAA,QACF,CAAC;AAED,cAAM,oBAAoB,oBAAI,IAA6C;AAC3E,uBAAe,QAAQ,CAAC,SAAS;AAC/B,gBAAM,OAAO,KAAK;AAClB,gBAAM,aAAa,QAAQ,OAAO,SAAS,WAAW,OAA6C;AACnG,gBAAM,SAAS,OAAO,SAAS,WAAW,OACtC,cAAc,OAAO,WAAW,OAAO,WAAW,WAAW,KAC7D;AACJ,cAAI,CAAC,OAAQ;AACb,gBAAM,YAAY,KAAK;AACvB,gBAAM,eAAe,aAAa,OAAO,cAAc,WAAW,YAAkD;AACpH,gBAAM,WAAW,OAAO,cAAc,WAAW,YAC7C,gBAAgB,OAAO,aAAa,OAAO,WAAW,aAAa,KACnE;AACJ,cAAI,CAAC,SAAU;AACf,gBAAM,QAAQ,gBAAgB,OAAO,aAAa,gBAAgB,WAC9D,aAAa,cACb;AACJ,gBAAM,SAAS,kBAAkB,IAAI,MAAM,KAAK,CAAC;AACjD,cAAI,CAAC,OAAO,KAAK,CAAC,UAAU,MAAM,OAAO,QAAQ,GAAG;AAClD,mBAAO,KAAK,EAAE,IAAI,UAAU,MAAM,CAAC;AACnC,8BAAkB,IAAI,QAAQ,MAAM;AAAA,UACtC;AAAA,QACF,CAAC;AAED,cAAM,qBAAqB,oBAAI,IAA6C;AAC5E,wBAAgB,QAAQ,CAAC,SAAS;AAChC,gBAAM,OAAO,KAAK;AAClB,gBAAM,aAAa,QAAQ,OAAO,SAAS,WAAW,OAA6C;AACnG,gBAAM,SAAS,OAAO,SAAS,WAAW,OACtC,cAAc,OAAO,WAAW,OAAO,WAAW,WAAW,KAC7D;AACJ,cAAI,CAAC,OAAQ;AACb,gBAAM,aAAa,KAAK;AACxB,gBAAM,gBAAgB,cAAc,OAAO,eAAe,WAAW,aAAmD;AACxH,gBAAM,YAAY,OAAO,eAAe,WAAW,aAC/C,iBAAiB,OAAO,cAAc,OAAO,WAAW,cAAc,KACtE;AACJ,cAAI,CAAC,UAAW;AAChB,gBAAM,QAAQ,iBAAiB,OAAO,cAAc,gBAAgB,WAChE,cAAc,cACd;AACJ,gBAAM,SAAS,mBAAmB,IAAI,MAAM,KAAK,CAAC;AAClD,cAAI,CAAC,OAAO,KAAK,CAAC,UAAU,MAAM,OAAO,SAAS,GAAG;AACnD,mBAAO,KAAK,EAAE,IAAI,WAAW,MAAM,CAAC;AACpC,+BAAmB,IAAI,QAAQ,MAAM;AAAA,UACvC;AAAA,QACF,CAAC;AAED,cAAM,gBAAgB,MACnB,IAAI,CAAC,SAAkB;AACtB,cAAI,CAAC,QAAQ,OAAO,SAAS,SAAU,QAAO;AAC9C,gBAAM,OAAO;AACb,gBAAM,YAAY,OAAO,KAAK,OAAO,WAAW,KAAK,KAAK;AAC1D,cAAI,CAAC,aAAa,CAAC,UAAU,KAAK,EAAE,OAAQ,QAAO;AACnD,gBAAM,SAAS,kBAAkB,IAAI,SAAS,KAAK,CAAC;AACpD,gBAAM,YAAY,mBAAmB,IAAI,SAAS,KAAK,CAAC;AACxD,gBAAMC,eACJ,OAAO,KAAK,aAAa,WACrB,KAAK,WACL,OAAO,KAAK,cAAc,WACxB,KAAK,YACL;AACR,gBAAM,oBACJ,OAAO,KAAK,mBAAmB,WAC3B,KAAK,iBACL,OAAO,KAAK,oBAAoB,WAC9B,KAAK,kBACL;AACR,gBAAM,WAAWA,gBAAeA,aAAY,KAAK,EAAE,SAASA,aAAY,KAAK,IAAI;AACjF,gBAAM,iBAAiB,qBAAqB,kBAAkB,KAAK,EAAE,SAAS,kBAAkB,KAAK,IAAI;AACzG,iBAAO;AAAA,YACL,GAAG;AAAA,YACH,WAAW,OAAO,IAAI,CAAC,UAAU,MAAM,EAAE;AAAA,YACzC;AAAA,YACA,YAAY,UAAU,IAAI,CAAC,UAAU,MAAM,EAAE;AAAA,YAC7C;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF,CAAC,EACA;AAAA,UACC,CAAC,SAA0E,SAAS;AAAA,QACtF;AAEF,gBAAQ,QAAQ;AAAA,MAClB,SAAS,KAAK;AAKZ,gBAAQ,KAAK,wEAAwE,GAAG;AACxF,gBAAQ,QAAQ,MAAM,IAAI,CAAC,SAAkB;AAC3C,cAAI,CAAC,QAAQ,OAAO,SAAS,SAAU,QAAO;AAC9C,iBAAO;AAAA,YACL,GAAI;AAAA,YACJ,eAAe;AAAA,cACb,IAAI;AAAA,cACJ,QAAQ,eAAe,QAAQ,IAAI,UAAU;AAAA,YAC/C;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF,CAAC;AAED,MAAM,EAAE,MAAM,KAAK,OAAO,IAAI;AAGvB,MAAM,MAAM,KAAK;AAExB,MAAM,wBAAwB,EAAE,OAAO;AAAA,EACrC,IAAI,EAAE,OAAO,EAAE,KAAK;AAAA,EACpB,OAAO,EAAE,OAAO,EAAE,SAAS;AAC7B,CAAC;AAED,MAAM,qBAAqB,EACxB,OAAO;AAAA,EACN,IAAI,EAAE,OAAO,EAAE,KAAK;AAAA,EACpB,OAAO,EAAE,OAAO,EAAE,SAAS;AAAA,EAC3B,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC5C,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EACvC,gBAAgB,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC/C,aAAa,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS;AAAA,EACnD,mBAAmB,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS;AAAA,EACzD,cAAc,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC7C,gBAAgB,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC/C,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC5C,mBAAmB,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAClD,eAAe,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS;AAAA,EACrD,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EACvC,iBAAiB,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS;AAAA,EACvD,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS;AAAA,EACjD,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC3C,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC3C,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,SAAS;AAAA,EAC/C,QAAQ,EAAE,MAAM,qBAAqB,EAAE,SAAS;AAAA,EAChD,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,SAAS;AAAA,EAChD,WAAW,EAAE,MAAM,qBAAqB,EAAE,SAAS;AAAA,EACnD,gBAAgB,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS;AAAA,EACtD,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS;AAClD,CAAC,EACA,YAAY;AAEf,MAAM,2BAA2B,EAAE,OAAO;AAAA,EACxC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS;AACjC,CAAC;AAEM,MAAM,UAAU,2BAA2B;AAAA,EAChD,cAAc;AAAA,EACd,aAAa;AAAA,EACb,oBAAoB,8BAA8B,kBAAkB;AAAA,EACpE,QAAQ;AAAA,IACN,QAAQ;AAAA,IACR,gBAAgB;AAAA,IAChB,aAAa;AAAA,EACf;AAAA,EACA,QAAQ;AAAA,IACN,QAAQ;AAAA,IACR,gBAAgB;AAAA,IAChB,aAAa;AAAA,EACf;AAAA,EACA,KAAK;AAAA,IACH,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAAA,IAC1C,gBAAgB;AAAA,IAChB,aAAa;AAAA,EACf;AACF,CAAC;",
4
+ "sourcesContent": ["import { z } from 'zod'\nimport { makeCrudRoute } from '@open-mercato/shared/lib/crud/factory'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { CustomerDeal, CustomerDealPersonLink, CustomerDealCompanyLink } from '../../data/entities'\nimport { dealCreateSchema, dealUpdateSchema } from '../../data/validators'\nimport { E } from '#generated/entities.ids.generated'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { parseBooleanFromUnknown } from '@open-mercato/shared/lib/boolean'\nimport {\n applyEntityIdRestriction,\n findMatchingEntityIdsWithQueryEngine,\n findMatchingEntityIdsBySearchTokensAcrossSources,\n parseScopedCommandInput,\n} from '../utils'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport {\n createCustomersCrudOpenApi,\n createPagedListResponseSchema,\n defaultOkResponseSchema,\n} from '../openapi'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { isTenantDataEncryptionEnabled } from '@open-mercato/shared/lib/encryption/toggles'\nimport { escapeLikePattern } from '@open-mercato/shared/lib/db/escapeLikePattern'\nimport { consumeAdvancedFilterState, mergeAdvancedFilterTree } from '@open-mercato/shared/lib/crud/advanced-filter-integration'\nimport { fetchStuckDealIds } from '../../lib/stuckDeals'\n\nconst rawBodySchema = z.object({}).passthrough()\n\nconst stringOrStringArray = z.union([z.string(), z.array(z.string())])\nconst booleanQueryParam = z.preprocess((value) => {\n const parsed = parseBooleanFromUnknown(value)\n return parsed === null ? value : parsed\n}, z.boolean()).optional()\n\nexport const dealListQuerySchema = z\n .object({\n page: z.coerce.number().min(1).default(1),\n pageSize: z.coerce.number().min(1).max(100).default(50),\n id: z.string().uuid().optional(),\n search: z.string().optional(),\n status: stringOrStringArray.optional(),\n pipelineStage: z.string().optional(),\n pipelineId: stringOrStringArray.optional(),\n pipelineStageId: z.union([z.string().uuid(), z.literal('__unassigned')]).optional(),\n ownerUserId: stringOrStringArray.optional(),\n expectedCloseAtFrom: z.string().optional(),\n expectedCloseAtTo: z.string().optional(),\n isStuck: booleanQueryParam,\n isOverdue: booleanQueryParam,\n valueCurrency: stringOrStringArray.optional(),\n sortField: z.string().optional(),\n sortDir: z.enum(['asc', 'desc']).optional(),\n /**\n * @deprecated Use `personId` instead. The `personEntityId` alias is kept for backward\n * compatibility with older clients and will be removed in a future minor release.\n */\n personEntityId: z.string().uuid().optional().describe('Deprecated; use personId'),\n /**\n * @deprecated Use `companyId` instead. The `companyEntityId` alias is kept for backward\n * compatibility with older clients and will be removed in a future minor release.\n */\n companyEntityId: z.string().uuid().optional().describe('Deprecated; use companyId'),\n personId: stringOrStringArray.optional(),\n companyId: stringOrStringArray.optional(),\n })\n .passthrough()\n\nconst routeMetadata = {\n GET: { requireAuth: true, requireFeatures: ['customers.deals.view'] },\n POST: { requireAuth: true, requireFeatures: ['customers.deals.manage'] },\n PUT: { requireAuth: true, requireFeatures: ['customers.deals.manage'] },\n DELETE: { requireAuth: true, requireFeatures: ['customers.deals.manage'] },\n}\n\nexport const metadata = routeMetadata\n\nexport type DealListQuery = z.infer<typeof dealListQuerySchema>\n\nfunction parseUuid(value: unknown): string | null {\n if (typeof value !== 'string') return null\n const trimmed = value.trim()\n if (!trimmed.length) return null\n const result = z.string().uuid().safeParse(trimmed)\n return result.success ? trimmed : null\n}\n\nfunction normalizeStringList(value: unknown): string[] {\n const set = new Set<string>()\n const visit = (entry: unknown) => {\n if (entry == null) return\n if (Array.isArray(entry)) {\n entry.forEach(visit)\n return\n }\n if (typeof entry !== 'string') return\n entry\n .split(',')\n .map((token) => token.trim())\n .filter((token) => token.length > 0)\n .forEach((token) => set.add(token))\n }\n visit(value)\n return Array.from(set)\n}\n\nfunction parseDateInput(value: unknown): Date | null {\n if (!(typeof value === 'string') || value.trim().length === 0) return null\n const date = new Date(value)\n return Number.isNaN(date.getTime()) ? null : date\n}\n\n/**\n * Pre-pagination ID narrowing for person/company filters.\n *\n * Mirrors the SQL the aggregate route uses (`EXISTS ... IN (...)`) so the list endpoint\n * and the lane-header aggregate return a consistent set of deals for the same filters.\n * Semantics: OR within a category (any selected person/company matches), AND across\n * categories (deal must match at least one person AND at least one company when both\n * filter lists are provided).\n *\n * Returns the matched deal IDs (UUIDs). An empty array means \"no deals match\" \u2014 callers\n * must intersect with `restrictedIds` (which will collapse the list to zero).\n */\nasync function fetchDealIdsMatchingAssociations(\n em: EntityManager,\n organizationId: string,\n tenantId: string,\n personIds: string[],\n companyIds: string[],\n): Promise<string[]> {\n if (!personIds.length && !companyIds.length) return []\n const where: string[] = [\n 'organization_id = ?',\n 'tenant_id = ?',\n 'deleted_at IS NULL',\n ]\n const values: Array<string | number> = [organizationId, tenantId]\n if (personIds.length) {\n const placeholders = personIds.map(() => '?').join(',')\n where.push(\n `EXISTS (SELECT 1 FROM customer_deal_people dp WHERE dp.deal_id = customer_deals.id AND dp.person_entity_id IN (${placeholders}))`,\n )\n values.push(...personIds)\n }\n if (companyIds.length) {\n const placeholders = companyIds.map(() => '?').join(',')\n where.push(\n `EXISTS (SELECT 1 FROM customer_deal_companies dc WHERE dc.deal_id = customer_deals.id AND dc.company_entity_id IN (${placeholders}))`,\n )\n values.push(...companyIds)\n }\n const rows = await em.getConnection().execute<Array<{ id: string }>>(\n `SELECT id FROM customer_deals WHERE ${where.join(' AND ')}`,\n values,\n )\n return rows.map((row) => row.id)\n}\n\nfunction normalizeCurrencyList(value: unknown): string[] {\n const set = new Set<string>()\n const visit = (entry: unknown) => {\n if (entry == null) return\n if (Array.isArray(entry)) {\n entry.forEach(visit)\n return\n }\n if (typeof entry !== 'string') return\n entry\n .split(',')\n .map((token) => token.trim().toUpperCase())\n .filter((token) => /^[A-Z]{3}$/.test(token))\n .forEach((token) => set.add(token))\n }\n visit(value)\n return Array.from(set)\n}\n\nfunction normalizeUuidList(values: Array<unknown>): string[] {\n const set = new Set<string>()\n values.forEach((candidate) => {\n if (Array.isArray(candidate)) {\n candidate.forEach((entry) => {\n const parsed = parseUuid(entry)\n if (parsed) set.add(parsed)\n })\n return\n }\n if (typeof candidate === 'string' && candidate.includes(',')) {\n candidate\n .split(',')\n .map((entry) => entry.trim())\n .forEach((entry) => {\n const parsed = parseUuid(entry)\n if (parsed) set.add(parsed)\n })\n return\n }\n const parsed = parseUuid(candidate)\n if (parsed) set.add(parsed)\n })\n return Array.from(set)\n}\n\nexport async function buildDealListFilters(query: DealListQuery, ctx?: import('@open-mercato/shared/lib/crud/factory').CrudCtx) {\n const advancedFilterTree = consumeAdvancedFilterState(query)\n const filters: Record<string, unknown> = {}\n let restrictedIds: string[] | null = null\n\n const intersectIds = (ids: string[]) => {\n if (restrictedIds === null) {\n restrictedIds = ids\n return\n }\n const lookup = new Set(ids)\n restrictedIds = restrictedIds.filter((id) => lookup.has(id))\n }\n\n if (query.id) filters.id = { $eq: query.id }\n\n if (query.search) {\n const matchingIds = ctx\n ? await findMatchingEntityIdsBySearchTokensAcrossSources({\n ctx,\n query: query.search,\n sources: [\n {\n entityType: E.customers.customer_deal,\n fields: [\n 'title',\n 'description',\n 'status',\n 'pipeline_stage',\n 'source',\n 'value_amount',\n 'value_currency',\n 'cf:competitive_risk',\n 'cf:implementation_complexity',\n ],\n },\n ],\n })\n : null\n if (matchingIds !== null && matchingIds.length > 0) {\n intersectIds(matchingIds)\n } else if (isTenantDataEncryptionEnabled()) {\n // `customers:customer_deal.title` and `.description` are encrypted at rest\n // (see `encryption.ts`). The `$ilike` fallback below would silently match\n // nothing on the ciphertext and produce empty pages without disclosing why \u2014\n // collapse the result to \"no matches\" instead so the kanban + list views\n // agree, and lane aggregates stay consistent with the list endpoint.\n intersectIds([])\n } else {\n const searchPattern = `%${escapeLikePattern(query.search)}%`\n filters.$or = [\n { title: { $ilike: searchPattern } },\n { description: { $ilike: searchPattern } },\n ]\n }\n }\n\n const statusList = query.status ? normalizeStringList(query.status) : []\n if (statusList.length > 0) {\n filters.status = statusList.length === 1 ? { $eq: statusList[0] } : { $in: statusList }\n }\n\n if (query.pipelineStage) {\n filters.pipeline_stage = { $eq: query.pipelineStage }\n }\n\n const pipelineIds = query.pipelineId ? normalizeUuidList([query.pipelineId]) : []\n if (pipelineIds.length > 0) {\n filters.pipeline_id = pipelineIds.length === 1 ? { $eq: pipelineIds[0] } : { $in: pipelineIds }\n }\n\n if (query.pipelineStageId === '__unassigned') {\n filters.pipeline_stage_id = { $eq: null }\n } else if (query.pipelineStageId) {\n filters.pipeline_stage_id = { $eq: query.pipelineStageId }\n }\n\n const ownerUserIds = query.ownerUserId ? normalizeUuidList([query.ownerUserId]) : []\n if (ownerUserIds.length > 0) {\n filters.owner_user_id =\n ownerUserIds.length === 1 ? { $eq: ownerUserIds[0] } : { $in: ownerUserIds }\n }\n\n // Currency filter (additive; sourced by the kanban Currency popover). Codes are\n // normalised to upper-case so `usd` / `USD` / mixed-case query params all hit the same\n // stored value (the deals API persists `value_currency` upper-case already).\n const currencyCodes = query.valueCurrency ? normalizeCurrencyList(query.valueCurrency) : []\n if (currencyCodes.length > 0) {\n filters.value_currency =\n currencyCodes.length === 1 ? { $eq: currencyCodes[0] } : { $in: currencyCodes }\n }\n\n const expectedCloseFrom = parseDateInput(query.expectedCloseAtFrom)\n const expectedCloseTo = parseDateInput(query.expectedCloseAtTo)\n if (expectedCloseFrom || expectedCloseTo) {\n const range: Record<string, Date> = {}\n if (expectedCloseFrom) range.$gte = expectedCloseFrom\n if (expectedCloseTo) range.$lte = expectedCloseTo\n filters.expected_close_at = range\n }\n\n if (query.isOverdue) {\n const today = new Date()\n today.setHours(0, 0, 0, 0)\n if (statusList.length === 0) {\n filters.status = { $eq: 'open' }\n }\n const existingRange =\n filters.expected_close_at && typeof filters.expected_close_at === 'object'\n ? (filters.expected_close_at as Record<string, Date>)\n : {}\n existingRange.$lt = today\n filters.expected_close_at = existingRange\n }\n\n if (query.isStuck && ctx) {\n const tenantId = ctx.auth?.tenantId\n // CrudCtx.auth carries `orgId` (not `organizationId`). The previous code referenced\n // `organizationId` which is always `undefined`, so the typeof check below silently\n // skipped the entire isStuck branch \u2014 `?isStuck=true` was a no-op on this endpoint.\n const organizationId = ctx.auth?.orgId\n if (typeof tenantId === 'string' && typeof organizationId === 'string') {\n const em = ctx.container.resolve<EntityManager>('em')\n const stuckIds = await fetchStuckDealIds(em, organizationId, tenantId)\n intersectIds(stuckIds)\n }\n }\n\n // Pre-pagination association filter. Must run on the FULL dataset (before pagination),\n // otherwise matching deals on later pages disappear and `total` would be wrong. Read the\n // raw URL too so legacy `?personEntityId=` / `?companyEntityId=` keep working alongside the\n // canonical `?personId=` / `?companyId=`.\n const url = ctx?.request ? new URL(ctx.request.url) : null\n const personCandidates: unknown[] = [query.personId, query.personEntityId]\n const companyCandidates: unknown[] = [query.companyId, query.companyEntityId]\n if (url) {\n personCandidates.push(url.searchParams.getAll('personId'))\n personCandidates.push(url.searchParams.getAll('personEntityId'))\n companyCandidates.push(url.searchParams.getAll('companyId'))\n companyCandidates.push(url.searchParams.getAll('companyEntityId'))\n }\n const selectedPersonIds = normalizeUuidList(personCandidates)\n const selectedCompanyIds = normalizeUuidList(companyCandidates)\n if ((selectedPersonIds.length > 0 || selectedCompanyIds.length > 0) && ctx) {\n const tenantId = ctx.auth?.tenantId\n // `ctx.auth` exposes `orgId` (see AuthContext in @open-mercato/shared/lib/auth/server).\n // Read it under the correct key \u2014 the previous code's `organizationId` would always be\n // `undefined`, silently disabling association filtering on the deals list endpoint.\n const organizationId = ctx.auth?.orgId\n if (typeof tenantId === 'string' && typeof organizationId === 'string') {\n const em = ctx.container.resolve<EntityManager>('em')\n const matchedIds = await fetchDealIdsMatchingAssociations(\n em,\n organizationId,\n tenantId,\n selectedPersonIds,\n selectedCompanyIds,\n )\n // intersectIds with empty array \u2192 no rows; collapses the page to zero, total stays correct.\n intersectIds(matchedIds)\n }\n }\n\n if (ctx && advancedFilterTree) {\n const advancedFilters = mergeAdvancedFilterTree({ ...filters }, advancedFilterTree)\n const matchedIds = await findMatchingEntityIdsWithQueryEngine({\n ctx,\n entityId: E.customers.customer_deal,\n filters: advancedFilters,\n })\n if (matchedIds !== null) {\n intersectIds(matchedIds)\n }\n }\n\n if (restrictedIds !== null) {\n applyEntityIdRestriction(filters, restrictedIds)\n }\n\n return filters\n}\n\nconst crud = makeCrudRoute<unknown, unknown, DealListQuery>({\n metadata: routeMetadata,\n orm: {\n entity: CustomerDeal,\n idField: 'id',\n orgField: 'organizationId',\n tenantField: 'tenantId',\n softDeleteField: 'deletedAt',\n },\n indexer: {\n entityType: E.customers.customer_deal,\n },\n enrichers: { entityId: 'customers.deal' },\n list: {\n schema: dealListQuerySchema,\n entityId: E.customers.customer_deal,\n fields: [\n 'id',\n 'title',\n 'description',\n 'status',\n 'pipeline_stage',\n 'pipeline_id',\n 'pipeline_stage_id',\n 'value_amount',\n 'value_currency',\n 'probability',\n 'expected_close_at',\n 'owner_user_id',\n 'source',\n 'closure_outcome',\n 'loss_reason_id',\n 'loss_notes',\n 'organization_id',\n 'tenant_id',\n 'created_at',\n 'updated_at',\n ],\n decorateCustomFields: {\n entityIds: E.customers.customer_deal,\n },\n sortFieldMap: {\n createdAt: 'created_at',\n updatedAt: 'updated_at',\n title: 'title',\n value: 'value_amount',\n probability: 'probability',\n expectedCloseAt: 'expected_close_at',\n },\n buildFilters: buildDealListFilters,\n },\n actions: {\n create: {\n commandId: 'customers.deals.create',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n return parseScopedCommandInput(dealCreateSchema, raw ?? {}, ctx, translate)\n },\n response: ({ result }) => ({ id: result?.dealId ?? result?.id ?? null }),\n status: 201,\n },\n update: {\n commandId: 'customers.deals.update',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n return parseScopedCommandInput(dealUpdateSchema, raw ?? {}, ctx, translate)\n },\n response: () => ({ ok: true }),\n },\n delete: {\n commandId: 'customers.deals.delete',\n schema: rawBodySchema,\n mapInput: async ({ parsed, ctx }) => {\n const { translate } = await resolveTranslations()\n const id =\n parsed?.body?.id ??\n parsed?.id ??\n parsed?.query?.id ??\n (ctx.request ? new URL(ctx.request.url).searchParams.get('id') : null)\n if (!id) throw new CrudHttpError(400, { error: translate('customers.errors.deal_required', 'Deal id is required') })\n return { id }\n },\n response: () => ({ ok: true }),\n },\n },\n hooks: {\n // afterList only DECORATES results with `people`/`companies` arrays \u2014 it must not filter,\n // because filtering after pagination would drop deals on later pages and rewrite `total`\n // to a misleading value. Association filtering happens pre-pagination in `buildFilters`\n // via `fetchDealIdsMatchingAssociations`.\n afterList: async (payload, ctx) => {\n const items = Array.isArray(payload.items) ? payload.items : []\n if (!items.length) return\n const scopeSource = (items[0] ?? {}) as Record<string, unknown>\n const tenantIdRaw = scopeSource.tenantId ?? scopeSource.tenant_id\n const fallbackTenantId = (typeof tenantIdRaw === 'string' && tenantIdRaw.trim().length ? tenantIdRaw : null) ?? ctx.auth?.tenantId ?? null\n const orgIdRaw = scopeSource.organizationId ?? scopeSource.organization_id\n const fallbackOrganizationId = (typeof orgIdRaw === 'string' && orgIdRaw.trim().length ? orgIdRaw : null) ?? ctx.auth?.orgId ?? null\n const ids = items\n .map((item: unknown) => {\n if (!item || typeof item !== 'object') return null\n const candidate = (item as Record<string, unknown>).id\n return typeof candidate === 'string' && candidate.trim().length ? candidate : null\n })\n .filter((value: string | null): value is string => typeof value === 'string' && value.length > 0)\n if (!ids.length) {\n payload.items = []\n payload.total = 0\n return\n }\n try {\n const em = (ctx.container.resolve('em') as EntityManager)\n const [allPersonLinks, allCompanyLinks] = await Promise.all([\n findWithDecryption(\n em,\n CustomerDealPersonLink,\n { deal: { $in: ids } },\n { populate: ['person'] },\n { tenantId: fallbackTenantId, organizationId: fallbackOrganizationId },\n ),\n findWithDecryption(\n em,\n CustomerDealCompanyLink,\n { deal: { $in: ids } },\n { populate: ['company'] },\n { tenantId: fallbackTenantId, organizationId: fallbackOrganizationId },\n ),\n ])\n\n const personAssignments = new Map<string, { id: string; label: string }[]>()\n allPersonLinks.forEach((link) => {\n const deal = link.deal\n const dealRecord = deal && typeof deal === 'object' ? deal as unknown as Record<string, unknown> : null\n const dealId = typeof deal === 'string' ? deal\n : dealRecord && typeof dealRecord.id === 'string' ? dealRecord.id\n : null\n if (!dealId) return\n const personRef = link.person\n const personRecord = personRef && typeof personRef === 'object' ? personRef as unknown as Record<string, unknown> : null\n const personId = typeof personRef === 'string' ? personRef\n : personRecord && typeof personRecord.id === 'string' ? personRecord.id\n : null\n if (!personId) return\n const label = personRecord && typeof personRecord.displayName === 'string'\n ? personRecord.displayName\n : ''\n const bucket = personAssignments.get(dealId) ?? []\n if (!bucket.some((entry) => entry.id === personId)) {\n bucket.push({ id: personId, label })\n personAssignments.set(dealId, bucket)\n }\n })\n\n const companyAssignments = new Map<string, { id: string; label: string }[]>()\n allCompanyLinks.forEach((link) => {\n const deal = link.deal\n const dealRecord = deal && typeof deal === 'object' ? deal as unknown as Record<string, unknown> : null\n const dealId = typeof deal === 'string' ? deal\n : dealRecord && typeof dealRecord.id === 'string' ? dealRecord.id\n : null\n if (!dealId) return\n const companyRef = link.company\n const companyRecord = companyRef && typeof companyRef === 'object' ? companyRef as unknown as Record<string, unknown> : null\n const companyId = typeof companyRef === 'string' ? companyRef\n : companyRecord && typeof companyRecord.id === 'string' ? companyRecord.id\n : null\n if (!companyId) return\n const label = companyRecord && typeof companyRecord.displayName === 'string'\n ? companyRecord.displayName\n : ''\n const bucket = companyAssignments.get(dealId) ?? []\n if (!bucket.some((entry) => entry.id === companyId)) {\n bucket.push({ id: companyId, label })\n companyAssignments.set(dealId, bucket)\n }\n })\n\n const enhancedItems = items\n .map((item: unknown) => {\n if (!item || typeof item !== 'object') return null\n const data = item as Record<string, unknown>\n const candidate = typeof data.id === 'string' ? data.id : null\n if (!candidate || !candidate.trim().length) return null\n const people = personAssignments.get(candidate) ?? []\n const companies = companyAssignments.get(candidate) ?? []\n const tenantIdRaw =\n typeof data.tenantId === 'string'\n ? data.tenantId\n : typeof data.tenant_id === 'string'\n ? data.tenant_id\n : null\n const organizationIdRaw =\n typeof data.organizationId === 'string'\n ? data.organizationId\n : typeof data.organization_id === 'string'\n ? data.organization_id\n : null\n const tenantId = tenantIdRaw && tenantIdRaw.trim().length ? tenantIdRaw.trim() : null\n const organizationId = organizationIdRaw && organizationIdRaw.trim().length ? organizationIdRaw.trim() : null\n return {\n ...data,\n personIds: people.map((entry) => entry.id),\n people,\n companyIds: companies.map((entry) => entry.id),\n companies,\n tenantId,\n organizationId,\n }\n })\n .filter(\n (item: Record<string, unknown> | null): item is Record<string, unknown> => item !== null,\n )\n\n payload.items = enhancedItems\n } catch (err) {\n // We swallow rather than fail the request because the kanban is still useful without\n // people/companies labels (cards just lose their company pill). Tag every item with\n // `_associations: { ok: false }` so a future surface can render a degraded-state hint\n // instead of silently showing cards without company badges.\n console.warn('[customers.deals] failed to decorate items with person/company links', err)\n payload.items = items.map((item: unknown) => {\n if (!item || typeof item !== 'object') return item\n return {\n ...(item as Record<string, unknown>),\n _associations: {\n ok: false,\n reason: err instanceof Error ? err.message : 'unknown',\n },\n }\n })\n }\n },\n },\n})\n\nconst { POST, PUT, DELETE } = crud\n\nexport { POST, PUT, DELETE }\nexport const GET = crud.GET\n\nconst dealAssociationSchema = z.object({\n id: z.string().uuid(),\n label: z.string().nullable(),\n})\n\nconst dealListItemSchema = z\n .object({\n id: z.string().uuid(),\n title: z.string().nullable(),\n description: z.string().nullable().optional(),\n status: z.string().nullable().optional(),\n pipeline_stage: z.string().nullable().optional(),\n pipeline_id: z.string().uuid().nullable().optional(),\n pipeline_stage_id: z.string().uuid().nullable().optional(),\n value_amount: z.number().nullable().optional(),\n value_currency: z.string().nullable().optional(),\n probability: z.number().nullable().optional(),\n expected_close_at: z.string().nullable().optional(),\n owner_user_id: z.string().uuid().nullable().optional(),\n source: z.string().nullable().optional(),\n organization_id: z.string().uuid().nullable().optional(),\n tenant_id: z.string().uuid().nullable().optional(),\n created_at: z.string().nullable().optional(),\n updated_at: z.string().nullable().optional(),\n personIds: z.array(z.string().uuid()).optional(),\n people: z.array(dealAssociationSchema).optional(),\n companyIds: z.array(z.string().uuid()).optional(),\n companies: z.array(dealAssociationSchema).optional(),\n organizationId: z.string().uuid().nullable().optional(),\n tenantId: z.string().uuid().nullable().optional(),\n })\n .passthrough()\n\nconst dealCreateResponseSchema = z.object({\n id: z.string().uuid().nullable(),\n})\n\nexport const openApi = createCustomersCrudOpenApi({\n resourceName: 'Deal',\n querySchema: dealListQuerySchema,\n listResponseSchema: createPagedListResponseSchema(dealListItemSchema),\n create: {\n schema: dealCreateSchema,\n responseSchema: dealCreateResponseSchema,\n description: 'Creates a sales deal, optionally associating people and companies.',\n },\n update: {\n schema: dealUpdateSchema,\n responseSchema: defaultOkResponseSchema,\n description: 'Updates pipeline position, metadata, or associations for an existing deal.',\n },\n del: {\n schema: z.object({ id: z.string().uuid() }),\n responseSchema: defaultOkResponseSchema,\n description: 'Deletes a deal by `id`. The identifier may be provided in the body or query parameters.',\n },\n})\n"],
5
+ "mappings": "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",
6
6
  "names": ["parsed", "tenantIdRaw"]
7
7
  }
@@ -96,7 +96,8 @@ const crud = makeCrudRoute({
96
96
  "organization_id",
97
97
  "tenant_id",
98
98
  "kind",
99
- "created_at"
99
+ "created_at",
100
+ "updated_at"
100
101
  ],
101
102
  sortFieldMap: {
102
103
  name: "display_name",
@@ -381,7 +382,15 @@ const crud = makeCrudRoute({
381
382
  const parsed = personUpdateSchema.parse(base);
382
383
  return Object.keys(custom).length ? { ...parsed, customFields: custom } : parsed;
383
384
  },
384
- response: () => ({ ok: true })
385
+ // Return the freshly-bumped updatedAt so inline-edit detail pages can refresh
386
+ // their optimistic-lock token between sequential saves (#2055).
387
+ response: (arg) => {
388
+ const raw = arg?.updatedAt ?? arg?.result?.updatedAt ?? null;
389
+ return {
390
+ ok: true,
391
+ updatedAt: raw instanceof Date ? raw.toISOString() : typeof raw === "string" ? raw : null
392
+ };
393
+ }
385
394
  },
386
395
  delete: {
387
396
  commandId: "customers.people.delete",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/customers/api/people/route.ts"],
4
- "sourcesContent": ["import type { EntityManager, FilterQuery } from '@mikro-orm/postgresql'\nimport { z } from 'zod'\nimport { makeCrudRoute } from '@open-mercato/shared/lib/crud/factory'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport {\n CustomerDealPersonLink,\n CustomerEntity,\n CustomerPersonCompanyLink,\n CustomerPersonProfile,\n} from '../../data/entities'\nimport { E } from '#generated/entities.ids.generated'\nimport { personCreateSchema, personUpdateSchema } from '../../data/validators'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport {\n applyEntityIdExclusion,\n applyEntityIdRestriction,\n findMatchingEntityIdsWithQueryEngine,\n findMatchingEntityIdsBySearchTokensAcrossSources,\n withScopedPayload,\n} from '../utils'\nimport { buildCustomFieldFiltersFromQuery, extractAllCustomFieldEntries, splitCustomFieldPayload } from '@open-mercato/shared/lib/crud/custom-fields'\nimport { escapeLikePattern } from '@open-mercato/shared/lib/db/escapeLikePattern'\nimport { parseBooleanToken } from '@open-mercato/shared/lib/boolean'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { consumeAdvancedFilterState, mergeAdvancedFilterTree } from '@open-mercato/shared/lib/crud/advanced-filter-integration'\nimport {\n createCustomersCrudOpenApi,\n createPagedListResponseSchema,\n defaultOkResponseSchema,\n} from '../openapi'\nimport {\n filterActivePersonCompanyLinks,\n withActiveCustomerPersonCompanyLinkFilter,\n} from '../../lib/personCompanyLinkTable'\nimport { normalizeProfilePayload } from './payload'\n\nconst rawBodySchema = z.object({}).passthrough()\n\nconst listSchema = z\n .object({\n page: z.coerce.number().min(1).default(1),\n pageSize: z.coerce.number().min(1).max(100).default(50),\n search: z.string().optional(),\n email: z.string().optional(),\n emailStartsWith: z.string().optional(),\n emailContains: z.string().optional(),\n status: z.string().optional(),\n lifecycleStage: z.string().optional(),\n source: z.string().optional(),\n hasEmail: z.string().optional(),\n hasPhone: z.string().optional(),\n hasNextInteraction: z.string().optional(),\n createdFrom: z.string().optional(),\n createdTo: z.string().optional(),\n sortField: z.string().optional(),\n sortDir: z.enum(['asc', 'desc']).optional(),\n id: z.string().uuid().optional(),\n tagIds: z.string().optional(),\n tagIdsEmpty: z.string().optional(),\n excludeIds: z.string().optional(),\n excludeLinkedCompanyId: z.string().uuid().optional(),\n excludeLinkedDealId: z.string().uuid().optional(),\n })\n .passthrough()\n\nconst routeMetadata = {\n GET: { requireAuth: true, requireFeatures: ['customers.people.view'] },\n POST: { requireAuth: true, requireFeatures: ['customers.people.manage'] },\n PUT: { requireAuth: true, requireFeatures: ['customers.people.manage'] },\n DELETE: { requireAuth: true, requireFeatures: ['customers.people.manage'] },\n}\n\nexport const metadata = routeMetadata\n\nconst crud = makeCrudRoute({\n metadata: routeMetadata,\n orm: {\n entity: CustomerEntity,\n idField: 'id',\n orgField: 'organizationId',\n tenantField: 'tenantId',\n softDeleteField: 'deletedAt',\n },\n enrichers: { entityId: 'customers.person' },\n indexer: { entityType: E.customers.customer_entity },\n list: {\n schema: listSchema,\n entityId: E.customers.customer_entity,\n fields: [\n 'id',\n 'display_name',\n 'description',\n 'owner_user_id',\n 'primary_email',\n 'primary_phone',\n 'status',\n 'lifecycle_stage',\n 'source',\n 'next_interaction_at',\n 'next_interaction_name',\n 'next_interaction_ref_id',\n 'next_interaction_icon',\n 'next_interaction_color',\n 'organization_id',\n 'tenant_id',\n 'kind',\n 'created_at',\n ],\n sortFieldMap: {\n name: 'display_name',\n email: 'primary_email',\n primaryEmail: 'primary_email',\n status: 'status',\n lifecycleStage: 'lifecycle_stage',\n source: 'source',\n nextInteractionAt: 'next_interaction_at',\n createdAt: 'created_at',\n updatedAt: 'updated_at',\n },\n buildFilters: async (query, ctx) => {\n const advancedFilterTree = consumeAdvancedFilterState(query)\n const filters: Record<string, unknown> = { kind: { $eq: 'person' } }\n if (query.id) filters.id = { $eq: query.id }\n if (query.search) {\n const matchingIds = ctx\n ? await findMatchingEntityIdsBySearchTokensAcrossSources({\n ctx,\n query: query.search,\n sources: [\n {\n entityType: E.customers.customer_entity,\n fields: [\n 'display_name',\n 'primary_email',\n 'primary_phone',\n 'description',\n 'status',\n 'lifecycle_stage',\n 'source',\n 'next_interaction_name',\n ],\n },\n {\n entityType: E.customers.customer_person_profile,\n fields: [\n 'display_name',\n 'primary_email',\n 'primary_phone',\n 'status',\n 'lifecycle_stage',\n 'source',\n 'first_name',\n 'last_name',\n 'preferred_name',\n 'job_title',\n 'department',\n 'seniority',\n 'timezone',\n 'linked_in_url',\n 'twitter_url',\n ],\n mapToEntityIds: {\n table: 'customer_people',\n targetColumn: 'entity_id',\n },\n },\n ],\n })\n : null\n if (matchingIds !== null && matchingIds.length > 0) {\n applyEntityIdRestriction(filters, matchingIds)\n } else {\n const searchPattern = `%${escapeLikePattern(query.search)}%`\n filters.$or = [\n { display_name: { $ilike: searchPattern } },\n { primary_email: { $ilike: searchPattern } },\n { primary_phone: { $ilike: searchPattern } },\n { description: { $ilike: searchPattern } },\n { next_interaction_name: { $ilike: searchPattern } },\n ]\n }\n }\n const email = typeof query.email === 'string' ? query.email.trim().toLowerCase() : ''\n const emailStartsWith = typeof query.emailStartsWith === 'string' ? query.emailStartsWith.trim().toLowerCase() : ''\n const emailContains = typeof query.emailContains === 'string' ? query.emailContains.trim().toLowerCase() : ''\n if (email) {\n filters.primary_email = { $eq: email }\n } else if (emailStartsWith) {\n filters.primary_email = { $ilike: `${escapeLikePattern(emailStartsWith)}%` }\n } else if (emailContains) {\n filters.primary_email = { $ilike: `%${escapeLikePattern(emailContains)}%` }\n }\n if (query.status) {\n filters.status = { $eq: query.status }\n }\n if (query.lifecycleStage) {\n filters.lifecycle_stage = { $eq: query.lifecycleStage }\n }\n if (query.source) {\n filters.source = { $eq: query.source }\n }\n const tagIdsRaw = typeof query.tagIds === 'string' ? query.tagIds : ''\n const tagIds = tagIdsRaw\n .split(',')\n .map((value: string) => value.trim())\n .filter((value: string) => value.length > 0)\n const tagIdsEmpty = parseBooleanToken(query.tagIdsEmpty) === true\n if (tagIdsEmpty) {\n filters.id = { $eq: '00000000-0000-0000-0000-000000000000' }\n } else if (tagIds.length > 0) {\n filters['tag_assignments.tag_id'] = { $in: tagIds }\n }\n const excludedIds = new Set<string>()\n const excludeIdsRaw = typeof query.excludeIds === 'string' ? query.excludeIds : ''\n excludeIdsRaw\n .split(',')\n .map((value: string) => value.trim())\n .filter((value: string) => value.length > 0)\n .forEach((value: string) => excludedIds.add(value))\n if (ctx && query.excludeLinkedCompanyId) {\n try {\n const em = ctx.container.resolve('em') as EntityManager\n const decryptionScope = {\n tenantId: ctx.auth?.tenantId ?? null,\n organizationId: ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null,\n }\n const linkWhere = await withActiveCustomerPersonCompanyLinkFilter(\n em,\n { company: query.excludeLinkedCompanyId },\n 'customers.people.GET',\n )\n const links = filterActivePersonCompanyLinks(\n await findWithDecryption(\n em,\n CustomerPersonCompanyLink,\n linkWhere,\n { populate: ['person'] },\n decryptionScope,\n ),\n )\n links.forEach((link) => {\n const personId = link.person?.id\n if (typeof personId === 'string' && personId.length > 0) excludedIds.add(personId)\n })\n } catch (err) {\n console.warn('[customers.people.list] exclusion lookup failed; falling back to base result set', err)\n }\n }\n if (ctx && query.excludeLinkedDealId) {\n try {\n const em = ctx.container.resolve('em') as EntityManager\n const decryptionScope = {\n tenantId: ctx.auth?.tenantId ?? null,\n organizationId: ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null,\n }\n const links = await findWithDecryption(\n em,\n CustomerDealPersonLink,\n {\n deal: query.excludeLinkedDealId,\n },\n { populate: ['person'] },\n decryptionScope,\n )\n links.forEach((link) => {\n const personId = link.person?.id\n if (typeof personId === 'string' && personId.length > 0) excludedIds.add(personId)\n })\n } catch (err) {\n console.warn('[customers.people.list] exclusion lookup failed; falling back to base result set', err)\n }\n }\n applyEntityIdExclusion(filters, Array.from(excludedIds))\n const hasEmail = parseBooleanToken(query.hasEmail)\n if (!email && !emailStartsWith && !emailContains && hasEmail !== null) {\n filters.primary_email = { $exists: hasEmail }\n }\n const hasPhone = parseBooleanToken(query.hasPhone)\n if (hasPhone !== null) {\n filters.primary_phone = { $exists: hasPhone }\n }\n const hasNextInteraction = parseBooleanToken(query.hasNextInteraction)\n if (hasNextInteraction !== null) {\n filters.next_interaction_at = { $exists: hasNextInteraction }\n }\n const createdRange: Record<string, Date> = {}\n if (query.createdFrom) {\n const from = new Date(query.createdFrom)\n if (!Number.isNaN(from.getTime())) createdRange.$gte = from\n }\n if (query.createdTo) {\n const to = new Date(query.createdTo)\n if (!Number.isNaN(to.getTime())) createdRange.$lte = to\n }\n if (Object.keys(createdRange).length) {\n filters.created_at = createdRange\n }\n if (ctx) {\n try {\n const em = ctx.container.resolve('em') as EntityManager\n const cfFilters = await buildCustomFieldFiltersFromQuery({\n entityIds: [E.customers.customer_entity, E.customers.customer_person_profile],\n query,\n em,\n tenantId: ctx.auth?.tenantId ?? null,\n })\n Object.assign(filters, cfFilters)\n } catch (err) {\n console.warn('[customers.people.list] custom field filter resolution failed; falling back to base filters', err)\n }\n }\n if (ctx && advancedFilterTree) {\n const advancedFilters = mergeAdvancedFilterTree({ ...filters }, advancedFilterTree)\n const matchedIds = await findMatchingEntityIdsWithQueryEngine({\n ctx,\n entityId: E.customers.customer_entity,\n filters: advancedFilters,\n customFieldSources: [\n {\n entityId: E.customers.customer_person_profile,\n table: 'customer_people',\n alias: 'person_profile',\n recordIdColumn: 'id',\n join: { fromField: 'id', toField: 'entity_id' },\n },\n ],\n joins: [\n {\n alias: 'tag_assignments',\n table: 'customer_tag_assignments',\n from: { field: 'id' },\n to: { field: 'entity_id' },\n type: 'left',\n },\n ],\n })\n applyEntityIdRestriction(filters, matchedIds)\n }\n return filters\n },\n customFieldSources: [\n {\n entityId: E.customers.customer_person_profile,\n table: 'customer_people',\n alias: 'person_profile',\n recordIdColumn: 'id',\n join: { fromField: 'id', toField: 'entity_id' },\n },\n ],\n joins: [\n {\n alias: 'tag_assignments',\n table: 'customer_tag_assignments',\n from: { field: 'id' },\n to: { field: 'entity_id' },\n type: 'left',\n },\n ],\n transformItem: (item) => {\n if (!item || typeof item !== 'object') return item\n const record = item as Record<string, unknown>\n const normalized: Record<string, unknown> = { ...record }\n delete normalized.kind\n const cfEntries = extractAllCustomFieldEntries(record)\n for (const key of Object.keys(normalized)) {\n if (key.startsWith('cf:')) {\n delete normalized[key]\n }\n }\n return { ...normalized, ...cfEntries }\n },\n },\n actions: {\n create: {\n commandId: 'customers.people.create',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n const scoped = withScopedPayload(raw ?? {}, ctx, translate)\n const { base, custom } = splitCustomFieldPayload(scoped)\n const parsed = personCreateSchema.parse(base)\n return Object.keys(custom).length ? { ...parsed, customFields: custom } : parsed\n },\n response: ({ result }) => ({\n id: result?.entityId ?? result?.id ?? null,\n personId: result?.personId ?? null,\n }),\n status: 201,\n },\n update: {\n commandId: 'customers.people.update',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n const scoped = withScopedPayload(raw ?? {}, ctx, translate)\n const normalized = normalizeProfilePayload(scoped, translate)\n const { base, custom } = splitCustomFieldPayload(normalized)\n const parsed = personUpdateSchema.parse(base)\n return Object.keys(custom).length ? { ...parsed, customFields: custom } : parsed\n },\n response: () => ({ ok: true }),\n },\n delete: {\n commandId: 'customers.people.delete',\n schema: rawBodySchema,\n mapInput: async ({ parsed, ctx }) => {\n const { translate } = await resolveTranslations()\n const id =\n parsed?.body?.id ??\n parsed?.id ??\n parsed?.query?.id ??\n (ctx.request ? new URL(ctx.request.url).searchParams.get('id') : null)\n if (!id) throw new CrudHttpError(400, { error: translate('customers.errors.person_required', 'Person id is required') })\n return { id }\n },\n response: () => ({ ok: true }),\n },\n },\n hooks: {\n afterList: async (payload, ctx) => {\n const items = Array.isArray(payload?.items) ? payload.items : []\n const ids = items\n .map((item: unknown) => (\n item && typeof item === 'object' && typeof (item as Record<string, unknown>).id === 'string'\n ? (item as Record<string, unknown>).id as string\n : null\n ))\n .filter((id: string | null): id is string => typeof id === 'string' && id.length > 0)\n if (!ids.length) return\n\n const em = ctx.container.resolve('em') as EntityManager\n const decryptionScope = {\n tenantId: ctx.auth?.tenantId ?? null,\n organizationId: ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null,\n }\n const profileWhere: Record<string, unknown> = {\n entity: { $in: ids },\n tenantId: ctx.auth?.tenantId ?? null,\n }\n if (ctx.selectedOrganizationId) {\n profileWhere.organizationId = ctx.selectedOrganizationId\n }\n\n const [entities, profiles] = await Promise.all([\n findWithDecryption(\n em,\n CustomerEntity,\n {\n id: { $in: ids },\n deletedAt: null,\n kind: 'person',\n } as FilterQuery<CustomerEntity>,\n undefined,\n decryptionScope,\n ),\n findWithDecryption(\n em,\n CustomerPersonProfile,\n profileWhere as FilterQuery<CustomerPersonProfile>,\n { populate: ['entity', 'company'] },\n decryptionScope,\n ),\n ])\n\n const entitiesById = new Map<string, CustomerEntity>()\n for (const entity of entities) {\n entitiesById.set(entity.id, entity)\n }\n\n const profilesByEntityId = new Map<string, CustomerPersonProfile>()\n for (const profile of profiles) {\n const profileEntity = (profile as { entity?: { id?: unknown } }).entity\n const entityId = typeof profileEntity?.id === 'string' ? profileEntity.id : null\n if (entityId) profilesByEntityId.set(entityId, profile)\n }\n\n payload.items = items.map((item: unknown) => {\n if (!item || typeof item !== 'object') return item\n const record = item as Record<string, unknown>\n const entity = typeof record.id === 'string' ? entitiesById.get(record.id) : undefined\n const profile = typeof record.id === 'string' ? profilesByEntityId.get(record.id) : undefined\n if (!entity && !profile) return item\n return {\n ...record,\n display_name: entity?.displayName ?? record.display_name ?? null,\n description: entity?.description ?? record.description ?? null,\n owner_user_id: entity?.ownerUserId ?? record.owner_user_id ?? null,\n primary_email: entity?.primaryEmail ?? record.primary_email ?? null,\n primary_phone: entity?.primaryPhone ?? record.primary_phone ?? null,\n status: entity?.status ?? record.status ?? null,\n lifecycle_stage: entity?.lifecycleStage ?? record.lifecycle_stage ?? null,\n source: entity?.source ?? record.source ?? null,\n next_interaction_at: entity?.nextInteractionAt ? entity.nextInteractionAt.toISOString() : record.next_interaction_at ?? null,\n next_interaction_name: entity?.nextInteractionName ?? record.next_interaction_name ?? null,\n next_interaction_ref_id: entity?.nextInteractionRefId ?? record.next_interaction_ref_id ?? null,\n next_interaction_icon: entity?.nextInteractionIcon ?? record.next_interaction_icon ?? null,\n next_interaction_color: entity?.nextInteractionColor ?? record.next_interaction_color ?? null,\n first_name: profile?.firstName ?? null,\n last_name: profile?.lastName ?? null,\n preferred_name: profile?.preferredName ?? null,\n job_title: profile?.jobTitle ?? null,\n department: profile?.department ?? null,\n seniority: profile?.seniority ?? null,\n timezone: profile?.timezone ?? null,\n linked_in_url: profile?.linkedInUrl ?? null,\n twitter_url: profile?.twitterUrl ?? null,\n company_entity_id:\n profile?.company && typeof profile.company === 'object'\n ? profile.company.id\n : profile?.company ?? null,\n }\n })\n },\n },\n})\n\nconst { POST, PUT, DELETE } = crud\n\nexport { POST, PUT, DELETE }\nexport const GET = crud.GET\n\nconst personListItemSchema = z.object({\n id: z.string().uuid(),\n display_name: z.string().optional(),\n description: z.string().nullable().optional(),\n owner_user_id: z.string().uuid().nullable().optional(),\n primary_email: z.string().nullable().optional(),\n primary_phone: z.string().nullable().optional(),\n status: z.string().nullable().optional(),\n lifecycle_stage: z.string().nullable().optional(),\n source: z.string().nullable().optional(),\n next_interaction_at: z.string().nullable().optional(),\n next_interaction_name: z.string().nullable().optional(),\n next_interaction_ref_id: z.string().nullable().optional(),\n next_interaction_icon: z.string().nullable().optional(),\n next_interaction_color: z.string().nullable().optional(),\n organization_id: z.string().uuid().nullable().optional(),\n tenant_id: z.string().uuid().nullable().optional(),\n created_at: z.string().nullable().optional(),\n})\n\nconst personCreateResponseSchema = z.object({\n id: z.string().uuid().nullable(),\n personId: z.string().uuid().nullable(),\n})\n\nexport const openApi = createCustomersCrudOpenApi({\n resourceName: 'Person',\n pluralName: 'People',\n querySchema: listSchema,\n listResponseSchema: createPagedListResponseSchema(personListItemSchema),\n create: {\n schema: personCreateSchema,\n responseSchema: personCreateResponseSchema,\n description: 'Creates a person contact using scoped organization and tenant identifiers.',\n },\n update: {\n schema: personUpdateSchema,\n responseSchema: defaultOkResponseSchema,\n description: 'Updates contact details or custom fields for a person.',\n },\n del: {\n schema: z.object({ id: z.string().uuid() }),\n responseSchema: defaultOkResponseSchema,\n description: 'Deletes a person by id. Request body or query may provide the identifier.',\n errors: [\n {\n status: 422,\n description: 'Person has dependent records (e.g. linked deals); unlink or reassign before delete.',\n schema: z.object({\n error: z.string(),\n code: z.literal('PERSON_HAS_DEPENDENTS'),\n }),\n },\n ],\n },\n})\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { EntityManager, FilterQuery } from '@mikro-orm/postgresql'\nimport { z } from 'zod'\nimport { makeCrudRoute } from '@open-mercato/shared/lib/crud/factory'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport {\n CustomerDealPersonLink,\n CustomerEntity,\n CustomerPersonCompanyLink,\n CustomerPersonProfile,\n} from '../../data/entities'\nimport { E } from '#generated/entities.ids.generated'\nimport { personCreateSchema, personUpdateSchema } from '../../data/validators'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport {\n applyEntityIdExclusion,\n applyEntityIdRestriction,\n findMatchingEntityIdsWithQueryEngine,\n findMatchingEntityIdsBySearchTokensAcrossSources,\n withScopedPayload,\n} from '../utils'\nimport { buildCustomFieldFiltersFromQuery, extractAllCustomFieldEntries, splitCustomFieldPayload } from '@open-mercato/shared/lib/crud/custom-fields'\nimport { escapeLikePattern } from '@open-mercato/shared/lib/db/escapeLikePattern'\nimport { parseBooleanToken } from '@open-mercato/shared/lib/boolean'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { consumeAdvancedFilterState, mergeAdvancedFilterTree } from '@open-mercato/shared/lib/crud/advanced-filter-integration'\nimport {\n createCustomersCrudOpenApi,\n createPagedListResponseSchema,\n defaultOkResponseSchema,\n} from '../openapi'\nimport {\n filterActivePersonCompanyLinks,\n withActiveCustomerPersonCompanyLinkFilter,\n} from '../../lib/personCompanyLinkTable'\nimport { normalizeProfilePayload } from './payload'\n\nconst rawBodySchema = z.object({}).passthrough()\n\nconst listSchema = z\n .object({\n page: z.coerce.number().min(1).default(1),\n pageSize: z.coerce.number().min(1).max(100).default(50),\n search: z.string().optional(),\n email: z.string().optional(),\n emailStartsWith: z.string().optional(),\n emailContains: z.string().optional(),\n status: z.string().optional(),\n lifecycleStage: z.string().optional(),\n source: z.string().optional(),\n hasEmail: z.string().optional(),\n hasPhone: z.string().optional(),\n hasNextInteraction: z.string().optional(),\n createdFrom: z.string().optional(),\n createdTo: z.string().optional(),\n sortField: z.string().optional(),\n sortDir: z.enum(['asc', 'desc']).optional(),\n id: z.string().uuid().optional(),\n tagIds: z.string().optional(),\n tagIdsEmpty: z.string().optional(),\n excludeIds: z.string().optional(),\n excludeLinkedCompanyId: z.string().uuid().optional(),\n excludeLinkedDealId: z.string().uuid().optional(),\n })\n .passthrough()\n\nconst routeMetadata = {\n GET: { requireAuth: true, requireFeatures: ['customers.people.view'] },\n POST: { requireAuth: true, requireFeatures: ['customers.people.manage'] },\n PUT: { requireAuth: true, requireFeatures: ['customers.people.manage'] },\n DELETE: { requireAuth: true, requireFeatures: ['customers.people.manage'] },\n}\n\nexport const metadata = routeMetadata\n\nconst crud = makeCrudRoute({\n metadata: routeMetadata,\n orm: {\n entity: CustomerEntity,\n idField: 'id',\n orgField: 'organizationId',\n tenantField: 'tenantId',\n softDeleteField: 'deletedAt',\n },\n enrichers: { entityId: 'customers.person' },\n indexer: { entityType: E.customers.customer_entity },\n list: {\n schema: listSchema,\n entityId: E.customers.customer_entity,\n fields: [\n 'id',\n 'display_name',\n 'description',\n 'owner_user_id',\n 'primary_email',\n 'primary_phone',\n 'status',\n 'lifecycle_stage',\n 'source',\n 'next_interaction_at',\n 'next_interaction_name',\n 'next_interaction_ref_id',\n 'next_interaction_icon',\n 'next_interaction_color',\n 'organization_id',\n 'tenant_id',\n 'kind',\n 'created_at',\n 'updated_at',\n ],\n sortFieldMap: {\n name: 'display_name',\n email: 'primary_email',\n primaryEmail: 'primary_email',\n status: 'status',\n lifecycleStage: 'lifecycle_stage',\n source: 'source',\n nextInteractionAt: 'next_interaction_at',\n createdAt: 'created_at',\n updatedAt: 'updated_at',\n },\n buildFilters: async (query, ctx) => {\n const advancedFilterTree = consumeAdvancedFilterState(query)\n const filters: Record<string, unknown> = { kind: { $eq: 'person' } }\n if (query.id) filters.id = { $eq: query.id }\n if (query.search) {\n const matchingIds = ctx\n ? await findMatchingEntityIdsBySearchTokensAcrossSources({\n ctx,\n query: query.search,\n sources: [\n {\n entityType: E.customers.customer_entity,\n fields: [\n 'display_name',\n 'primary_email',\n 'primary_phone',\n 'description',\n 'status',\n 'lifecycle_stage',\n 'source',\n 'next_interaction_name',\n ],\n },\n {\n entityType: E.customers.customer_person_profile,\n fields: [\n 'display_name',\n 'primary_email',\n 'primary_phone',\n 'status',\n 'lifecycle_stage',\n 'source',\n 'first_name',\n 'last_name',\n 'preferred_name',\n 'job_title',\n 'department',\n 'seniority',\n 'timezone',\n 'linked_in_url',\n 'twitter_url',\n ],\n mapToEntityIds: {\n table: 'customer_people',\n targetColumn: 'entity_id',\n },\n },\n ],\n })\n : null\n if (matchingIds !== null && matchingIds.length > 0) {\n applyEntityIdRestriction(filters, matchingIds)\n } else {\n const searchPattern = `%${escapeLikePattern(query.search)}%`\n filters.$or = [\n { display_name: { $ilike: searchPattern } },\n { primary_email: { $ilike: searchPattern } },\n { primary_phone: { $ilike: searchPattern } },\n { description: { $ilike: searchPattern } },\n { next_interaction_name: { $ilike: searchPattern } },\n ]\n }\n }\n const email = typeof query.email === 'string' ? query.email.trim().toLowerCase() : ''\n const emailStartsWith = typeof query.emailStartsWith === 'string' ? query.emailStartsWith.trim().toLowerCase() : ''\n const emailContains = typeof query.emailContains === 'string' ? query.emailContains.trim().toLowerCase() : ''\n if (email) {\n filters.primary_email = { $eq: email }\n } else if (emailStartsWith) {\n filters.primary_email = { $ilike: `${escapeLikePattern(emailStartsWith)}%` }\n } else if (emailContains) {\n filters.primary_email = { $ilike: `%${escapeLikePattern(emailContains)}%` }\n }\n if (query.status) {\n filters.status = { $eq: query.status }\n }\n if (query.lifecycleStage) {\n filters.lifecycle_stage = { $eq: query.lifecycleStage }\n }\n if (query.source) {\n filters.source = { $eq: query.source }\n }\n const tagIdsRaw = typeof query.tagIds === 'string' ? query.tagIds : ''\n const tagIds = tagIdsRaw\n .split(',')\n .map((value: string) => value.trim())\n .filter((value: string) => value.length > 0)\n const tagIdsEmpty = parseBooleanToken(query.tagIdsEmpty) === true\n if (tagIdsEmpty) {\n filters.id = { $eq: '00000000-0000-0000-0000-000000000000' }\n } else if (tagIds.length > 0) {\n filters['tag_assignments.tag_id'] = { $in: tagIds }\n }\n const excludedIds = new Set<string>()\n const excludeIdsRaw = typeof query.excludeIds === 'string' ? query.excludeIds : ''\n excludeIdsRaw\n .split(',')\n .map((value: string) => value.trim())\n .filter((value: string) => value.length > 0)\n .forEach((value: string) => excludedIds.add(value))\n if (ctx && query.excludeLinkedCompanyId) {\n try {\n const em = ctx.container.resolve('em') as EntityManager\n const decryptionScope = {\n tenantId: ctx.auth?.tenantId ?? null,\n organizationId: ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null,\n }\n const linkWhere = await withActiveCustomerPersonCompanyLinkFilter(\n em,\n { company: query.excludeLinkedCompanyId },\n 'customers.people.GET',\n )\n const links = filterActivePersonCompanyLinks(\n await findWithDecryption(\n em,\n CustomerPersonCompanyLink,\n linkWhere,\n { populate: ['person'] },\n decryptionScope,\n ),\n )\n links.forEach((link) => {\n const personId = link.person?.id\n if (typeof personId === 'string' && personId.length > 0) excludedIds.add(personId)\n })\n } catch (err) {\n console.warn('[customers.people.list] exclusion lookup failed; falling back to base result set', err)\n }\n }\n if (ctx && query.excludeLinkedDealId) {\n try {\n const em = ctx.container.resolve('em') as EntityManager\n const decryptionScope = {\n tenantId: ctx.auth?.tenantId ?? null,\n organizationId: ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null,\n }\n const links = await findWithDecryption(\n em,\n CustomerDealPersonLink,\n {\n deal: query.excludeLinkedDealId,\n },\n { populate: ['person'] },\n decryptionScope,\n )\n links.forEach((link) => {\n const personId = link.person?.id\n if (typeof personId === 'string' && personId.length > 0) excludedIds.add(personId)\n })\n } catch (err) {\n console.warn('[customers.people.list] exclusion lookup failed; falling back to base result set', err)\n }\n }\n applyEntityIdExclusion(filters, Array.from(excludedIds))\n const hasEmail = parseBooleanToken(query.hasEmail)\n if (!email && !emailStartsWith && !emailContains && hasEmail !== null) {\n filters.primary_email = { $exists: hasEmail }\n }\n const hasPhone = parseBooleanToken(query.hasPhone)\n if (hasPhone !== null) {\n filters.primary_phone = { $exists: hasPhone }\n }\n const hasNextInteraction = parseBooleanToken(query.hasNextInteraction)\n if (hasNextInteraction !== null) {\n filters.next_interaction_at = { $exists: hasNextInteraction }\n }\n const createdRange: Record<string, Date> = {}\n if (query.createdFrom) {\n const from = new Date(query.createdFrom)\n if (!Number.isNaN(from.getTime())) createdRange.$gte = from\n }\n if (query.createdTo) {\n const to = new Date(query.createdTo)\n if (!Number.isNaN(to.getTime())) createdRange.$lte = to\n }\n if (Object.keys(createdRange).length) {\n filters.created_at = createdRange\n }\n if (ctx) {\n try {\n const em = ctx.container.resolve('em') as EntityManager\n const cfFilters = await buildCustomFieldFiltersFromQuery({\n entityIds: [E.customers.customer_entity, E.customers.customer_person_profile],\n query,\n em,\n tenantId: ctx.auth?.tenantId ?? null,\n })\n Object.assign(filters, cfFilters)\n } catch (err) {\n console.warn('[customers.people.list] custom field filter resolution failed; falling back to base filters', err)\n }\n }\n if (ctx && advancedFilterTree) {\n const advancedFilters = mergeAdvancedFilterTree({ ...filters }, advancedFilterTree)\n const matchedIds = await findMatchingEntityIdsWithQueryEngine({\n ctx,\n entityId: E.customers.customer_entity,\n filters: advancedFilters,\n customFieldSources: [\n {\n entityId: E.customers.customer_person_profile,\n table: 'customer_people',\n alias: 'person_profile',\n recordIdColumn: 'id',\n join: { fromField: 'id', toField: 'entity_id' },\n },\n ],\n joins: [\n {\n alias: 'tag_assignments',\n table: 'customer_tag_assignments',\n from: { field: 'id' },\n to: { field: 'entity_id' },\n type: 'left',\n },\n ],\n })\n applyEntityIdRestriction(filters, matchedIds)\n }\n return filters\n },\n customFieldSources: [\n {\n entityId: E.customers.customer_person_profile,\n table: 'customer_people',\n alias: 'person_profile',\n recordIdColumn: 'id',\n join: { fromField: 'id', toField: 'entity_id' },\n },\n ],\n joins: [\n {\n alias: 'tag_assignments',\n table: 'customer_tag_assignments',\n from: { field: 'id' },\n to: { field: 'entity_id' },\n type: 'left',\n },\n ],\n transformItem: (item) => {\n if (!item || typeof item !== 'object') return item\n const record = item as Record<string, unknown>\n const normalized: Record<string, unknown> = { ...record }\n delete normalized.kind\n const cfEntries = extractAllCustomFieldEntries(record)\n for (const key of Object.keys(normalized)) {\n if (key.startsWith('cf:')) {\n delete normalized[key]\n }\n }\n return { ...normalized, ...cfEntries }\n },\n },\n actions: {\n create: {\n commandId: 'customers.people.create',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n const scoped = withScopedPayload(raw ?? {}, ctx, translate)\n const { base, custom } = splitCustomFieldPayload(scoped)\n const parsed = personCreateSchema.parse(base)\n return Object.keys(custom).length ? { ...parsed, customFields: custom } : parsed\n },\n response: ({ result }) => ({\n id: result?.entityId ?? result?.id ?? null,\n personId: result?.personId ?? null,\n }),\n status: 201,\n },\n update: {\n commandId: 'customers.people.update',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n const scoped = withScopedPayload(raw ?? {}, ctx, translate)\n const normalized = normalizeProfilePayload(scoped, translate)\n const { base, custom } = splitCustomFieldPayload(normalized)\n const parsed = personUpdateSchema.parse(base)\n return Object.keys(custom).length ? { ...parsed, customFields: custom } : parsed\n },\n // Return the freshly-bumped updatedAt so inline-edit detail pages can refresh\n // their optimistic-lock token between sequential saves (#2055).\n response: (arg: { result?: unknown; updatedAt?: Date | string | null }) => {\n const raw = arg?.updatedAt\n ?? (arg?.result as { updatedAt?: Date | string | null } | null | undefined)?.updatedAt\n ?? null\n return {\n ok: true,\n updatedAt: raw instanceof Date ? raw.toISOString() : (typeof raw === 'string' ? raw : null),\n }\n },\n },\n delete: {\n commandId: 'customers.people.delete',\n schema: rawBodySchema,\n mapInput: async ({ parsed, ctx }) => {\n const { translate } = await resolveTranslations()\n const id =\n parsed?.body?.id ??\n parsed?.id ??\n parsed?.query?.id ??\n (ctx.request ? new URL(ctx.request.url).searchParams.get('id') : null)\n if (!id) throw new CrudHttpError(400, { error: translate('customers.errors.person_required', 'Person id is required') })\n return { id }\n },\n response: () => ({ ok: true }),\n },\n },\n hooks: {\n afterList: async (payload, ctx) => {\n const items = Array.isArray(payload?.items) ? payload.items : []\n const ids = items\n .map((item: unknown) => (\n item && typeof item === 'object' && typeof (item as Record<string, unknown>).id === 'string'\n ? (item as Record<string, unknown>).id as string\n : null\n ))\n .filter((id: string | null): id is string => typeof id === 'string' && id.length > 0)\n if (!ids.length) return\n\n const em = ctx.container.resolve('em') as EntityManager\n const decryptionScope = {\n tenantId: ctx.auth?.tenantId ?? null,\n organizationId: ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null,\n }\n const profileWhere: Record<string, unknown> = {\n entity: { $in: ids },\n tenantId: ctx.auth?.tenantId ?? null,\n }\n if (ctx.selectedOrganizationId) {\n profileWhere.organizationId = ctx.selectedOrganizationId\n }\n\n const [entities, profiles] = await Promise.all([\n findWithDecryption(\n em,\n CustomerEntity,\n {\n id: { $in: ids },\n deletedAt: null,\n kind: 'person',\n } as FilterQuery<CustomerEntity>,\n undefined,\n decryptionScope,\n ),\n findWithDecryption(\n em,\n CustomerPersonProfile,\n profileWhere as FilterQuery<CustomerPersonProfile>,\n { populate: ['entity', 'company'] },\n decryptionScope,\n ),\n ])\n\n const entitiesById = new Map<string, CustomerEntity>()\n for (const entity of entities) {\n entitiesById.set(entity.id, entity)\n }\n\n const profilesByEntityId = new Map<string, CustomerPersonProfile>()\n for (const profile of profiles) {\n const profileEntity = (profile as { entity?: { id?: unknown } }).entity\n const entityId = typeof profileEntity?.id === 'string' ? profileEntity.id : null\n if (entityId) profilesByEntityId.set(entityId, profile)\n }\n\n payload.items = items.map((item: unknown) => {\n if (!item || typeof item !== 'object') return item\n const record = item as Record<string, unknown>\n const entity = typeof record.id === 'string' ? entitiesById.get(record.id) : undefined\n const profile = typeof record.id === 'string' ? profilesByEntityId.get(record.id) : undefined\n if (!entity && !profile) return item\n return {\n ...record,\n display_name: entity?.displayName ?? record.display_name ?? null,\n description: entity?.description ?? record.description ?? null,\n owner_user_id: entity?.ownerUserId ?? record.owner_user_id ?? null,\n primary_email: entity?.primaryEmail ?? record.primary_email ?? null,\n primary_phone: entity?.primaryPhone ?? record.primary_phone ?? null,\n status: entity?.status ?? record.status ?? null,\n lifecycle_stage: entity?.lifecycleStage ?? record.lifecycle_stage ?? null,\n source: entity?.source ?? record.source ?? null,\n next_interaction_at: entity?.nextInteractionAt ? entity.nextInteractionAt.toISOString() : record.next_interaction_at ?? null,\n next_interaction_name: entity?.nextInteractionName ?? record.next_interaction_name ?? null,\n next_interaction_ref_id: entity?.nextInteractionRefId ?? record.next_interaction_ref_id ?? null,\n next_interaction_icon: entity?.nextInteractionIcon ?? record.next_interaction_icon ?? null,\n next_interaction_color: entity?.nextInteractionColor ?? record.next_interaction_color ?? null,\n first_name: profile?.firstName ?? null,\n last_name: profile?.lastName ?? null,\n preferred_name: profile?.preferredName ?? null,\n job_title: profile?.jobTitle ?? null,\n department: profile?.department ?? null,\n seniority: profile?.seniority ?? null,\n timezone: profile?.timezone ?? null,\n linked_in_url: profile?.linkedInUrl ?? null,\n twitter_url: profile?.twitterUrl ?? null,\n company_entity_id:\n profile?.company && typeof profile.company === 'object'\n ? profile.company.id\n : profile?.company ?? null,\n }\n })\n },\n },\n})\n\nconst { POST, PUT, DELETE } = crud\n\nexport { POST, PUT, DELETE }\nexport const GET = crud.GET\n\nconst personListItemSchema = z.object({\n id: z.string().uuid(),\n display_name: z.string().optional(),\n description: z.string().nullable().optional(),\n owner_user_id: z.string().uuid().nullable().optional(),\n primary_email: z.string().nullable().optional(),\n primary_phone: z.string().nullable().optional(),\n status: z.string().nullable().optional(),\n lifecycle_stage: z.string().nullable().optional(),\n source: z.string().nullable().optional(),\n next_interaction_at: z.string().nullable().optional(),\n next_interaction_name: z.string().nullable().optional(),\n next_interaction_ref_id: z.string().nullable().optional(),\n next_interaction_icon: z.string().nullable().optional(),\n next_interaction_color: z.string().nullable().optional(),\n organization_id: z.string().uuid().nullable().optional(),\n tenant_id: z.string().uuid().nullable().optional(),\n created_at: z.string().nullable().optional(),\n})\n\nconst personCreateResponseSchema = z.object({\n id: z.string().uuid().nullable(),\n personId: z.string().uuid().nullable(),\n})\n\nexport const openApi = createCustomersCrudOpenApi({\n resourceName: 'Person',\n pluralName: 'People',\n querySchema: listSchema,\n listResponseSchema: createPagedListResponseSchema(personListItemSchema),\n create: {\n schema: personCreateSchema,\n responseSchema: personCreateResponseSchema,\n description: 'Creates a person contact using scoped organization and tenant identifiers.',\n },\n update: {\n schema: personUpdateSchema,\n responseSchema: defaultOkResponseSchema,\n description: 'Updates contact details or custom fields for a person.',\n },\n del: {\n schema: z.object({ id: z.string().uuid() }),\n responseSchema: defaultOkResponseSchema,\n description: 'Deletes a person by id. Request body or query may provide the identifier.',\n errors: [\n {\n status: 422,\n description: 'Person has dependent records (e.g. linked deals); unlink or reassign before delete.',\n schema: z.object({\n error: z.string(),\n code: z.literal('PERSON_HAS_DEPENDENTS'),\n }),\n },\n ],\n },\n})\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -490,6 +490,7 @@ const todoItemSchema = z.object({
490
490
  todoDueAt: z.string().nullable().optional(),
491
491
  todoCustomValues: z.record(z.string(), z.unknown()).nullable().optional(),
492
492
  todoOrganizationId: z.string().nullable(),
493
+ todoUpdatedAt: z.string().nullable().optional(),
493
494
  organizationId: z.string(),
494
495
  tenantId: z.string(),
495
496
  createdAt: z.string(),