@open-mercato/core 0.6.6-develop.6256.1.9fc16aedc4 → 0.6.6-develop.6286.1.d985c5c374

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 (234) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/dist/generated/entities/carrier_shipment_idempotency_key/index.js +19 -0
  3. package/dist/generated/entities/carrier_shipment_idempotency_key/index.js.map +7 -0
  4. package/dist/generated/entities.ids.generated.js +2 -1
  5. package/dist/generated/entities.ids.generated.js.map +2 -2
  6. package/dist/generated/entity-fields-registry.js +10 -0
  7. package/dist/generated/entity-fields-registry.js.map +2 -2
  8. package/dist/modules/catalog/lib/productResolution.js +45 -0
  9. package/dist/modules/catalog/lib/productResolution.js.map +7 -0
  10. package/dist/modules/communication_channels/workers/channel-import-history.js +1 -1
  11. package/dist/modules/communication_channels/workers/channel-import-history.js.map +2 -2
  12. package/dist/modules/currencies/api/fetch-configs/route.js +34 -0
  13. package/dist/modules/currencies/api/fetch-configs/route.js.map +2 -2
  14. package/dist/modules/currencies/components/CurrencyFetchingConfig.js +17 -15
  15. package/dist/modules/currencies/components/CurrencyFetchingConfig.js.map +2 -2
  16. package/dist/modules/customers/api/companies/[id]/route.js +176 -161
  17. package/dist/modules/customers/api/companies/[id]/route.js.map +2 -2
  18. package/dist/modules/customers/api/people/[id]/route.js +75 -59
  19. package/dist/modules/customers/api/people/[id]/route.js.map +2 -2
  20. package/dist/modules/customers/backend/config/customers/pipeline-stages/page.js +17 -10
  21. package/dist/modules/customers/backend/config/customers/pipeline-stages/page.js.map +2 -2
  22. package/dist/modules/customers/components/detail/ActivitiesAddNewMenu.js +6 -4
  23. package/dist/modules/customers/components/detail/ActivitiesAddNewMenu.js.map +2 -2
  24. package/dist/modules/customers/components/detail/AiActionChips.js +5 -2
  25. package/dist/modules/customers/components/detail/AiActionChips.js.map +2 -2
  26. package/dist/modules/customers/components/detail/schedule/ParticipantsField.js +19 -21
  27. package/dist/modules/customers/components/detail/schedule/ParticipantsField.js.map +2 -2
  28. package/dist/modules/data_sync/api/runs/[id]/cancel.js +1 -1
  29. package/dist/modules/data_sync/api/runs/[id]/cancel.js.map +2 -2
  30. package/dist/modules/data_sync/backend/data-sync/page.js +9 -45
  31. package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
  32. package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.js +11 -17
  33. package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.js.map +2 -2
  34. package/dist/modules/data_sync/components/IntegrationScheduleTab.js +12 -10
  35. package/dist/modules/data_sync/components/IntegrationScheduleTab.js.map +2 -2
  36. package/dist/modules/data_sync/lib/id-mapping.js +46 -1
  37. package/dist/modules/data_sync/lib/id-mapping.js.map +2 -2
  38. package/dist/modules/data_sync/lib/sync-engine.js +2 -2
  39. package/dist/modules/data_sync/lib/sync-engine.js.map +2 -2
  40. package/dist/modules/data_sync/lib/syncRunStatus.js +30 -0
  41. package/dist/modules/data_sync/lib/syncRunStatus.js.map +7 -0
  42. package/dist/modules/entities/api/records.js +6 -0
  43. package/dist/modules/entities/api/records.js.map +2 -2
  44. package/dist/modules/feature_toggles/api/global/route.js +17 -15
  45. package/dist/modules/feature_toggles/api/global/route.js.map +2 -2
  46. package/dist/modules/feature_toggles/api/openapi.js +2 -2
  47. package/dist/modules/feature_toggles/api/openapi.js.map +2 -2
  48. package/dist/modules/feature_toggles/commands/global.js +14 -0
  49. package/dist/modules/feature_toggles/commands/global.js.map +2 -2
  50. package/dist/modules/inbox_ops/backend/inbox-ops/page.js +6 -0
  51. package/dist/modules/inbox_ops/backend/inbox-ops/page.js.map +2 -2
  52. package/dist/modules/messages/api/[id]/conversation/archive/route.js +25 -7
  53. package/dist/modules/messages/api/[id]/conversation/archive/route.js.map +2 -2
  54. package/dist/modules/messages/api/[id]/conversation/read/route.js +24 -6
  55. package/dist/modules/messages/api/[id]/conversation/read/route.js.map +2 -2
  56. package/dist/modules/messages/api/[id]/route.js +13 -1
  57. package/dist/modules/messages/api/[id]/route.js.map +2 -2
  58. package/dist/modules/messages/api/openapi.js +3 -1
  59. package/dist/modules/messages/api/openapi.js.map +2 -2
  60. package/dist/modules/messages/commands/conversation.js +77 -0
  61. package/dist/modules/messages/commands/conversation.js.map +2 -2
  62. package/dist/modules/messages/components/MessageDetailPageClient.js +16 -4
  63. package/dist/modules/messages/components/MessageDetailPageClient.js.map +2 -2
  64. package/dist/modules/messages/components/message-detail/hooks/useMessageDetails.js +3 -1
  65. package/dist/modules/messages/components/message-detail/hooks/useMessageDetails.js.map +2 -2
  66. package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsActions.js +29 -4
  67. package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsActions.js.map +2 -2
  68. package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsQueries.js +10 -1
  69. package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsQueries.js.map +2 -2
  70. package/dist/modules/messages/components/message-detail/panels/MainMessageHeader.js +13 -11
  71. package/dist/modules/messages/components/message-detail/panels/MainMessageHeader.js.map +2 -2
  72. package/dist/modules/payment_gateways/api/cancel/route.js +5 -0
  73. package/dist/modules/payment_gateways/api/cancel/route.js.map +2 -2
  74. package/dist/modules/payment_gateways/api/capture/route.js +5 -0
  75. package/dist/modules/payment_gateways/api/capture/route.js.map +2 -2
  76. package/dist/modules/payment_gateways/api/refund/route.js +5 -0
  77. package/dist/modules/payment_gateways/api/refund/route.js.map +2 -2
  78. package/dist/modules/payment_gateways/lib/gateway-service.js +52 -25
  79. package/dist/modules/payment_gateways/lib/gateway-service.js.map +2 -2
  80. package/dist/modules/payment_gateways/lib/status-machine.js +13 -0
  81. package/dist/modules/payment_gateways/lib/status-machine.js.map +2 -2
  82. package/dist/modules/perspectives/api/[tableId]/route.js +8 -2
  83. package/dist/modules/perspectives/api/[tableId]/route.js.map +2 -2
  84. package/dist/modules/perspectives/data/entities.js +33 -3
  85. package/dist/modules/perspectives/data/entities.js.map +2 -2
  86. package/dist/modules/perspectives/migrations/Migration20260619120000_perspectives_live_row_uniqueness.js +63 -0
  87. package/dist/modules/perspectives/migrations/Migration20260619120000_perspectives_live_row_uniqueness.js.map +7 -0
  88. package/dist/modules/perspectives/services/perspectiveService.js +17 -0
  89. package/dist/modules/perspectives/services/perspectiveService.js.map +2 -2
  90. package/dist/modules/planner/commands/availability-weekly.js +33 -1
  91. package/dist/modules/planner/commands/availability-weekly.js.map +2 -2
  92. package/dist/modules/planner/components/AvailabilityRulesEditor.js +14 -2
  93. package/dist/modules/planner/components/AvailabilityRulesEditor.js.map +2 -2
  94. package/dist/modules/progress/api/active/route.js +1 -1
  95. package/dist/modules/progress/api/active/route.js.map +2 -2
  96. package/dist/modules/progress/lib/progressService.js.map +1 -1
  97. package/dist/modules/progress/lib/progressServiceImpl.js +33 -8
  98. package/dist/modules/progress/lib/progressServiceImpl.js.map +2 -2
  99. package/dist/modules/query_index/api/status.js +19 -24
  100. package/dist/modules/query_index/api/status.js.map +3 -3
  101. package/dist/modules/query_index/lib/coverage.js +35 -0
  102. package/dist/modules/query_index/lib/coverage.js.map +2 -2
  103. package/dist/modules/query_index/lib/engine.js +11 -6
  104. package/dist/modules/query_index/lib/engine.js.map +2 -2
  105. package/dist/modules/resources/api/resource-types.js +5 -37
  106. package/dist/modules/resources/api/resource-types.js.map +2 -2
  107. package/dist/modules/resources/api/resourceTypeCounts.js +35 -0
  108. package/dist/modules/resources/api/resourceTypeCounts.js.map +7 -0
  109. package/dist/modules/resources/backend/resources/resource-types/[id]/edit/page.js +1 -1
  110. package/dist/modules/resources/backend/resources/resource-types/[id]/edit/page.js.map +1 -1
  111. package/dist/modules/resources/backend/resources/resource-types/page.js +2 -1
  112. package/dist/modules/resources/backend/resources/resource-types/page.js.map +2 -2
  113. package/dist/modules/sales/components/documents/ReturnDialog.js +4 -1
  114. package/dist/modules/sales/components/documents/ReturnDialog.js.map +2 -2
  115. package/dist/modules/sales/components/documents/ShipmentDialog.js +17 -2
  116. package/dist/modules/sales/components/documents/ShipmentDialog.js.map +2 -2
  117. package/dist/modules/sales/di.js +4 -0
  118. package/dist/modules/sales/di.js.map +2 -2
  119. package/dist/modules/sales/services/salesOrderService.js +26 -0
  120. package/dist/modules/sales/services/salesOrderService.js.map +7 -0
  121. package/dist/modules/shipping_carriers/api/shipments/route.js +8 -0
  122. package/dist/modules/shipping_carriers/api/shipments/route.js.map +2 -2
  123. package/dist/modules/shipping_carriers/data/entities.js +38 -0
  124. package/dist/modules/shipping_carriers/data/entities.js.map +2 -2
  125. package/dist/modules/shipping_carriers/data/validators.js +2 -1
  126. package/dist/modules/shipping_carriers/data/validators.js.map +2 -2
  127. package/dist/modules/shipping_carriers/lib/shipment-idempotency.js +76 -0
  128. package/dist/modules/shipping_carriers/lib/shipment-idempotency.js.map +7 -0
  129. package/dist/modules/shipping_carriers/lib/shipment-wizard/hooks/shipmentApi.js +2 -1
  130. package/dist/modules/shipping_carriers/lib/shipment-wizard/hooks/shipmentApi.js.map +2 -2
  131. package/dist/modules/shipping_carriers/lib/shipment-wizard/hooks/useShipmentWizard.js +20 -2
  132. package/dist/modules/shipping_carriers/lib/shipment-wizard/hooks/useShipmentWizard.js.map +2 -2
  133. package/dist/modules/shipping_carriers/lib/shipping-service.js +82 -43
  134. package/dist/modules/shipping_carriers/lib/shipping-service.js.map +2 -2
  135. package/dist/modules/shipping_carriers/migrations/Migration20260618173616_shipping_carriers.js +14 -0
  136. package/dist/modules/shipping_carriers/migrations/Migration20260618173616_shipping_carriers.js.map +7 -0
  137. package/dist/modules/staff/lib/timesheets-ui/ListView.js +15 -6
  138. package/dist/modules/staff/lib/timesheets-ui/ListView.js.map +2 -2
  139. package/dist/modules/translations/components/TranslationManager.js +9 -18
  140. package/dist/modules/translations/components/TranslationManager.js.map +2 -2
  141. package/generated/entities/carrier_shipment_idempotency_key/index.ts +8 -0
  142. package/generated/entities.ids.generated.ts +2 -1
  143. package/generated/entity-fields-registry.ts +10 -0
  144. package/package.json +9 -8
  145. package/src/modules/catalog/lib/productResolution.ts +75 -0
  146. package/src/modules/communication_channels/workers/channel-import-history.ts +1 -1
  147. package/src/modules/currencies/api/fetch-configs/route.ts +36 -0
  148. package/src/modules/currencies/components/CurrencyFetchingConfig.tsx +20 -17
  149. package/src/modules/currencies/i18n/de.json +2 -1
  150. package/src/modules/currencies/i18n/en.json +2 -1
  151. package/src/modules/currencies/i18n/es.json +2 -1
  152. package/src/modules/currencies/i18n/pl.json +2 -1
  153. package/src/modules/customers/api/companies/[id]/route.ts +214 -189
  154. package/src/modules/customers/api/people/[id]/route.ts +106 -80
  155. package/src/modules/customers/backend/config/customers/pipeline-stages/page.tsx +19 -12
  156. package/src/modules/customers/components/detail/ActivitiesAddNewMenu.tsx +8 -6
  157. package/src/modules/customers/components/detail/AiActionChips.tsx +6 -3
  158. package/src/modules/customers/components/detail/schedule/ParticipantsField.tsx +16 -18
  159. package/src/modules/data_sync/api/runs/[id]/cancel.ts +1 -1
  160. package/src/modules/data_sync/backend/data-sync/page.tsx +11 -58
  161. package/src/modules/data_sync/backend/data-sync/runs/[id]/page.tsx +13 -20
  162. package/src/modules/data_sync/components/IntegrationScheduleTab.tsx +10 -8
  163. package/src/modules/data_sync/lib/id-mapping.ts +58 -1
  164. package/src/modules/data_sync/lib/sync-engine.ts +2 -2
  165. package/src/modules/data_sync/lib/syncRunStatus.ts +39 -0
  166. package/src/modules/entities/api/records.ts +14 -0
  167. package/src/modules/feature_toggles/api/global/route.ts +16 -14
  168. package/src/modules/feature_toggles/api/openapi.ts +2 -2
  169. package/src/modules/feature_toggles/commands/global.ts +15 -0
  170. package/src/modules/inbox_ops/backend/inbox-ops/page.tsx +7 -0
  171. package/src/modules/messages/api/[id]/conversation/archive/route.ts +29 -6
  172. package/src/modules/messages/api/[id]/conversation/read/route.ts +29 -6
  173. package/src/modules/messages/api/[id]/route.ts +15 -0
  174. package/src/modules/messages/api/openapi.ts +2 -0
  175. package/src/modules/messages/commands/conversation.ts +87 -0
  176. package/src/modules/messages/components/MessageDetailPageClient.tsx +16 -4
  177. package/src/modules/messages/components/message-detail/hooks/useMessageDetails.ts +2 -0
  178. package/src/modules/messages/components/message-detail/hooks/useMessageDetailsActions.ts +39 -4
  179. package/src/modules/messages/components/message-detail/hooks/useMessageDetailsQueries.ts +15 -1
  180. package/src/modules/messages/components/message-detail/panels/MainMessageHeader.tsx +29 -14
  181. package/src/modules/messages/components/message-detail/types.ts +2 -0
  182. package/src/modules/messages/i18n/de.json +4 -0
  183. package/src/modules/messages/i18n/en.json +4 -0
  184. package/src/modules/messages/i18n/es.json +4 -0
  185. package/src/modules/messages/i18n/pl.json +4 -0
  186. package/src/modules/payment_gateways/api/cancel/route.ts +5 -0
  187. package/src/modules/payment_gateways/api/capture/route.ts +5 -0
  188. package/src/modules/payment_gateways/api/refund/route.ts +5 -0
  189. package/src/modules/payment_gateways/lib/gateway-service.ts +58 -25
  190. package/src/modules/payment_gateways/lib/status-machine.ts +16 -0
  191. package/src/modules/perspectives/api/[tableId]/route.ts +8 -2
  192. package/src/modules/perspectives/data/entities.ts +43 -3
  193. package/src/modules/perspectives/migrations/.snapshot-open-mercato.json +69 -25
  194. package/src/modules/perspectives/migrations/Migration20260619120000_perspectives_live_row_uniqueness.ts +65 -0
  195. package/src/modules/perspectives/services/perspectiveService.ts +17 -0
  196. package/src/modules/planner/commands/availability-weekly.ts +48 -1
  197. package/src/modules/planner/components/AvailabilityRulesEditor.tsx +31 -10
  198. package/src/modules/progress/api/active/route.ts +1 -1
  199. package/src/modules/progress/lib/progressService.ts +2 -2
  200. package/src/modules/progress/lib/progressServiceImpl.ts +33 -8
  201. package/src/modules/query_index/api/status.ts +28 -32
  202. package/src/modules/query_index/lib/coverage.ts +63 -0
  203. package/src/modules/query_index/lib/engine.ts +37 -24
  204. package/src/modules/resources/api/resource-types.ts +4 -44
  205. package/src/modules/resources/api/resourceTypeCounts.ts +74 -0
  206. package/src/modules/resources/backend/resources/resource-types/[id]/edit/page.tsx +1 -1
  207. package/src/modules/resources/backend/resources/resource-types/page.tsx +1 -0
  208. package/src/modules/sales/components/documents/ReturnDialog.tsx +4 -1
  209. package/src/modules/sales/components/documents/ShipmentDialog.tsx +20 -2
  210. package/src/modules/sales/di.ts +6 -0
  211. package/src/modules/sales/services/salesOrderService.ts +38 -0
  212. package/src/modules/shipping_carriers/api/shipments/route.ts +8 -0
  213. package/src/modules/shipping_carriers/data/entities.ts +33 -0
  214. package/src/modules/shipping_carriers/data/validators.ts +1 -0
  215. package/src/modules/shipping_carriers/i18n/de.json +1 -0
  216. package/src/modules/shipping_carriers/i18n/en.json +1 -0
  217. package/src/modules/shipping_carriers/i18n/es.json +1 -0
  218. package/src/modules/shipping_carriers/i18n/pl.json +1 -0
  219. package/src/modules/shipping_carriers/lib/shipment-idempotency.ts +119 -0
  220. package/src/modules/shipping_carriers/lib/shipment-wizard/hooks/shipmentApi.ts +3 -1
  221. package/src/modules/shipping_carriers/lib/shipment-wizard/hooks/useShipmentWizard.ts +24 -2
  222. package/src/modules/shipping_carriers/lib/shipping-service.ts +87 -43
  223. package/src/modules/shipping_carriers/migrations/.snapshot-open-mercato.json +197 -0
  224. package/src/modules/shipping_carriers/migrations/Migration20260618173616_shipping_carriers.ts +14 -0
  225. package/src/modules/staff/i18n/de.json +1 -0
  226. package/src/modules/staff/i18n/en.json +1 -0
  227. package/src/modules/staff/i18n/es.json +1 -0
  228. package/src/modules/staff/i18n/pl.json +1 -0
  229. package/src/modules/staff/lib/timesheets-ui/ListView.tsx +15 -7
  230. package/src/modules/translations/components/TranslationManager.tsx +17 -24
  231. package/src/modules/translations/i18n/de.json +1 -0
  232. package/src/modules/translations/i18n/en.json +1 -0
  233. package/src/modules/translations/i18n/es.json +1 -0
  234. package/src/modules/translations/i18n/pl.json +1 -0
