@open-mercato/core 0.6.5-develop.5337.1.534b781eac → 0.6.5-develop.5382.1.f542de69af

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 (119) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/AGENTS.md +1 -1
  3. package/dist/modules/attachments/api/library/route.js +2 -2
  4. package/dist/modules/attachments/api/library/route.js.map +2 -2
  5. package/dist/modules/attachments/components/AttachmentContentPreview.js +9 -5
  6. package/dist/modules/attachments/components/AttachmentContentPreview.js.map +2 -2
  7. package/dist/modules/audit_logs/api/audit-logs/actions/redo/route.js +3 -2
  8. package/dist/modules/audit_logs/api/audit-logs/actions/redo/route.js.map +2 -2
  9. package/dist/modules/auth/commands/users.js +20 -14
  10. package/dist/modules/auth/commands/users.js.map +2 -2
  11. package/dist/modules/auth/data/entities.js +1 -1
  12. package/dist/modules/auth/data/entities.js.map +2 -2
  13. package/dist/modules/auth/migrations/Migration20260610120000.js +30 -0
  14. package/dist/modules/auth/migrations/Migration20260610120000.js.map +7 -0
  15. package/dist/modules/catalog/ai-tools/configuration-pack.js.map +1 -1
  16. package/dist/modules/catalog/ai-tools/prices-offers-pack.js.map +1 -1
  17. package/dist/modules/catalog/ai-tools/products-pack.js.map +1 -1
  18. package/dist/modules/catalog/ai-tools/variants-pack.js.map +1 -1
  19. package/dist/modules/communication_channels/data/entities.js.map +1 -1
  20. package/dist/modules/communication_channels/encryption.js.map +1 -1
  21. package/dist/modules/communication_channels/lib/thread-matcher.js.map +1 -1
  22. package/dist/modules/communication_channels/lib/thread-token.js.map +1 -1
  23. package/dist/modules/currencies/api/currencies/route.js +4 -3
  24. package/dist/modules/currencies/api/currencies/route.js.map +2 -2
  25. package/dist/modules/customer_accounts/api/admin/roles.js +2 -1
  26. package/dist/modules/customer_accounts/api/admin/roles.js.map +2 -2
  27. package/dist/modules/customer_accounts/events.js +1 -1
  28. package/dist/modules/customer_accounts/events.js.map +1 -1
  29. package/dist/modules/customer_accounts/lib/resolveTenantContext.js.map +1 -1
  30. package/dist/modules/customers/acl.js +1 -1
  31. package/dist/modules/customers/acl.js.map +1 -1
  32. package/dist/modules/customers/ai-tools/companies-pack.js.map +1 -1
  33. package/dist/modules/customers/ai-tools/deals-pack.js.map +1 -1
  34. package/dist/modules/customers/ai-tools/people-pack.js.map +1 -1
  35. package/dist/modules/customers/api/companies/route.js +4 -4
  36. package/dist/modules/customers/api/companies/route.js.map +2 -2
  37. package/dist/modules/customers/api/people/route.js +4 -4
  38. package/dist/modules/customers/api/people/route.js.map +2 -2
  39. package/dist/modules/customers/commands/addresses.js +5 -5
  40. package/dist/modules/customers/commands/addresses.js.map +2 -2
  41. package/dist/modules/customers/commands/comments.js +5 -5
  42. package/dist/modules/customers/commands/comments.js.map +2 -2
  43. package/dist/modules/customers/commands/deals.js +2 -2
  44. package/dist/modules/customers/commands/deals.js.map +2 -2
  45. package/dist/modules/customers/commands/entity-roles.js +2 -1
  46. package/dist/modules/customers/commands/entity-roles.js.map +2 -2
  47. package/dist/modules/customers/commands/interactions.js +8 -5
  48. package/dist/modules/customers/commands/interactions.js.map +2 -2
  49. package/dist/modules/customers/commands/shared.js +21 -6
  50. package/dist/modules/customers/commands/shared.js.map +2 -2
  51. package/dist/modules/customers/commands/tags.js +3 -3
  52. package/dist/modules/customers/commands/tags.js.map +2 -2
  53. package/dist/modules/customers/components/detail/assignableStaff.js +21 -8
  54. package/dist/modules/customers/components/detail/assignableStaff.js.map +2 -2
  55. package/dist/modules/customers/migrations/Migration20260519120000_pipeline_stage_color_tones.js.map +1 -1
  56. package/dist/modules/data_sync/api/run.js +1 -1
  57. package/dist/modules/data_sync/api/run.js.map +2 -2
  58. package/dist/modules/payment_gateways/api/transactions/route.js +2 -4
  59. package/dist/modules/payment_gateways/api/transactions/route.js.map +2 -2
  60. package/dist/modules/progress/api/jobs/[id]/route.js +7 -2
  61. package/dist/modules/progress/api/jobs/[id]/route.js.map +2 -2
  62. package/dist/modules/progress/api/jobs/route.js +1 -1
  63. package/dist/modules/progress/api/jobs/route.js.map +2 -2
  64. package/dist/modules/progress/lib/progressServiceImpl.js +8 -2
  65. package/dist/modules/progress/lib/progressServiceImpl.js.map +2 -2
  66. package/dist/modules/resources/api/resources.js +2 -3
  67. package/dist/modules/resources/api/resources.js.map +2 -2
  68. package/dist/modules/sales/api/documents/factory.js +2 -2
  69. package/dist/modules/sales/api/documents/factory.js.map +2 -2
  70. package/dist/modules/sync_excel/api/import/route.js +1 -1
  71. package/dist/modules/sync_excel/api/import/route.js.map +2 -2
  72. package/dist/modules/workflows/api/definitions/route.js +3 -2
  73. package/dist/modules/workflows/api/definitions/route.js.map +2 -2
  74. package/package.json +7 -7
  75. package/src/modules/attachments/api/library/route.ts +2 -2
  76. package/src/modules/attachments/components/AttachmentContentPreview.tsx +6 -6
  77. package/src/modules/audit_logs/api/audit-logs/actions/redo/route.ts +14 -2
  78. package/src/modules/auth/commands/users.ts +32 -15
  79. package/src/modules/auth/data/entities.ts +11 -1
  80. package/src/modules/auth/migrations/.snapshot-open-mercato.json +0 -10
  81. package/src/modules/auth/migrations/Migration20260610120000.ts +53 -0
  82. package/src/modules/catalog/ai-tools/configuration-pack.ts +1 -1
  83. package/src/modules/catalog/ai-tools/prices-offers-pack.ts +1 -1
  84. package/src/modules/catalog/ai-tools/products-pack.ts +1 -1
  85. package/src/modules/catalog/ai-tools/variants-pack.ts +1 -1
  86. package/src/modules/communication_channels/data/entities.ts +2 -2
  87. package/src/modules/communication_channels/encryption.ts +1 -1
  88. package/src/modules/communication_channels/lib/adapter.ts +1 -1
  89. package/src/modules/communication_channels/lib/thread-matcher.ts +1 -1
  90. package/src/modules/communication_channels/lib/thread-token.ts +1 -1
  91. package/src/modules/currencies/api/currencies/route.ts +4 -3
  92. package/src/modules/customer_accounts/api/admin/roles.ts +2 -1
  93. package/src/modules/customer_accounts/events.ts +1 -1
  94. package/src/modules/customer_accounts/lib/resolveTenantContext.ts +2 -2
  95. package/src/modules/customers/acl.ts +1 -1
  96. package/src/modules/customers/ai-tools/companies-pack.ts +1 -1
  97. package/src/modules/customers/ai-tools/deals-pack.ts +1 -1
  98. package/src/modules/customers/ai-tools/people-pack.ts +1 -1
  99. package/src/modules/customers/api/companies/route.ts +4 -4
  100. package/src/modules/customers/api/people/route.ts +4 -4
  101. package/src/modules/customers/commands/addresses.ts +5 -5
  102. package/src/modules/customers/commands/comments.ts +5 -5
  103. package/src/modules/customers/commands/deals.ts +2 -2
  104. package/src/modules/customers/commands/entity-roles.ts +2 -1
  105. package/src/modules/customers/commands/interactions.ts +8 -5
  106. package/src/modules/customers/commands/shared.ts +26 -4
  107. package/src/modules/customers/commands/tags.ts +3 -3
  108. package/src/modules/customers/components/detail/assignableStaff.ts +32 -8
  109. package/src/modules/customers/migrations/Migration20260519120000_pipeline_stage_color_tones.ts +1 -1
  110. package/src/modules/data_sync/api/run.ts +1 -1
  111. package/src/modules/payment_gateways/api/transactions/route.ts +2 -5
  112. package/src/modules/progress/api/jobs/[id]/route.ts +6 -1
  113. package/src/modules/progress/api/jobs/route.ts +1 -1
  114. package/src/modules/progress/lib/progressServiceImpl.ts +7 -1
  115. package/src/modules/resources/api/resources.ts +2 -3
  116. package/src/modules/sales/api/documents/factory.ts +2 -2
  117. package/src/modules/staff/AGENTS.md +1 -1
  118. package/src/modules/sync_excel/api/import/route.ts +1 -1
  119. package/src/modules/workflows/api/definitions/route.ts +3 -2