@@ -414,102 +414,106 @@ export async function GET(_req: Request, ctx: { params?: { id?: string } }) {
414
414
  userFeatures: undefined,
415
415
  })
416
416
 
417
- const profile = company.companyProfile
418
- ? await findOneWithDecryption(
419
- em,
420
- CustomerCompanyProfile,
421
- {
422
- id: company.companyProfile.id,
423
- tenantId: company.tenantId,
424
- organizationId: company.organizationId,
425
- },
426
- {},
427
- companyScope,
428
- )
429
- : await findOneWithDecryption(
430
- em,
431
- CustomerCompanyProfile,
432
- {
433
- entity: company,
434
- tenantId: company.tenantId,
435
- organizationId: company.organizationId,
436
- },
437
- {},
438
- companyScope,
439
- )
440
-
441
- const addresses = includeAddresses
442
- ? await findWithDecryption(
443
- em,
444
- CustomerAddress,
445
- {
446
- entity: company.id,
447
- tenantId: company.tenantId,
448
- organizationId: company.organizationId,
449
- },
450
- { orderBy: { isPrimary: 'desc', createdAt: 'desc' } },
451
- companyScope,
452
- )
453
- : []
454
- const tagAssignments = await findWithDecryption(
455
- em,
456
- CustomerTagAssignment,
457
- {
458
- entity: company.id,
459
- tenantId: company.tenantId,
460
- organizationId: company.organizationId,
461
- },
462
- { populate: ['tag'] },
463
- companyScope,
464
- )
465
- const labelAssignments = await findWithDecryption(
466
- em,
467
- CustomerLabelAssignment,
468
- {
469
- entity: company.id,
470
- tenantId: company.tenantId,
471
- organizationId: company.organizationId,
472
- },
473
- { populate: ['label'] },
474
- companyScope,
475
- )
476
-
477
- const comments = includeComments
478
- ? await findWithDecryption(
479
- em,
480
- CustomerComment,
481
- {
482
- entity: company.id,
483
- tenantId: company.tenantId,
484
- organizationId: company.organizationId,
485
- },
486
- { orderBy: { createdAt: 'desc' }, limit: 50 },
487
- companyScope,
488
- )
489
- : []
490
417
  const shouldLoadCanonicalInteractions = includeInteractions || includeActivities || includeTodos
491
- const canonicalInteractionRows = shouldLoadCanonicalInteractions
492
- ? await findWithDecryption(
493
- em,
494
- CustomerInteraction,
495
- interactionFlags.unified
496
- ? {
497
- entity: company.id,
498
- tenantId: company.tenantId,
499
- organizationId: company.organizationId,
500
- deletedAt: null,
501
- ...emailVisibilityFilter,
502
- }
503
- : {
504
- entity: company.id,
505
- tenantId: company.tenantId,
506
- organizationId: company.organizationId,
507
- ...emailVisibilityFilter,
508
- },
509
- { orderBy: { scheduledAt: 'asc', createdAt: 'desc' }, limit: 100 },
510
- companyScope,
511
- )
512
- : []
418
+
419
+ // These reads only depend on the resolved company + scope + email visibility
420
+ // filter, so dispatch them together to avoid a server-side request waterfall
421
+ // before the detail surface can render (issue #3203).
422
+ const [profile, addresses, tagAssignments, labelAssignments, comments, canonicalInteractionRows] = await Promise.all([
423
+ company.companyProfile
424
+ ? findOneWithDecryption(
425
+ em,
426
+ CustomerCompanyProfile,
427
+ {
428
+ id: company.companyProfile.id,
429
+ tenantId: company.tenantId,
430
+ organizationId: company.organizationId,
431
+ },
432
+ {},
433
+ companyScope,
434
+ )
435
+ : findOneWithDecryption(
436
+ em,
437
+ CustomerCompanyProfile,
438
+ {
439
+ entity: company,
440
+ tenantId: company.tenantId,
441
+ organizationId: company.organizationId,
442
+ },
443
+ {},
444
+ companyScope,
445
+ ),
446
+ includeAddresses
447
+ ? findWithDecryption(
448
+ em,
449
+ CustomerAddress,
450
+ {
451
+ entity: company.id,
452
+ tenantId: company.tenantId,
453
+ organizationId: company.organizationId,
454
+ },
455
+ { orderBy: { isPrimary: 'desc', createdAt: 'desc' } },
456
+ companyScope,
457
+ )
458
+ : Promise.resolve<CustomerAddress[]>([]),
459
+ findWithDecryption(
460
+ em,
461
+ CustomerTagAssignment,
462
+ {
463
+ entity: company.id,
464
+ tenantId: company.tenantId,
465
+ organizationId: company.organizationId,
466
+ },
467
+ { populate: ['tag'] },
468
+ companyScope,
469
+ ),
470
+ findWithDecryption(
471
+ em,
472
+ CustomerLabelAssignment,
473
+ {
474
+ entity: company.id,
475
+ tenantId: company.tenantId,
476
+ organizationId: company.organizationId,
477
+ },
478
+ { populate: ['label'] },
479
+ companyScope,
480
+ ),
481
+ includeComments
482
+ ? findWithDecryption(
483
+ em,
484
+ CustomerComment,
485
+ {
486
+ entity: company.id,
487
+ tenantId: company.tenantId,
488
+ organizationId: company.organizationId,
489
+ },
490
+ { orderBy: { createdAt: 'desc' }, limit: 50 },
491
+ companyScope,
492
+ )
493
+ : Promise.resolve<CustomerComment[]>([]),
494
+ shouldLoadCanonicalInteractions
495
+ ? findWithDecryption(
496
+ em,
497
+ CustomerInteraction,
498
+ interactionFlags.unified
499
+ ? {
500
+ entity: company.id,
501
+ tenantId: company.tenantId,
502
+ organizationId: company.organizationId,
503
+ deletedAt: null,
504
+ ...emailVisibilityFilter,
505
+ }
506
+ : {
507
+ entity: company.id,
508
+ tenantId: company.tenantId,
509
+ organizationId: company.organizationId,
510
+ ...emailVisibilityFilter,
511
+ },
512
+ { orderBy: { scheduledAt: 'asc', createdAt: 'desc' }, limit: 100 },
513
+ companyScope,
514
+ )
515
+ : Promise.resolve<CustomerInteraction[]>([]),
516
+ ])
513
517
  const canonicalActiveInteractions = canonicalInteractionRows.filter((interaction) => !interaction.deletedAt)