@@ -262,7 +262,7 @@ async function syncDealPeople(em, deal, personIds) {
262
262
  if (!personIds || !personIds.length) return;
263
263
  const unique = Array.from(new Set(personIds));
264
264
  for (const personId of unique) {
265
- const person = await requireCustomerEntity(em, personId, "person", "Person not found");
265
+ const person = await requireCustomerEntity(em, personId, { tenantId: deal.tenantId, organizationId: deal.organizationId }, "person", "Person not found");
266
266
  ensureSameScope(person, deal.organizationId, deal.tenantId);
267
267
  const link = em.create(CustomerDealPersonLink, {
268
268
  deal,
@@ -277,7 +277,7 @@ async function syncDealCompanies(em, deal, companyIds) {
277
277
  if (!companyIds || !companyIds.length) return;
278
278
  const unique = Array.from(new Set(companyIds));
279
279
  for (const companyId of unique) {
280
- const company = await requireCustomerEntity(em, companyId, "company", "Company not found");
280
+ const company = await requireCustomerEntity(em, companyId, { tenantId: deal.tenantId, organizationId: deal.organizationId }, "company", "Company not found");
281
281
  ensureSameScope(company, deal.organizationId, deal.tenantId);
282
282
  const link = em.create(CustomerDealCompanyLink, {
283
283
  deal,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/customers/commands/deals.ts"],
4
- "sourcesContent": ["import { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport {\n parseWithCustomFields,\n setCustomFieldsIfAny,\n emitCrudSideEffects,\n emitCrudUndoSideEffects,\n requireId,\n normalizeAuthorUserId,\n} from '@open-mercato/shared/lib/commands/helpers'\nimport { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'\nimport { resolveRedoSnapshot } from '@open-mercato/shared/lib/commands/redo'\nimport { runCrudCommandWrite } from '@open-mercato/shared/lib/commands/runCrudCommandWrite'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport {\n CustomerDeal,\n CustomerDealPersonLink,\n CustomerDealCompanyLink,\n CustomerDealStageTransition,\n CustomerPipelineStage,\n} from '../data/entities'\nimport {\n dealCreateSchema,\n dealUpdateSchema,\n type DealCreateInput,\n type DealUpdateInput,\n} from '../data/validators'\nimport {\n ensureOrganizationScope,\n ensureTenantScope,\n requireCustomerEntity,\n ensureSameScope,\n extractUndoPayload,\n ensureDictionaryEntry,\n} from './shared'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport {\n loadCustomFieldSnapshot,\n buildCustomFieldResetMap,\n type CustomFieldChangeSet,\n} from '@open-mercato/shared/lib/commands/customFieldSnapshots'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport type { CrudIndexerConfig, CrudEventsConfig } from '@open-mercato/shared/lib/crud/types'\nimport { E } from '#generated/entities.ids.generated'\nimport { findWithDecryption, findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { isMissingDealStageTransitionTable, warnMissingDealStageTransitionTable } from '../lib/dealStageTransitionTable'\n\nconst DEAL_ENTITY_ID = 'customers:customer_deal'\nconst dealCrudIndexer: CrudIndexerConfig<CustomerDeal> = {\n entityType: E.customers.customer_deal,\n}\n\nconst dealCrudEvents: CrudEventsConfig = {\n module: 'customers',\n entity: 'deal',\n persistent: true,\n buildPayload: (ctx) => ({\n id: ctx.identifiers.id,\n organizationId: ctx.identifiers.organizationId,\n tenantId: ctx.identifiers.tenantId,\n }),\n}\n\ntype PipelineStageSnapshot = {\n id: string\n pipelineId: string\n label: string\n order: number\n}\n\ntype DealStageTransitionSnapshot = {\n id: string\n pipelineId: string\n stageId: string\n stageLabel: string\n stageOrder: number\n transitionedAt: Date | string\n transitionedByUserId: string | null\n}\n\nfunction coerceSnapshotDate(value: Date | string | null | undefined, fieldName: string): Date | null {\n if (value === undefined || value === null) return null\n if (value instanceof Date) return value\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) {\n throw new Error(`[internal] Invalid ${fieldName} undo snapshot date: ${value}`)\n }\n return date\n}\n\nfunction coerceRequiredSnapshotDate(value: Date | string, fieldName: string): Date {\n const date = coerceSnapshotDate(value, fieldName)\n if (!date) {\n throw new Error(`[internal] Missing ${fieldName} undo snapshot date`)\n }\n return date\n}\n\nasync function loadPipelineStageSnapshot(\n em: EntityManager,\n pipelineStageId: string,\n tenantId: string,\n organizationId: string,\n): Promise<PipelineStageSnapshot | null> {\n const stage = await findOneWithDecryption(em, CustomerPipelineStage, { id: pipelineStageId }, {}, { tenantId, organizationId })\n if (!stage) return null\n return {\n id: stage.id,\n pipelineId: stage.pipelineId,\n label: stage.label,\n order: stage.order,\n }\n}\n\nasync function resolvePipelineStageValue(\n em: EntityManager,\n pipelineStageId: string,\n tenantId: string,\n organizationId: string,\n): Promise<string | null> {\n const stage = await loadPipelineStageSnapshot(em, pipelineStageId, tenantId, organizationId)\n if (!stage) return null\n const entry = await ensureDictionaryEntry(em, {\n tenantId,\n organizationId,\n kind: 'pipeline_stage',\n value: stage.label,\n })\n return entry?.value ?? stage.label\n}\n\nfunction resolvePipelineAssignment(input: {\n pipelineId?: string | null\n pipelineStageId?: string | null\n stageSnapshot: PipelineStageSnapshot | null\n}): { pipelineId: string | null; pipelineStageId: string | null } {\n const requestedPipelineId = input.pipelineId ?? null\n const requestedPipelineStageId = input.pipelineStageId ?? null\n\n if (requestedPipelineStageId && !input.stageSnapshot) {\n throw new CrudHttpError(400, { error: 'Pipeline stage not found' })\n }\n\n if (\n requestedPipelineId &&\n input.stageSnapshot &&\n input.stageSnapshot.pipelineId !== requestedPipelineId\n ) {\n throw new CrudHttpError(400, {\n error: 'Pipeline stage does not belong to the selected pipeline',\n })\n }\n\n return {\n pipelineId: requestedPipelineId ?? input.stageSnapshot?.pipelineId ?? null,\n pipelineStageId: requestedPipelineStageId,\n }\n}\n\nasync function upsertDealStageTransition(\n em: EntityManager,\n input: {\n deal: CustomerDeal\n pipelineId: string\n stageId: string\n stageLabel: string\n stageOrder: number\n transitionedByUserId: string | null\n transitionedAt?: Date\n },\n): Promise<void> {\n let existing: CustomerDealStageTransition | null = null\n try {\n existing = await findOneWithDecryption(\n em,\n CustomerDealStageTransition,\n { deal: input.deal.id, stageId: input.stageId, deletedAt: null },\n {},\n { tenantId: input.deal.tenantId, organizationId: input.deal.organizationId },\n )\n } catch (error) {\n if (!isMissingDealStageTransitionTable(error)) {\n throw error\n }\n warnMissingDealStageTransitionTable('customers.commands.deals.upsertTransition')\n return\n }\n const transitionedAt = input.transitionedAt ?? new Date()\n if (existing) {\n existing.pipelineId = input.pipelineId\n existing.stageLabel = input.stageLabel\n existing.stageOrder = input.stageOrder\n existing.transitionedAt = transitionedAt\n existing.transitionedByUserId = input.transitionedByUserId\n existing.deletedAt = null\n existing.isActive = true\n return\n }\n\n const transition = em.create(CustomerDealStageTransition, {\n organizationId: input.deal.organizationId,\n tenantId: input.deal.tenantId,\n deal: input.deal,\n pipelineId: input.pipelineId,\n stageId: input.stageId,\n stageLabel: input.stageLabel,\n stageOrder: input.stageOrder,\n transitionedAt,\n transitionedByUserId: input.transitionedByUserId,\n isActive: true,\n })\n em.persist(transition)\n}\n\nasync function deleteDealStageTransitions(em: EntityManager, deal: CustomerDeal): Promise<void> {\n try {\n await em.nativeDelete(CustomerDealStageTransition, { deal: deal.id })\n } catch (error) {\n if (!isMissingDealStageTransitionTable(error)) {\n throw error\n }\n warnMissingDealStageTransitionTable('customers.commands.deals.deleteTransitions')\n }\n}\n\nasync function restoreDealStageTransitions(\n em: EntityManager,\n deal: CustomerDeal,\n transitions: DealStageTransitionSnapshot[],\n): Promise<void> {\n if (!transitions.length) return\n for (const transitionSnapshot of transitions) {\n const transition = em.create(CustomerDealStageTransition, {\n id: transitionSnapshot.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n deal,\n pipelineId: transitionSnapshot.pipelineId,\n stageId: transitionSnapshot.stageId,\n stageLabel: transitionSnapshot.stageLabel,\n stageOrder: transitionSnapshot.stageOrder,\n transitionedAt: coerceRequiredSnapshotDate(transitionSnapshot.transitionedAt, 'transitionedAt'),\n transitionedByUserId: transitionSnapshot.transitionedByUserId,\n isActive: true,\n })\n em.persist(transition)\n }\n}\n\ntype DealSnapshot = {\n deal: {\n id: string\n organizationId: string\n tenantId: string\n title: string\n description: string | null\n status: string\n pipelineStage: string | null\n pipelineId: string | null\n pipelineStageId: string | null\n valueAmount: string | null\n valueCurrency: string | null\n probability: number | null\n expectedCloseAt: Date | string | null\n ownerUserId: string | null\n source: string | null\n closureOutcome: string | null\n lossReasonId: string | null\n lossNotes: string | null\n }\n people: string[]\n companies: string[]\n transitions: DealStageTransitionSnapshot[]\n custom?: Record<string, unknown>\n}\n\ntype DealUndoPayload = {\n before?: DealSnapshot | null\n after?: DealSnapshot | null\n}\n\ntype DealChangeMap = Record<string, { from: unknown; to: unknown }> & {\n custom?: CustomFieldChangeSet\n}\n\nasync function loadDealSnapshot(em: EntityManager, id: string): Promise<DealSnapshot | null> {\n const deal = await findOneWithDecryption(em, CustomerDeal, { id, deletedAt: null })\n if (!deal) return null\n const decryptionScope = { tenantId: deal.tenantId ?? null, organizationId: deal.organizationId ?? null }\n const peopleLinks = await findWithDecryption(\n em,\n CustomerDealPersonLink,\n { deal: deal },\n { populate: ['person'] },\n decryptionScope,\n )\n const companyLinks = await findWithDecryption(\n em,\n CustomerDealCompanyLink,\n { deal: deal },\n { populate: ['company'] },\n decryptionScope,\n )\n const transitions = await findWithDecryption(\n em,\n CustomerDealStageTransition,\n { deal: deal.id, deletedAt: null },\n { orderBy: { stageOrder: 'ASC', transitionedAt: 'ASC' } },\n decryptionScope,\n ).catch((error: unknown) => {\n if (!isMissingDealStageTransitionTable(error)) {\n throw error\n }\n warnMissingDealStageTransitionTable('customers.commands.deals.loadSnapshot')\n return [] as CustomerDealStageTransition[]\n })\n const custom = await loadCustomFieldSnapshot(em, {\n entityId: DEAL_ENTITY_ID,\n recordId: deal.id,\n tenantId: deal.tenantId,\n organizationId: deal.organizationId,\n })\n return {\n deal: {\n id: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n title: deal.title,\n description: deal.description ?? null,\n status: deal.status,\n pipelineStage: deal.pipelineStage ?? null,\n pipelineId: deal.pipelineId ?? null,\n pipelineStageId: deal.pipelineStageId ?? null,\n valueAmount: deal.valueAmount ?? null,\n valueCurrency: deal.valueCurrency ?? null,\n probability: deal.probability ?? null,\n expectedCloseAt: deal.expectedCloseAt ?? null,\n ownerUserId: deal.ownerUserId ?? null,\n source: deal.source ?? null,\n closureOutcome: deal.closureOutcome ?? null,\n lossReasonId: deal.lossReasonId ?? null,\n lossNotes: deal.lossNotes ?? null,\n },\n people: peopleLinks.map((link) =>\n typeof link.person === 'string' ? link.person : link.person.id\n ),\n companies: companyLinks.map((link) =>\n typeof link.company === 'string' ? link.company : link.company.id\n ),\n transitions: transitions.map((transition) => ({\n id: transition.id,\n pipelineId: transition.pipelineId,\n stageId: transition.stageId,\n stageLabel: transition.stageLabel,\n stageOrder: transition.stageOrder,\n transitionedAt: transition.transitionedAt,\n transitionedByUserId: transition.transitionedByUserId ?? null,\n })),\n custom,\n }\n}\n\nfunction toNumericString(value: number | null | undefined): string | null {\n if (value === undefined || value === null) return null\n return value.toString()\n}\n\nasync function syncDealPeople(\n em: EntityManager,\n deal: CustomerDeal,\n personIds: string[] | undefined | null\n): Promise<void> {\n if (personIds === undefined) return\n await em.nativeDelete(CustomerDealPersonLink, { deal })\n if (!personIds || !personIds.length) return\n const unique = Array.from(new Set(personIds))\n for (const personId of unique) {\n const person = await requireCustomerEntity(em, personId, 'person', 'Person not found')\n ensureSameScope(person, deal.organizationId, deal.tenantId)\n const link = em.create(CustomerDealPersonLink, {\n deal,\n person,\n })\n em.persist(link)\n }\n}\n\nasync function syncDealCompanies(\n em: EntityManager,\n deal: CustomerDeal,\n companyIds: string[] | undefined | null\n): Promise<void> {\n if (companyIds === undefined) return\n await em.nativeDelete(CustomerDealCompanyLink, { deal })\n if (!companyIds || !companyIds.length) return\n const unique = Array.from(new Set(companyIds))\n for (const companyId of unique) {\n const company = await requireCustomerEntity(em, companyId, 'company', 'Company not found')\n ensureSameScope(company, deal.organizationId, deal.tenantId)\n const link = em.create(CustomerDealCompanyLink, {\n deal,\n company,\n })\n em.persist(link)\n }\n}\n\nconst createDealCommand: CommandHandler<DealCreateInput, { dealId: string }> = {\n id: 'customers.deals.create',\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(dealCreateSchema, rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const normalizedTransitionAuthorUserId = normalizeAuthorUserId(null, ctx.auth)\n let deal!: CustomerDeal\n let stageSnapshot: PipelineStageSnapshot | null = null\n let pipelineAssignment: { pipelineId: string | null; pipelineStageId: string | null } = {\n pipelineId: null,\n pipelineStageId: null,\n }\n let resolvedPipelineStageLabel: string | null = null\n await withAtomicFlush(em, [\n async () => {\n stageSnapshot = parsed.pipelineStageId\n ? await loadPipelineStageSnapshot(em, parsed.pipelineStageId, parsed.tenantId, parsed.organizationId)\n : null\n pipelineAssignment = resolvePipelineAssignment({\n pipelineId: parsed.pipelineId,\n pipelineStageId: parsed.pipelineStageId,\n stageSnapshot,\n })\n resolvedPipelineStageLabel = stageSnapshot\n ? (await ensureDictionaryEntry(em, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n kind: 'pipeline_stage',\n value: stageSnapshot.label,\n }))?.value ?? stageSnapshot.label\n : parsed.pipelineStage ?? null\n },\n async () => {\n deal = em.create(CustomerDeal, {\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n title: parsed.title,\n description: parsed.description ?? null,\n status: parsed.status ?? 'open',\n pipelineStage: resolvedPipelineStageLabel,\n pipelineId: pipelineAssignment.pipelineId,\n pipelineStageId: pipelineAssignment.pipelineStageId,\n valueAmount: toNumericString(parsed.valueAmount),\n valueCurrency: parsed.valueCurrency ?? null,\n probability: parsed.probability ?? null,\n expectedCloseAt: parsed.expectedCloseAt ?? null,\n ownerUserId: parsed.ownerUserId ?? null,\n source: parsed.source ?? null,\n closureOutcome: parsed.closureOutcome ?? null,\n lossReasonId: parsed.lossReasonId ?? null,\n lossNotes: parsed.lossNotes ?? null,\n })\n em.persist(deal)\n await em.flush()\n },\n async () => {\n const snapshot = stageSnapshot\n if (!snapshot) return\n await upsertDealStageTransition(em, {\n deal,\n pipelineId: snapshot.pipelineId,\n stageId: snapshot.id,\n stageLabel: snapshot.label,\n stageOrder: snapshot.order,\n transitionedByUserId: normalizedTransitionAuthorUserId,\n })\n },\n () => syncDealPeople(em, deal, parsed.personIds ?? []),\n () => syncDealCompanies(em, deal, parsed.companyIds ?? []),\n ], { transaction: true })\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: DEAL_ENTITY_ID,\n recordId: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n values: custom,\n notify: false,\n })\n\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: deal,\n identifiers: {\n id: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n },\n indexer: dealCrudIndexer,\n events: dealCrudEvents,\n })\n\n return { dealId: deal.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadDealSnapshot(em, result.dealId)\n },\n buildLog: async ({ result, ctx }) => {\n const { translate } = await resolveTranslations()\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadDealSnapshot(em, result.dealId)\n return {\n actionLabel: translate('customers.audit.deals.create', 'Create deal'),\n resourceKind: 'customers.deal',\n resourceId: result.dealId,\n tenantId: snapshot?.deal.tenantId ?? null,\n organizationId: snapshot?.deal.organizationId ?? null,\n snapshotAfter: snapshot ?? null,\n payload: {\n undo: {\n after: snapshot,\n } satisfies DealUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const dealId = logEntry?.resourceId\n if (!dealId) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const deal = await findOneWithDecryption(em, CustomerDeal, { id: dealId })\n if (!deal) return\n await deleteDealStageTransitions(em, deal)\n await em.nativeDelete(CustomerDealPersonLink, { deal })\n await em.nativeDelete(CustomerDealCompanyLink, { deal })\n em.remove(deal)\n await em.flush()\n },\n redo: async ({ logEntry, ctx }) => {\n const after = resolveRedoSnapshot<DealSnapshot>(logEntry)\n if (!after) {\n throw new CrudHttpError(400, { error: '[internal] redo snapshot unavailable for deal create' })\n }\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let deal = await findOneWithDecryption(em, CustomerDeal, { id: after.deal.id })\n if (!deal) {\n deal = em.create(CustomerDeal, {\n id: after.deal.id,\n organizationId: after.deal.organizationId,\n tenantId: after.deal.tenantId,\n title: after.deal.title,\n description: after.deal.description,\n status: after.deal.status,\n pipelineStage: after.deal.pipelineStage,\n pipelineId: after.deal.pipelineId,\n pipelineStageId: after.deal.pipelineStageId,\n valueAmount: after.deal.valueAmount,\n valueCurrency: after.deal.valueCurrency,\n probability: after.deal.probability,\n expectedCloseAt: after.deal.expectedCloseAt,\n ownerUserId: after.deal.ownerUserId,\n source: after.deal.source,\n closureOutcome: after.deal.closureOutcome,\n lossReasonId: after.deal.lossReasonId,\n lossNotes: after.deal.lossNotes,\n })\n em.persist(deal)\n }\n const restoredDeal = deal\n await withAtomicFlush(em, [\n () => syncDealPeople(em, restoredDeal, after.people),\n () => syncDealCompanies(em, restoredDeal, after.companies),\n () => deleteDealStageTransitions(em, restoredDeal),\n () => restoreDealStageTransitions(em, restoredDeal, after.transitions),\n ], { transaction: true })\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: restoredDeal,\n identifiers: {\n id: restoredDeal.id,\n organizationId: restoredDeal.organizationId,\n tenantId: restoredDeal.tenantId,\n },\n indexer: dealCrudIndexer,\n events: dealCrudEvents,\n })\n\n const restoreValues = buildCustomFieldResetMap(after.custom, undefined)\n if (Object.keys(restoreValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: DEAL_ENTITY_ID,\n recordId: restoredDeal.id,\n organizationId: restoredDeal.organizationId,\n tenantId: restoredDeal.tenantId,\n values: restoreValues,\n notify: false,\n })\n }\n\n return { dealId: restoredDeal.id }\n },\n}\n\nconst updateDealCommand: CommandHandler<DealUpdateInput, { dealId: string }> = {\n id: 'customers.deals.update',\n async prepare(rawInput, ctx) {\n const { parsed } = parseWithCustomFields(dealUpdateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadDealSnapshot(em, parsed.id)\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(dealUpdateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const deal = await findOneWithDecryption(em, CustomerDeal, { id: parsed.id, deletedAt: null })\n const record = deal ?? null\n if (!record) throw new CrudHttpError(404, { error: 'Deal not found' })\n ensureTenantScope(ctx, record.tenantId)\n ensureOrganizationScope(ctx, record.organizationId)\n\n const previousStatus = record.status\n const previousPipelineStageId = record.pipelineStageId ?? null\n const normalizedTransitionAuthorUserId = normalizeAuthorUserId(null, ctx.auth)\n\n let nextStageSnapshot: PipelineStageSnapshot | null = null\n let nextPipelineAssignment: { pipelineId: string | null; pipelineStageId: string | null } = {\n pipelineId: record.pipelineId ?? null,\n pipelineStageId: record.pipelineStageId ?? null,\n }\n let nextPipelineStageLabel: string | null = null\n let resolvedCurrentPipelineStageLabel: string | null = null\n\n await runCrudCommandWrite({\n ctx,\n em,\n entityId: DEAL_ENTITY_ID,\n action: 'updated',\n scope: { tenantId: record.tenantId, organizationId: record.organizationId },\n customFields: custom,\n events: dealCrudEvents,\n indexer: dealCrudIndexer,\n sideEffect: () => ({\n entity: record,\n identifiers: {\n id: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n },\n }),\n phases: [\n async () => {\n const pipelineAssignmentChanged =\n parsed.pipelineId !== undefined || parsed.pipelineStageId !== undefined\n const requestedPipelineStageId =\n parsed.pipelineStageId !== undefined\n ? parsed.pipelineStageId ?? null\n : record.pipelineStageId ?? null\n const requestedPipelineId =\n parsed.pipelineId !== undefined ? parsed.pipelineId ?? null : record.pipelineId ?? null\n\n nextStageSnapshot = requestedPipelineStageId && (pipelineAssignmentChanged || !record.pipelineStage)\n ? await loadPipelineStageSnapshot(em, requestedPipelineStageId, record.tenantId, record.organizationId)\n : null\n if (pipelineAssignmentChanged) {\n nextPipelineAssignment = resolvePipelineAssignment({\n pipelineId: requestedPipelineId,\n pipelineStageId: requestedPipelineStageId,\n stageSnapshot: nextStageSnapshot,\n })\n }\n nextPipelineStageLabel = nextStageSnapshot\n ? (await ensureDictionaryEntry(em, {\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n kind: 'pipeline_stage',\n value: nextStageSnapshot.label,\n }))?.value ?? nextStageSnapshot.label\n : null\n resolvedCurrentPipelineStageLabel =\n !nextStageSnapshot && record.pipelineStageId && (parsed.pipelineStageId !== undefined || !record.pipelineStage)\n ? await resolvePipelineStageValue(em, record.pipelineStageId, record.tenantId, record.organizationId)\n : null\n },\n () => {\n if (parsed.title !== undefined) record.title = parsed.title\n if (parsed.description !== undefined) record.description = parsed.description ?? null\n if (parsed.status !== undefined) record.status = parsed.status ?? record.status\n if (parsed.pipelineStage !== undefined) record.pipelineStage = parsed.pipelineStage ?? null\n if (parsed.pipelineId !== undefined || (parsed.pipelineStageId !== undefined && nextStageSnapshot)) {\n record.pipelineId = nextPipelineAssignment.pipelineId\n }\n if (parsed.pipelineStageId !== undefined) record.pipelineStageId = nextPipelineAssignment.pipelineStageId\n\n if (nextPipelineStageLabel && (parsed.pipelineStageId !== undefined || !record.pipelineStage)) {\n record.pipelineStage = nextPipelineStageLabel\n } else if (resolvedCurrentPipelineStageLabel && (parsed.pipelineStageId !== undefined || !record.pipelineStage)) {\n record.pipelineStage = resolvedCurrentPipelineStageLabel\n }\n\n if (parsed.valueAmount !== undefined) record.valueAmount = toNumericString(parsed.valueAmount)\n if (parsed.valueCurrency !== undefined) record.valueCurrency = parsed.valueCurrency ?? null\n if (parsed.probability !== undefined) record.probability = parsed.probability ?? null\n if (parsed.expectedCloseAt !== undefined) record.expectedCloseAt = parsed.expectedCloseAt ?? null\n if (parsed.ownerUserId !== undefined) record.ownerUserId = parsed.ownerUserId ?? null\n if (parsed.source !== undefined) record.source = parsed.source ?? null\n if (parsed.closureOutcome !== undefined) record.closureOutcome = parsed.closureOutcome ?? null\n if (parsed.lossReasonId !== undefined) record.lossReasonId = parsed.lossReasonId ?? null\n if (parsed.lossNotes !== undefined) record.lossNotes = parsed.lossNotes ?? null\n },\n async () => {\n // CRITICAL: persist the scalar mutations above before any further `em.findOne` / sync\n // helpers run inside this transaction. MikroORM v7's identity-map silently discards\n // pending scalar changes on `record` if a query (such as the stage-transition lookup\n // inside `upsertDealStageTransition`, or the linked-entity finds inside\n // `syncDealPeople` / `syncDealCompanies`) executes on the same `EntityManager`\n // before we explicitly flush. Without this flush, the entire kanban drag-and-drop\n // returns 200 OK but never actually updates `customer_deals` rows \u2014 the card\n // snaps back to its source lane on the next refetch (see SPEC-018).\n await em.flush()\n },\n async () => {\n const snapshot = nextStageSnapshot\n if (!snapshot) return\n const shouldRecord =\n parsed.pipelineStageId !== undefined &&\n parsed.pipelineStageId !== null &&\n parsed.pipelineStageId !== previousPipelineStageId\n if (!shouldRecord) return\n await upsertDealStageTransition(em, {\n deal: record,\n pipelineId: snapshot.pipelineId,\n stageId: snapshot.id,\n stageLabel: nextPipelineStageLabel ?? snapshot.label,\n stageOrder: snapshot.order,\n transitionedByUserId: normalizedTransitionAuthorUserId,\n })\n },\n () => syncDealPeople(em, record, parsed.personIds),\n () => syncDealCompanies(em, record, parsed.companyIds),\n ],\n })\n\n // Emit a lifecycle event for deal won/lost status changes; the notifications\n // subscriber translates these into recipient notifications.\n const newStatus = record.status\n const normalizedStatus = newStatus === 'win' ? 'won' : newStatus === 'loose' ? 'lost' : newStatus\n if (previousStatus !== newStatus && (normalizedStatus === 'won' || normalizedStatus === 'lost')) {\n const closureEvent = normalizedStatus === 'won' ? 'customers.deal.won' : 'customers.deal.lost'\n try {\n const eventBus = ctx.container.resolve('eventBus') as { emitEvent(event: string, payload: unknown, options?: unknown): Promise<void> } | undefined\n if (eventBus) {\n await eventBus.emitEvent(\n closureEvent,\n {\n id: record.id,\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n ownerUserId: record.ownerUserId ?? null,\n title: record.title,\n valueAmount: record.valueAmount ?? null,\n valueCurrency: record.valueCurrency ?? null,\n },\n { persistent: true },\n )\n }\n } catch (err) {\n console.warn('[customers.deals.update] deal closure event emit failed', closureEvent, err)\n }\n }\n\n return { dealId: record.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadDealSnapshot(em, result.dealId)\n },\n buildLog: async ({ result, snapshots, ctx }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as DealSnapshot | undefined\n if (!before) return null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const afterSnapshot = await loadDealSnapshot(em, result.dealId)\n return {\n actionLabel: translate('customers.audit.deals.update', 'Update deal'),\n resourceKind: 'customers.deal',\n resourceId: before.deal.id,\n tenantId: before.deal.tenantId,\n organizationId: before.deal.organizationId,\n snapshotBefore: before,\n snapshotAfter: afterSnapshot ?? null,\n payload: {\n undo: {\n before,\n after: afterSnapshot ?? null,\n } satisfies DealUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<DealUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const normalizedTransitionAuthorUserId = normalizeAuthorUserId(null, ctx.auth)\n let deal = await findOneWithDecryption(em, CustomerDeal, { id: before.deal.id })\n if (!deal) {\n deal = em.create(CustomerDeal, {\n id: before.deal.id,\n organizationId: before.deal.organizationId,\n tenantId: before.deal.tenantId,\n title: before.deal.title,\n description: before.deal.description,\n status: before.deal.status,\n pipelineStage: before.deal.pipelineStage,\n pipelineId: before.deal.pipelineId,\n pipelineStageId: before.deal.pipelineStageId,\n valueAmount: before.deal.valueAmount,\n valueCurrency: before.deal.valueCurrency,\n probability: before.deal.probability,\n expectedCloseAt: coerceSnapshotDate(before.deal.expectedCloseAt, 'expectedCloseAt'),\n ownerUserId: before.deal.ownerUserId,\n source: before.deal.source,\n closureOutcome: before.deal.closureOutcome,\n lossReasonId: before.deal.lossReasonId,\n lossNotes: before.deal.lossNotes,\n })\n em.persist(deal)\n }\n const revertedStageSnapshot = before.deal.pipelineStageId\n ? await loadPipelineStageSnapshot(em, before.deal.pipelineStageId, before.deal.tenantId, before.deal.organizationId)\n : null\n const existingTransition = before.deal.pipelineStageId\n ? before.transitions.find((transition) => transition.stageId === before.deal.pipelineStageId) ?? null\n : null\n const shouldRecordRevertTransition =\n before.deal.pipelineStageId !== (payload?.after?.deal.pipelineStageId ?? null) &&\n !!before.deal.pipelineStageId &&\n !!(revertedStageSnapshot?.pipelineId ?? before.deal.pipelineId ?? existingTransition?.pipelineId) &&\n !!(revertedStageSnapshot?.label ?? before.deal.pipelineStage ?? existingTransition?.stageLabel)\n\n await withAtomicFlush(em, [\n () => {\n deal.title = before.deal.title\n deal.description = before.deal.description\n deal.status = before.deal.status\n deal.pipelineStage = before.deal.pipelineStage\n deal.pipelineId = before.deal.pipelineId\n deal.pipelineStageId = before.deal.pipelineStageId\n deal.valueAmount = before.deal.valueAmount\n deal.valueCurrency = before.deal.valueCurrency\n deal.probability = before.deal.probability\n deal.expectedCloseAt = coerceSnapshotDate(before.deal.expectedCloseAt, 'expectedCloseAt')\n deal.ownerUserId = before.deal.ownerUserId\n deal.source = before.deal.source\n deal.closureOutcome = before.deal.closureOutcome\n deal.lossReasonId = before.deal.lossReasonId\n deal.lossNotes = before.deal.lossNotes\n },\n async () => {\n // Mirror of the fix applied to the forward `execute` path: persist the scalar\n // mutations on `deal` before any further `em.findOne` (the transition lookup\n // inside `upsertDealStageTransition`) or sync-helper queries run on the same EM.\n // MikroORM v7 silently discards the pending scalar changes if we don't flush here\n // (see SPEC-018), which would make an undo of a kanban stage move silently no-op.\n await em.flush()\n },\n async () => {\n if (!shouldRecordRevertTransition || !before.deal.pipelineStageId) return\n const pipelineId = revertedStageSnapshot?.pipelineId ?? before.deal.pipelineId ?? existingTransition?.pipelineId\n const stageLabel = revertedStageSnapshot?.label ?? before.deal.pipelineStage ?? existingTransition?.stageLabel\n if (!pipelineId || !stageLabel) return\n await upsertDealStageTransition(em, {\n deal,\n pipelineId,\n stageId: before.deal.pipelineStageId,\n stageLabel,\n stageOrder: revertedStageSnapshot?.order ?? existingTransition?.stageOrder ?? 0,\n transitionedByUserId: normalizedTransitionAuthorUserId,\n })\n },\n () => syncDealPeople(em, deal, before.people),\n () => syncDealCompanies(em, deal, before.companies),\n ], { transaction: true })\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: deal,\n identifiers: {\n id: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n },\n indexer: dealCrudIndexer,\n events: dealCrudEvents,\n })\n\n const resetValues = buildCustomFieldResetMap(before.custom, payload?.after?.custom)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: DEAL_ENTITY_ID,\n recordId: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n values: resetValues,\n notify: false,\n })\n }\n },\n}\n\nconst deleteDealCommand: CommandHandler<{ body?: Record<string, unknown>; query?: Record<string, unknown> }, { dealId: string }> =\n {\n id: 'customers.deals.delete',\n async prepare(input, ctx) {\n const id = requireId(input, 'Deal id required')\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadDealSnapshot(em, id)\n return snapshot ? { before: snapshot } : {}\n },\n async execute(input, ctx) {\n const id = requireId(input, 'Deal id required')\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const deal = await findOneWithDecryption(em, CustomerDeal, { id, deletedAt: null })\n const record = deal ?? null\n if (!record) throw new CrudHttpError(404, { error: 'Deal not found' })\n ensureTenantScope(ctx, record.tenantId)\n ensureOrganizationScope(ctx, record.organizationId)\n await deleteDealStageTransitions(em, record)\n await em.nativeDelete(CustomerDealPersonLink, { deal: record })\n await em.nativeDelete(CustomerDealCompanyLink, { deal: record })\n em.remove(record)\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'deleted',\n entity: record,\n identifiers: {\n id: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n },\n indexer: dealCrudIndexer,\n events: dealCrudEvents,\n })\n return { dealId: record.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as DealSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('customers.audit.deals.delete', 'Delete deal'),\n resourceKind: 'customers.deal',\n resourceId: before.deal.id,\n tenantId: before.deal.tenantId,\n organizationId: before.deal.organizationId,\n snapshotBefore: before,\n payload: {\n undo: {\n before,\n } satisfies DealUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<DealUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let deal = await findOneWithDecryption(em, CustomerDeal, { id: before.deal.id })\n if (!deal) {\n deal = em.create(CustomerDeal, {\n id: before.deal.id,\n organizationId: before.deal.organizationId,\n tenantId: before.deal.tenantId,\n title: before.deal.title,\n description: before.deal.description,\n status: before.deal.status,\n pipelineStage: before.deal.pipelineStage,\n pipelineId: before.deal.pipelineId,\n pipelineStageId: before.deal.pipelineStageId,\n valueAmount: before.deal.valueAmount,\n valueCurrency: before.deal.valueCurrency,\n probability: before.deal.probability,\n expectedCloseAt: coerceSnapshotDate(before.deal.expectedCloseAt, 'expectedCloseAt'),\n ownerUserId: before.deal.ownerUserId,\n source: before.deal.source,\n closureOutcome: before.deal.closureOutcome,\n lossReasonId: before.deal.lossReasonId,\n lossNotes: before.deal.lossNotes,\n })\n em.persist(deal)\n }\n await withAtomicFlush(em, [\n () => syncDealPeople(em, deal, before.people),\n () => syncDealCompanies(em, deal, before.companies),\n () => deleteDealStageTransitions(em, deal),\n () => restoreDealStageTransitions(em, deal, before.transitions),\n ], { transaction: true })\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'created',\n entity: deal,\n identifiers: {\n id: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n },\n indexer: dealCrudIndexer,\n events: dealCrudEvents,\n })\n\n const resetValues = buildCustomFieldResetMap(before.custom, undefined)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: DEAL_ENTITY_ID,\n recordId: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n values: resetValues,\n notify: false,\n })\n }\n },\n }\n\nregisterCommand(createDealCommand)\nregisterCommand(updateDealCommand)\nregisterCommand(deleteDealCommand)\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport {\n parseWithCustomFields,\n setCustomFieldsIfAny,\n emitCrudSideEffects,\n emitCrudUndoSideEffects,\n requireId,\n normalizeAuthorUserId,\n} from '@open-mercato/shared/lib/commands/helpers'\nimport { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'\nimport { resolveRedoSnapshot } from '@open-mercato/shared/lib/commands/redo'\nimport { runCrudCommandWrite } from '@open-mercato/shared/lib/commands/runCrudCommandWrite'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport {\n CustomerDeal,\n CustomerDealPersonLink,\n CustomerDealCompanyLink,\n CustomerDealStageTransition,\n CustomerPipelineStage,\n} from '../data/entities'\nimport {\n dealCreateSchema,\n dealUpdateSchema,\n type DealCreateInput,\n type DealUpdateInput,\n} from '../data/validators'\nimport {\n ensureOrganizationScope,\n ensureTenantScope,\n requireCustomerEntity,\n ensureSameScope,\n extractUndoPayload,\n ensureDictionaryEntry,\n} from './shared'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport {\n loadCustomFieldSnapshot,\n buildCustomFieldResetMap,\n type CustomFieldChangeSet,\n} from '@open-mercato/shared/lib/commands/customFieldSnapshots'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport type { CrudIndexerConfig, CrudEventsConfig } from '@open-mercato/shared/lib/crud/types'\nimport { E } from '#generated/entities.ids.generated'\nimport { findWithDecryption, findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { isMissingDealStageTransitionTable, warnMissingDealStageTransitionTable } from '../lib/dealStageTransitionTable'\n\nconst DEAL_ENTITY_ID = 'customers:customer_deal'\nconst dealCrudIndexer: CrudIndexerConfig<CustomerDeal> = {\n entityType: E.customers.customer_deal,\n}\n\nconst dealCrudEvents: CrudEventsConfig = {\n module: 'customers',\n entity: 'deal',\n persistent: true,\n buildPayload: (ctx) => ({\n id: ctx.identifiers.id,\n organizationId: ctx.identifiers.organizationId,\n tenantId: ctx.identifiers.tenantId,\n }),\n}\n\ntype PipelineStageSnapshot = {\n id: string\n pipelineId: string\n label: string\n order: number\n}\n\ntype DealStageTransitionSnapshot = {\n id: string\n pipelineId: string\n stageId: string\n stageLabel: string\n stageOrder: number\n transitionedAt: Date | string\n transitionedByUserId: string | null\n}\n\nfunction coerceSnapshotDate(value: Date | string | null | undefined, fieldName: string): Date | null {\n if (value === undefined || value === null) return null\n if (value instanceof Date) return value\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) {\n throw new Error(`[internal] Invalid ${fieldName} undo snapshot date: ${value}`)\n }\n return date\n}\n\nfunction coerceRequiredSnapshotDate(value: Date | string, fieldName: string): Date {\n const date = coerceSnapshotDate(value, fieldName)\n if (!date) {\n throw new Error(`[internal] Missing ${fieldName} undo snapshot date`)\n }\n return date\n}\n\nasync function loadPipelineStageSnapshot(\n em: EntityManager,\n pipelineStageId: string,\n tenantId: string,\n organizationId: string,\n): Promise<PipelineStageSnapshot | null> {\n const stage = await findOneWithDecryption(em, CustomerPipelineStage, { id: pipelineStageId }, {}, { tenantId, organizationId })\n if (!stage) return null\n return {\n id: stage.id,\n pipelineId: stage.pipelineId,\n label: stage.label,\n order: stage.order,\n }\n}\n\nasync function resolvePipelineStageValue(\n em: EntityManager,\n pipelineStageId: string,\n tenantId: string,\n organizationId: string,\n): Promise<string | null> {\n const stage = await loadPipelineStageSnapshot(em, pipelineStageId, tenantId, organizationId)\n if (!stage) return null\n const entry = await ensureDictionaryEntry(em, {\n tenantId,\n organizationId,\n kind: 'pipeline_stage',\n value: stage.label,\n })\n return entry?.value ?? stage.label\n}\n\nfunction resolvePipelineAssignment(input: {\n pipelineId?: string | null\n pipelineStageId?: string | null\n stageSnapshot: PipelineStageSnapshot | null\n}): { pipelineId: string | null; pipelineStageId: string | null } {\n const requestedPipelineId = input.pipelineId ?? null\n const requestedPipelineStageId = input.pipelineStageId ?? null\n\n if (requestedPipelineStageId && !input.stageSnapshot) {\n throw new CrudHttpError(400, { error: 'Pipeline stage not found' })\n }\n\n if (\n requestedPipelineId &&\n input.stageSnapshot &&\n input.stageSnapshot.pipelineId !== requestedPipelineId\n ) {\n throw new CrudHttpError(400, {\n error: 'Pipeline stage does not belong to the selected pipeline',\n })\n }\n\n return {\n pipelineId: requestedPipelineId ?? input.stageSnapshot?.pipelineId ?? null,\n pipelineStageId: requestedPipelineStageId,\n }\n}\n\nasync function upsertDealStageTransition(\n em: EntityManager,\n input: {\n deal: CustomerDeal\n pipelineId: string\n stageId: string\n stageLabel: string\n stageOrder: number\n transitionedByUserId: string | null\n transitionedAt?: Date\n },\n): Promise<void> {\n let existing: CustomerDealStageTransition | null = null\n try {\n existing = await findOneWithDecryption(\n em,\n CustomerDealStageTransition,\n { deal: input.deal.id, stageId: input.stageId, deletedAt: null },\n {},\n { tenantId: input.deal.tenantId, organizationId: input.deal.organizationId },\n )\n } catch (error) {\n if (!isMissingDealStageTransitionTable(error)) {\n throw error\n }\n warnMissingDealStageTransitionTable('customers.commands.deals.upsertTransition')\n return\n }\n const transitionedAt = input.transitionedAt ?? new Date()\n if (existing) {\n existing.pipelineId = input.pipelineId\n existing.stageLabel = input.stageLabel\n existing.stageOrder = input.stageOrder\n existing.transitionedAt = transitionedAt\n existing.transitionedByUserId = input.transitionedByUserId\n existing.deletedAt = null\n existing.isActive = true\n return\n }\n\n const transition = em.create(CustomerDealStageTransition, {\n organizationId: input.deal.organizationId,\n tenantId: input.deal.tenantId,\n deal: input.deal,\n pipelineId: input.pipelineId,\n stageId: input.stageId,\n stageLabel: input.stageLabel,\n stageOrder: input.stageOrder,\n transitionedAt,\n transitionedByUserId: input.transitionedByUserId,\n isActive: true,\n })\n em.persist(transition)\n}\n\nasync function deleteDealStageTransitions(em: EntityManager, deal: CustomerDeal): Promise<void> {\n try {\n await em.nativeDelete(CustomerDealStageTransition, { deal: deal.id })\n } catch (error) {\n if (!isMissingDealStageTransitionTable(error)) {\n throw error\n }\n warnMissingDealStageTransitionTable('customers.commands.deals.deleteTransitions')\n }\n}\n\nasync function restoreDealStageTransitions(\n em: EntityManager,\n deal: CustomerDeal,\n transitions: DealStageTransitionSnapshot[],\n): Promise<void> {\n if (!transitions.length) return\n for (const transitionSnapshot of transitions) {\n const transition = em.create(CustomerDealStageTransition, {\n id: transitionSnapshot.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n deal,\n pipelineId: transitionSnapshot.pipelineId,\n stageId: transitionSnapshot.stageId,\n stageLabel: transitionSnapshot.stageLabel,\n stageOrder: transitionSnapshot.stageOrder,\n transitionedAt: coerceRequiredSnapshotDate(transitionSnapshot.transitionedAt, 'transitionedAt'),\n transitionedByUserId: transitionSnapshot.transitionedByUserId,\n isActive: true,\n })\n em.persist(transition)\n }\n}\n\ntype DealSnapshot = {\n deal: {\n id: string\n organizationId: string\n tenantId: string\n title: string\n description: string | null\n status: string\n pipelineStage: string | null\n pipelineId: string | null\n pipelineStageId: string | null\n valueAmount: string | null\n valueCurrency: string | null\n probability: number | null\n expectedCloseAt: Date | string | null\n ownerUserId: string | null\n source: string | null\n closureOutcome: string | null\n lossReasonId: string | null\n lossNotes: string | null\n }\n people: string[]\n companies: string[]\n transitions: DealStageTransitionSnapshot[]\n custom?: Record<string, unknown>\n}\n\ntype DealUndoPayload = {\n before?: DealSnapshot | null\n after?: DealSnapshot | null\n}\n\ntype DealChangeMap = Record<string, { from: unknown; to: unknown }> & {\n custom?: CustomFieldChangeSet\n}\n\nasync function loadDealSnapshot(em: EntityManager, id: string): Promise<DealSnapshot | null> {\n const deal = await findOneWithDecryption(em, CustomerDeal, { id, deletedAt: null })\n if (!deal) return null\n const decryptionScope = { tenantId: deal.tenantId ?? null, organizationId: deal.organizationId ?? null }\n const peopleLinks = await findWithDecryption(\n em,\n CustomerDealPersonLink,\n { deal: deal },\n { populate: ['person'] },\n decryptionScope,\n )\n const companyLinks = await findWithDecryption(\n em,\n CustomerDealCompanyLink,\n { deal: deal },\n { populate: ['company'] },\n decryptionScope,\n )\n const transitions = await findWithDecryption(\n em,\n CustomerDealStageTransition,\n { deal: deal.id, deletedAt: null },\n { orderBy: { stageOrder: 'ASC', transitionedAt: 'ASC' } },\n decryptionScope,\n ).catch((error: unknown) => {\n if (!isMissingDealStageTransitionTable(error)) {\n throw error\n }\n warnMissingDealStageTransitionTable('customers.commands.deals.loadSnapshot')\n return [] as CustomerDealStageTransition[]\n })\n const custom = await loadCustomFieldSnapshot(em, {\n entityId: DEAL_ENTITY_ID,\n recordId: deal.id,\n tenantId: deal.tenantId,\n organizationId: deal.organizationId,\n })\n return {\n deal: {\n id: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n title: deal.title,\n description: deal.description ?? null,\n status: deal.status,\n pipelineStage: deal.pipelineStage ?? null,\n pipelineId: deal.pipelineId ?? null,\n pipelineStageId: deal.pipelineStageId ?? null,\n valueAmount: deal.valueAmount ?? null,\n valueCurrency: deal.valueCurrency ?? null,\n probability: deal.probability ?? null,\n expectedCloseAt: deal.expectedCloseAt ?? null,\n ownerUserId: deal.ownerUserId ?? null,\n source: deal.source ?? null,\n closureOutcome: deal.closureOutcome ?? null,\n lossReasonId: deal.lossReasonId ?? null,\n lossNotes: deal.lossNotes ?? null,\n },\n people: peopleLinks.map((link) =>\n typeof link.person === 'string' ? link.person : link.person.id\n ),\n companies: companyLinks.map((link) =>\n typeof link.company === 'string' ? link.company : link.company.id\n ),\n transitions: transitions.map((transition) => ({\n id: transition.id,\n pipelineId: transition.pipelineId,\n stageId: transition.stageId,\n stageLabel: transition.stageLabel,\n stageOrder: transition.stageOrder,\n transitionedAt: transition.transitionedAt,\n transitionedByUserId: transition.transitionedByUserId ?? null,\n })),\n custom,\n }\n}\n\nfunction toNumericString(value: number | null | undefined): string | null {\n if (value === undefined || value === null) return null\n return value.toString()\n}\n\nasync function syncDealPeople(\n em: EntityManager,\n deal: CustomerDeal,\n personIds: string[] | undefined | null\n): Promise<void> {\n if (personIds === undefined) return\n await em.nativeDelete(CustomerDealPersonLink, { deal })\n if (!personIds || !personIds.length) return\n const unique = Array.from(new Set(personIds))\n for (const personId of unique) {\n const person = await requireCustomerEntity(em, personId, { tenantId: deal.tenantId, organizationId: deal.organizationId }, 'person', 'Person not found')\n ensureSameScope(person, deal.organizationId, deal.tenantId)\n const link = em.create(CustomerDealPersonLink, {\n deal,\n person,\n })\n em.persist(link)\n }\n}\n\nasync function syncDealCompanies(\n em: EntityManager,\n deal: CustomerDeal,\n companyIds: string[] | undefined | null\n): Promise<void> {\n if (companyIds === undefined) return\n await em.nativeDelete(CustomerDealCompanyLink, { deal })\n if (!companyIds || !companyIds.length) return\n const unique = Array.from(new Set(companyIds))\n for (const companyId of unique) {\n const company = await requireCustomerEntity(em, companyId, { tenantId: deal.tenantId, organizationId: deal.organizationId }, 'company', 'Company not found')\n ensureSameScope(company, deal.organizationId, deal.tenantId)\n const link = em.create(CustomerDealCompanyLink, {\n deal,\n company,\n })\n em.persist(link)\n }\n}\n\nconst createDealCommand: CommandHandler<DealCreateInput, { dealId: string }> = {\n id: 'customers.deals.create',\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(dealCreateSchema, rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const normalizedTransitionAuthorUserId = normalizeAuthorUserId(null, ctx.auth)\n let deal!: CustomerDeal\n let stageSnapshot: PipelineStageSnapshot | null = null\n let pipelineAssignment: { pipelineId: string | null; pipelineStageId: string | null } = {\n pipelineId: null,\n pipelineStageId: null,\n }\n let resolvedPipelineStageLabel: string | null = null\n await withAtomicFlush(em, [\n async () => {\n stageSnapshot = parsed.pipelineStageId\n ? await loadPipelineStageSnapshot(em, parsed.pipelineStageId, parsed.tenantId, parsed.organizationId)\n : null\n pipelineAssignment = resolvePipelineAssignment({\n pipelineId: parsed.pipelineId,\n pipelineStageId: parsed.pipelineStageId,\n stageSnapshot,\n })\n resolvedPipelineStageLabel = stageSnapshot\n ? (await ensureDictionaryEntry(em, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n kind: 'pipeline_stage',\n value: stageSnapshot.label,\n }))?.value ?? stageSnapshot.label\n : parsed.pipelineStage ?? null\n },\n async () => {\n deal = em.create(CustomerDeal, {\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n title: parsed.title,\n description: parsed.description ?? null,\n status: parsed.status ?? 'open',\n pipelineStage: resolvedPipelineStageLabel,\n pipelineId: pipelineAssignment.pipelineId,\n pipelineStageId: pipelineAssignment.pipelineStageId,\n valueAmount: toNumericString(parsed.valueAmount),\n valueCurrency: parsed.valueCurrency ?? null,\n probability: parsed.probability ?? null,\n expectedCloseAt: parsed.expectedCloseAt ?? null,\n ownerUserId: parsed.ownerUserId ?? null,\n source: parsed.source ?? null,\n closureOutcome: parsed.closureOutcome ?? null,\n lossReasonId: parsed.lossReasonId ?? null,\n lossNotes: parsed.lossNotes ?? null,\n })\n em.persist(deal)\n await em.flush()\n },\n async () => {\n const snapshot = stageSnapshot\n if (!snapshot) return\n await upsertDealStageTransition(em, {\n deal,\n pipelineId: snapshot.pipelineId,\n stageId: snapshot.id,\n stageLabel: snapshot.label,\n stageOrder: snapshot.order,\n transitionedByUserId: normalizedTransitionAuthorUserId,\n })\n },\n () => syncDealPeople(em, deal, parsed.personIds ?? []),\n () => syncDealCompanies(em, deal, parsed.companyIds ?? []),\n ], { transaction: true })\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: DEAL_ENTITY_ID,\n recordId: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n values: custom,\n notify: false,\n })\n\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: deal,\n identifiers: {\n id: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n },\n indexer: dealCrudIndexer,\n events: dealCrudEvents,\n })\n\n return { dealId: deal.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadDealSnapshot(em, result.dealId)\n },\n buildLog: async ({ result, ctx }) => {\n const { translate } = await resolveTranslations()\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadDealSnapshot(em, result.dealId)\n return {\n actionLabel: translate('customers.audit.deals.create', 'Create deal'),\n resourceKind: 'customers.deal',\n resourceId: result.dealId,\n tenantId: snapshot?.deal.tenantId ?? null,\n organizationId: snapshot?.deal.organizationId ?? null,\n snapshotAfter: snapshot ?? null,\n payload: {\n undo: {\n after: snapshot,\n } satisfies DealUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const dealId = logEntry?.resourceId\n if (!dealId) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const deal = await findOneWithDecryption(em, CustomerDeal, { id: dealId })\n if (!deal) return\n await deleteDealStageTransitions(em, deal)\n await em.nativeDelete(CustomerDealPersonLink, { deal })\n await em.nativeDelete(CustomerDealCompanyLink, { deal })\n em.remove(deal)\n await em.flush()\n },\n redo: async ({ logEntry, ctx }) => {\n const after = resolveRedoSnapshot<DealSnapshot>(logEntry)\n if (!after) {\n throw new CrudHttpError(400, { error: '[internal] redo snapshot unavailable for deal create' })\n }\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let deal = await findOneWithDecryption(em, CustomerDeal, { id: after.deal.id })\n if (!deal) {\n deal = em.create(CustomerDeal, {\n id: after.deal.id,\n organizationId: after.deal.organizationId,\n tenantId: after.deal.tenantId,\n title: after.deal.title,\n description: after.deal.description,\n status: after.deal.status,\n pipelineStage: after.deal.pipelineStage,\n pipelineId: after.deal.pipelineId,\n pipelineStageId: after.deal.pipelineStageId,\n valueAmount: after.deal.valueAmount,\n valueCurrency: after.deal.valueCurrency,\n probability: after.deal.probability,\n expectedCloseAt: after.deal.expectedCloseAt,\n ownerUserId: after.deal.ownerUserId,\n source: after.deal.source,\n closureOutcome: after.deal.closureOutcome,\n lossReasonId: after.deal.lossReasonId,\n lossNotes: after.deal.lossNotes,\n })\n em.persist(deal)\n }\n const restoredDeal = deal\n await withAtomicFlush(em, [\n () => syncDealPeople(em, restoredDeal, after.people),\n () => syncDealCompanies(em, restoredDeal, after.companies),\n () => deleteDealStageTransitions(em, restoredDeal),\n () => restoreDealStageTransitions(em, restoredDeal, after.transitions),\n ], { transaction: true })\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: restoredDeal,\n identifiers: {\n id: restoredDeal.id,\n organizationId: restoredDeal.organizationId,\n tenantId: restoredDeal.tenantId,\n },\n indexer: dealCrudIndexer,\n events: dealCrudEvents,\n })\n\n const restoreValues = buildCustomFieldResetMap(after.custom, undefined)\n if (Object.keys(restoreValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: DEAL_ENTITY_ID,\n recordId: restoredDeal.id,\n organizationId: restoredDeal.organizationId,\n tenantId: restoredDeal.tenantId,\n values: restoreValues,\n notify: false,\n })\n }\n\n return { dealId: restoredDeal.id }\n },\n}\n\nconst updateDealCommand: CommandHandler<DealUpdateInput, { dealId: string }> = {\n id: 'customers.deals.update',\n async prepare(rawInput, ctx) {\n const { parsed } = parseWithCustomFields(dealUpdateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadDealSnapshot(em, parsed.id)\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(dealUpdateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const deal = await findOneWithDecryption(em, CustomerDeal, { id: parsed.id, deletedAt: null })\n const record = deal ?? null\n if (!record) throw new CrudHttpError(404, { error: 'Deal not found' })\n ensureTenantScope(ctx, record.tenantId)\n ensureOrganizationScope(ctx, record.organizationId)\n\n const previousStatus = record.status\n const previousPipelineStageId = record.pipelineStageId ?? null\n const normalizedTransitionAuthorUserId = normalizeAuthorUserId(null, ctx.auth)\n\n let nextStageSnapshot: PipelineStageSnapshot | null = null\n let nextPipelineAssignment: { pipelineId: string | null; pipelineStageId: string | null } = {\n pipelineId: record.pipelineId ?? null,\n pipelineStageId: record.pipelineStageId ?? null,\n }\n let nextPipelineStageLabel: string | null = null\n let resolvedCurrentPipelineStageLabel: string | null = null\n\n await runCrudCommandWrite({\n ctx,\n em,\n entityId: DEAL_ENTITY_ID,\n action: 'updated',\n scope: { tenantId: record.tenantId, organizationId: record.organizationId },\n customFields: custom,\n events: dealCrudEvents,\n indexer: dealCrudIndexer,\n sideEffect: () => ({\n entity: record,\n identifiers: {\n id: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n },\n }),\n phases: [\n async () => {\n const pipelineAssignmentChanged =\n parsed.pipelineId !== undefined || parsed.pipelineStageId !== undefined\n const requestedPipelineStageId =\n parsed.pipelineStageId !== undefined\n ? parsed.pipelineStageId ?? null\n : record.pipelineStageId ?? null\n const requestedPipelineId =\n parsed.pipelineId !== undefined ? parsed.pipelineId ?? null : record.pipelineId ?? null\n\n nextStageSnapshot = requestedPipelineStageId && (pipelineAssignmentChanged || !record.pipelineStage)\n ? await loadPipelineStageSnapshot(em, requestedPipelineStageId, record.tenantId, record.organizationId)\n : null\n if (pipelineAssignmentChanged) {\n nextPipelineAssignment = resolvePipelineAssignment({\n pipelineId: requestedPipelineId,\n pipelineStageId: requestedPipelineStageId,\n stageSnapshot: nextStageSnapshot,\n })\n }\n nextPipelineStageLabel = nextStageSnapshot\n ? (await ensureDictionaryEntry(em, {\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n kind: 'pipeline_stage',\n value: nextStageSnapshot.label,\n }))?.value ?? nextStageSnapshot.label\n : null\n resolvedCurrentPipelineStageLabel =\n !nextStageSnapshot && record.pipelineStageId && (parsed.pipelineStageId !== undefined || !record.pipelineStage)\n ? await resolvePipelineStageValue(em, record.pipelineStageId, record.tenantId, record.organizationId)\n : null\n },\n () => {\n if (parsed.title !== undefined) record.title = parsed.title\n if (parsed.description !== undefined) record.description = parsed.description ?? null\n if (parsed.status !== undefined) record.status = parsed.status ?? record.status\n if (parsed.pipelineStage !== undefined) record.pipelineStage = parsed.pipelineStage ?? null\n if (parsed.pipelineId !== undefined || (parsed.pipelineStageId !== undefined && nextStageSnapshot)) {\n record.pipelineId = nextPipelineAssignment.pipelineId\n }\n if (parsed.pipelineStageId !== undefined) record.pipelineStageId = nextPipelineAssignment.pipelineStageId\n\n if (nextPipelineStageLabel && (parsed.pipelineStageId !== undefined || !record.pipelineStage)) {\n record.pipelineStage = nextPipelineStageLabel\n } else if (resolvedCurrentPipelineStageLabel && (parsed.pipelineStageId !== undefined || !record.pipelineStage)) {\n record.pipelineStage = resolvedCurrentPipelineStageLabel\n }\n\n if (parsed.valueAmount !== undefined) record.valueAmount = toNumericString(parsed.valueAmount)\n if (parsed.valueCurrency !== undefined) record.valueCurrency = parsed.valueCurrency ?? null\n if (parsed.probability !== undefined) record.probability = parsed.probability ?? null\n if (parsed.expectedCloseAt !== undefined) record.expectedCloseAt = parsed.expectedCloseAt ?? null\n if (parsed.ownerUserId !== undefined) record.ownerUserId = parsed.ownerUserId ?? null\n if (parsed.source !== undefined) record.source = parsed.source ?? null\n if (parsed.closureOutcome !== undefined) record.closureOutcome = parsed.closureOutcome ?? null\n if (parsed.lossReasonId !== undefined) record.lossReasonId = parsed.lossReasonId ?? null\n if (parsed.lossNotes !== undefined) record.lossNotes = parsed.lossNotes ?? null\n },\n async () => {\n // CRITICAL: persist the scalar mutations above before any further `em.findOne` / sync\n // helpers run inside this transaction. MikroORM v7's identity-map silently discards\n // pending scalar changes on `record` if a query (such as the stage-transition lookup\n // inside `upsertDealStageTransition`, or the linked-entity finds inside\n // `syncDealPeople` / `syncDealCompanies`) executes on the same `EntityManager`\n // before we explicitly flush. Without this flush, the entire kanban drag-and-drop\n // returns 200 OK but never actually updates `customer_deals` rows \u2014 the card\n // snaps back to its source lane on the next refetch (see SPEC-018).\n await em.flush()\n },\n async () => {\n const snapshot = nextStageSnapshot\n if (!snapshot) return\n const shouldRecord =\n parsed.pipelineStageId !== undefined &&\n parsed.pipelineStageId !== null &&\n parsed.pipelineStageId !== previousPipelineStageId\n if (!shouldRecord) return\n await upsertDealStageTransition(em, {\n deal: record,\n pipelineId: snapshot.pipelineId,\n stageId: snapshot.id,\n stageLabel: nextPipelineStageLabel ?? snapshot.label,\n stageOrder: snapshot.order,\n transitionedByUserId: normalizedTransitionAuthorUserId,\n })\n },\n () => syncDealPeople(em, record, parsed.personIds),\n () => syncDealCompanies(em, record, parsed.companyIds),\n ],\n })\n\n // Emit a lifecycle event for deal won/lost status changes; the notifications\n // subscriber translates these into recipient notifications.\n const newStatus = record.status\n const normalizedStatus = newStatus === 'win' ? 'won' : newStatus === 'loose' ? 'lost' : newStatus\n if (previousStatus !== newStatus && (normalizedStatus === 'won' || normalizedStatus === 'lost')) {\n const closureEvent = normalizedStatus === 'won' ? 'customers.deal.won' : 'customers.deal.lost'\n try {\n const eventBus = ctx.container.resolve('eventBus') as { emitEvent(event: string, payload: unknown, options?: unknown): Promise<void> } | undefined\n if (eventBus) {\n await eventBus.emitEvent(\n closureEvent,\n {\n id: record.id,\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n ownerUserId: record.ownerUserId ?? null,\n title: record.title,\n valueAmount: record.valueAmount ?? null,\n valueCurrency: record.valueCurrency ?? null,\n },\n { persistent: true },\n )\n }\n } catch (err) {\n console.warn('[customers.deals.update] deal closure event emit failed', closureEvent, err)\n }\n }\n\n return { dealId: record.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadDealSnapshot(em, result.dealId)\n },\n buildLog: async ({ result, snapshots, ctx }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as DealSnapshot | undefined\n if (!before) return null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const afterSnapshot = await loadDealSnapshot(em, result.dealId)\n return {\n actionLabel: translate('customers.audit.deals.update', 'Update deal'),\n resourceKind: 'customers.deal',\n resourceId: before.deal.id,\n tenantId: before.deal.tenantId,\n organizationId: before.deal.organizationId,\n snapshotBefore: before,\n snapshotAfter: afterSnapshot ?? null,\n payload: {\n undo: {\n before,\n after: afterSnapshot ?? null,\n } satisfies DealUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<DealUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const normalizedTransitionAuthorUserId = normalizeAuthorUserId(null, ctx.auth)\n let deal = await findOneWithDecryption(em, CustomerDeal, { id: before.deal.id })\n if (!deal) {\n deal = em.create(CustomerDeal, {\n id: before.deal.id,\n organizationId: before.deal.organizationId,\n tenantId: before.deal.tenantId,\n title: before.deal.title,\n description: before.deal.description,\n status: before.deal.status,\n pipelineStage: before.deal.pipelineStage,\n pipelineId: before.deal.pipelineId,\n pipelineStageId: before.deal.pipelineStageId,\n valueAmount: before.deal.valueAmount,\n valueCurrency: before.deal.valueCurrency,\n probability: before.deal.probability,\n expectedCloseAt: coerceSnapshotDate(before.deal.expectedCloseAt, 'expectedCloseAt'),\n ownerUserId: before.deal.ownerUserId,\n source: before.deal.source,\n closureOutcome: before.deal.closureOutcome,\n lossReasonId: before.deal.lossReasonId,\n lossNotes: before.deal.lossNotes,\n })\n em.persist(deal)\n }\n const revertedStageSnapshot = before.deal.pipelineStageId\n ? await loadPipelineStageSnapshot(em, before.deal.pipelineStageId, before.deal.tenantId, before.deal.organizationId)\n : null\n const existingTransition = before.deal.pipelineStageId\n ? before.transitions.find((transition) => transition.stageId === before.deal.pipelineStageId) ?? null\n : null\n const shouldRecordRevertTransition =\n before.deal.pipelineStageId !== (payload?.after?.deal.pipelineStageId ?? null) &&\n !!before.deal.pipelineStageId &&\n !!(revertedStageSnapshot?.pipelineId ?? before.deal.pipelineId ?? existingTransition?.pipelineId) &&\n !!(revertedStageSnapshot?.label ?? before.deal.pipelineStage ?? existingTransition?.stageLabel)\n\n await withAtomicFlush(em, [\n () => {\n deal.title = before.deal.title\n deal.description = before.deal.description\n deal.status = before.deal.status\n deal.pipelineStage = before.deal.pipelineStage\n deal.pipelineId = before.deal.pipelineId\n deal.pipelineStageId = before.deal.pipelineStageId\n deal.valueAmount = before.deal.valueAmount\n deal.valueCurrency = before.deal.valueCurrency\n deal.probability = before.deal.probability\n deal.expectedCloseAt = coerceSnapshotDate(before.deal.expectedCloseAt, 'expectedCloseAt')\n deal.ownerUserId = before.deal.ownerUserId\n deal.source = before.deal.source\n deal.closureOutcome = before.deal.closureOutcome\n deal.lossReasonId = before.deal.lossReasonId\n deal.lossNotes = before.deal.lossNotes\n },\n async () => {\n // Mirror of the fix applied to the forward `execute` path: persist the scalar\n // mutations on `deal` before any further `em.findOne` (the transition lookup\n // inside `upsertDealStageTransition`) or sync-helper queries run on the same EM.\n // MikroORM v7 silently discards the pending scalar changes if we don't flush here\n // (see SPEC-018), which would make an undo of a kanban stage move silently no-op.\n await em.flush()\n },\n async () => {\n if (!shouldRecordRevertTransition || !before.deal.pipelineStageId) return\n const pipelineId = revertedStageSnapshot?.pipelineId ?? before.deal.pipelineId ?? existingTransition?.pipelineId\n const stageLabel = revertedStageSnapshot?.label ?? before.deal.pipelineStage ?? existingTransition?.stageLabel\n if (!pipelineId || !stageLabel) return\n await upsertDealStageTransition(em, {\n deal,\n pipelineId,\n stageId: before.deal.pipelineStageId,\n stageLabel,\n stageOrder: revertedStageSnapshot?.order ?? existingTransition?.stageOrder ?? 0,\n transitionedByUserId: normalizedTransitionAuthorUserId,\n })\n },\n () => syncDealPeople(em, deal, before.people),\n () => syncDealCompanies(em, deal, before.companies),\n ], { transaction: true })\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: deal,\n identifiers: {\n id: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n },\n indexer: dealCrudIndexer,\n events: dealCrudEvents,\n })\n\n const resetValues = buildCustomFieldResetMap(before.custom, payload?.after?.custom)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: DEAL_ENTITY_ID,\n recordId: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n values: resetValues,\n notify: false,\n })\n }\n },\n}\n\nconst deleteDealCommand: CommandHandler<{ body?: Record<string, unknown>; query?: Record<string, unknown> }, { dealId: string }> =\n {\n id: 'customers.deals.delete',\n async prepare(input, ctx) {\n const id = requireId(input, 'Deal id required')\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadDealSnapshot(em, id)\n return snapshot ? { before: snapshot } : {}\n },\n async execute(input, ctx) {\n const id = requireId(input, 'Deal id required')\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const deal = await findOneWithDecryption(em, CustomerDeal, { id, deletedAt: null })\n const record = deal ?? null\n if (!record) throw new CrudHttpError(404, { error: 'Deal not found' })\n ensureTenantScope(ctx, record.tenantId)\n ensureOrganizationScope(ctx, record.organizationId)\n await deleteDealStageTransitions(em, record)\n await em.nativeDelete(CustomerDealPersonLink, { deal: record })\n await em.nativeDelete(CustomerDealCompanyLink, { deal: record })\n em.remove(record)\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'deleted',\n entity: record,\n identifiers: {\n id: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n },\n indexer: dealCrudIndexer,\n events: dealCrudEvents,\n })\n return { dealId: record.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as DealSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('customers.audit.deals.delete', 'Delete deal'),\n resourceKind: 'customers.deal',\n resourceId: before.deal.id,\n tenantId: before.deal.tenantId,\n organizationId: before.deal.organizationId,\n snapshotBefore: before,\n payload: {\n undo: {\n before,\n } satisfies DealUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<DealUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let deal = await findOneWithDecryption(em, CustomerDeal, { id: before.deal.id })\n if (!deal) {\n deal = em.create(CustomerDeal, {\n id: before.deal.id,\n organizationId: before.deal.organizationId,\n tenantId: before.deal.tenantId,\n title: before.deal.title,\n description: before.deal.description,\n status: before.deal.status,\n pipelineStage: before.deal.pipelineStage,\n pipelineId: before.deal.pipelineId,\n pipelineStageId: before.deal.pipelineStageId,\n valueAmount: before.deal.valueAmount,\n valueCurrency: before.deal.valueCurrency,\n probability: before.deal.probability,\n expectedCloseAt: coerceSnapshotDate(before.deal.expectedCloseAt, 'expectedCloseAt'),\n ownerUserId: before.deal.ownerUserId,\n source: before.deal.source,\n closureOutcome: before.deal.closureOutcome,\n lossReasonId: before.deal.lossReasonId,\n lossNotes: before.deal.lossNotes,\n })\n em.persist(deal)\n }\n await withAtomicFlush(em, [\n () => syncDealPeople(em, deal, before.people),\n () => syncDealCompanies(em, deal, before.companies),\n () => deleteDealStageTransitions(em, deal),\n () => restoreDealStageTransitions(em, deal, before.transitions),\n ], { transaction: true })\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'created',\n entity: deal,\n identifiers: {\n id: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n },\n indexer: dealCrudIndexer,\n events: dealCrudEvents,\n })\n\n const resetValues = buildCustomFieldResetMap(before.custom, undefined)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: DEAL_ENTITY_ID,\n recordId: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n values: resetValues,\n notify: false,\n })\n }\n },\n }\n\nregisterCommand(createDealCommand)\nregisterCommand(updateDealCommand)\nregisterCommand(deleteDealCommand)\n"],
5
+ "mappings": "AAAA,SAAS,uBAAuB;AAEhC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,uBAAuB;AAChC,SAAS,2BAA2B;AACpC,SAAS,2BAA2B;AAGpC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAGK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,2BAA2B;AACpC;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP,SAAS,qBAAqB;AAE9B,SAAS,SAAS;AAClB,SAAS,oBAAoB,6BAA6B;AAC1D,SAAS,mCAAmC,2CAA2C;AAEvF,MAAM,iBAAiB;AACvB,MAAM,kBAAmD;AAAA,EACvD,YAAY,EAAE,UAAU;AAC1B;AAEA,MAAM,iBAAmC;AAAA,EACvC,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,cAAc,CAAC,SAAS;AAAA,IACtB,IAAI,IAAI,YAAY;AAAA,IACpB,gBAAgB,IAAI,YAAY;AAAA,IAChC,UAAU,IAAI,YAAY;AAAA,EAC5B;AACF;AAmBA,SAAS,mBAAmB,OAAyC,WAAgC;AACnG,MAAI,UAAU,UAAa,UAAU,KAAM,QAAO;AAClD,MAAI,iBAAiB,KAAM,QAAO;AAClC,QAAM,OAAO,IAAI,KAAK,KAAK;AAC3B,MAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,GAAG;AAChC,UAAM,IAAI,MAAM,sBAAsB,SAAS,wBAAwB,KAAK,EAAE;AAAA,EAChF;AACA,SAAO;AACT;AAEA,SAAS,2BAA2B,OAAsB,WAAyB;AACjF,QAAM,OAAO,mBAAmB,OAAO,SAAS;AAChD,MAAI,CAAC,MAAM;AACT,UAAM,IAAI,MAAM,sBAAsB,SAAS,qBAAqB;AAAA,EACtE;AACA,SAAO;AACT;AAEA,eAAe,0BACb,IACA,iBACA,UACA,gBACuC;AACvC,QAAM,QAAQ,MAAM,sBAAsB,IAAI,uBAAuB,EAAE,IAAI,gBAAgB,GAAG,CAAC,GAAG,EAAE,UAAU,eAAe,CAAC;AAC9H,MAAI,CAAC,MAAO,QAAO;AACnB,SAAO;AAAA,IACL,IAAI,MAAM;AAAA,IACV,YAAY,MAAM;AAAA,IAClB,OAAO,MAAM;AAAA,IACb,OAAO,MAAM;AAAA,EACf;AACF;AAEA,eAAe,0BACb,IACA,iBACA,UACA,gBACwB;AACxB,QAAM,QAAQ,MAAM,0BAA0B,IAAI,iBAAiB,UAAU,cAAc;AAC3F,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,QAAQ,MAAM,sBAAsB,IAAI;AAAA,IAC5C;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN,OAAO,MAAM;AAAA,EACf,CAAC;AACD,SAAO,OAAO,SAAS,MAAM;AAC/B;AAEA,SAAS,0BAA0B,OAI+B;AAChE,QAAM,sBAAsB,MAAM,cAAc;AAChD,QAAM,2BAA2B,MAAM,mBAAmB;AAE1D,MAAI,4BAA4B,CAAC,MAAM,eAAe;AACpD,UAAM,IAAI,cAAc,KAAK,EAAE,OAAO,2BAA2B,CAAC;AAAA,EACpE;AAEA,MACE,uBACA,MAAM,iBACN,MAAM,cAAc,eAAe,qBACnC;AACA,UAAM,IAAI,cAAc,KAAK;AAAA,MAC3B,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,YAAY,uBAAuB,MAAM,eAAe,cAAc;AAAA,IACtE,iBAAiB;AAAA,EACnB;AACF;AAEA,eAAe,0BACb,IACA,OASe;AACf,MAAI,WAA+C;AACnD,MAAI;AACF,eAAW,MAAM;AAAA,MACf;AAAA,MACA;AAAA,MACA,EAAE,MAAM,MAAM,KAAK,IAAI,SAAS,MAAM,SAAS,WAAW,KAAK;AAAA,MAC/D,CAAC;AAAA,MACD,EAAE,UAAU,MAAM,KAAK,UAAU,gBAAgB,MAAM,KAAK,eAAe;AAAA,IAC7E;AAAA,EACF,SAAS,OAAO;AACd,QAAI,CAAC,kCAAkC,KAAK,GAAG;AAC7C,YAAM;AAAA,IACR;AACA,wCAAoC,2CAA2C;AAC/E;AAAA,EACF;AACA,QAAM,iBAAiB,MAAM,kBAAkB,oBAAI,KAAK;AACxD,MAAI,UAAU;AACZ,aAAS,aAAa,MAAM;AAC5B,aAAS,aAAa,MAAM;AAC5B,aAAS,aAAa,MAAM;AAC5B,aAAS,iBAAiB;AAC1B,aAAS,uBAAuB,MAAM;AACtC,aAAS,YAAY;AACrB,aAAS,WAAW;AACpB;AAAA,EACF;AAEA,QAAM,aAAa,GAAG,OAAO,6BAA6B;AAAA,IACxD,gBAAgB,MAAM,KAAK;AAAA,IAC3B,UAAU,MAAM,KAAK;AAAA,IACrB,MAAM,MAAM;AAAA,IACZ,YAAY,MAAM;AAAA,IAClB,SAAS,MAAM;AAAA,IACf,YAAY,MAAM;AAAA,IAClB,YAAY,MAAM;AAAA,IAClB;AAAA,IACA,sBAAsB,MAAM;AAAA,IAC5B,UAAU;AAAA,EACZ,CAAC;AACD,KAAG,QAAQ,UAAU;AACvB;AAEA,eAAe,2BAA2B,IAAmB,MAAmC;AAC9F,MAAI;AACF,UAAM,GAAG,aAAa,6BAA6B,EAAE,MAAM,KAAK,GAAG,CAAC;AAAA,EACtE,SAAS,OAAO;AACd,QAAI,CAAC,kCAAkC,KAAK,GAAG;AAC7C,YAAM;AAAA,IACR;AACA,wCAAoC,4CAA4C;AAAA,EAClF;AACF;AAEA,eAAe,4BACb,IACA,MACA,aACe;AACf,MAAI,CAAC,YAAY,OAAQ;AACzB,aAAW,sBAAsB,aAAa;AAC5C,UAAM,aAAa,GAAG,OAAO,6BAA6B;AAAA,MACxD,IAAI,mBAAmB;AAAA,MACvB,gBAAgB,KAAK;AAAA,MACrB,UAAU,KAAK;AAAA,MACf;AAAA,MACA,YAAY,mBAAmB;AAAA,MAC/B,SAAS,mBAAmB;AAAA,MAC5B,YAAY,mBAAmB;AAAA,MAC/B,YAAY,mBAAmB;AAAA,MAC/B,gBAAgB,2BAA2B,mBAAmB,gBAAgB,gBAAgB;AAAA,MAC9F,sBAAsB,mBAAmB;AAAA,MACzC,UAAU;AAAA,IACZ,CAAC;AACD,OAAG,QAAQ,UAAU;AAAA,EACvB;AACF;AAsCA,eAAe,iBAAiB,IAAmB,IAA0C;AAC3F,QAAM,OAAO,MAAM,sBAAsB,IAAI,cAAc,EAAE,IAAI,WAAW,KAAK,CAAC;AAClF,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,kBAAkB,EAAE,UAAU,KAAK,YAAY,MAAM,gBAAgB,KAAK,kBAAkB,KAAK;AACvG,QAAM,cAAc,MAAM;AAAA,IACxB;AAAA,IACA;AAAA,IACA,EAAE,KAAW;AAAA,IACb,EAAE,UAAU,CAAC,QAAQ,EAAE;AAAA,IACvB;AAAA,EACF;AACA,QAAM,eAAe,MAAM;AAAA,IACzB;AAAA,IACA;AAAA,IACA,EAAE,KAAW;AAAA,IACb,EAAE,UAAU,CAAC,SAAS,EAAE;AAAA,IACxB;AAAA,EACF;AACA,QAAM,cAAc,MAAM;AAAA,IACxB;AAAA,IACA;AAAA,IACA,EAAE,MAAM,KAAK,IAAI,WAAW,KAAK;AAAA,IACjC,EAAE,SAAS,EAAE,YAAY,OAAO,gBAAgB,MAAM,EAAE;AAAA,IACxD;AAAA,EACF,EAAE,MAAM,CAAC,UAAmB;AAC1B,QAAI,CAAC,kCAAkC,KAAK,GAAG;AAC7C,YAAM;AAAA,IACR;AACA,wCAAoC,uCAAuC;AAC3E,WAAO,CAAC;AAAA,EACV,CAAC;AACD,QAAM,SAAS,MAAM,wBAAwB,IAAI;AAAA,IAC/C,UAAU;AAAA,IACV,UAAU,KAAK;AAAA,IACf,UAAU,KAAK;AAAA,IACf,gBAAgB,KAAK;AAAA,EACvB,CAAC;AACD,SAAO;AAAA,IACL,MAAM;AAAA,MACJ,IAAI,KAAK;AAAA,MACT,gBAAgB,KAAK;AAAA,MACrB,UAAU,KAAK;AAAA,MACf,OAAO,KAAK;AAAA,MACZ,aAAa,KAAK,eAAe;AAAA,MACjC,QAAQ,KAAK;AAAA,MACb,eAAe,KAAK,iBAAiB;AAAA,MACrC,YAAY,KAAK,cAAc;AAAA,MAC/B,iBAAiB,KAAK,mBAAmB;AAAA,MACzC,aAAa,KAAK,eAAe;AAAA,MACjC,eAAe,KAAK,iBAAiB;AAAA,MACrC,aAAa,KAAK,eAAe;AAAA,MACjC,iBAAiB,KAAK,mBAAmB;AAAA,MACzC,aAAa,KAAK,eAAe;AAAA,MACjC,QAAQ,KAAK,UAAU;AAAA,MACvB,gBAAgB,KAAK,kBAAkB;AAAA,MACvC,cAAc,KAAK,gBAAgB;AAAA,MACnC,WAAW,KAAK,aAAa;AAAA,IAC/B;AAAA,IACA,QAAQ,YAAY;AAAA,MAAI,CAAC,SACvB,OAAO,KAAK,WAAW,WAAW,KAAK,SAAS,KAAK,OAAO;AAAA,IAC9D;AAAA,IACA,WAAW,aAAa;AAAA,MAAI,CAAC,SAC3B,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU,KAAK,QAAQ;AAAA,IACjE;AAAA,IACA,aAAa,YAAY,IAAI,CAAC,gBAAgB;AAAA,MAC5C,IAAI,WAAW;AAAA,MACf,YAAY,WAAW;AAAA,MACvB,SAAS,WAAW;AAAA,MACpB,YAAY,WAAW;AAAA,MACvB,YAAY,WAAW;AAAA,MACvB,gBAAgB,WAAW;AAAA,MAC3B,sBAAsB,WAAW,wBAAwB;AAAA,IAC3D,EAAE;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,gBAAgB,OAAiD;AACxE,MAAI,UAAU,UAAa,UAAU,KAAM,QAAO;AAClD,SAAO,MAAM,SAAS;AACxB;AAEA,eAAe,eACb,IACA,MACA,WACe;AACf,MAAI,cAAc,OAAW;AAC7B,QAAM,GAAG,aAAa,wBAAwB,EAAE,KAAK,CAAC;AACtD,MAAI,CAAC,aAAa,CAAC,UAAU,OAAQ;AACrC,QAAM,SAAS,MAAM,KAAK,IAAI,IAAI,SAAS,CAAC;AAC5C,aAAW,YAAY,QAAQ;AAC7B,UAAM,SAAS,MAAM,sBAAsB,IAAI,UAAU,EAAE,UAAU,KAAK,UAAU,gBAAgB,KAAK,eAAe,GAAG,UAAU,kBAAkB;AACvJ,oBAAgB,QAAQ,KAAK,gBAAgB,KAAK,QAAQ;AAC1D,UAAM,OAAO,GAAG,OAAO,wBAAwB;AAAA,MAC7C;AAAA,MACA;AAAA,IACF,CAAC;AACD,OAAG,QAAQ,IAAI;AAAA,EACjB;AACF;AAEA,eAAe,kBACb,IACA,MACA,YACe;AACf,MAAI,eAAe,OAAW;AAC9B,QAAM,GAAG,aAAa,yBAAyB,EAAE,KAAK,CAAC;AACvD,MAAI,CAAC,cAAc,CAAC,WAAW,OAAQ;AACvC,QAAM,SAAS,MAAM,KAAK,IAAI,IAAI,UAAU,CAAC;AAC7C,aAAW,aAAa,QAAQ;AAC9B,UAAM,UAAU,MAAM,sBAAsB,IAAI,WAAW,EAAE,UAAU,KAAK,UAAU,gBAAgB,KAAK,eAAe,GAAG,WAAW,mBAAmB;AAC3J,oBAAgB,SAAS,KAAK,gBAAgB,KAAK,QAAQ;AAC3D,UAAM,OAAO,GAAG,OAAO,yBAAyB;AAAA,MAC9C;AAAA,MACA;AAAA,IACF,CAAC;AACD,OAAG,QAAQ,IAAI;AAAA,EACjB;AACF;AAEA,MAAM,oBAAyE;AAAA,EAC7E,IAAI;AAAA,EACJ,MAAM,QAAQ,UAAU,KAAK;AAC3B,UAAM,EAAE,QAAQ,OAAO,IAAI,sBAAsB,kBAAkB,QAAQ;AAC3E,sBAAkB,KAAK,OAAO,QAAQ;AACtC,4BAAwB,KAAK,OAAO,cAAc;AAElD,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,mCAAmC,sBAAsB,MAAM,IAAI,IAAI;AAC7E,QAAI;AACJ,QAAI,gBAA8C;AAClD,QAAI,qBAAoF;AAAA,MACtF,YAAY;AAAA,MACZ,iBAAiB;AAAA,IACnB;AACA,QAAI,6BAA4C;AAChD,UAAM,gBAAgB,IAAI;AAAA,MACxB,YAAY;AACV,wBAAgB,OAAO,kBACnB,MAAM,0BAA0B,IAAI,OAAO,iBAAiB,OAAO,UAAU,OAAO,cAAc,IAClG;AACJ,6BAAqB,0BAA0B;AAAA,UAC7C,YAAY,OAAO;AAAA,UACnB,iBAAiB,OAAO;AAAA,UACxB;AAAA,QACF,CAAC;AACD,qCAA6B,iBACxB,MAAM,sBAAsB,IAAI;AAAA,UACjC,UAAU,OAAO;AAAA,UACjB,gBAAgB,OAAO;AAAA,UACvB,MAAM;AAAA,UACN,OAAO,cAAc;AAAA,QACvB,CAAC,IAAI,SAAS,cAAc,QAC1B,OAAO,iBAAiB;AAAA,MAC9B;AAAA,MACA,YAAY;AACV,eAAO,GAAG,OAAO,cAAc;AAAA,UAC7B,gBAAgB,OAAO;AAAA,UACvB,UAAU,OAAO;AAAA,UACjB,OAAO,OAAO;AAAA,UACd,aAAa,OAAO,eAAe;AAAA,UACnC,QAAQ,OAAO,UAAU;AAAA,UACzB,eAAe;AAAA,UACf,YAAY,mBAAmB;AAAA,UAC/B,iBAAiB,mBAAmB;AAAA,UACpC,aAAa,gBAAgB,OAAO,WAAW;AAAA,UAC/C,eAAe,OAAO,iBAAiB;AAAA,UACvC,aAAa,OAAO,eAAe;AAAA,UACnC,iBAAiB,OAAO,mBAAmB;AAAA,UAC3C,aAAa,OAAO,eAAe;AAAA,UACnC,QAAQ,OAAO,UAAU;AAAA,UACzB,gBAAgB,OAAO,kBAAkB;AAAA,UACzC,cAAc,OAAO,gBAAgB;AAAA,UACrC,WAAW,OAAO,aAAa;AAAA,QACjC,CAAC;AACD,WAAG,QAAQ,IAAI;AACf,cAAM,GAAG,MAAM;AAAA,MACjB;AAAA,MACA,YAAY;AACV,cAAM,WAAW;AACjB,YAAI,CAAC,SAAU;AACf,cAAM,0BAA0B,IAAI;AAAA,UAClC;AAAA,UACA,YAAY,SAAS;AAAA,UACrB,SAAS,SAAS;AAAA,UAClB,YAAY,SAAS;AAAA,UACrB,YAAY,SAAS;AAAA,UACrB,sBAAsB;AAAA,QACxB,CAAC;AAAA,MACH;AAAA,MACA,MAAM,eAAe,IAAI,MAAM,OAAO,aAAa,CAAC,CAAC;AAAA,MACrD,MAAM,kBAAkB,IAAI,MAAM,OAAO,cAAc,CAAC,CAAC;AAAA,IAC3D,GAAG,EAAE,aAAa,KAAK,CAAC;AAExB,UAAM,KAAM,IAAI,UAAU,QAAQ,YAAY;AAC9C,UAAM,qBAAqB;AAAA,MACzB,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,UAAU,KAAK;AAAA,MACf,gBAAgB,KAAK;AAAA,MACrB,UAAU,KAAK;AAAA,MACf,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV,CAAC;AAED,UAAM,oBAAoB;AAAA,MACxB,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,aAAa;AAAA,QACX,IAAI,KAAK;AAAA,QACT,gBAAgB,KAAK;AAAA,QACrB,UAAU,KAAK;AAAA,MACjB;AAAA,MACA,SAAS;AAAA,MACT,QAAQ;AAAA,IACV,CAAC;AAED,WAAO,EAAE,QAAQ,KAAK,GAAG;AAAA,EAC3B;AAAA,EACA,cAAc,OAAO,QAAQ,QAAQ,QAAQ;AAC3C,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,WAAO,MAAM,iBAAiB,IAAI,OAAO,MAAM;AAAA,EACjD;AAAA,EACA,UAAU,OAAO,EAAE,QAAQ,IAAI,MAAM;AACnC,UAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAChD,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,WAAW,MAAM,iBAAiB,IAAI,OAAO,MAAM;AACzD,WAAO;AAAA,MACL,aAAa,UAAU,gCAAgC,aAAa;AAAA,MACpE,cAAc;AAAA,MACd,YAAY,OAAO;AAAA,MACnB,UAAU,UAAU,KAAK,YAAY;AAAA,MACrC,gBAAgB,UAAU,KAAK,kBAAkB;AAAA,MACjD,eAAe,YAAY;AAAA,MAC3B,SAAS;AAAA,QACP,MAAM;AAAA,UACJ,OAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EACA,MAAM,OAAO,EAAE,UAAU,IAAI,MAAM;AACjC,UAAM,SAAS,UAAU;AACzB,QAAI,CAAC,OAAQ;AACb,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,OAAO,MAAM,sBAAsB,IAAI,cAAc,EAAE,IAAI,OAAO,CAAC;AACzE,QAAI,CAAC,KAAM;AACX,UAAM,2BAA2B,IAAI,IAAI;AACzC,UAAM,GAAG,aAAa,wBAAwB,EAAE,KAAK,CAAC;AACtD,UAAM,GAAG,aAAa,yBAAyB,EAAE,KAAK,CAAC;AACvD,OAAG,OAAO,IAAI;AACd,UAAM,GAAG,MAAM;AAAA,EACjB;AAAA,EACA,MAAM,OAAO,EAAE,UAAU,IAAI,MAAM;AACjC,UAAM,QAAQ,oBAAkC,QAAQ;AACxD,QAAI,CAAC,OAAO;AACV,YAAM,IAAI,cAAc,KAAK,EAAE,OAAO,uDAAuD,CAAC;AAAA,IAChG;AACA,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,QAAI,OAAO,MAAM,sBAAsB,IAAI,cAAc,EAAE,IAAI,MAAM,KAAK,GAAG,CAAC;AAC9E,QAAI,CAAC,MAAM;AACT,aAAO,GAAG,OAAO,cAAc;AAAA,QAC7B,IAAI,MAAM,KAAK;AAAA,QACf,gBAAgB,MAAM,KAAK;AAAA,QAC3B,UAAU,MAAM,KAAK;AAAA,QACrB,OAAO,MAAM,KAAK;AAAA,QAClB,aAAa,MAAM,KAAK;AAAA,QACxB,QAAQ,MAAM,KAAK;AAAA,QACnB,eAAe,MAAM,KAAK;AAAA,QAC1B,YAAY,MAAM,KAAK;AAAA,QACvB,iBAAiB,MAAM,KAAK;AAAA,QAC5B,aAAa,MAAM,KAAK;AAAA,QACxB,eAAe,MAAM,KAAK;AAAA,QAC1B,aAAa,MAAM,KAAK;AAAA,QACxB,iBAAiB,MAAM,KAAK;AAAA,QAC5B,aAAa,MAAM,KAAK;AAAA,QACxB,QAAQ,MAAM,KAAK;AAAA,QACnB,gBAAgB,MAAM,KAAK;AAAA,QAC3B,cAAc,MAAM,KAAK;AAAA,QACzB,WAAW,MAAM,KAAK;AAAA,MACxB,CAAC;AACD,SAAG,QAAQ,IAAI;AAAA,IACjB;AACA,UAAM,eAAe;AACrB,UAAM,gBAAgB,IAAI;AAAA,MACxB,MAAM,eAAe,IAAI,cAAc,MAAM,MAAM;AAAA,MACnD,MAAM,kBAAkB,IAAI,cAAc,MAAM,SAAS;AAAA,MACzD,MAAM,2BAA2B,IAAI,YAAY;AAAA,MACjD,MAAM,4BAA4B,IAAI,cAAc,MAAM,WAAW;AAAA,IACvE,GAAG,EAAE,aAAa,KAAK,CAAC;AAExB,UAAM,KAAM,IAAI,UAAU,QAAQ,YAAY;AAC9C,UAAM,oBAAoB;AAAA,MACxB,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,aAAa;AAAA,QACX,IAAI,aAAa;AAAA,QACjB,gBAAgB,aAAa;AAAA,QAC7B,UAAU,aAAa;AAAA,MACzB;AAAA,MACA,SAAS;AAAA,MACT,QAAQ;AAAA,IACV,CAAC;AAED,UAAM,gBAAgB,yBAAyB,MAAM,QAAQ,MAAS;AACtE,QAAI,OAAO,KAAK,aAAa,EAAE,QAAQ;AACrC,YAAM,qBAAqB;AAAA,QACzB,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,UAAU,aAAa;AAAA,QACvB,gBAAgB,aAAa;AAAA,QAC7B,UAAU,aAAa;AAAA,QACvB,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV,CAAC;AAAA,IACH;AAEA,WAAO,EAAE,QAAQ,aAAa,GAAG;AAAA,EACnC;AACF;AAEA,MAAM,oBAAyE;AAAA,EAC7E,IAAI;AAAA,EACJ,MAAM,QAAQ,UAAU,KAAK;AAC3B,UAAM,EAAE,OAAO,IAAI,sBAAsB,kBAAkB,QAAQ;AACnE,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,WAAW,MAAM,iBAAiB,IAAI,OAAO,EAAE;AACrD,WAAO,WAAW,EAAE,QAAQ,SAAS,IAAI,CAAC;AAAA,EAC5C;AAAA,EACA,MAAM,QAAQ,UAAU,KAAK;AAC3B,UAAM,EAAE,QAAQ,OAAO,IAAI,sBAAsB,kBAAkB,QAAQ;AAC3E,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,OAAO,MAAM,sBAAsB,IAAI,cAAc,EAAE,IAAI,OAAO,IAAI,WAAW,KAAK,CAAC;AAC7F,UAAM,SAAS,QAAQ;AACvB,QAAI,CAAC,OAAQ,OAAM,IAAI,cAAc,KAAK,EAAE,OAAO,iBAAiB,CAAC;AACrE,sBAAkB,KAAK,OAAO,QAAQ;AACtC,4BAAwB,KAAK,OAAO,cAAc;AAElD,UAAM,iBAAiB,OAAO;AAC9B,UAAM,0BAA0B,OAAO,mBAAmB;AAC1D,UAAM,mCAAmC,sBAAsB,MAAM,IAAI,IAAI;AAE7E,QAAI,oBAAkD;AACtD,QAAI,yBAAwF;AAAA,MAC1F,YAAY,OAAO,cAAc;AAAA,MACjC,iBAAiB,OAAO,mBAAmB;AAAA,IAC7C;AACA,QAAI,yBAAwC;AAC5C,QAAI,oCAAmD;AAEvD,UAAM,oBAAoB;AAAA,MACxB;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,OAAO,EAAE,UAAU,OAAO,UAAU,gBAAgB,OAAO,eAAe;AAAA,MAC1E,cAAc;AAAA,MACd,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,YAAY,OAAO;AAAA,QACjB,QAAQ;AAAA,QACR,aAAa;AAAA,UACX,IAAI,OAAO;AAAA,UACX,gBAAgB,OAAO;AAAA,UACvB,UAAU,OAAO;AAAA,QACnB;AAAA,MACF;AAAA,MACA,QAAQ;AAAA,QACN,YAAY;AACV,gBAAM,4BACJ,OAAO,eAAe,UAAa,OAAO,oBAAoB;AAChE,gBAAM,2BACJ,OAAO,oBAAoB,SACvB,OAAO,mBAAmB,OAC1B,OAAO,mBAAmB;AAChC,gBAAM,sBACJ,OAAO,eAAe,SAAY,OAAO,cAAc,OAAO,OAAO,cAAc;AAErF,8BAAoB,6BAA6B,6BAA6B,CAAC,OAAO,iBAClF,MAAM,0BAA0B,IAAI,0BAA0B,OAAO,UAAU,OAAO,cAAc,IACpG;AACJ,cAAI,2BAA2B;AAC7B,qCAAyB,0BAA0B;AAAA,cACjD,YAAY;AAAA,cACZ,iBAAiB;AAAA,cACjB,eAAe;AAAA,YACjB,CAAC;AAAA,UACH;AACA,mCAAyB,qBACpB,MAAM,sBAAsB,IAAI;AAAA,YACjC,UAAU,OAAO;AAAA,YACjB,gBAAgB,OAAO;AAAA,YACvB,MAAM;AAAA,YACN,OAAO,kBAAkB;AAAA,UAC3B,CAAC,IAAI,SAAS,kBAAkB,QAC9B;AACJ,8CACE,CAAC,qBAAqB,OAAO,oBAAoB,OAAO,oBAAoB,UAAa,CAAC,OAAO,iBAC7F,MAAM,0BAA0B,IAAI,OAAO,iBAAiB,OAAO,UAAU,OAAO,cAAc,IAClG;AAAA,QACR;AAAA,QACA,MAAM;AACJ,cAAI,OAAO,UAAU,OAAW,QAAO,QAAQ,OAAO;AACtD,cAAI,OAAO,gBAAgB,OAAW,QAAO,cAAc,OAAO,eAAe;AACjF,cAAI,OAAO,WAAW,OAAW,QAAO,SAAS,OAAO,UAAU,OAAO;AACzE,cAAI,OAAO,kBAAkB,OAAW,QAAO,gBAAgB,OAAO,iBAAiB;AACvF,cAAI,OAAO,eAAe,UAAc,OAAO,oBAAoB,UAAa,mBAAoB;AAClG,mBAAO,aAAa,uBAAuB;AAAA,UAC7C;AACA,cAAI,OAAO,oBAAoB,OAAW,QAAO,kBAAkB,uBAAuB;AAE1F,cAAI,2BAA2B,OAAO,oBAAoB,UAAa,CAAC,OAAO,gBAAgB;AAC7F,mBAAO,gBAAgB;AAAA,UACzB,WAAW,sCAAsC,OAAO,oBAAoB,UAAa,CAAC,OAAO,gBAAgB;AAC/G,mBAAO,gBAAgB;AAAA,UACzB;AAEA,cAAI,OAAO,gBAAgB,OAAW,QAAO,cAAc,gBAAgB,OAAO,WAAW;AAC7F,cAAI,OAAO,kBAAkB,OAAW,QAAO,gBAAgB,OAAO,iBAAiB;AACvF,cAAI,OAAO,gBAAgB,OAAW,QAAO,cAAc,OAAO,eAAe;AACjF,cAAI,OAAO,oBAAoB,OAAW,QAAO,kBAAkB,OAAO,mBAAmB;AAC7F,cAAI,OAAO,gBAAgB,OAAW,QAAO,cAAc,OAAO,eAAe;AACjF,cAAI,OAAO,WAAW,OAAW,QAAO,SAAS,OAAO,UAAU;AAClE,cAAI,OAAO,mBAAmB,OAAW,QAAO,iBAAiB,OAAO,kBAAkB;AAC1F,cAAI,OAAO,iBAAiB,OAAW,QAAO,eAAe,OAAO,gBAAgB;AACpF,cAAI,OAAO,cAAc,OAAW,QAAO,YAAY,OAAO,aAAa;AAAA,QAC7E;AAAA,QACA,YAAY;AASV,gBAAM,GAAG,MAAM;AAAA,QACjB;AAAA,QACA,YAAY;AACV,gBAAM,WAAW;AACjB,cAAI,CAAC,SAAU;AACf,gBAAM,eACJ,OAAO,oBAAoB,UAC3B,OAAO,oBAAoB,QAC3B,OAAO,oBAAoB;AAC7B,cAAI,CAAC,aAAc;AACnB,gBAAM,0BAA0B,IAAI;AAAA,YAClC,MAAM;AAAA,YACN,YAAY,SAAS;AAAA,YACrB,SAAS,SAAS;AAAA,YAClB,YAAY,0BAA0B,SAAS;AAAA,YAC/C,YAAY,SAAS;AAAA,YACrB,sBAAsB;AAAA,UACxB,CAAC;AAAA,QACH;AAAA,QACA,MAAM,eAAe,IAAI,QAAQ,OAAO,SAAS;AAAA,QACjD,MAAM,kBAAkB,IAAI,QAAQ,OAAO,UAAU;AAAA,MACvD;AAAA,IACF,CAAC;AAID,UAAM,YAAY,OAAO;AACzB,UAAM,mBAAmB,cAAc,QAAQ,QAAQ,cAAc,UAAU,SAAS;AACxF,QAAI,mBAAmB,cAAc,qBAAqB,SAAS,qBAAqB,SAAS;AAC/F,YAAM,eAAe,qBAAqB,QAAQ,uBAAuB;AACzE,UAAI;AACF,cAAM,WAAW,IAAI,UAAU,QAAQ,UAAU;AACjD,YAAI,UAAU;AACZ,gBAAM,SAAS;AAAA,YACb;AAAA,YACA;AAAA,cACE,IAAI,OAAO;AAAA,cACX,UAAU,OAAO;AAAA,cACjB,gBAAgB,OAAO;AAAA,cACvB,aAAa,OAAO,eAAe;AAAA,cACnC,OAAO,OAAO;AAAA,cACd,aAAa,OAAO,eAAe;AAAA,cACnC,eAAe,OAAO,iBAAiB;AAAA,YACzC;AAAA,YACA,EAAE,YAAY,KAAK;AAAA,UACrB;AAAA,QACF;AAAA,MACF,SAAS,KAAK;AACZ,gBAAQ,KAAK,2DAA2D,cAAc,GAAG;AAAA,MAC3F;AAAA,IACF;AAEA,WAAO,EAAE,QAAQ,OAAO,GAAG;AAAA,EAC7B;AAAA,EACA,cAAc,OAAO,QAAQ,QAAQ,QAAQ;AAC3C,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,WAAO,MAAM,iBAAiB,IAAI,OAAO,MAAM;AAAA,EACjD;AAAA,EACA,UAAU,OAAO,EAAE,QAAQ,WAAW,IAAI,MAAM;AAC9C,UAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAChD,UAAM,SAAS,UAAU;AACzB,QAAI,CAAC,OAAQ,QAAO;AACpB,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,gBAAgB,MAAM,iBAAiB,IAAI,OAAO,MAAM;AAC9D,WAAO;AAAA,MACL,aAAa,UAAU,gCAAgC,aAAa;AAAA,MACpE,cAAc;AAAA,MACd,YAAY,OAAO,KAAK;AAAA,MACxB,UAAU,OAAO,KAAK;AAAA,MACtB,gBAAgB,OAAO,KAAK;AAAA,MAC5B,gBAAgB;AAAA,MAChB,eAAe,iBAAiB;AAAA,MAChC,SAAS;AAAA,QACP,MAAM;AAAA,UACJ;AAAA,UACA,OAAO,iBAAiB;AAAA,QAC1B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EACA,MAAM,OAAO,EAAE,UAAU,IAAI,MAAM;AACjC,UAAM,UAAU,mBAAoC,QAAQ;AAC5D,UAAM,SAAS,SAAS;AACxB,QAAI,CAAC,OAAQ;AACb,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,mCAAmC,sBAAsB,MAAM,IAAI,IAAI;AAC7E,QAAI,OAAO,MAAM,sBAAsB,IAAI,cAAc,EAAE,IAAI,OAAO,KAAK,GAAG,CAAC;AAC/E,QAAI,CAAC,MAAM;AACT,aAAO,GAAG,OAAO,cAAc;AAAA,QAC7B,IAAI,OAAO,KAAK;AAAA,QAChB,gBAAgB,OAAO,KAAK;AAAA,QAC5B,UAAU,OAAO,KAAK;AAAA,QACtB,OAAO,OAAO,KAAK;AAAA,QACnB,aAAa,OAAO,KAAK;AAAA,QACzB,QAAQ,OAAO,KAAK;AAAA,QACpB,eAAe,OAAO,KAAK;AAAA,QAC3B,YAAY,OAAO,KAAK;AAAA,QACxB,iBAAiB,OAAO,KAAK;AAAA,QAC7B,aAAa,OAAO,KAAK;AAAA,QACzB,eAAe,OAAO,KAAK;AAAA,QAC3B,aAAa,OAAO,KAAK;AAAA,QACzB,iBAAiB,mBAAmB,OAAO,KAAK,iBAAiB,iBAAiB;AAAA,QAClF,aAAa,OAAO,KAAK;AAAA,QACzB,QAAQ,OAAO,KAAK;AAAA,QACpB,gBAAgB,OAAO,KAAK;AAAA,QAC5B,cAAc,OAAO,KAAK;AAAA,QAC1B,WAAW,OAAO,KAAK;AAAA,MACzB,CAAC;AACD,SAAG,QAAQ,IAAI;AAAA,IACjB;AACA,UAAM,wBAAwB,OAAO,KAAK,kBACtC,MAAM,0BAA0B,IAAI,OAAO,KAAK,iBAAiB,OAAO,KAAK,UAAU,OAAO,KAAK,cAAc,IACjH;AACJ,UAAM,qBAAqB,OAAO,KAAK,kBACnC,OAAO,YAAY,KAAK,CAAC,eAAe,WAAW,YAAY,OAAO,KAAK,eAAe,KAAK,OAC/F;AACJ,UAAM,+BACJ,OAAO,KAAK,qBAAqB,SAAS,OAAO,KAAK,mBAAmB,SACzE,CAAC,CAAC,OAAO,KAAK,mBACd,CAAC,EAAE,uBAAuB,cAAc,OAAO,KAAK,cAAc,oBAAoB,eACtF,CAAC,EAAE,uBAAuB,SAAS,OAAO,KAAK,iBAAiB,oBAAoB;AAEtF,UAAM,gBAAgB,IAAI;AAAA,MACxB,MAAM;AACJ,aAAK,QAAQ,OAAO,KAAK;AACzB,aAAK,cAAc,OAAO,KAAK;AAC/B,aAAK,SAAS,OAAO,KAAK;AAC1B,aAAK,gBAAgB,OAAO,KAAK;AACjC,aAAK,aAAa,OAAO,KAAK;AAC9B,aAAK,kBAAkB,OAAO,KAAK;AACnC,aAAK,cAAc,OAAO,KAAK;AAC/B,aAAK,gBAAgB,OAAO,KAAK;AACjC,aAAK,cAAc,OAAO,KAAK;AAC/B,aAAK,kBAAkB,mBAAmB,OAAO,KAAK,iBAAiB,iBAAiB;AACxF,aAAK,cAAc,OAAO,KAAK;AAC/B,aAAK,SAAS,OAAO,KAAK;AAC1B,aAAK,iBAAiB,OAAO,KAAK;AAClC,aAAK,eAAe,OAAO,KAAK;AAChC,aAAK,YAAY,OAAO,KAAK;AAAA,MAC/B;AAAA,MACA,YAAY;AAMV,cAAM,GAAG,MAAM;AAAA,MACjB;AAAA,MACA,YAAY;AACV,YAAI,CAAC,gCAAgC,CAAC,OAAO,KAAK,gBAAiB;AACnE,cAAM,aAAa,uBAAuB,cAAc,OAAO,KAAK,cAAc,oBAAoB;AACtG,cAAM,aAAa,uBAAuB,SAAS,OAAO,KAAK,iBAAiB,oBAAoB;AACpG,YAAI,CAAC,cAAc,CAAC,WAAY;AAChC,cAAM,0BAA0B,IAAI;AAAA,UAClC;AAAA,UACA;AAAA,UACA,SAAS,OAAO,KAAK;AAAA,UACrB;AAAA,UACA,YAAY,uBAAuB,SAAS,oBAAoB,cAAc;AAAA,UAC9E,sBAAsB;AAAA,QACxB,CAAC;AAAA,MACH;AAAA,MACA,MAAM,eAAe,IAAI,MAAM,OAAO,MAAM;AAAA,MAC5C,MAAM,kBAAkB,IAAI,MAAM,OAAO,SAAS;AAAA,IACpD,GAAG,EAAE,aAAa,KAAK,CAAC;AAExB,UAAM,KAAM,IAAI,UAAU,QAAQ,YAAY;AAC9C,UAAM,wBAAwB;AAAA,MAC5B,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,aAAa;AAAA,QACX,IAAI,KAAK;AAAA,QACT,gBAAgB,KAAK;AAAA,QACrB,UAAU,KAAK;AAAA,MACjB;AAAA,MACA,SAAS;AAAA,MACT,QAAQ;AAAA,IACV,CAAC;AAED,UAAM,cAAc,yBAAyB,OAAO,QAAQ,SAAS,OAAO,MAAM;AAClF,QAAI,OAAO,KAAK,WAAW,EAAE,QAAQ;AACnC,YAAM,qBAAqB;AAAA,QACzB,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,UAAU,KAAK;AAAA,QACf,gBAAgB,KAAK;AAAA,QACrB,UAAU,KAAK;AAAA,QACf,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEA,MAAM,oBACJ;AAAA,EACE,IAAI;AAAA,EACJ,MAAM,QAAQ,OAAO,KAAK;AACxB,UAAM,KAAK,UAAU,OAAO,kBAAkB;AAC9C,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,WAAW,MAAM,iBAAiB,IAAI,EAAE;AAC9C,WAAO,WAAW,EAAE,QAAQ,SAAS,IAAI,CAAC;AAAA,EAC5C;AAAA,EACA,MAAM,QAAQ,OAAO,KAAK;AACxB,UAAM,KAAK,UAAU,OAAO,kBAAkB;AAC9C,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,OAAO,MAAM,sBAAsB,IAAI,cAAc,EAAE,IAAI,WAAW,KAAK,CAAC;AAClF,UAAM,SAAS,QAAQ;AACvB,QAAI,CAAC,OAAQ,OAAM,IAAI,cAAc,KAAK,EAAE,OAAO,iBAAiB,CAAC;AACrE,sBAAkB,KAAK,OAAO,QAAQ;AACtC,4BAAwB,KAAK,OAAO,cAAc;AAClD,UAAM,2BAA2B,IAAI,MAAM;AAC3C,UAAM,GAAG,aAAa,wBAAwB,EAAE,MAAM,OAAO,CAAC;AAC9D,UAAM,GAAG,aAAa,yBAAyB,EAAE,MAAM,OAAO,CAAC;AAC/D,OAAG,OAAO,MAAM;AAChB,UAAM,GAAG,MAAM;AAEf,UAAM,KAAM,IAAI,UAAU,QAAQ,YAAY;AAC9C,UAAM,oBAAoB;AAAA,MACxB,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,aAAa;AAAA,QACX,IAAI,OAAO;AAAA,QACX,gBAAgB,OAAO;AAAA,QACvB,UAAU,OAAO;AAAA,MACnB;AAAA,MACA,SAAS;AAAA,MACT,QAAQ;AAAA,IACV,CAAC;AACD,WAAO,EAAE,QAAQ,OAAO,GAAG;AAAA,EAC7B;AAAA,EACA,UAAU,OAAO,EAAE,UAAU,MAAM;AACjC,UAAM,SAAS,UAAU;AACzB,QAAI,CAAC,OAAQ,QAAO;AACpB,UAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAChD,WAAO;AAAA,MACL,aAAa,UAAU,gCAAgC,aAAa;AAAA,MACpE,cAAc;AAAA,MACd,YAAY,OAAO,KAAK;AAAA,MACxB,UAAU,OAAO,KAAK;AAAA,MACtB,gBAAgB,OAAO,KAAK;AAAA,MAC5B,gBAAgB;AAAA,MAChB,SAAS;AAAA,QACP,MAAM;AAAA,UACJ;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EACA,MAAM,OAAO,EAAE,UAAU,IAAI,MAAM;AACjC,UAAM,UAAU,mBAAoC,QAAQ;AAC5D,UAAM,SAAS,SAAS;AACxB,QAAI,CAAC,OAAQ;AACb,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,QAAI,OAAO,MAAM,sBAAsB,IAAI,cAAc,EAAE,IAAI,OAAO,KAAK,GAAG,CAAC;AAC/E,QAAI,CAAC,MAAM;AACT,aAAO,GAAG,OAAO,cAAc;AAAA,QAC7B,IAAI,OAAO,KAAK;AAAA,QAChB,gBAAgB,OAAO,KAAK;AAAA,QAC5B,UAAU,OAAO,KAAK;AAAA,QACtB,OAAO,OAAO,KAAK;AAAA,QACnB,aAAa,OAAO,KAAK;AAAA,QACzB,QAAQ,OAAO,KAAK;AAAA,QACpB,eAAe,OAAO,KAAK;AAAA,QAC3B,YAAY,OAAO,KAAK;AAAA,QACxB,iBAAiB,OAAO,KAAK;AAAA,QAC7B,aAAa,OAAO,KAAK;AAAA,QACzB,eAAe,OAAO,KAAK;AAAA,QAC3B,aAAa,OAAO,KAAK;AAAA,QACzB,iBAAiB,mBAAmB,OAAO,KAAK,iBAAiB,iBAAiB;AAAA,QAClF,aAAa,OAAO,KAAK;AAAA,QACzB,QAAQ,OAAO,KAAK;AAAA,QACpB,gBAAgB,OAAO,KAAK;AAAA,QAC5B,cAAc,OAAO,KAAK;AAAA,QAC1B,WAAW,OAAO,KAAK;AAAA,MACzB,CAAC;AACD,SAAG,QAAQ,IAAI;AAAA,IACjB;AACA,UAAM,gBAAgB,IAAI;AAAA,MACxB,MAAM,eAAe,IAAI,MAAM,OAAO,MAAM;AAAA,MAC5C,MAAM,kBAAkB,IAAI,MAAM,OAAO,SAAS;AAAA,MAClD,MAAM,2BAA2B,IAAI,IAAI;AAAA,MACzC,MAAM,4BAA4B,IAAI,MAAM,OAAO,WAAW;AAAA,IAChE,GAAG,EAAE,aAAa,KAAK,CAAC;AAExB,UAAM,KAAM,IAAI,UAAU,QAAQ,YAAY;AAC9C,UAAM,wBAAwB;AAAA,MAC5B,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,aAAa;AAAA,QACX,IAAI,KAAK;AAAA,QACT,gBAAgB,KAAK;AAAA,QACrB,UAAU,KAAK;AAAA,MACjB;AAAA,MACA,SAAS;AAAA,MACT,QAAQ;AAAA,IACV,CAAC;AAED,UAAM,cAAc,yBAAyB,OAAO,QAAQ,MAAS;AACrE,QAAI,OAAO,KAAK,WAAW,EAAE,QAAQ;AACnC,YAAM,qBAAqB;AAAA,QACzB,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,UAAU,KAAK;AAAA,QACf,gBAAgB,KAAK;AAAA,QACrB,UAAU,KAAK;AAAA,QACf,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEF,gBAAgB,iBAAiB;AACjC,gBAAgB,iBAAiB;AACjC,gBAAgB,iBAAiB;",
6
6
  "names": []
7
7
  }
@@ -79,7 +79,7 @@ const createEntityRoleCommand = {
79
79
  ensureTenantScope(ctx, parsed.tenantId);
80
80
  ensureOrganizationScope(ctx, parsed.organizationId);
81
81
  const em = ctx.container.resolve("em").fork();
82
- const entity = await requireCustomerEntity(em, parsed.entityId, parsed.entityType, "Customer not found");
82
+ const entity = await requireCustomerEntity(em, parsed.entityId, { tenantId: parsed.tenantId, organizationId: parsed.organizationId }, parsed.entityType, "Customer not found");
83
83
  ensureSameScope(entity, parsed.organizationId, parsed.tenantId);
84
84
  const activeExisting = await findOneWithDecryption(
85
85
  em,
@@ -416,6 +416,7 @@ const deleteEntityRoleCommand = {
416
416
  const entity = await requireCustomerEntity(
417
417
  em,
418
418
  before.role.entityId,
419
+ { tenantId: before.role.tenantId, organizationId: before.role.organizationId },
419
420
  before.role.entityType,
420
421
  "Customer not found"
421
422
  );
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/customers/commands/entity-roles.ts"],
4
- "sourcesContent": ["import { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport type { CrudEventsConfig } from '@open-mercato/shared/lib/crud/types'\nimport { emitCrudSideEffects, emitCrudUndoSideEffects } from '@open-mercato/shared/lib/commands/helpers'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { CustomerEntity, CustomerEntityRole } from '../data/entities'\nimport {\n entityRoleCreateSchema,\n entityRoleUpdateSchema,\n entityRoleDeleteSchema,\n type EntityRoleCreateInput,\n type EntityRoleUpdateInput,\n type EntityRoleDeleteInput,\n} from '../data/validators'\nimport {\n ensureOrganizationScope,\n ensureSameScope,\n ensureTenantScope,\n extractUndoPayload,\n requireCustomerEntity,\n resolveParentResourceKind,\n} from './shared'\nimport { resolveRedoSnapshot } from '@open-mercato/shared/lib/commands/redo'\n\ntype EntityRoleSnapshot = {\n role: {\n id: string\n entityType: 'company' | 'person'\n entityId: string\n userId: string\n roleType: string\n organizationId: string\n tenantId: string\n }\n entityKind: 'company' | 'person' | null\n}\n\ntype EntityRoleUndoPayload = {\n before?: EntityRoleSnapshot | null\n after?: EntityRoleSnapshot | null\n /**\n * True when createEntityRole \"undeleted\" a previously soft-deleted row\n * instead of inserting a fresh one. Undo must restore that soft-delete\n * state rather than soft-delete the freshly-restored row.\n */\n wasUndelete?: boolean\n /** userId held by the soft-deleted row before undelete; restored on undo. */\n previousUserId?: string | null\n /** deletedAt timestamp held by the soft-deleted row before undelete. */\n previousDeletedAt?: string | null\n}\n\nconst entityRoleCrudEvents: CrudEventsConfig = {\n module: 'customers',\n entity: 'entity_role',\n persistent: true,\n buildPayload: (ctx) => ({\n id: ctx.identifiers.id,\n organizationId: ctx.identifiers.organizationId,\n tenantId: ctx.identifiers.tenantId,\n entityId:\n ctx.entity && typeof ctx.entity === 'object' && 'entityId' in (ctx.entity as Record<string, unknown>)\n ? (ctx.entity as CustomerEntityRole).entityId\n : null,\n entityType:\n ctx.entity && typeof ctx.entity === 'object' && 'entityType' in (ctx.entity as Record<string, unknown>)\n ? (ctx.entity as CustomerEntityRole).entityType\n : null,\n roleType:\n ctx.entity && typeof ctx.entity === 'object' && 'roleType' in (ctx.entity as Record<string, unknown>)\n ? (ctx.entity as CustomerEntityRole).roleType\n : null,\n userId:\n ctx.entity && typeof ctx.entity === 'object' && 'userId' in (ctx.entity as Record<string, unknown>)\n ? (ctx.entity as CustomerEntityRole).userId\n : null,\n ...(ctx.syncOrigin ? { syncOrigin: ctx.syncOrigin } : {}),\n }),\n}\n\nfunction getRoleIdentifiers(role: CustomerEntityRole) {\n return {\n id: role.id,\n organizationId: role.organizationId,\n tenantId: role.tenantId,\n }\n}\n\nasync function loadEntityRoleSnapshot(\n em: EntityManager,\n id: string,\n scope?: { tenantId?: string | null; organizationId?: string | null },\n): Promise<EntityRoleSnapshot | null> {\n const filter: Record<string, unknown> = { id, deletedAt: null }\n if (scope?.tenantId) filter.tenantId = scope.tenantId\n if (scope?.organizationId) filter.organizationId = scope.organizationId\n const role = await findOneWithDecryption(\n em,\n CustomerEntityRole,\n filter,\n undefined,\n { tenantId: scope?.tenantId ?? null, organizationId: scope?.organizationId ?? null },\n )\n if (!role) return null\n\n const entity = await findOneWithDecryption(\n em,\n CustomerEntity,\n { id: role.entityId, tenantId: role.tenantId, deletedAt: null },\n undefined,\n { tenantId: role.tenantId, organizationId: role.organizationId },\n )\n\n return {\n role: {\n id: role.id,\n entityType: role.entityType as 'company' | 'person',\n entityId: role.entityId,\n userId: role.userId,\n roleType: role.roleType,\n organizationId: role.organizationId,\n tenantId: role.tenantId,\n },\n entityKind: entity?.kind === 'company' || entity?.kind === 'person' ? entity.kind : null,\n }\n}\n\nconst createEntityRoleCommand: CommandHandler<EntityRoleCreateInput, { roleId: string; wasUndelete: boolean; previousUserId: string | null; previousDeletedAt: string | null }> = {\n id: 'customers.entityRoles.create',\n async execute(rawInput, ctx) {\n const parsed = entityRoleCreateSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entity = await requireCustomerEntity(em, parsed.entityId, parsed.entityType, 'Customer not found')\n ensureSameScope(entity, parsed.organizationId, parsed.tenantId)\n\n const activeExisting = await findOneWithDecryption(\n em,\n CustomerEntityRole,\n {\n entityType: parsed.entityType,\n entityId: parsed.entityId,\n roleType: parsed.roleType,\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n deletedAt: null,\n },\n undefined,\n { tenantId: parsed.tenantId, organizationId: parsed.organizationId },\n )\n if (activeExisting) {\n throw new CrudHttpError(409, { error: 'Role type already assigned for this entity' })\n }\n\n const softDeleted = await findOneWithDecryption(\n em,\n CustomerEntityRole,\n {\n entityType: parsed.entityType,\n entityId: parsed.entityId,\n roleType: parsed.roleType,\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n },\n undefined,\n { tenantId: parsed.tenantId, organizationId: parsed.organizationId },\n )\n let role: CustomerEntityRole\n let wasUndelete = false\n let previousUserId: string | null = null\n let previousDeletedAt: string | null = null\n if (softDeleted) {\n wasUndelete = true\n previousUserId = softDeleted.userId ?? null\n previousDeletedAt = softDeleted.deletedAt instanceof Date ? softDeleted.deletedAt.toISOString() : null\n softDeleted.deletedAt = null\n softDeleted.userId = parsed.userId\n role = softDeleted\n } else {\n role = em.create(CustomerEntityRole, {\n entityType: parsed.entityType,\n entityId: parsed.entityId,\n userId: parsed.userId,\n roleType: parsed.roleType,\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n })\n em.persist(role)\n }\n await em.flush()\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'created',\n entity: role,\n identifiers: getRoleIdentifiers(role),\n syncOrigin: ctx.syncOrigin,\n events: entityRoleCrudEvents,\n indexer: { entityType: 'customers:entity_role' },\n })\n\n return { roleId: role.id, wasUndelete, previousUserId, previousDeletedAt }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager)\n return loadEntityRoleSnapshot(em, result.roleId, {\n tenantId: ctx.auth?.tenantId ?? null,\n organizationId: ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null,\n })\n },\n buildLog: async ({ result, snapshots }) => {\n const { translate } = await resolveTranslations()\n const snapshot = snapshots.after as EntityRoleSnapshot | undefined\n return {\n actionLabel: translate('customers.audit.entityRoles.create', 'Create entity role'),\n resourceKind: 'customers.entityRole',\n resourceId: result.roleId,\n parentResourceKind: resolveParentResourceKind(snapshot?.entityKind),\n parentResourceId: snapshot?.role.entityId ?? null,\n tenantId: snapshot?.role.tenantId ?? null,\n organizationId: snapshot?.role.organizationId ?? null,\n snapshotAfter: snapshot ?? null,\n payload: {\n undo: {\n after: snapshot ?? null,\n wasUndelete: result.wasUndelete,\n previousUserId: result.previousUserId,\n previousDeletedAt: result.previousDeletedAt,\n } satisfies EntityRoleUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<EntityRoleUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const role = await findOneWithDecryption(\n em,\n CustomerEntityRole,\n { id: after.role.id },\n undefined,\n { tenantId: after.role.tenantId, organizationId: after.role.organizationId },\n )\n if (!role) return\n\n if (payload?.wasUndelete) {\n role.deletedAt = payload.previousDeletedAt ? new Date(payload.previousDeletedAt) : new Date()\n if (payload.previousUserId) role.userId = payload.previousUserId\n } else {\n role.deletedAt = new Date()\n }\n await em.flush()\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudUndoSideEffects({\n dataEngine,\n action: 'deleted',\n entity: role,\n identifiers: getRoleIdentifiers(role),\n syncOrigin: ctx.syncOrigin,\n events: entityRoleCrudEvents,\n indexer: { entityType: 'customers:entity_role' },\n })\n },\n redo: async ({ logEntry, ctx }) => {\n const after = resolveRedoSnapshot<EntityRoleSnapshot>(logEntry)\n if (!after) {\n throw new CrudHttpError(400, { error: '[internal] redo snapshot unavailable for entity role create' })\n }\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let role = await findOneWithDecryption(\n em,\n CustomerEntityRole,\n { id: after.role.id },\n undefined,\n { tenantId: after.role.tenantId, organizationId: after.role.organizationId },\n )\n if (!role) {\n role = em.create(CustomerEntityRole, {\n id: after.role.id,\n entityType: after.role.entityType,\n entityId: after.role.entityId,\n userId: after.role.userId,\n roleType: after.role.roleType,\n organizationId: after.role.organizationId,\n tenantId: after.role.tenantId,\n })\n em.persist(role)\n } else {\n role.deletedAt = null\n role.userId = after.role.userId\n }\n await em.flush()\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'created',\n entity: role,\n identifiers: getRoleIdentifiers(role),\n syncOrigin: ctx.syncOrigin,\n events: entityRoleCrudEvents,\n indexer: { entityType: 'customers:entity_role' },\n })\n\n return {\n roleId: role.id,\n wasUndelete: false,\n previousUserId: null,\n previousDeletedAt: null,\n }\n },\n}\n\nconst updateEntityRoleCommand: CommandHandler<EntityRoleUpdateInput, { roleId: string }> = {\n id: 'customers.entityRoles.update',\n async prepare(rawInput, ctx) {\n const parsed = entityRoleUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadEntityRoleSnapshot(em, parsed.id, {\n tenantId: ctx.auth?.tenantId ?? null,\n organizationId: ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null,\n })\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const parsed = entityRoleUpdateSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const role = await findOneWithDecryption(\n em,\n CustomerEntityRole,\n { id: parsed.id, tenantId: parsed.tenantId, organizationId: parsed.organizationId, deletedAt: null },\n undefined,\n { tenantId: parsed.tenantId, organizationId: parsed.organizationId },\n )\n if (!role) {\n throw new CrudHttpError(404, { error: 'Role not found' })\n }\n\n role.userId = parsed.userId\n await em.flush()\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'updated',\n entity: role,\n identifiers: getRoleIdentifiers(role),\n syncOrigin: ctx.syncOrigin,\n events: entityRoleCrudEvents,\n indexer: { entityType: 'customers:entity_role' },\n })\n\n return { roleId: role.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = ctx.container.resolve('em') as EntityManager\n return loadEntityRoleSnapshot(em, result.roleId, {\n tenantId: ctx.auth?.tenantId ?? null,\n organizationId: ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null,\n })\n },\n buildLog: async ({ result, snapshots }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as EntityRoleSnapshot | undefined\n const after = snapshots.after as EntityRoleSnapshot | undefined\n return {\n actionLabel: translate('customers.audit.entityRoles.update', 'Update entity role'),\n resourceKind: 'customers.entityRole',\n resourceId: result.roleId,\n parentResourceKind: resolveParentResourceKind(after?.entityKind ?? before?.entityKind),\n parentResourceId: after?.role.entityId ?? before?.role.entityId ?? null,\n tenantId: after?.role.tenantId ?? before?.role.tenantId ?? null,\n organizationId: after?.role.organizationId ?? before?.role.organizationId ?? null,\n snapshotBefore: before ?? null,\n snapshotAfter: after ?? null,\n payload: {\n undo: {\n before: before ?? null,\n after: after ?? null,\n } satisfies EntityRoleUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<EntityRoleUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const role = await findOneWithDecryption(\n em,\n CustomerEntityRole,\n { id: before.role.id },\n undefined,\n { tenantId: before.role.tenantId, organizationId: before.role.organizationId },\n )\n if (!role) return\n\n role.userId = before.role.userId\n await em.flush()\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudUndoSideEffects({\n dataEngine,\n action: 'updated',\n entity: role,\n identifiers: getRoleIdentifiers(role),\n syncOrigin: ctx.syncOrigin,\n events: entityRoleCrudEvents,\n indexer: { entityType: 'customers:entity_role' },\n })\n },\n}\n\nconst deleteEntityRoleCommand: CommandHandler<EntityRoleDeleteInput, { roleId: string }> = {\n id: 'customers.entityRoles.delete',\n async prepare(rawInput, ctx) {\n const parsed = entityRoleDeleteSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadEntityRoleSnapshot(em, parsed.id, {\n tenantId: ctx.auth?.tenantId ?? null,\n organizationId: ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null,\n })\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const parsed = entityRoleDeleteSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const role = await findOneWithDecryption(\n em,\n CustomerEntityRole,\n { id: parsed.id, tenantId: parsed.tenantId, organizationId: parsed.organizationId, deletedAt: null },\n undefined,\n { tenantId: parsed.tenantId, organizationId: parsed.organizationId },\n )\n if (!role) {\n throw new CrudHttpError(404, { error: 'Role not found' })\n }\n\n role.deletedAt = new Date()\n await em.flush()\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'deleted',\n entity: role,\n identifiers: getRoleIdentifiers(role),\n syncOrigin: ctx.syncOrigin,\n events: entityRoleCrudEvents,\n indexer: { entityType: 'customers:entity_role' },\n })\n\n return { roleId: role.id }\n },\n buildLog: async ({ result, snapshots }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as EntityRoleSnapshot | undefined\n return {\n actionLabel: translate('customers.audit.entityRoles.delete', 'Delete entity role'),\n resourceKind: 'customers.entityRole',\n resourceId: result.roleId,\n parentResourceKind: resolveParentResourceKind(before?.entityKind),\n parentResourceId: before?.role.entityId ?? null,\n tenantId: before?.role.tenantId ?? null,\n organizationId: before?.role.organizationId ?? null,\n snapshotBefore: before ?? null,\n payload: {\n undo: {\n before: before ?? null,\n } satisfies EntityRoleUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<EntityRoleUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entity = await requireCustomerEntity(\n em,\n before.role.entityId,\n before.role.entityType,\n 'Customer not found',\n )\n ensureSameScope(entity, before.role.organizationId, before.role.tenantId)\n\n let role = await findOneWithDecryption(\n em,\n CustomerEntityRole,\n { id: before.role.id },\n undefined,\n { tenantId: before.role.tenantId, organizationId: before.role.organizationId },\n )\n if (!role) {\n role = em.create(CustomerEntityRole, {\n id: before.role.id,\n entityType: before.role.entityType,\n entityId: before.role.entityId,\n userId: before.role.userId,\n roleType: before.role.roleType,\n organizationId: before.role.organizationId,\n tenantId: before.role.tenantId,\n })\n em.persist(role)\n } else {\n role.userId = before.role.userId\n role.roleType = before.role.roleType\n role.deletedAt = null\n }\n await em.flush()\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudUndoSideEffects({\n dataEngine,\n action: 'created',\n entity: role,\n identifiers: getRoleIdentifiers(role),\n syncOrigin: ctx.syncOrigin,\n events: entityRoleCrudEvents,\n indexer: { entityType: 'customers:entity_role' },\n })\n },\n}\n\nregisterCommand(createEntityRoleCommand)\nregisterCommand(updateEntityRoleCommand)\nregisterCommand(deleteEntityRoleCommand)\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport type { CrudEventsConfig } from '@open-mercato/shared/lib/crud/types'\nimport { emitCrudSideEffects, emitCrudUndoSideEffects } from '@open-mercato/shared/lib/commands/helpers'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { CustomerEntity, CustomerEntityRole } from '../data/entities'\nimport {\n entityRoleCreateSchema,\n entityRoleUpdateSchema,\n entityRoleDeleteSchema,\n type EntityRoleCreateInput,\n type EntityRoleUpdateInput,\n type EntityRoleDeleteInput,\n} from '../data/validators'\nimport {\n ensureOrganizationScope,\n ensureSameScope,\n ensureTenantScope,\n extractUndoPayload,\n requireCustomerEntity,\n resolveParentResourceKind,\n} from './shared'\nimport { resolveRedoSnapshot } from '@open-mercato/shared/lib/commands/redo'\n\ntype EntityRoleSnapshot = {\n role: {\n id: string\n entityType: 'company' | 'person'\n entityId: string\n userId: string\n roleType: string\n organizationId: string\n tenantId: string\n }\n entityKind: 'company' | 'person' | null\n}\n\ntype EntityRoleUndoPayload = {\n before?: EntityRoleSnapshot | null\n after?: EntityRoleSnapshot | null\n /**\n * True when createEntityRole \"undeleted\" a previously soft-deleted row\n * instead of inserting a fresh one. Undo must restore that soft-delete\n * state rather than soft-delete the freshly-restored row.\n */\n wasUndelete?: boolean\n /** userId held by the soft-deleted row before undelete; restored on undo. */\n previousUserId?: string | null\n /** deletedAt timestamp held by the soft-deleted row before undelete. */\n previousDeletedAt?: string | null\n}\n\nconst entityRoleCrudEvents: CrudEventsConfig = {\n module: 'customers',\n entity: 'entity_role',\n persistent: true,\n buildPayload: (ctx) => ({\n id: ctx.identifiers.id,\n organizationId: ctx.identifiers.organizationId,\n tenantId: ctx.identifiers.tenantId,\n entityId:\n ctx.entity && typeof ctx.entity === 'object' && 'entityId' in (ctx.entity as Record<string, unknown>)\n ? (ctx.entity as CustomerEntityRole).entityId\n : null,\n entityType:\n ctx.entity && typeof ctx.entity === 'object' && 'entityType' in (ctx.entity as Record<string, unknown>)\n ? (ctx.entity as CustomerEntityRole).entityType\n : null,\n roleType:\n ctx.entity && typeof ctx.entity === 'object' && 'roleType' in (ctx.entity as Record<string, unknown>)\n ? (ctx.entity as CustomerEntityRole).roleType\n : null,\n userId:\n ctx.entity && typeof ctx.entity === 'object' && 'userId' in (ctx.entity as Record<string, unknown>)\n ? (ctx.entity as CustomerEntityRole).userId\n : null,\n ...(ctx.syncOrigin ? { syncOrigin: ctx.syncOrigin } : {}),\n }),\n}\n\nfunction getRoleIdentifiers(role: CustomerEntityRole) {\n return {\n id: role.id,\n organizationId: role.organizationId,\n tenantId: role.tenantId,\n }\n}\n\nasync function loadEntityRoleSnapshot(\n em: EntityManager,\n id: string,\n scope?: { tenantId?: string | null; organizationId?: string | null },\n): Promise<EntityRoleSnapshot | null> {\n const filter: Record<string, unknown> = { id, deletedAt: null }\n if (scope?.tenantId) filter.tenantId = scope.tenantId\n if (scope?.organizationId) filter.organizationId = scope.organizationId\n const role = await findOneWithDecryption(\n em,\n CustomerEntityRole,\n filter,\n undefined,\n { tenantId: scope?.tenantId ?? null, organizationId: scope?.organizationId ?? null },\n )\n if (!role) return null\n\n const entity = await findOneWithDecryption(\n em,\n CustomerEntity,\n { id: role.entityId, tenantId: role.tenantId, deletedAt: null },\n undefined,\n { tenantId: role.tenantId, organizationId: role.organizationId },\n )\n\n return {\n role: {\n id: role.id,\n entityType: role.entityType as 'company' | 'person',\n entityId: role.entityId,\n userId: role.userId,\n roleType: role.roleType,\n organizationId: role.organizationId,\n tenantId: role.tenantId,\n },\n entityKind: entity?.kind === 'company' || entity?.kind === 'person' ? entity.kind : null,\n }\n}\n\nconst createEntityRoleCommand: CommandHandler<EntityRoleCreateInput, { roleId: string; wasUndelete: boolean; previousUserId: string | null; previousDeletedAt: string | null }> = {\n id: 'customers.entityRoles.create',\n async execute(rawInput, ctx) {\n const parsed = entityRoleCreateSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entity = await requireCustomerEntity(em, parsed.entityId, { tenantId: parsed.tenantId, organizationId: parsed.organizationId }, parsed.entityType, 'Customer not found')\n ensureSameScope(entity, parsed.organizationId, parsed.tenantId)\n\n const activeExisting = await findOneWithDecryption(\n em,\n CustomerEntityRole,\n {\n entityType: parsed.entityType,\n entityId: parsed.entityId,\n roleType: parsed.roleType,\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n deletedAt: null,\n },\n undefined,\n { tenantId: parsed.tenantId, organizationId: parsed.organizationId },\n )\n if (activeExisting) {\n throw new CrudHttpError(409, { error: 'Role type already assigned for this entity' })\n }\n\n const softDeleted = await findOneWithDecryption(\n em,\n CustomerEntityRole,\n {\n entityType: parsed.entityType,\n entityId: parsed.entityId,\n roleType: parsed.roleType,\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n },\n undefined,\n { tenantId: parsed.tenantId, organizationId: parsed.organizationId },\n )\n let role: CustomerEntityRole\n let wasUndelete = false\n let previousUserId: string | null = null\n let previousDeletedAt: string | null = null\n if (softDeleted) {\n wasUndelete = true\n previousUserId = softDeleted.userId ?? null\n previousDeletedAt = softDeleted.deletedAt instanceof Date ? softDeleted.deletedAt.toISOString() : null\n softDeleted.deletedAt = null\n softDeleted.userId = parsed.userId\n role = softDeleted\n } else {\n role = em.create(CustomerEntityRole, {\n entityType: parsed.entityType,\n entityId: parsed.entityId,\n userId: parsed.userId,\n roleType: parsed.roleType,\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n })\n em.persist(role)\n }\n await em.flush()\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'created',\n entity: role,\n identifiers: getRoleIdentifiers(role),\n syncOrigin: ctx.syncOrigin,\n events: entityRoleCrudEvents,\n indexer: { entityType: 'customers:entity_role' },\n })\n\n return { roleId: role.id, wasUndelete, previousUserId, previousDeletedAt }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager)\n return loadEntityRoleSnapshot(em, result.roleId, {\n tenantId: ctx.auth?.tenantId ?? null,\n organizationId: ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null,\n })\n },\n buildLog: async ({ result, snapshots }) => {\n const { translate } = await resolveTranslations()\n const snapshot = snapshots.after as EntityRoleSnapshot | undefined\n return {\n actionLabel: translate('customers.audit.entityRoles.create', 'Create entity role'),\n resourceKind: 'customers.entityRole',\n resourceId: result.roleId,\n parentResourceKind: resolveParentResourceKind(snapshot?.entityKind),\n parentResourceId: snapshot?.role.entityId ?? null,\n tenantId: snapshot?.role.tenantId ?? null,\n organizationId: snapshot?.role.organizationId ?? null,\n snapshotAfter: snapshot ?? null,\n payload: {\n undo: {\n after: snapshot ?? null,\n wasUndelete: result.wasUndelete,\n previousUserId: result.previousUserId,\n previousDeletedAt: result.previousDeletedAt,\n } satisfies EntityRoleUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<EntityRoleUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const role = await findOneWithDecryption(\n em,\n CustomerEntityRole,\n { id: after.role.id },\n undefined,\n { tenantId: after.role.tenantId, organizationId: after.role.organizationId },\n )\n if (!role) return\n\n if (payload?.wasUndelete) {\n role.deletedAt = payload.previousDeletedAt ? new Date(payload.previousDeletedAt) : new Date()\n if (payload.previousUserId) role.userId = payload.previousUserId\n } else {\n role.deletedAt = new Date()\n }\n await em.flush()\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudUndoSideEffects({\n dataEngine,\n action: 'deleted',\n entity: role,\n identifiers: getRoleIdentifiers(role),\n syncOrigin: ctx.syncOrigin,\n events: entityRoleCrudEvents,\n indexer: { entityType: 'customers:entity_role' },\n })\n },\n redo: async ({ logEntry, ctx }) => {\n const after = resolveRedoSnapshot<EntityRoleSnapshot>(logEntry)\n if (!after) {\n throw new CrudHttpError(400, { error: '[internal] redo snapshot unavailable for entity role create' })\n }\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let role = await findOneWithDecryption(\n em,\n CustomerEntityRole,\n { id: after.role.id },\n undefined,\n { tenantId: after.role.tenantId, organizationId: after.role.organizationId },\n )\n if (!role) {\n role = em.create(CustomerEntityRole, {\n id: after.role.id,\n entityType: after.role.entityType,\n entityId: after.role.entityId,\n userId: after.role.userId,\n roleType: after.role.roleType,\n organizationId: after.role.organizationId,\n tenantId: after.role.tenantId,\n })\n em.persist(role)\n } else {\n role.deletedAt = null\n role.userId = after.role.userId\n }\n await em.flush()\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'created',\n entity: role,\n identifiers: getRoleIdentifiers(role),\n syncOrigin: ctx.syncOrigin,\n events: entityRoleCrudEvents,\n indexer: { entityType: 'customers:entity_role' },\n })\n\n return {\n roleId: role.id,\n wasUndelete: false,\n previousUserId: null,\n previousDeletedAt: null,\n }\n },\n}\n\nconst updateEntityRoleCommand: CommandHandler<EntityRoleUpdateInput, { roleId: string }> = {\n id: 'customers.entityRoles.update',\n async prepare(rawInput, ctx) {\n const parsed = entityRoleUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadEntityRoleSnapshot(em, parsed.id, {\n tenantId: ctx.auth?.tenantId ?? null,\n organizationId: ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null,\n })\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const parsed = entityRoleUpdateSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const role = await findOneWithDecryption(\n em,\n CustomerEntityRole,\n { id: parsed.id, tenantId: parsed.tenantId, organizationId: parsed.organizationId, deletedAt: null },\n undefined,\n { tenantId: parsed.tenantId, organizationId: parsed.organizationId },\n )\n if (!role) {\n throw new CrudHttpError(404, { error: 'Role not found' })\n }\n\n role.userId = parsed.userId\n await em.flush()\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'updated',\n entity: role,\n identifiers: getRoleIdentifiers(role),\n syncOrigin: ctx.syncOrigin,\n events: entityRoleCrudEvents,\n indexer: { entityType: 'customers:entity_role' },\n })\n\n return { roleId: role.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = ctx.container.resolve('em') as EntityManager\n return loadEntityRoleSnapshot(em, result.roleId, {\n tenantId: ctx.auth?.tenantId ?? null,\n organizationId: ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null,\n })\n },\n buildLog: async ({ result, snapshots }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as EntityRoleSnapshot | undefined\n const after = snapshots.after as EntityRoleSnapshot | undefined\n return {\n actionLabel: translate('customers.audit.entityRoles.update', 'Update entity role'),\n resourceKind: 'customers.entityRole',\n resourceId: result.roleId,\n parentResourceKind: resolveParentResourceKind(after?.entityKind ?? before?.entityKind),\n parentResourceId: after?.role.entityId ?? before?.role.entityId ?? null,\n tenantId: after?.role.tenantId ?? before?.role.tenantId ?? null,\n organizationId: after?.role.organizationId ?? before?.role.organizationId ?? null,\n snapshotBefore: before ?? null,\n snapshotAfter: after ?? null,\n payload: {\n undo: {\n before: before ?? null,\n after: after ?? null,\n } satisfies EntityRoleUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<EntityRoleUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const role = await findOneWithDecryption(\n em,\n CustomerEntityRole,\n { id: before.role.id },\n undefined,\n { tenantId: before.role.tenantId, organizationId: before.role.organizationId },\n )\n if (!role) return\n\n role.userId = before.role.userId\n await em.flush()\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudUndoSideEffects({\n dataEngine,\n action: 'updated',\n entity: role,\n identifiers: getRoleIdentifiers(role),\n syncOrigin: ctx.syncOrigin,\n events: entityRoleCrudEvents,\n indexer: { entityType: 'customers:entity_role' },\n })\n },\n}\n\nconst deleteEntityRoleCommand: CommandHandler<EntityRoleDeleteInput, { roleId: string }> = {\n id: 'customers.entityRoles.delete',\n async prepare(rawInput, ctx) {\n const parsed = entityRoleDeleteSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadEntityRoleSnapshot(em, parsed.id, {\n tenantId: ctx.auth?.tenantId ?? null,\n organizationId: ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null,\n })\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const parsed = entityRoleDeleteSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const role = await findOneWithDecryption(\n em,\n CustomerEntityRole,\n { id: parsed.id, tenantId: parsed.tenantId, organizationId: parsed.organizationId, deletedAt: null },\n undefined,\n { tenantId: parsed.tenantId, organizationId: parsed.organizationId },\n )\n if (!role) {\n throw new CrudHttpError(404, { error: 'Role not found' })\n }\n\n role.deletedAt = new Date()\n await em.flush()\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'deleted',\n entity: role,\n identifiers: getRoleIdentifiers(role),\n syncOrigin: ctx.syncOrigin,\n events: entityRoleCrudEvents,\n indexer: { entityType: 'customers:entity_role' },\n })\n\n return { roleId: role.id }\n },\n buildLog: async ({ result, snapshots }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as EntityRoleSnapshot | undefined\n return {\n actionLabel: translate('customers.audit.entityRoles.delete', 'Delete entity role'),\n resourceKind: 'customers.entityRole',\n resourceId: result.roleId,\n parentResourceKind: resolveParentResourceKind(before?.entityKind),\n parentResourceId: before?.role.entityId ?? null,\n tenantId: before?.role.tenantId ?? null,\n organizationId: before?.role.organizationId ?? null,\n snapshotBefore: before ?? null,\n payload: {\n undo: {\n before: before ?? null,\n } satisfies EntityRoleUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<EntityRoleUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entity = await requireCustomerEntity(\n em,\n before.role.entityId,\n { tenantId: before.role.tenantId, organizationId: before.role.organizationId },\n before.role.entityType,\n 'Customer not found',\n )\n ensureSameScope(entity, before.role.organizationId, before.role.tenantId)\n\n let role = await findOneWithDecryption(\n em,\n CustomerEntityRole,\n { id: before.role.id },\n undefined,\n { tenantId: before.role.tenantId, organizationId: before.role.organizationId },\n )\n if (!role) {\n role = em.create(CustomerEntityRole, {\n id: before.role.id,\n entityType: before.role.entityType,\n entityId: before.role.entityId,\n userId: before.role.userId,\n roleType: before.role.roleType,\n organizationId: before.role.organizationId,\n tenantId: before.role.tenantId,\n })\n em.persist(role)\n } else {\n role.userId = before.role.userId\n role.roleType = before.role.roleType\n role.deletedAt = null\n }\n await em.flush()\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudUndoSideEffects({\n dataEngine,\n action: 'created',\n entity: role,\n identifiers: getRoleIdentifiers(role),\n syncOrigin: ctx.syncOrigin,\n events: entityRoleCrudEvents,\n indexer: { entityType: 'customers:entity_role' },\n })\n },\n}\n\nregisterCommand(createEntityRoleCommand)\nregisterCommand(updateEntityRoleCommand)\nregisterCommand(deleteEntityRoleCommand)\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -222,7 +222,7 @@ const createInteractionCommand = {
222
222
  const em = ctx.container.resolve("em").fork();
223
223
  const normalizedAuthor = normalizeAuthorUserId(parsed.authorUserId ?? null, ctx.auth);
224
224
  const { interaction, entityId, nextInteractionId } = await runInTransaction(em, async (trx) => {
225
- const entity = await requireTimelineParentEntity(trx, parsed.entityId);
225
+ const entity = await requireTimelineParentEntity(trx, parsed.entityId, { tenantId: parsed.tenantId, organizationId: parsed.organizationId });
226
226
  ensureTenantScope(ctx, entity.tenantId);
227
227
  ensureOrganizationScope(ctx, entity.organizationId);
228
228
  if (parsed.dealId) {
@@ -351,7 +351,7 @@ const createInteractionCommand = {
351
351
  }
352
352
  const em = ctx.container.resolve("em").fork();
353
353
  const { interaction, nextInteractionId } = await runInTransaction(em, async (trx) => {
354
- const entity = await requireTimelineParentEntity(trx, after.interaction.entityId);
354
+ const entity = await requireTimelineParentEntity(trx, after.interaction.entityId, { tenantId: after.interaction.tenantId, organizationId: after.interaction.organizationId });
355
355
  let interaction2 = await findOneWithDecryption(trx, CustomerInteraction, { id: after.interaction.id });
356
356
  if (!interaction2) {
357
357
  interaction2 = buildInteractionGraph(trx, {
@@ -587,7 +587,7 @@ const updateInteractionCommand = {
587
587
  const em = ctx.container.resolve("em").fork();
588
588
  const { interaction, nextInteractionId } = await runInTransaction(em, async (trx) => {
589
589
  let interaction2 = await findOneWithDecryption(trx, CustomerInteraction, { id: before.interaction.id });
590
- const entity = await requireTimelineParentEntity(trx, before.interaction.entityId);
590
+ const entity = await requireTimelineParentEntity(trx, before.interaction.entityId, { tenantId: before.interaction.tenantId, organizationId: before.interaction.organizationId });
591
591
  if (!interaction2) {
592
592
  interaction2 = trx.create(CustomerInteraction, {
593
593
  id: before.interaction.id,
@@ -1023,7 +1023,7 @@ const deleteInteractionCommand = {
1023
1023
  if (!before) return;
1024
1024
  const em = ctx.container.resolve("em").fork();
1025
1025
  const { interaction, nextInteractionId } = await runInTransaction(em, async (trx) => {
1026
- const entity = await requireTimelineParentEntity(trx, before.interaction.entityId);
1026
+ const entity = await requireTimelineParentEntity(trx, before.interaction.entityId, { tenantId: before.interaction.tenantId, organizationId: before.interaction.organizationId });
1027
1027
  let interaction2 = await findOneWithDecryption(trx, CustomerInteraction, { id: before.interaction.id });
1028
1028
  if (!interaction2) {
1029
1029
  interaction2 = trx.create(CustomerInteraction, {
@@ -1135,7 +1135,10 @@ const recomputeNextCommand = {
1135
1135
  const parsed = recomputeNextSchema.parse(rawInput);
1136
1136
  const em = ctx.container.resolve("em").fork();
1137
1137
  const projection = await recomputeNextInteraction(em, parsed.entityId);
1138
- const entity = await requireTimelineParentEntity(em, parsed.entityId);
1138
+ const entity = await requireTimelineParentEntity(em, parsed.entityId, {
1139
+ tenantId: ctx.auth?.tenantId ?? "",
1140
+ organizationId: ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? ""
1141
+ });
1139
1142
  await emitNextInteractionUpdatedEvent(ctx, {
1140
1143
  entityId: parsed.entityId,
1141
1144
  nextInteractionId: projection.nextInteractionId