514
518
  const canonicalInteractions = shouldLoadCanonicalInteractions
515
519
  ? await hydrateCanonicalInteractions({
@@ -775,32 +779,35 @@ export async function GET(_req: Request, ctx: { params?: { id?: string } }) {
775
779
  relatedPeople = Array.from(relatedPeopleById.values())
776
780
  }
777
781
 
778
- const entityCustomFieldValues = await loadCustomFieldValues({
779
- em,
780
- entityId: E.customers.customer_entity,
781
- recordIds: [company.id],
782
- tenantIdByRecord: { [company.id]: company.tenantId ?? null },
783
- organizationIdByRecord: { [company.id]: company.organizationId ?? null },
784
- tenantFallbacks: [
785
- company.tenantId ?? auth.tenantId ?? null,
786
- ].filter((v): v is string => !!v),
787
- })
788
- let profileCustomFieldValues: Record<string, Record<string, unknown>> = {}
782
+ // Entity custom fields, profile custom fields, and the routing lookup do not
783
+ // depend on each other (profileId is already resolved above), so load them in
784
+ // parallel instead of three sequential awaits (issue #3203).
789
785
  const profileId = profile?.id ?? null
790
- if (profileId) {
791
- profileCustomFieldValues = await loadCustomFieldValues({
786
+ const [entityCustomFieldValues, profileCustomFieldValues, routing] = await Promise.all([
787
+ loadCustomFieldValues({
792
788
  em,
793
- entityId: E.customers.customer_company_profile,
794
- recordIds: [profileId],
795
- tenantIdByRecord: { [profileId]: profile?.tenantId ?? null },
796
- organizationIdByRecord: { [profileId]: profile?.organizationId ?? null },
789
+ entityId: E.customers.customer_entity,
790
+ recordIds: [company.id],
791
+ tenantIdByRecord: { [company.id]: company.tenantId ?? null },
792
+ organizationIdByRecord: { [company.id]: company.organizationId ?? null },
797
793
  tenantFallbacks: [
798
- profile?.tenantId ?? company.tenantId ?? auth.tenantId ?? null,
794
+ company.tenantId ?? auth.tenantId ?? null,
799
795
  ].filter((v): v is string => !!v),
800
- })
801
- }
802
-
803
- const routing = await resolveCompanyCustomFieldRouting(em, company.tenantId ?? null, company.organizationId ?? null)
796
+ }),
797
+ profileId
798
+ ? loadCustomFieldValues({
799
+ em,
800
+ entityId: E.customers.customer_company_profile,
801
+ recordIds: [profileId],
802
+ tenantIdByRecord: { [profileId]: profile?.tenantId ?? null },
803
+ organizationIdByRecord: { [profileId]: profile?.organizationId ?? null },
804
+ tenantFallbacks: [
805
+ profile?.tenantId ?? company.tenantId ?? auth.tenantId ?? null,
806
+ ].filter((v): v is string => !!v),
807
+ })
808
+ : Promise.resolve<Record<string, Record<string, unknown>>>({}),
809
+ resolveCompanyCustomFieldRouting(em, company.tenantId ?? null, company.organizationId ?? null),
810
+ ])
804
811
  const customFields = normalizeCustomerDetailCustomFields(
805
812
  mergeCompanyCustomFieldValues(
806
813
  routing,
@@ -809,85 +816,103 @@ export async function GET(_req: Request, ctx: { params?: { id?: string } }) {
809
816
  ),
810
817
  )
811
818
 
812
- const activityCount = await em.count(CustomerInteraction, {
813
- entity: company.id,
814
- organizationId: company.organizationId,
815
- tenantId: company.tenantId,
816
- deletedAt: null,
817
- interactionType: { $ne: 'task' },
818
- ...emailVisibilityFilter,
819
- })
820
- const interactionCount = await em.count(CustomerInteraction, {
821
- entity: company.id,
822
- organizationId: company.organizationId,
823
- tenantId: company.tenantId,
824
- deletedAt: null,
825
- ...emailVisibilityFilter,
826
- })
827
- const todoCount = interactionFlags.unified
828
- ? await em.count(CustomerInteraction, {
829
- entity: company.id,
830
- organizationId: company.organizationId,
831
- tenantId: company.tenantId,
832
- deletedAt: null,
833
- interactionType: 'task',
834
- })
835
- : await em.count(CustomerTodoLink, {
836
- entity: company.id,
837
- organizationId: company.organizationId,
838
- tenantId: company.tenantId,
839
- })
840
- const commentsCount = includeComments
841
- ? comments.length
842
- : await em.count(CustomerComment, {
843
- entity: company.id,
844
- organizationId: company.organizationId,
845
- tenantId: company.tenantId,
846
- })
847
- const addressesCount = includeAddresses
848
- ? addresses.length
849
- : await em.count(CustomerAddress, {
850
- entity: company.id,
851
- organizationId: company.organizationId,
852
- tenantId: company.tenantId,
853
- })
854
- const peopleCount = includePeople
855
- ? relatedPeople.length
856
- : filterActivePersonCompanyLinks(
857
- await findWithDecryption(
819
+ // The count queries, related-people fallback, and KPI interaction fallback are
820
+ // all independent of each other; dispatch them together rather than awaiting
821
+ // each inline so the response counts/KPIs are assembled in one parallel round
822
+ // instead of a waterfall (issue #3203).
823
+ const peopleCountQuery = includePeople
824
+ ? Promise.resolve(relatedPeople.length)
825
+ : (async () => {
826
+ const peopleLinkWhere = await withActiveCustomerPersonCompanyLinkFilter(
858
827
  em,
859
- CustomerPersonCompanyLink,
860
- await withActiveCustomerPersonCompanyLinkFilter(
828
+ {
829
+ company: company.id,
830
+ organizationId: company.organizationId,
831
+ tenantId: company.tenantId,
832
+ },
833
+ 'customers.companies.GET',
834
+ )
835
+ return filterActivePersonCompanyLinks(
836
+ await findWithDecryption(
861
837
  em,
862
- {
863
- company: company.id,
864
- organizationId: company.organizationId,
865
- tenantId: company.tenantId,
866
- },
867
- 'customers.companies.GET',
838
+ CustomerPersonCompanyLink,
839
+ peopleLinkWhere,
840
+ {},
841
+ { tenantId: company.tenantId, organizationId: company.organizationId },
868
842
  ),
869
- {},
870
- { tenantId: company.tenantId, organizationId: company.organizationId },
871
- ),
872
- ).length
873
- const kpiInteractionRows = canonicalActiveInteractions.length
874
- ? canonicalActiveInteractions
875
- : await findWithDecryption(
876
- em,
877
- CustomerInteraction,
878
- {
843
+ ).length
844
+ })()
845
+ const [
846
+ activityCount,
847
+ interactionCount,
848
+ todoCount,
849
+ commentsCount,
850
+ addressesCount,
851
+ peopleCount,
852
+ kpiInteractionRows,
853
+ ] = await Promise.all([
854
+ em.count(CustomerInteraction, {
855
+ entity: company.id,
856
+ organizationId: company.organizationId,
857
+ tenantId: company.tenantId,
858
+ deletedAt: null,
859
+ interactionType: { $ne: 'task' },
860
+ ...emailVisibilityFilter,
861
+ }),
862
+ em.count(CustomerInteraction, {
863
+ entity: company.id,
864
+ organizationId: company.organizationId,
865
+ tenantId: company.tenantId,
866
+ deletedAt: null,
867
+ ...emailVisibilityFilter,
868
+ }),
869
+ interactionFlags.unified
870
+ ? em.count(CustomerInteraction, {
879
871
  entity: company.id,
880
872
  organizationId: company.organizationId,
881
873
  tenantId: company.tenantId,
882
874
  deletedAt: null,
883
- ...emailVisibilityFilter,
884
- },
885
- {
886
- fields: ['id', 'occurredAt', 'scheduledAt', 'createdAt'],
887
- orderBy: { createdAt: 'DESC' },
888
- },
889
- { tenantId: company.tenantId, organizationId: company.organizationId },
890
- )
875
+ interactionType: 'task',
876
+ })
877
+ : em.count(CustomerTodoLink, {
878
+ entity: company.id,
879
+ organizationId: company.organizationId,
880
+ tenantId: company.tenantId,
881
+ }),
882
+ includeComments
883
+ ? Promise.resolve(comments.length)
884
+ : em.count(CustomerComment, {
885
+ entity: company.id,
886
+ organizationId: company.organizationId,
887
+ tenantId: company.tenantId,
888
+ }),
889
+ includeAddresses
890
+ ? Promise.resolve(addresses.length)
891
+ : em.count(CustomerAddress, {
892
+ entity: company.id,
893
+ organizationId: company.organizationId,
894
+ tenantId: company.tenantId,
895
+ }),
896
+ peopleCountQuery,
897
+ canonicalActiveInteractions.length
898
+ ? Promise.resolve(canonicalActiveInteractions)
899
+ : findWithDecryption(
900
+ em,
901
+ CustomerInteraction,
902
+ {
903
+ entity: company.id,
904
+ organizationId: company.organizationId,
905
+ tenantId: company.tenantId,
906
+ deletedAt: null,
907
+ ...emailVisibilityFilter,
908
+ },
909
+ {
910
+ fields: ['id', 'occurredAt', 'scheduledAt', 'createdAt'],
911
+ orderBy: { createdAt: 'DESC' },
912
+ },
913
+ { tenantId: company.tenantId, organizationId: company.organizationId },
914
+ ),
915
+ ])
891
916
  const activityTrend = computeActivityTrend(
892
917
  kpiInteractionRows
893
918
  .map((interaction) => interaction.occurredAt ?? interaction.scheduledAt ?? interaction.createdAt)