@open-mercato/core 0.6.5-develop.5116.1.f0af9e5080 → 0.6.5-develop.5155.1.148d10a46d

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 (29) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/modules/communication_channels/lib/email-mime.js +18 -1
  3. package/dist/modules/communication_channels/lib/email-mime.js.map +2 -2
  4. package/dist/modules/customers/components/formConfig.js +4 -1
  5. package/dist/modules/customers/components/formConfig.js.map +2 -2
  6. package/dist/modules/customers/data/validators.js +5 -1
  7. package/dist/modules/customers/data/validators.js.map +2 -2
  8. package/dist/modules/sales/commands/configuration.js +2 -2
  9. package/dist/modules/sales/commands/configuration.js.map +2 -2
  10. package/dist/modules/sales/commands/documents.js +17 -13
  11. package/dist/modules/sales/commands/documents.js.map +2 -2
  12. package/dist/modules/sales/commands/payments.js +6 -6
  13. package/dist/modules/sales/commands/payments.js.map +2 -2
  14. package/dist/modules/sales/commands/shipments.js +6 -6
  15. package/dist/modules/sales/commands/shipments.js.map +2 -2
  16. package/dist/modules/sales/lib/dictionaries.js +2 -2
  17. package/dist/modules/sales/lib/dictionaries.js.map +2 -2
  18. package/dist/modules/staff/components/TeamMemberForm.js +5 -2
  19. package/dist/modules/staff/components/TeamMemberForm.js.map +2 -2
  20. package/package.json +14 -14
  21. package/src/modules/communication_channels/lib/email-mime.ts +33 -6
  22. package/src/modules/customers/components/formConfig.tsx +16 -1
  23. package/src/modules/customers/data/validators.ts +8 -1
  24. package/src/modules/sales/commands/configuration.ts +2 -2
  25. package/src/modules/sales/commands/documents.ts +13 -9
  26. package/src/modules/sales/commands/payments.ts +6 -6
  27. package/src/modules/sales/commands/shipments.ts +6 -6
  28. package/src/modules/sales/lib/dictionaries.ts +3 -2
  29. package/src/modules/staff/components/TeamMemberForm.tsx +6 -1
@@ -254,7 +254,7 @@ const createPaymentCommand = {
254
254
  tx.persist(order2);
255
255
  }
256
256
  if (input.documentStatusEntryId !== void 0) {
257
- const orderStatus = await resolveDictionaryEntryValue(tx, input.documentStatusEntryId ?? null);
257
+ const orderStatus = await resolveDictionaryEntryValue(tx, input.documentStatusEntryId ?? null, { tenantId: input.tenantId });
258
258
  if (input.documentStatusEntryId && !orderStatus) {
259
259
  throw new CrudHttpError(400, {
260
260
  error: translate("sales.documents.detail.statusInvalid", "Selected status could not be found.")
@@ -266,7 +266,7 @@ const createPaymentCommand = {
266
266
  tx.persist(order2);
267
267
  }
268
268
  if (input.lineStatusEntryId !== void 0) {
269
- const lineStatus = await resolveDictionaryEntryValue(tx, input.lineStatusEntryId ?? null);
269
+ const lineStatus = await resolveDictionaryEntryValue(tx, input.lineStatusEntryId ?? null, { tenantId: input.tenantId });
270
270
  if (input.lineStatusEntryId && !lineStatus) {
271
271
  throw new CrudHttpError(400, {
272
272
  error: translate("sales.documents.detail.statusInvalid", "Selected status could not be found.")
@@ -280,7 +280,7 @@ const createPaymentCommand = {
280
280
  });
281
281
  orderLines.forEach((line) => tx.persist(line));
282
282
  }
283
- const status = await resolveDictionaryEntryValue(tx, input.statusEntryId ?? null);
283
+ const status = await resolveDictionaryEntryValue(tx, input.statusEntryId ?? null, { tenantId: input.tenantId });
284
284
  const payment2 = tx.create(SalesPayment, {
285
285
  organizationId: input.organizationId,
286
286
  tenantId: input.tenantId,
@@ -621,7 +621,7 @@ const updatePaymentCommand = {
621
621
  throw new CrudHttpError(400, { error: translate("sales.payments.order_required", "Order is required for payments.") });
622
622
  }
623
623
  if (currentOrder && input.documentStatusEntryId !== void 0) {
624
- const orderStatus = await resolveDictionaryEntryValue(tx, input.documentStatusEntryId ?? null);
624
+ const orderStatus = await resolveDictionaryEntryValue(tx, input.documentStatusEntryId ?? null, { tenantId: resolvedTenantId });
625
625
  if (input.documentStatusEntryId && !orderStatus) {
626
626
  throw new CrudHttpError(400, {
627
627
  error: translate("sales.documents.detail.statusInvalid", "Selected status could not be found.")
@@ -633,7 +633,7 @@ const updatePaymentCommand = {
633
633
  tx.persist(currentOrder);
634
634
  }
635
635
  if (currentOrder && input.lineStatusEntryId !== void 0) {
636
- const lineStatus = await resolveDictionaryEntryValue(tx, input.lineStatusEntryId ?? null);
636
+ const lineStatus = await resolveDictionaryEntryValue(tx, input.lineStatusEntryId ?? null, { tenantId: resolvedTenantId });
637
637
  if (input.lineStatusEntryId && !lineStatus) {
638
638
  throw new CrudHttpError(400, {
639
639
  error: translate("sales.documents.detail.statusInvalid", "Selected status could not be found.")
@@ -650,7 +650,7 @@ const updatePaymentCommand = {
650
650
  if (input.paymentReference !== void 0) payment.paymentReference = input.paymentReference ?? null;
651
651
  if (input.statusEntryId !== void 0) {
652
652
  payment.statusEntryId = input.statusEntryId ?? null;
653
- payment.status = await resolveDictionaryEntryValue(tx, input.statusEntryId ?? null);
653
+ payment.status = await resolveDictionaryEntryValue(tx, input.statusEntryId ?? null, { tenantId: resolvedTenantId });
654
654
  }
655
655
  if (input.amount !== void 0) payment.amount = toNumericString(input.amount) ?? "0";
656
656
  if (input.currencyCode !== void 0) payment.currencyCode = input.currencyCode;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/sales/commands/payments.ts"],
4
- "sourcesContent": ["// @ts-nocheck\n\nimport { registerCommand, type CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { LockMode } from '@mikro-orm/core'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { loadCustomFieldValues } from '@open-mercato/shared/lib/crud/custom-fields'\nimport { setRecordCustomFields } from '@open-mercato/core/modules/entities/lib/helpers'\nimport { E } from '#generated/entities.ids.generated'\nimport {\n SalesInvoice,\n SalesOrder,\n SalesOrderLine,\n SalesPayment,\n SalesPaymentAllocation,\n SalesPaymentMethod,\n} from '../data/entities'\nimport {\n paymentCreateSchema,\n paymentUpdateSchema,\n type PaymentCreateInput,\n type PaymentUpdateInput,\n} from '../data/validators'\nimport {\n assertFound,\n cloneJson,\n ensureOrganizationScope,\n ensureSameScope,\n ensureTenantScope,\n extractUndoPayload,\n toNumericString,\n} from './shared'\nimport { resolveDictionaryEntryValue } from '../lib/dictionaries'\nimport { resolveRedoSnapshot } from '@open-mercato/shared/lib/commands/redo'\nimport { invalidateCrudCache } from '@open-mercato/shared/lib/crud/cache'\nimport { emitCrudSideEffects } from '@open-mercato/shared/lib/commands/helpers'\nimport type { CrudEventsConfig } from '@open-mercato/shared/lib/crud/types'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport { findOneWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { resolveNotificationService } from '../../notifications/lib/notificationService'\nimport { buildFeatureNotificationFromType } from '../../notifications/lib/notificationBuilder'\nimport { notificationTypes } from '../notifications'\n\nexport type PaymentAllocationSnapshot = {\n id: string\n orderId: string | null\n invoiceId: string | null\n amount: number\n currencyCode: string\n metadata: Record<string, unknown> | null\n}\n\nexport type PaymentSnapshot = {\n id: string\n orderId: string | null\n organizationId: string\n tenantId: string\n paymentMethodId: string | null\n paymentReference: string | null\n statusEntryId: string | null\n status: string | null\n amount: number\n currencyCode: string\n capturedAmount: number\n refundedAmount: number\n receivedAt: string | null\n capturedAt: string | null\n metadata: Record<string, unknown> | null\n customFields?: Record<string, unknown> | null\n customFieldSetId?: string | null\n allocations: PaymentAllocationSnapshot[]\n}\n\ntype PaymentUndoPayload = {\n before?: PaymentSnapshot | null\n after?: PaymentSnapshot | null\n orderPaymentMethodIdBefore?: string | null\n orderPaymentMethodCodeBefore?: string | null\n}\n\nconst toNumber = (value: unknown): number => {\n if (typeof value === 'number' && Number.isFinite(value)) return value\n if (typeof value === 'string' && value.trim().length) {\n const parsed = Number(value)\n if (!Number.isNaN(parsed)) return parsed\n }\n return 0\n}\n\nconst normalizeCustomFieldsInput = (input: unknown): Record<string, unknown> =>\n input && typeof input === 'object' && !Array.isArray(input) ? (input as Record<string, unknown>) : {}\n\nconst paymentCrudEvents: CrudEventsConfig = {\n module: 'sales',\n entity: 'payment',\n persistent: true,\n buildPayload: (ctx) => ({\n id: ctx.identifiers.id,\n organizationId: ctx.identifiers.organizationId,\n tenantId: ctx.identifiers.tenantId,\n }),\n}\n\nconst ORDER_RESOURCE = 'sales.order'\n\nasync function invalidateOrderCache(container: any, order: SalesOrder | null | undefined, tenantId: string | null) {\n if (!order) return\n await invalidateCrudCache(\n container,\n ORDER_RESOURCE,\n { id: order.id, organizationId: order.organizationId, tenantId: order.tenantId },\n tenantId,\n 'updated'\n )\n}\n\nexport async function loadPaymentSnapshot(em: EntityManager, id: string, scope?: { tenantId?: string | null; organizationId?: string | null }): Promise<PaymentSnapshot | null> {\n const payment = await findOneWithDecryption(\n em,\n SalesPayment,\n { id },\n { populate: ['order', 'allocations', 'allocations.order', 'allocations.invoice'] },\n scope,\n )\n if (!payment) return null\n const allocations: PaymentAllocationSnapshot[] = Array.from(payment.allocations ?? []).map((allocation) => ({\n id: allocation.id,\n orderId:\n typeof allocation.order === 'string'\n ? allocation.order\n : allocation.order?.id ?? (allocation as any).order_id ?? null,\n invoiceId:\n typeof allocation.invoice === 'string'\n ? allocation.invoice\n : allocation.invoice?.id ?? (allocation as any).invoice_id ?? null,\n amount: toNumber(allocation.amount),\n currencyCode: allocation.currencyCode,\n metadata: allocation.metadata ? cloneJson(allocation.metadata) : null,\n }))\n const customFieldValues = await loadCustomFieldValues({\n em,\n entityId: E.sales.sales_payment,\n recordIds: [payment.id],\n tenantIdByRecord: { [payment.id]: payment.tenantId ?? null },\n organizationIdByRecord: { [payment.id]: payment.organizationId ?? null },\n })\n const customFields = customFieldValues[payment.id]\n const normalizedCustomFields =\n customFields && Object.keys(customFields).length ? customFields : null\n return {\n id: payment.id,\n orderId: typeof payment.order === 'string' ? payment.order : payment.order?.id ?? null,\n organizationId: payment.organizationId,\n tenantId: payment.tenantId,\n paymentMethodId:\n typeof payment.paymentMethod === 'string'\n ? payment.paymentMethod\n : payment.paymentMethod?.id ?? null,\n paymentReference: payment.paymentReference ?? null,\n statusEntryId: payment.statusEntryId ?? null,\n status: payment.status ?? null,\n amount: toNumber(payment.amount),\n currencyCode: payment.currencyCode,\n capturedAmount: toNumber(payment.capturedAmount),\n refundedAmount: toNumber(payment.refundedAmount),\n receivedAt: payment.receivedAt ? payment.receivedAt.toISOString() : null,\n capturedAt: payment.capturedAt ? payment.capturedAt.toISOString() : null,\n metadata: payment.metadata ? cloneJson(payment.metadata) : null,\n customFields: normalizedCustomFields,\n customFieldSetId: (payment as any).customFieldSetId ?? (payment as any).custom_field_set_id ?? null,\n allocations,\n }\n}\n\nexport async function restorePaymentSnapshot(em: EntityManager, snapshot: PaymentSnapshot): Promise<void> {\n const orderRef = snapshot.orderId ? em.getReference(SalesOrder, snapshot.orderId) : null\n const methodRef = snapshot.paymentMethodId\n ? em.getReference(SalesPaymentMethod, snapshot.paymentMethodId)\n : null\n const entity =\n (await findOneWithDecryption(em, SalesPayment, { id: snapshot.id }, {}, { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId })) ??\n em.create(SalesPayment, {\n id: snapshot.id,\n createdAt: new Date(),\n organizationId: snapshot.organizationId,\n tenantId: snapshot.tenantId,\n })\n entity.order = orderRef\n entity.paymentMethod = methodRef\n entity.organizationId = snapshot.organizationId\n entity.tenantId = snapshot.tenantId\n entity.paymentReference = snapshot.paymentReference\n entity.statusEntryId = snapshot.statusEntryId\n entity.status = snapshot.status\n entity.amount = toNumericString(snapshot.amount) ?? '0'\n entity.currencyCode = snapshot.currencyCode\n entity.capturedAmount = toNumericString(snapshot.capturedAmount) ?? '0'\n entity.refundedAmount = toNumericString(snapshot.refundedAmount) ?? '0'\n entity.receivedAt = snapshot.receivedAt ? new Date(snapshot.receivedAt) : null\n entity.capturedAt = snapshot.capturedAt ? new Date(snapshot.capturedAt) : null\n entity.metadata = snapshot.metadata ? cloneJson(snapshot.metadata) : null\n entity.customFieldSetId =\n (snapshot as any).customFieldSetId ?? (snapshot as any).custom_field_set_id ?? null\n entity.updatedAt = new Date()\n await em.flush()\n\n if ((snapshot as any).customFields !== undefined) {\n await setRecordCustomFields(em, {\n entityId: E.sales.sales_payment,\n recordId: entity.id,\n organizationId: entity.organizationId,\n tenantId: entity.tenantId,\n values:\n snapshot.customFields && typeof snapshot.customFields === 'object'\n ? (snapshot.customFields as Record<string, unknown>)\n : {},\n })\n }\n\n const existingAllocations = await findWithDecryption(em, SalesPaymentAllocation, { payment: entity }, {}, { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId })\n existingAllocations.forEach((allocation) => em.remove(allocation))\n snapshot.allocations.forEach((allocation) => {\n const order =\n allocation.orderId && typeof allocation.orderId === 'string'\n ? em.getReference(SalesOrder, allocation.orderId)\n : null\n const invoice =\n allocation.invoiceId && typeof allocation.invoiceId === 'string'\n ? em.getReference(SalesInvoice, allocation.invoiceId)\n : null\n const newAllocation = em.create(SalesPaymentAllocation, {\n payment: entity,\n order,\n invoice,\n organizationId: snapshot.organizationId,\n tenantId: snapshot.tenantId,\n amount: toNumericString(allocation.amount) ?? '0',\n currencyCode: allocation.currencyCode,\n metadata: allocation.metadata ? cloneJson(allocation.metadata) : null,\n })\n em.persist(newAllocation)\n })\n em.persist(entity)\n}\n\nasync function recomputeOrderPaymentTotals(\n em: EntityManager,\n order: SalesOrder,\n options?: { lock?: boolean }\n): Promise<{ paidTotalAmount: number; refundedTotalAmount: number; outstandingAmount: number }> {\n const orderId = order.id\n const scope = { organizationId: order.organizationId, tenantId: order.tenantId }\n\n if (options?.lock) {\n // Raw findOne is intentional: this acquires a row lock only \u2014 no encrypted\n // SalesOrder field is read, so decryption (findOneWithDecryption) is unnecessary.\n // Scope filter is defence-in-depth (#2111): the caller is expected to pass a\n // correctly scoped order, but filtering here ensures we never lock a foreign\n // tenant's row even if a caller messed up.\n await em.findOne(SalesOrder, { id: orderId, ...scope }, { lockMode: LockMode.PESSIMISTIC_WRITE })\n }\n\n const allocations = await findWithDecryption(\n em,\n SalesPaymentAllocation,\n { ...scope, order: orderId },\n { populate: ['payment'] },\n scope,\n )\n\n const paymentIds = new Set<string>()\n allocations.forEach((allocation) => {\n const paymentRef = allocation.payment\n const paymentId =\n typeof paymentRef === 'object' && paymentRef !== null\n ? paymentRef.id\n : typeof paymentRef === 'string'\n ? paymentRef\n : null\n if (paymentId) paymentIds.add(paymentId)\n })\n\n const payments =\n paymentIds.size > 0\n ? await findWithDecryption(em, SalesPayment, { id: { $in: Array.from(paymentIds) }, deletedAt: null, ...scope }, {}, scope)\n : await findWithDecryption(em, SalesPayment, { order: orderId, deletedAt: null, ...scope }, {}, scope)\n\n const resolvePaidAmount = (payment: SalesPayment) => {\n const captured = toNumber(payment.capturedAmount)\n return captured > 0 ? captured : toNumber(payment.amount)\n }\n\n const activePaymentIds = new Set(payments.map((payment) => payment.id))\n const paidTotal =\n allocations.length > 0\n ? allocations.reduce((sum, allocation) => {\n const paymentRef = allocation.payment\n const paymentId =\n typeof paymentRef === 'object' && paymentRef !== null\n ? paymentRef.id\n : typeof paymentRef === 'string'\n ? paymentRef\n : null\n if (paymentId && !activePaymentIds.has(paymentId)) return sum\n return sum + toNumber(allocation.amount)\n }, 0)\n : payments.reduce((sum, payment) => sum + resolvePaidAmount(payment), 0)\n\n const refundedTotal = payments.reduce(\n (sum, payment) => sum + toNumber(payment.refundedAmount),\n 0\n )\n\n const grandTotal = toNumber(order.grandTotalGrossAmount)\n const outstanding = Math.max(grandTotal - paidTotal + refundedTotal, 0)\n order.paidTotalAmount = toNumericString(paidTotal) ?? '0'\n order.refundedTotalAmount = toNumericString(refundedTotal) ?? '0'\n order.outstandingAmount = toNumericString(outstanding) ?? '0'\n return {\n paidTotalAmount: paidTotal,\n refundedTotalAmount: refundedTotal,\n outstandingAmount: outstanding,\n }\n}\n\nconst createPaymentCommand: CommandHandler<\n PaymentCreateInput,\n { paymentId: string; orderTotals?: { paidTotalAmount: number; refundedTotalAmount: number; outstandingAmount: number }; orderPaymentMethodIdBefore?: string | null; orderPaymentMethodCodeBefore?: string | null }\n> = {\n id: 'sales.payments.create',\n async execute(rawInput, ctx) {\n const input = paymentCreateSchema.parse(rawInput ?? {})\n ensureTenantScope(ctx, input.tenantId)\n ensureOrganizationScope(ctx, input.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const { translate } = await resolveTranslations()\n if (!input.orderId) {\n throw new CrudHttpError(400, { error: translate('sales.payments.order_required', 'Order is required for payments.') })\n }\n\n const { payment, order, totals, orderPaymentMethodIdBefore, orderPaymentMethodCodeBefore } = await em.transactional(async (tx) => {\n const order = assertFound(\n await findOneWithDecryption(tx, SalesOrder, { id: input.orderId }, { lockMode: LockMode.PESSIMISTIC_WRITE }, { tenantId: input.tenantId, organizationId: input.organizationId }),\n 'sales.payments.order_not_found'\n )\n ensureSameScope(order, input.organizationId, input.tenantId)\n if (order.deletedAt) {\n throw new CrudHttpError(404, { error: 'sales.payments.order_not_found' })\n }\n if (\n order.currencyCode &&\n input.currencyCode &&\n order.currencyCode.toUpperCase() !== input.currencyCode.toUpperCase()\n ) {\n throw new CrudHttpError(400, {\n error: translate('sales.payments.currency_mismatch', 'Payment currency must match the order currency.'),\n })\n }\n let paymentMethod = null\n if (input.paymentMethodId) {\n const method = assertFound(\n await findOneWithDecryption(tx, SalesPaymentMethod, { id: input.paymentMethodId }, {}, { tenantId: input.tenantId, organizationId: input.organizationId }),\n 'sales.payments.method_not_found'\n )\n ensureSameScope(method, input.organizationId, input.tenantId)\n paymentMethod = method\n }\n const orderPaymentMethodIdBefore = order.paymentMethodId ?? null\n const orderPaymentMethodCodeBefore = order.paymentMethodCode ?? null\n if (paymentMethod && !order.paymentMethodId) {\n order.paymentMethodId = paymentMethod.id\n order.paymentMethodCode = paymentMethod.code ?? null\n order.updatedAt = new Date()\n tx.persist(order)\n }\n if (input.documentStatusEntryId !== undefined) {\n const orderStatus = await resolveDictionaryEntryValue(tx, input.documentStatusEntryId ?? null)\n if (input.documentStatusEntryId && !orderStatus) {\n throw new CrudHttpError(400, {\n error: translate('sales.documents.detail.statusInvalid', 'Selected status could not be found.'),\n })\n }\n order.statusEntryId = input.documentStatusEntryId ?? null\n order.status = orderStatus\n order.updatedAt = new Date()\n tx.persist(order)\n }\n if (input.lineStatusEntryId !== undefined) {\n const lineStatus = await resolveDictionaryEntryValue(tx, input.lineStatusEntryId ?? null)\n if (input.lineStatusEntryId && !lineStatus) {\n throw new CrudHttpError(400, {\n error: translate('sales.documents.detail.statusInvalid', 'Selected status could not be found.'),\n })\n }\n const orderLines = await findWithDecryption(tx, SalesOrderLine, { order }, {}, { tenantId: input.tenantId, organizationId: input.organizationId })\n orderLines.forEach((line) => {\n line.statusEntryId = input.lineStatusEntryId ?? null\n line.status = lineStatus\n line.updatedAt = new Date()\n })\n orderLines.forEach((line) => tx.persist(line))\n }\n const status = await resolveDictionaryEntryValue(tx, input.statusEntryId ?? null)\n const payment = tx.create(SalesPayment, {\n organizationId: input.organizationId,\n tenantId: input.tenantId,\n order,\n paymentMethod,\n paymentReference: input.paymentReference ?? null,\n statusEntryId: input.statusEntryId ?? null,\n status,\n amount: toNumericString(input.amount) ?? '0',\n currencyCode: input.currencyCode,\n capturedAmount: toNumericString(input.capturedAmount) ?? '0',\n refundedAmount: toNumericString(input.refundedAmount) ?? '0',\n receivedAt: input.receivedAt ?? null,\n capturedAt: input.capturedAt ?? null,\n metadata: input.metadata ? cloneJson(input.metadata) : null,\n customFieldSetId: input.customFieldSetId ?? null,\n })\n const allocationInputs = Array.isArray(input.allocations) ? input.allocations : []\n const allocations = allocationInputs.length\n ? allocationInputs\n : [\n {\n orderId: input.orderId,\n invoiceId: null,\n amount: input.amount,\n currencyCode: input.currencyCode,\n metadata: null,\n },\n ]\n const orderCache = new Map<string, SalesOrder>([[order.id, order]])\n const invoiceCache = new Map<string, SalesInvoice>()\n for (const allocation of allocations) {\n let allocationOrder: SalesOrder | null = null\n if (allocation.orderId) {\n allocationOrder = orderCache.get(allocation.orderId) ?? null\n if (!allocationOrder) {\n allocationOrder = assertFound(\n await findOneWithDecryption(\n tx,\n SalesOrder,\n { id: allocation.orderId },\n {},\n { tenantId: input.tenantId, organizationId: input.organizationId },\n ),\n 'sales.payments.order_not_found',\n )\n ensureSameScope(allocationOrder, input.organizationId, input.tenantId)\n orderCache.set(allocation.orderId, allocationOrder)\n }\n }\n let allocationInvoice: SalesInvoice | null = null\n if (allocation.invoiceId) {\n allocationInvoice = invoiceCache.get(allocation.invoiceId) ?? null\n if (!allocationInvoice) {\n allocationInvoice = assertFound(\n await findOneWithDecryption(\n tx,\n SalesInvoice,\n { id: allocation.invoiceId },\n {},\n { tenantId: input.tenantId, organizationId: input.organizationId },\n ),\n 'sales.payments.invoice_not_found',\n )\n ensureSameScope(allocationInvoice, input.organizationId, input.tenantId)\n invoiceCache.set(allocation.invoiceId, allocationInvoice)\n }\n }\n const entity = tx.create(SalesPaymentAllocation, {\n payment,\n order: allocationOrder,\n invoice: allocationInvoice,\n organizationId: input.organizationId,\n tenantId: input.tenantId,\n amount: toNumericString(allocation.amount) ?? '0',\n currencyCode: allocation.currencyCode,\n metadata: allocation.metadata ? cloneJson(allocation.metadata) : null,\n })\n tx.persist(entity)\n }\n tx.persist(payment)\n if (input.customFields !== undefined) {\n if (!payment.id) {\n await tx.flush()\n }\n await setRecordCustomFields(tx, {\n entityId: E.sales.sales_payment,\n recordId: payment.id,\n organizationId: input.organizationId,\n tenantId: input.tenantId,\n values: normalizeCustomFieldsInput(input.customFields),\n })\n }\n await tx.flush()\n const totals = await recomputeOrderPaymentTotals(tx, order)\n await tx.flush()\n return { payment, order, totals, orderPaymentMethodIdBefore, orderPaymentMethodCodeBefore }\n })\n\n await invalidateOrderCache(ctx.container, order, ctx.auth?.tenantId ?? null)\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'created',\n entity: payment,\n identifiers: {\n id: payment.id,\n organizationId: payment.organizationId,\n tenantId: payment.tenantId,\n },\n indexer: { entityType: E.sales.sales_payment },\n events: paymentCrudEvents,\n })\n\n // Create notification for payment received\n try {\n const notificationService = resolveNotificationService(ctx.container)\n const typeDef = notificationTypes.find((type) => type.type === 'sales.payment.received')\n if (typeDef) {\n const amountDisplay = payment.amount && payment.currencyCode\n ? `${payment.currencyCode} ${payment.amount}`\n : ''\n const notificationInput = buildFeatureNotificationFromType(typeDef, {\n requiredFeature: 'sales.orders.manage',\n bodyVariables: {\n orderNumber: order.orderNumber ?? '',\n amount: amountDisplay,\n },\n sourceEntityType: 'sales:order',\n sourceEntityId: order.id,\n linkHref: `/backend/sales/orders/${order.id}`,\n })\n\n await notificationService.createForFeature(notificationInput, {\n tenantId: payment.tenantId,\n organizationId: payment.organizationId ?? null,\n })\n }\n } catch (err) {\n // Notification creation is non-critical, don't fail the command\n console.error('[sales.payments.create] Failed to create notification:', err)\n }\n\n return { paymentId: payment.id, orderTotals: totals, orderPaymentMethodIdBefore, orderPaymentMethodCodeBefore }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = ctx.auth?.tenantId ? { tenantId: ctx.auth.tenantId, organizationId: ctx.auth?.orgId ?? null } : undefined\n return result?.paymentId ? loadPaymentSnapshot(em, result.paymentId, scope) : null\n },\n buildLog: async ({ result, snapshots }) => {\n const after = snapshots.after as PaymentSnapshot | undefined\n if (!after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('sales.audit.payments.create', 'Create payment'),\n resourceKind: 'sales.payment',\n resourceId: result.paymentId,\n parentResourceKind: 'sales.order',\n parentResourceId: after.orderId ?? null,\n tenantId: after.tenantId,\n organizationId: after.organizationId,\n snapshotAfter: after,\n payload: { undo: { after, orderPaymentMethodIdBefore: result.orderPaymentMethodIdBefore ?? null, orderPaymentMethodCodeBefore: result.orderPaymentMethodCodeBefore ?? null } satisfies PaymentUndoPayload },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<PaymentUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const existing = await findOneWithDecryption(em, SalesPayment, { id: after.id }, {}, { tenantId: after.tenantId, organizationId: after.organizationId })\n if (existing) {\n const orderRef =\n typeof existing.order === 'string' ? existing.order : existing.order?.id ?? null\n const allocations = await findWithDecryption(em, SalesPaymentAllocation, { payment: existing }, {}, { tenantId: after.tenantId, organizationId: after.organizationId })\n const allocationOrders = allocations\n .map((allocation) =>\n typeof allocation.order === 'string'\n ? allocation.order\n : allocation.order?.id ?? null\n )\n .filter((value): value is string => typeof value === 'string' && value.length > 0)\n\n allocations.forEach((allocation) => em.remove(allocation))\n await em.flush()\n\n em.remove(existing)\n await em.flush()\n\n const orderIds = Array.from(\n new Set(\n [\n orderRef,\n ...allocationOrders,\n ].filter((value): value is string => typeof value === 'string' && value.length > 0)\n )\n )\n for (const id of orderIds) {\n await em.transactional(async (tx) => {\n const order = await findOneWithDecryption(tx, SalesOrder, { id }, { lockMode: LockMode.PESSIMISTIC_WRITE }, { tenantId: after.tenantId, organizationId: after.organizationId })\n if (!order) return\n if (id === after.orderId && 'orderPaymentMethodIdBefore' in (payload ?? {})) {\n order.paymentMethodId = payload.orderPaymentMethodIdBefore ?? null\n order.paymentMethodCode = payload.orderPaymentMethodCodeBefore ?? null\n order.updatedAt = new Date()\n await tx.flush()\n }\n await recomputeOrderPaymentTotals(tx, order)\n await tx.flush()\n })\n }\n }\n },\n redo: async ({ ctx, logEntry }) => {\n const after = resolveRedoSnapshot<PaymentSnapshot>(logEntry)\n const paymentId = after?.id ?? logEntry.resourceId ?? null\n if (!after || !paymentId) {\n throw new CrudHttpError(400, { error: '[internal] redo snapshot unavailable for sales.payments.create' })\n }\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n await restorePaymentSnapshot(em, after)\n await em.flush()\n\n const orderIds = Array.from(\n new Set(\n [\n after.orderId,\n ...after.allocations.map((allocation) => allocation.orderId),\n ].filter((value): value is string => typeof value === 'string' && value.length > 0)\n )\n )\n let totals: { paidTotalAmount: number; refundedTotalAmount: number; outstandingAmount: number } | undefined\n for (const orderId of orderIds) {\n const recomputed = await em.transactional(async (tx) => {\n const order = await findOneWithDecryption(\n tx,\n SalesOrder,\n { id: orderId },\n { lockMode: LockMode.PESSIMISTIC_WRITE },\n { tenantId: after.tenantId, organizationId: after.organizationId },\n )\n if (!order) return undefined\n if (orderId === after.orderId && after.paymentMethodId && !order.paymentMethodId) {\n const method = await findOneWithDecryption(\n tx,\n SalesPaymentMethod,\n { id: after.paymentMethodId },\n {},\n { tenantId: after.tenantId, organizationId: after.organizationId },\n )\n order.paymentMethodId = method?.id ?? after.paymentMethodId\n order.paymentMethodCode = method?.code ?? null\n order.updatedAt = new Date()\n await tx.flush()\n }\n const result = await recomputeOrderPaymentTotals(tx, order)\n await tx.flush()\n return result\n })\n if (recomputed && (!totals || orderId === after.orderId)) {\n totals = recomputed\n }\n // Raw findOne is intentional: the order is fetched only to read its id/scope\n // for cache invalidation \u2014 no encrypted field is read, so decryption is unnecessary.\n // Scope filter (#2111): never cache-invalidate a foreign tenant's order even\n // if a snapshot's orderId was somehow tampered with.\n const target = await em.findOne(SalesOrder, { id: orderId, organizationId: after.organizationId, tenantId: after.tenantId })\n if (target) {\n ensureSameScope(target, after.organizationId, after.tenantId)\n await invalidateOrderCache(ctx.container, target, ctx.auth?.tenantId ?? null)\n }\n }\n\n const payment = await findOneWithDecryption(em, SalesPayment, { id: after.id }, {}, { tenantId: after.tenantId, organizationId: after.organizationId })\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'created',\n entity: payment,\n identifiers: {\n id: after.id,\n organizationId: after.organizationId,\n tenantId: after.tenantId,\n },\n indexer: { entityType: E.sales.sales_payment },\n events: paymentCrudEvents,\n })\n\n return { paymentId: after.id, orderTotals: totals }\n },\n}\n\nconst updatePaymentCommand: CommandHandler<\n PaymentUpdateInput,\n { paymentId: string; orderTotals?: { paidTotalAmount: number; refundedTotalAmount: number; outstandingAmount: number } }\n> = {\n id: 'sales.payments.update',\n async prepare(rawInput, ctx) {\n const parsed = paymentUpdateSchema.parse(rawInput ?? {})\n if (!parsed.id) return {}\n const em = ctx.container.resolve('em') as EntityManager\n const scope = ctx.auth?.tenantId ? { tenantId: ctx.auth.tenantId, organizationId: ctx.auth?.orgId ?? null } : undefined\n const snapshot = await loadPaymentSnapshot(em, parsed.id, scope)\n if (snapshot) {\n ensureTenantScope(ctx, snapshot.tenantId)\n ensureOrganizationScope(ctx, snapshot.organizationId)\n }\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const input = paymentUpdateSchema.parse(rawInput ?? {})\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const { translate } = await resolveTranslations()\n const scopeSeed = assertFound(\n await findOneWithDecryption(em, SalesPayment, { id: input.id }, {}, { tenantId: input.tenantId, organizationId: input.organizationId }),\n 'sales.payments.not_found'\n )\n const resolvedTenantId = input.tenantId ?? scopeSeed.tenantId\n const resolvedOrganizationId = input.organizationId ?? scopeSeed.organizationId\n ensureTenantScope(ctx, resolvedTenantId)\n ensureOrganizationScope(ctx, resolvedOrganizationId)\n const payment = assertFound(\n await findOneWithDecryption(\n em,\n SalesPayment,\n { id: input.id },\n { populate: ['order'] },\n { tenantId: resolvedTenantId, organizationId: resolvedOrganizationId },\n ),\n 'sales.payments.not_found'\n )\n ensureSameScope(payment, resolvedOrganizationId, resolvedTenantId)\n const previousOrder = payment.order as SalesOrder | null\n // Apply payment scalar fields, order/line status changes and the\n // allocations rebuild in one transaction so a mid-write failure cannot\n // leave the payment and its allocations partially committed (#2336).\n await em.transactional(async (tx) => {\n if (input.orderId !== undefined) {\n if (!input.orderId) {\n payment.order = null\n } else {\n const order = assertFound(\n await findOneWithDecryption(tx, SalesOrder, { id: input.orderId }, {}, { tenantId: resolvedTenantId, organizationId: resolvedOrganizationId }),\n 'sales.payments.order_not_found'\n )\n ensureSameScope(order, resolvedOrganizationId, resolvedTenantId)\n if (\n order.currencyCode &&\n input.currencyCode &&\n order.currencyCode.toUpperCase() !== input.currencyCode.toUpperCase()\n ) {\n throw new CrudHttpError(400, {\n error: translate('sales.payments.currency_mismatch', 'Payment currency must match the order currency.'),\n })\n }\n payment.order = order\n }\n }\n if (input.paymentMethodId !== undefined) {\n if (!input.paymentMethodId) {\n payment.paymentMethod = null\n } else {\n const method = assertFound(\n await findOneWithDecryption(tx, SalesPaymentMethod, { id: input.paymentMethodId }, {}, { tenantId: resolvedTenantId, organizationId: resolvedOrganizationId }),\n 'sales.payments.method_not_found'\n )\n ensureSameScope(method, resolvedOrganizationId, resolvedTenantId)\n payment.paymentMethod = method\n }\n }\n const currentOrder = payment.order as SalesOrder | null\n if ((input.documentStatusEntryId !== undefined || input.lineStatusEntryId !== undefined) && !currentOrder) {\n throw new CrudHttpError(400, { error: translate('sales.payments.order_required', 'Order is required for payments.') })\n }\n if (currentOrder && input.documentStatusEntryId !== undefined) {\n const orderStatus = await resolveDictionaryEntryValue(tx, input.documentStatusEntryId ?? null)\n if (input.documentStatusEntryId && !orderStatus) {\n throw new CrudHttpError(400, {\n error: translate('sales.documents.detail.statusInvalid', 'Selected status could not be found.'),\n })\n }\n currentOrder.statusEntryId = input.documentStatusEntryId ?? null\n currentOrder.status = orderStatus\n currentOrder.updatedAt = new Date()\n tx.persist(currentOrder)\n }\n if (currentOrder && input.lineStatusEntryId !== undefined) {\n const lineStatus = await resolveDictionaryEntryValue(tx, input.lineStatusEntryId ?? null)\n if (input.lineStatusEntryId && !lineStatus) {\n throw new CrudHttpError(400, {\n error: translate('sales.documents.detail.statusInvalid', 'Selected status could not be found.'),\n })\n }\n const orderLines = await findWithDecryption(tx, SalesOrderLine, { order: currentOrder }, {}, { tenantId: resolvedTenantId, organizationId: resolvedOrganizationId })\n orderLines.forEach((line) => {\n line.statusEntryId = input.lineStatusEntryId ?? null\n line.status = lineStatus\n line.updatedAt = new Date()\n })\n orderLines.forEach((line) => tx.persist(line))\n }\n if (input.paymentReference !== undefined) payment.paymentReference = input.paymentReference ?? null\n if (input.statusEntryId !== undefined) {\n payment.statusEntryId = input.statusEntryId ?? null\n payment.status = await resolveDictionaryEntryValue(tx, input.statusEntryId ?? null)\n }\n if (input.amount !== undefined) payment.amount = toNumericString(input.amount) ?? '0'\n if (input.currencyCode !== undefined) payment.currencyCode = input.currencyCode\n if (input.capturedAmount !== undefined) {\n payment.capturedAmount = toNumericString(input.capturedAmount) ?? '0'\n }\n if (input.refundedAmount !== undefined) {\n payment.refundedAmount = toNumericString(input.refundedAmount) ?? '0'\n }\n if (input.receivedAt !== undefined) payment.receivedAt = input.receivedAt ?? null\n if (input.capturedAt !== undefined) payment.capturedAt = input.capturedAt ?? null\n if (input.metadata !== undefined) {\n payment.metadata = input.metadata ? cloneJson(input.metadata) : null\n }\n if (input.customFieldSetId !== undefined) {\n payment.customFieldSetId = input.customFieldSetId ?? null\n }\n if (input.customFields !== undefined) {\n if (!payment.id) {\n await tx.flush()\n }\n await setRecordCustomFields(tx, {\n entityId: E.sales.sales_payment,\n recordId: payment.id,\n organizationId: payment.organizationId,\n tenantId: payment.tenantId,\n values: normalizeCustomFieldsInput(input.customFields),\n })\n }\n payment.updatedAt = new Date()\n\n // Persist the payment scalar changes before any allocation query below.\n // MikroORM discards pending scalar mutations when a find() runs on the\n // same EntityManager before they are flushed, which would otherwise drop\n // the updated amount/reference when allocations are (re)synced.\n await tx.flush()\n\n if (input.allocations !== undefined) {\n const existingAllocations = await findWithDecryption(tx, SalesPaymentAllocation, { payment }, {}, { tenantId: payment.tenantId, organizationId: payment.organizationId })\n existingAllocations.forEach((allocation) => tx.remove(allocation))\n const allocationInputs = Array.isArray(input.allocations) ? input.allocations : []\n const paymentOrderId =\n (typeof payment.order === 'string' ? payment.order : payment.order?.id) ?? null\n const orderCache = new Map<string, SalesOrder>()\n if (currentOrder) orderCache.set(currentOrder.id, currentOrder)\n const invoiceCache = new Map<string, SalesInvoice>()\n for (const allocation of allocationInputs) {\n const orderId = allocation.orderId ?? paymentOrderId\n let order: SalesOrder | null = null\n if (orderId && typeof orderId === 'string') {\n order = orderCache.get(orderId) ?? null\n if (!order) {\n order = assertFound(\n await findOneWithDecryption(\n tx,\n SalesOrder,\n { id: orderId },\n {},\n { tenantId: payment.tenantId, organizationId: payment.organizationId },\n ),\n 'sales.payments.order_not_found',\n )\n ensureSameScope(order, payment.organizationId, payment.tenantId)\n orderCache.set(orderId, order)\n }\n }\n let invoice: SalesInvoice | null = null\n if (allocation.invoiceId) {\n invoice = invoiceCache.get(allocation.invoiceId) ?? null\n if (!invoice) {\n invoice = assertFound(\n await findOneWithDecryption(\n tx,\n SalesInvoice,\n { id: allocation.invoiceId },\n {},\n { tenantId: payment.tenantId, organizationId: payment.organizationId },\n ),\n 'sales.payments.invoice_not_found',\n )\n ensureSameScope(invoice, payment.organizationId, payment.tenantId)\n invoiceCache.set(allocation.invoiceId, invoice)\n }\n }\n const entity = tx.create(SalesPaymentAllocation, {\n payment,\n order,\n invoice,\n organizationId: payment.organizationId,\n tenantId: payment.tenantId,\n amount: toNumericString(allocation.amount) ?? '0',\n currencyCode: allocation.currencyCode,\n metadata: allocation.metadata ? cloneJson(allocation.metadata) : null,\n })\n tx.persist(entity)\n }\n } else if (input.amount !== undefined || input.currencyCode !== undefined) {\n // The caller changed the payment amount/currency without managing\n // allocations explicitly. A simple payment carries a single\n // auto-created allocation covering the full amount (see create); keep\n // it in sync so recomputeOrderPaymentTotals \u2014 which sums allocations in\n // preference to the payment amount \u2014 does not report a stale paid total\n // after a payment edit (#2455).\n const existingAllocations = await findWithDecryption(tx, SalesPaymentAllocation, { payment }, {}, { tenantId: payment.tenantId, organizationId: payment.organizationId })\n const paymentOrderId =\n (typeof payment.order === 'string' ? payment.order : payment.order?.id) ?? null\n const isDefaultAllocation = (allocation: SalesPaymentAllocation): boolean => {\n const allocationOrderId =\n typeof allocation.order === 'string' ? allocation.order : allocation.order?.id ?? null\n const allocationInvoiceId =\n typeof allocation.invoice === 'string' ? allocation.invoice : allocation.invoice?.id ?? null\n return allocationInvoiceId === null && allocationOrderId === paymentOrderId\n }\n if (existingAllocations.length === 1 && isDefaultAllocation(existingAllocations[0])) {\n const [allocation] = existingAllocations\n allocation.amount = toNumericString(toNumber(payment.amount)) ?? '0'\n allocation.currencyCode = payment.currencyCode\n tx.persist(allocation)\n }\n }\n })\n\n const nextOrderId =\n (payment.order as SalesOrder | null)?.id ??\n (typeof payment.order === 'string' ? payment.order : null)\n let totals: { paidTotalAmount: number; refundedTotalAmount: number; outstandingAmount: number } | undefined\n if (nextOrderId) {\n totals = await em.transactional(async (tx) => {\n // Scope filter (#2111): never lock or recompute totals on a foreign\n // tenant's order, even if payment.order somehow points there.\n const lockedOrder = await tx.findOne(\n SalesOrder,\n { id: nextOrderId, organizationId: payment.organizationId, tenantId: payment.tenantId },\n { lockMode: LockMode.PESSIMISTIC_WRITE },\n )\n if (!lockedOrder) return undefined\n ensureSameScope(lockedOrder, payment.organizationId, payment.tenantId)\n const result = await recomputeOrderPaymentTotals(tx, lockedOrder)\n await tx.flush()\n return result\n })\n if (totals) {\n // Raw findOne is intentional: the order is fetched only to read its id/scope\n // for cache invalidation \u2014 no encrypted field is read, so decryption is unnecessary.\n // Scope filter (#2111): same rationale as the lock above.\n const nextOrder = await em.findOne(SalesOrder, { id: nextOrderId, organizationId: payment.organizationId, tenantId: payment.tenantId })\n if (nextOrder) {\n ensureSameScope(nextOrder, payment.organizationId, payment.tenantId)\n await invalidateOrderCache(ctx.container, nextOrder, ctx.auth?.tenantId ?? null)\n }\n }\n }\n if (previousOrder && (!nextOrderId || previousOrder.id !== nextOrderId)) {\n await em.transactional(async (tx) => {\n // Scope filter (#2111): previousOrder was already loaded via the\n // payment's scope, so its tenant/org match the payment's. Filter\n // the lock query the same way as defence-in-depth.\n const lockedOrder = await tx.findOne(\n SalesOrder,\n { id: previousOrder.id, organizationId: payment.organizationId, tenantId: payment.tenantId },\n { lockMode: LockMode.PESSIMISTIC_WRITE },\n )\n if (!lockedOrder) return\n ensureSameScope(lockedOrder, payment.organizationId, payment.tenantId)\n await recomputeOrderPaymentTotals(tx, lockedOrder)\n await tx.flush()\n })\n await invalidateOrderCache(ctx.container, previousOrder, ctx.auth?.tenantId ?? null)\n }\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'updated',\n entity: payment,\n identifiers: {\n id: payment.id,\n organizationId: payment.organizationId,\n tenantId: payment.tenantId,\n },\n indexer: { entityType: E.sales.sales_payment },\n events: paymentCrudEvents,\n })\n\n return { paymentId: payment.id, orderTotals: totals }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = ctx.auth?.tenantId ? { tenantId: ctx.auth.tenantId, organizationId: ctx.auth?.orgId ?? null } : undefined\n return result?.paymentId ? loadPaymentSnapshot(em, result.paymentId, scope) : null\n },\n buildLog: async ({ snapshots, result }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as PaymentSnapshot | undefined\n const after = snapshots.after as PaymentSnapshot | undefined\n return {\n actionLabel: translate('sales.audit.payments.update', 'Update payment'),\n resourceKind: 'sales.payment',\n resourceId: result.paymentId,\n parentResourceKind: 'sales.order',\n parentResourceId: after?.orderId ?? before?.orderId ?? null,\n tenantId: after?.tenantId ?? before?.tenantId ?? null,\n organizationId: after?.organizationId ?? before?.organizationId ?? null,\n snapshotBefore: before ?? null,\n snapshotAfter: after ?? null,\n payload: { undo: { before, after } satisfies PaymentUndoPayload },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<PaymentUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n await restorePaymentSnapshot(em, before)\n await em.flush()\n if (before.orderId) {\n await em.transactional(async (tx) => {\n const order = await findOneWithDecryption(tx, SalesOrder, { id: before.orderId! }, { lockMode: LockMode.PESSIMISTIC_WRITE }, { tenantId: before.tenantId, organizationId: before.organizationId })\n if (!order) return\n await recomputeOrderPaymentTotals(tx, order)\n await tx.flush()\n })\n }\n },\n}\n\nconst deletePaymentCommand: CommandHandler<\n { id: string; orderId?: string | null; organizationId: string; tenantId: string },\n { paymentId: string; orderTotals?: { paidTotalAmount: number; refundedTotalAmount: number; outstandingAmount: number } }\n> = {\n id: 'sales.payments.delete',\n async prepare(rawInput, ctx) {\n const parsed = paymentUpdateSchema.parse(rawInput ?? {})\n if (!parsed.id) return {}\n const em = ctx.container.resolve('em') as EntityManager\n const scope = ctx.auth?.tenantId ? { tenantId: ctx.auth.tenantId, organizationId: ctx.auth?.orgId ?? null } : undefined\n const snapshot = await loadPaymentSnapshot(em, parsed.id, scope)\n if (snapshot) {\n ensureTenantScope(ctx, snapshot.tenantId)\n ensureOrganizationScope(ctx, snapshot.organizationId)\n }\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const input = paymentUpdateSchema.parse(rawInput ?? {})\n ensureTenantScope(ctx, input.tenantId)\n ensureOrganizationScope(ctx, input.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const payment = assertFound(\n await findOneWithDecryption(\n em,\n SalesPayment,\n { id: input.id },\n { populate: ['order'] },\n { tenantId: input.tenantId, organizationId: input.organizationId },\n ),\n 'sales.payments.not_found'\n )\n ensureSameScope(payment, input.organizationId, input.tenantId)\n const order = payment.order as SalesOrder | null\n const allocations = await findWithDecryption(em, SalesPaymentAllocation, { payment }, {}, { tenantId: payment.tenantId, organizationId: payment.organizationId })\n const allocationOrders = allocations\n .map((allocation) =>\n typeof allocation.order === 'string'\n ? allocation.order\n : allocation.order?.id ?? null\n )\n .filter((value): value is string => typeof value === 'string' && value.length > 0)\n // Remove the allocations and the payment in one transaction so a failure\n // between the two deletes cannot leave orphaned allocations committed\n // without their payment (#2336).\n await em.transactional(async (tx) => {\n allocations.forEach((allocation) => tx.remove(allocation))\n tx.remove(payment)\n })\n let totals: { paidTotalAmount: number; refundedTotalAmount: number; outstandingAmount: number } | undefined\n const orderIds = Array.from(\n new Set(\n [\n order && typeof order === 'object' ? order.id : null,\n ...allocationOrders,\n ].filter((value): value is string => typeof value === 'string' && value.length > 0)\n )\n )\n const primaryOrderId = order && typeof order === 'object' ? order.id : null\n for (const orderId of orderIds) {\n const recomputed = await em.transactional(async (tx) => {\n // Scope filter (#2111): never lock or recompute totals on a foreign\n // tenant's order, even if a payment allocation somehow points there.\n const lockedOrder = await tx.findOne(\n SalesOrder,\n { id: orderId, organizationId: payment.organizationId, tenantId: payment.tenantId },\n { lockMode: LockMode.PESSIMISTIC_WRITE },\n )\n if (!lockedOrder) return undefined\n ensureSameScope(lockedOrder, payment.organizationId, payment.tenantId)\n const result = await recomputeOrderPaymentTotals(tx, lockedOrder)\n await tx.flush()\n return result\n })\n if (recomputed && (!totals || (primaryOrderId && orderId === primaryOrderId))) {\n totals = recomputed\n }\n // Raw findOne is intentional: the order is fetched only to read its id/scope\n // for cache invalidation \u2014 no encrypted field is read, so decryption is unnecessary.\n // Scope filter (#2111): same rationale as the lock above.\n const target = await em.findOne(SalesOrder, { id: orderId, organizationId: payment.organizationId, tenantId: payment.tenantId })\n if (target) {\n ensureSameScope(target, payment.organizationId, payment.tenantId)\n await invalidateOrderCache(ctx.container, target, ctx.auth?.tenantId ?? null)\n }\n }\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'deleted',\n entity: payment,\n identifiers: {\n id: payment.id,\n organizationId: payment.organizationId,\n tenantId: payment.tenantId,\n },\n indexer: { entityType: E.sales.sales_payment },\n events: paymentCrudEvents,\n })\n if (allocations.length) {\n await Promise.all(\n allocations.map((allocation) =>\n emitCrudSideEffects({\n dataEngine,\n action: 'deleted',\n entity: allocation,\n identifiers: {\n id: allocation.id,\n organizationId: allocation.organizationId ?? null,\n tenantId: allocation.tenantId ?? null,\n },\n indexer: { entityType: E.sales.sales_payment_allocation },\n })\n )\n )\n }\n return { paymentId: payment.id, orderTotals: totals }\n },\n buildLog: async ({ snapshots, result }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as PaymentSnapshot | undefined\n return {\n actionLabel: translate('sales.audit.payments.delete', 'Delete payment'),\n resourceKind: 'sales.payment',\n resourceId: result.paymentId,\n parentResourceKind: 'sales.order',\n parentResourceId: before?.orderId ?? null,\n tenantId: before?.tenantId ?? null,\n organizationId: before?.organizationId ?? null,\n snapshotBefore: before ?? null,\n payload: { undo: { before } satisfies PaymentUndoPayload },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<PaymentUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n await restorePaymentSnapshot(em, before)\n await em.flush()\n if (before.orderId) {\n await em.transactional(async (tx) => {\n const order = await findOneWithDecryption(tx, SalesOrder, { id: before.orderId! }, { lockMode: LockMode.PESSIMISTIC_WRITE }, { tenantId: before.tenantId, organizationId: before.organizationId })\n if (!order) return\n await recomputeOrderPaymentTotals(tx, order)\n await tx.flush()\n })\n }\n },\n}\n\nexport const paymentCommands = [createPaymentCommand, updatePaymentCommand, deletePaymentCommand]\n\nregisterCommand(createPaymentCommand)\nregisterCommand(updatePaymentCommand)\nregisterCommand(deletePaymentCommand)\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["// @ts-nocheck\n\nimport { registerCommand, type CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { LockMode } from '@mikro-orm/core'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { loadCustomFieldValues } from '@open-mercato/shared/lib/crud/custom-fields'\nimport { setRecordCustomFields } from '@open-mercato/core/modules/entities/lib/helpers'\nimport { E } from '#generated/entities.ids.generated'\nimport {\n SalesInvoice,\n SalesOrder,\n SalesOrderLine,\n SalesPayment,\n SalesPaymentAllocation,\n SalesPaymentMethod,\n} from '../data/entities'\nimport {\n paymentCreateSchema,\n paymentUpdateSchema,\n type PaymentCreateInput,\n type PaymentUpdateInput,\n} from '../data/validators'\nimport {\n assertFound,\n cloneJson,\n ensureOrganizationScope,\n ensureSameScope,\n ensureTenantScope,\n extractUndoPayload,\n toNumericString,\n} from './shared'\nimport { resolveDictionaryEntryValue } from '../lib/dictionaries'\nimport { resolveRedoSnapshot } from '@open-mercato/shared/lib/commands/redo'\nimport { invalidateCrudCache } from '@open-mercato/shared/lib/crud/cache'\nimport { emitCrudSideEffects } from '@open-mercato/shared/lib/commands/helpers'\nimport type { CrudEventsConfig } from '@open-mercato/shared/lib/crud/types'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport { findOneWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { resolveNotificationService } from '../../notifications/lib/notificationService'\nimport { buildFeatureNotificationFromType } from '../../notifications/lib/notificationBuilder'\nimport { notificationTypes } from '../notifications'\n\nexport type PaymentAllocationSnapshot = {\n id: string\n orderId: string | null\n invoiceId: string | null\n amount: number\n currencyCode: string\n metadata: Record<string, unknown> | null\n}\n\nexport type PaymentSnapshot = {\n id: string\n orderId: string | null\n organizationId: string\n tenantId: string\n paymentMethodId: string | null\n paymentReference: string | null\n statusEntryId: string | null\n status: string | null\n amount: number\n currencyCode: string\n capturedAmount: number\n refundedAmount: number\n receivedAt: string | null\n capturedAt: string | null\n metadata: Record<string, unknown> | null\n customFields?: Record<string, unknown> | null\n customFieldSetId?: string | null\n allocations: PaymentAllocationSnapshot[]\n}\n\ntype PaymentUndoPayload = {\n before?: PaymentSnapshot | null\n after?: PaymentSnapshot | null\n orderPaymentMethodIdBefore?: string | null\n orderPaymentMethodCodeBefore?: string | null\n}\n\nconst toNumber = (value: unknown): number => {\n if (typeof value === 'number' && Number.isFinite(value)) return value\n if (typeof value === 'string' && value.trim().length) {\n const parsed = Number(value)\n if (!Number.isNaN(parsed)) return parsed\n }\n return 0\n}\n\nconst normalizeCustomFieldsInput = (input: unknown): Record<string, unknown> =>\n input && typeof input === 'object' && !Array.isArray(input) ? (input as Record<string, unknown>) : {}\n\nconst paymentCrudEvents: CrudEventsConfig = {\n module: 'sales',\n entity: 'payment',\n persistent: true,\n buildPayload: (ctx) => ({\n id: ctx.identifiers.id,\n organizationId: ctx.identifiers.organizationId,\n tenantId: ctx.identifiers.tenantId,\n }),\n}\n\nconst ORDER_RESOURCE = 'sales.order'\n\nasync function invalidateOrderCache(container: any, order: SalesOrder | null | undefined, tenantId: string | null) {\n if (!order) return\n await invalidateCrudCache(\n container,\n ORDER_RESOURCE,\n { id: order.id, organizationId: order.organizationId, tenantId: order.tenantId },\n tenantId,\n 'updated'\n )\n}\n\nexport async function loadPaymentSnapshot(em: EntityManager, id: string, scope?: { tenantId?: string | null; organizationId?: string | null }): Promise<PaymentSnapshot | null> {\n const payment = await findOneWithDecryption(\n em,\n SalesPayment,\n { id },\n { populate: ['order', 'allocations', 'allocations.order', 'allocations.invoice'] },\n scope,\n )\n if (!payment) return null\n const allocations: PaymentAllocationSnapshot[] = Array.from(payment.allocations ?? []).map((allocation) => ({\n id: allocation.id,\n orderId:\n typeof allocation.order === 'string'\n ? allocation.order\n : allocation.order?.id ?? (allocation as any).order_id ?? null,\n invoiceId:\n typeof allocation.invoice === 'string'\n ? allocation.invoice\n : allocation.invoice?.id ?? (allocation as any).invoice_id ?? null,\n amount: toNumber(allocation.amount),\n currencyCode: allocation.currencyCode,\n metadata: allocation.metadata ? cloneJson(allocation.metadata) : null,\n }))\n const customFieldValues = await loadCustomFieldValues({\n em,\n entityId: E.sales.sales_payment,\n recordIds: [payment.id],\n tenantIdByRecord: { [payment.id]: payment.tenantId ?? null },\n organizationIdByRecord: { [payment.id]: payment.organizationId ?? null },\n })\n const customFields = customFieldValues[payment.id]\n const normalizedCustomFields =\n customFields && Object.keys(customFields).length ? customFields : null\n return {\n id: payment.id,\n orderId: typeof payment.order === 'string' ? payment.order : payment.order?.id ?? null,\n organizationId: payment.organizationId,\n tenantId: payment.tenantId,\n paymentMethodId:\n typeof payment.paymentMethod === 'string'\n ? payment.paymentMethod\n : payment.paymentMethod?.id ?? null,\n paymentReference: payment.paymentReference ?? null,\n statusEntryId: payment.statusEntryId ?? null,\n status: payment.status ?? null,\n amount: toNumber(payment.amount),\n currencyCode: payment.currencyCode,\n capturedAmount: toNumber(payment.capturedAmount),\n refundedAmount: toNumber(payment.refundedAmount),\n receivedAt: payment.receivedAt ? payment.receivedAt.toISOString() : null,\n capturedAt: payment.capturedAt ? payment.capturedAt.toISOString() : null,\n metadata: payment.metadata ? cloneJson(payment.metadata) : null,\n customFields: normalizedCustomFields,\n customFieldSetId: (payment as any).customFieldSetId ?? (payment as any).custom_field_set_id ?? null,\n allocations,\n }\n}\n\nexport async function restorePaymentSnapshot(em: EntityManager, snapshot: PaymentSnapshot): Promise<void> {\n const orderRef = snapshot.orderId ? em.getReference(SalesOrder, snapshot.orderId) : null\n const methodRef = snapshot.paymentMethodId\n ? em.getReference(SalesPaymentMethod, snapshot.paymentMethodId)\n : null\n const entity =\n (await findOneWithDecryption(em, SalesPayment, { id: snapshot.id }, {}, { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId })) ??\n em.create(SalesPayment, {\n id: snapshot.id,\n createdAt: new Date(),\n organizationId: snapshot.organizationId,\n tenantId: snapshot.tenantId,\n })\n entity.order = orderRef\n entity.paymentMethod = methodRef\n entity.organizationId = snapshot.organizationId\n entity.tenantId = snapshot.tenantId\n entity.paymentReference = snapshot.paymentReference\n entity.statusEntryId = snapshot.statusEntryId\n entity.status = snapshot.status\n entity.amount = toNumericString(snapshot.amount) ?? '0'\n entity.currencyCode = snapshot.currencyCode\n entity.capturedAmount = toNumericString(snapshot.capturedAmount) ?? '0'\n entity.refundedAmount = toNumericString(snapshot.refundedAmount) ?? '0'\n entity.receivedAt = snapshot.receivedAt ? new Date(snapshot.receivedAt) : null\n entity.capturedAt = snapshot.capturedAt ? new Date(snapshot.capturedAt) : null\n entity.metadata = snapshot.metadata ? cloneJson(snapshot.metadata) : null\n entity.customFieldSetId =\n (snapshot as any).customFieldSetId ?? (snapshot as any).custom_field_set_id ?? null\n entity.updatedAt = new Date()\n await em.flush()\n\n if ((snapshot as any).customFields !== undefined) {\n await setRecordCustomFields(em, {\n entityId: E.sales.sales_payment,\n recordId: entity.id,\n organizationId: entity.organizationId,\n tenantId: entity.tenantId,\n values:\n snapshot.customFields && typeof snapshot.customFields === 'object'\n ? (snapshot.customFields as Record<string, unknown>)\n : {},\n })\n }\n\n const existingAllocations = await findWithDecryption(em, SalesPaymentAllocation, { payment: entity }, {}, { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId })\n existingAllocations.forEach((allocation) => em.remove(allocation))\n snapshot.allocations.forEach((allocation) => {\n const order =\n allocation.orderId && typeof allocation.orderId === 'string'\n ? em.getReference(SalesOrder, allocation.orderId)\n : null\n const invoice =\n allocation.invoiceId && typeof allocation.invoiceId === 'string'\n ? em.getReference(SalesInvoice, allocation.invoiceId)\n : null\n const newAllocation = em.create(SalesPaymentAllocation, {\n payment: entity,\n order,\n invoice,\n organizationId: snapshot.organizationId,\n tenantId: snapshot.tenantId,\n amount: toNumericString(allocation.amount) ?? '0',\n currencyCode: allocation.currencyCode,\n metadata: allocation.metadata ? cloneJson(allocation.metadata) : null,\n })\n em.persist(newAllocation)\n })\n em.persist(entity)\n}\n\nasync function recomputeOrderPaymentTotals(\n em: EntityManager,\n order: SalesOrder,\n options?: { lock?: boolean }\n): Promise<{ paidTotalAmount: number; refundedTotalAmount: number; outstandingAmount: number }> {\n const orderId = order.id\n const scope = { organizationId: order.organizationId, tenantId: order.tenantId }\n\n if (options?.lock) {\n // Raw findOne is intentional: this acquires a row lock only \u2014 no encrypted\n // SalesOrder field is read, so decryption (findOneWithDecryption) is unnecessary.\n // Scope filter is defence-in-depth (#2111): the caller is expected to pass a\n // correctly scoped order, but filtering here ensures we never lock a foreign\n // tenant's row even if a caller messed up.\n await em.findOne(SalesOrder, { id: orderId, ...scope }, { lockMode: LockMode.PESSIMISTIC_WRITE })\n }\n\n const allocations = await findWithDecryption(\n em,\n SalesPaymentAllocation,\n { ...scope, order: orderId },\n { populate: ['payment'] },\n scope,\n )\n\n const paymentIds = new Set<string>()\n allocations.forEach((allocation) => {\n const paymentRef = allocation.payment\n const paymentId =\n typeof paymentRef === 'object' && paymentRef !== null\n ? paymentRef.id\n : typeof paymentRef === 'string'\n ? paymentRef\n : null\n if (paymentId) paymentIds.add(paymentId)\n })\n\n const payments =\n paymentIds.size > 0\n ? await findWithDecryption(em, SalesPayment, { id: { $in: Array.from(paymentIds) }, deletedAt: null, ...scope }, {}, scope)\n : await findWithDecryption(em, SalesPayment, { order: orderId, deletedAt: null, ...scope }, {}, scope)\n\n const resolvePaidAmount = (payment: SalesPayment) => {\n const captured = toNumber(payment.capturedAmount)\n return captured > 0 ? captured : toNumber(payment.amount)\n }\n\n const activePaymentIds = new Set(payments.map((payment) => payment.id))\n const paidTotal =\n allocations.length > 0\n ? allocations.reduce((sum, allocation) => {\n const paymentRef = allocation.payment\n const paymentId =\n typeof paymentRef === 'object' && paymentRef !== null\n ? paymentRef.id\n : typeof paymentRef === 'string'\n ? paymentRef\n : null\n if (paymentId && !activePaymentIds.has(paymentId)) return sum\n return sum + toNumber(allocation.amount)\n }, 0)\n : payments.reduce((sum, payment) => sum + resolvePaidAmount(payment), 0)\n\n const refundedTotal = payments.reduce(\n (sum, payment) => sum + toNumber(payment.refundedAmount),\n 0\n )\n\n const grandTotal = toNumber(order.grandTotalGrossAmount)\n const outstanding = Math.max(grandTotal - paidTotal + refundedTotal, 0)\n order.paidTotalAmount = toNumericString(paidTotal) ?? '0'\n order.refundedTotalAmount = toNumericString(refundedTotal) ?? '0'\n order.outstandingAmount = toNumericString(outstanding) ?? '0'\n return {\n paidTotalAmount: paidTotal,\n refundedTotalAmount: refundedTotal,\n outstandingAmount: outstanding,\n }\n}\n\nconst createPaymentCommand: CommandHandler<\n PaymentCreateInput,\n { paymentId: string; orderTotals?: { paidTotalAmount: number; refundedTotalAmount: number; outstandingAmount: number }; orderPaymentMethodIdBefore?: string | null; orderPaymentMethodCodeBefore?: string | null }\n> = {\n id: 'sales.payments.create',\n async execute(rawInput, ctx) {\n const input = paymentCreateSchema.parse(rawInput ?? {})\n ensureTenantScope(ctx, input.tenantId)\n ensureOrganizationScope(ctx, input.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const { translate } = await resolveTranslations()\n if (!input.orderId) {\n throw new CrudHttpError(400, { error: translate('sales.payments.order_required', 'Order is required for payments.') })\n }\n\n const { payment, order, totals, orderPaymentMethodIdBefore, orderPaymentMethodCodeBefore } = await em.transactional(async (tx) => {\n const order = assertFound(\n await findOneWithDecryption(tx, SalesOrder, { id: input.orderId }, { lockMode: LockMode.PESSIMISTIC_WRITE }, { tenantId: input.tenantId, organizationId: input.organizationId }),\n 'sales.payments.order_not_found'\n )\n ensureSameScope(order, input.organizationId, input.tenantId)\n if (order.deletedAt) {\n throw new CrudHttpError(404, { error: 'sales.payments.order_not_found' })\n }\n if (\n order.currencyCode &&\n input.currencyCode &&\n order.currencyCode.toUpperCase() !== input.currencyCode.toUpperCase()\n ) {\n throw new CrudHttpError(400, {\n error: translate('sales.payments.currency_mismatch', 'Payment currency must match the order currency.'),\n })\n }\n let paymentMethod = null\n if (input.paymentMethodId) {\n const method = assertFound(\n await findOneWithDecryption(tx, SalesPaymentMethod, { id: input.paymentMethodId }, {}, { tenantId: input.tenantId, organizationId: input.organizationId }),\n 'sales.payments.method_not_found'\n )\n ensureSameScope(method, input.organizationId, input.tenantId)\n paymentMethod = method\n }\n const orderPaymentMethodIdBefore = order.paymentMethodId ?? null\n const orderPaymentMethodCodeBefore = order.paymentMethodCode ?? null\n if (paymentMethod && !order.paymentMethodId) {\n order.paymentMethodId = paymentMethod.id\n order.paymentMethodCode = paymentMethod.code ?? null\n order.updatedAt = new Date()\n tx.persist(order)\n }\n if (input.documentStatusEntryId !== undefined) {\n const orderStatus = await resolveDictionaryEntryValue(tx, input.documentStatusEntryId ?? null, { tenantId: input.tenantId })\n if (input.documentStatusEntryId && !orderStatus) {\n throw new CrudHttpError(400, {\n error: translate('sales.documents.detail.statusInvalid', 'Selected status could not be found.'),\n })\n }\n order.statusEntryId = input.documentStatusEntryId ?? null\n order.status = orderStatus\n order.updatedAt = new Date()\n tx.persist(order)\n }\n if (input.lineStatusEntryId !== undefined) {\n const lineStatus = await resolveDictionaryEntryValue(tx, input.lineStatusEntryId ?? null, { tenantId: input.tenantId })\n if (input.lineStatusEntryId && !lineStatus) {\n throw new CrudHttpError(400, {\n error: translate('sales.documents.detail.statusInvalid', 'Selected status could not be found.'),\n })\n }\n const orderLines = await findWithDecryption(tx, SalesOrderLine, { order }, {}, { tenantId: input.tenantId, organizationId: input.organizationId })\n orderLines.forEach((line) => {\n line.statusEntryId = input.lineStatusEntryId ?? null\n line.status = lineStatus\n line.updatedAt = new Date()\n })\n orderLines.forEach((line) => tx.persist(line))\n }\n const status = await resolveDictionaryEntryValue(tx, input.statusEntryId ?? null, { tenantId: input.tenantId })\n const payment = tx.create(SalesPayment, {\n organizationId: input.organizationId,\n tenantId: input.tenantId,\n order,\n paymentMethod,\n paymentReference: input.paymentReference ?? null,\n statusEntryId: input.statusEntryId ?? null,\n status,\n amount: toNumericString(input.amount) ?? '0',\n currencyCode: input.currencyCode,\n capturedAmount: toNumericString(input.capturedAmount) ?? '0',\n refundedAmount: toNumericString(input.refundedAmount) ?? '0',\n receivedAt: input.receivedAt ?? null,\n capturedAt: input.capturedAt ?? null,\n metadata: input.metadata ? cloneJson(input.metadata) : null,\n customFieldSetId: input.customFieldSetId ?? null,\n })\n const allocationInputs = Array.isArray(input.allocations) ? input.allocations : []\n const allocations = allocationInputs.length\n ? allocationInputs\n : [\n {\n orderId: input.orderId,\n invoiceId: null,\n amount: input.amount,\n currencyCode: input.currencyCode,\n metadata: null,\n },\n ]\n const orderCache = new Map<string, SalesOrder>([[order.id, order]])\n const invoiceCache = new Map<string, SalesInvoice>()\n for (const allocation of allocations) {\n let allocationOrder: SalesOrder | null = null\n if (allocation.orderId) {\n allocationOrder = orderCache.get(allocation.orderId) ?? null\n if (!allocationOrder) {\n allocationOrder = assertFound(\n await findOneWithDecryption(\n tx,\n SalesOrder,\n { id: allocation.orderId },\n {},\n { tenantId: input.tenantId, organizationId: input.organizationId },\n ),\n 'sales.payments.order_not_found',\n )\n ensureSameScope(allocationOrder, input.organizationId, input.tenantId)\n orderCache.set(allocation.orderId, allocationOrder)\n }\n }\n let allocationInvoice: SalesInvoice | null = null\n if (allocation.invoiceId) {\n allocationInvoice = invoiceCache.get(allocation.invoiceId) ?? null\n if (!allocationInvoice) {\n allocationInvoice = assertFound(\n await findOneWithDecryption(\n tx,\n SalesInvoice,\n { id: allocation.invoiceId },\n {},\n { tenantId: input.tenantId, organizationId: input.organizationId },\n ),\n 'sales.payments.invoice_not_found',\n )\n ensureSameScope(allocationInvoice, input.organizationId, input.tenantId)\n invoiceCache.set(allocation.invoiceId, allocationInvoice)\n }\n }\n const entity = tx.create(SalesPaymentAllocation, {\n payment,\n order: allocationOrder,\n invoice: allocationInvoice,\n organizationId: input.organizationId,\n tenantId: input.tenantId,\n amount: toNumericString(allocation.amount) ?? '0',\n currencyCode: allocation.currencyCode,\n metadata: allocation.metadata ? cloneJson(allocation.metadata) : null,\n })\n tx.persist(entity)\n }\n tx.persist(payment)\n if (input.customFields !== undefined) {\n if (!payment.id) {\n await tx.flush()\n }\n await setRecordCustomFields(tx, {\n entityId: E.sales.sales_payment,\n recordId: payment.id,\n organizationId: input.organizationId,\n tenantId: input.tenantId,\n values: normalizeCustomFieldsInput(input.customFields),\n })\n }\n await tx.flush()\n const totals = await recomputeOrderPaymentTotals(tx, order)\n await tx.flush()\n return { payment, order, totals, orderPaymentMethodIdBefore, orderPaymentMethodCodeBefore }\n })\n\n await invalidateOrderCache(ctx.container, order, ctx.auth?.tenantId ?? null)\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'created',\n entity: payment,\n identifiers: {\n id: payment.id,\n organizationId: payment.organizationId,\n tenantId: payment.tenantId,\n },\n indexer: { entityType: E.sales.sales_payment },\n events: paymentCrudEvents,\n })\n\n // Create notification for payment received\n try {\n const notificationService = resolveNotificationService(ctx.container)\n const typeDef = notificationTypes.find((type) => type.type === 'sales.payment.received')\n if (typeDef) {\n const amountDisplay = payment.amount && payment.currencyCode\n ? `${payment.currencyCode} ${payment.amount}`\n : ''\n const notificationInput = buildFeatureNotificationFromType(typeDef, {\n requiredFeature: 'sales.orders.manage',\n bodyVariables: {\n orderNumber: order.orderNumber ?? '',\n amount: amountDisplay,\n },\n sourceEntityType: 'sales:order',\n sourceEntityId: order.id,\n linkHref: `/backend/sales/orders/${order.id}`,\n })\n\n await notificationService.createForFeature(notificationInput, {\n tenantId: payment.tenantId,\n organizationId: payment.organizationId ?? null,\n })\n }\n } catch (err) {\n // Notification creation is non-critical, don't fail the command\n console.error('[sales.payments.create] Failed to create notification:', err)\n }\n\n return { paymentId: payment.id, orderTotals: totals, orderPaymentMethodIdBefore, orderPaymentMethodCodeBefore }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = ctx.auth?.tenantId ? { tenantId: ctx.auth.tenantId, organizationId: ctx.auth?.orgId ?? null } : undefined\n return result?.paymentId ? loadPaymentSnapshot(em, result.paymentId, scope) : null\n },\n buildLog: async ({ result, snapshots }) => {\n const after = snapshots.after as PaymentSnapshot | undefined\n if (!after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('sales.audit.payments.create', 'Create payment'),\n resourceKind: 'sales.payment',\n resourceId: result.paymentId,\n parentResourceKind: 'sales.order',\n parentResourceId: after.orderId ?? null,\n tenantId: after.tenantId,\n organizationId: after.organizationId,\n snapshotAfter: after,\n payload: { undo: { after, orderPaymentMethodIdBefore: result.orderPaymentMethodIdBefore ?? null, orderPaymentMethodCodeBefore: result.orderPaymentMethodCodeBefore ?? null } satisfies PaymentUndoPayload },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<PaymentUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const existing = await findOneWithDecryption(em, SalesPayment, { id: after.id }, {}, { tenantId: after.tenantId, organizationId: after.organizationId })\n if (existing) {\n const orderRef =\n typeof existing.order === 'string' ? existing.order : existing.order?.id ?? null\n const allocations = await findWithDecryption(em, SalesPaymentAllocation, { payment: existing }, {}, { tenantId: after.tenantId, organizationId: after.organizationId })\n const allocationOrders = allocations\n .map((allocation) =>\n typeof allocation.order === 'string'\n ? allocation.order\n : allocation.order?.id ?? null\n )\n .filter((value): value is string => typeof value === 'string' && value.length > 0)\n\n allocations.forEach((allocation) => em.remove(allocation))\n await em.flush()\n\n em.remove(existing)\n await em.flush()\n\n const orderIds = Array.from(\n new Set(\n [\n orderRef,\n ...allocationOrders,\n ].filter((value): value is string => typeof value === 'string' && value.length > 0)\n )\n )\n for (const id of orderIds) {\n await em.transactional(async (tx) => {\n const order = await findOneWithDecryption(tx, SalesOrder, { id }, { lockMode: LockMode.PESSIMISTIC_WRITE }, { tenantId: after.tenantId, organizationId: after.organizationId })\n if (!order) return\n if (id === after.orderId && 'orderPaymentMethodIdBefore' in (payload ?? {})) {\n order.paymentMethodId = payload.orderPaymentMethodIdBefore ?? null\n order.paymentMethodCode = payload.orderPaymentMethodCodeBefore ?? null\n order.updatedAt = new Date()\n await tx.flush()\n }\n await recomputeOrderPaymentTotals(tx, order)\n await tx.flush()\n })\n }\n }\n },\n redo: async ({ ctx, logEntry }) => {\n const after = resolveRedoSnapshot<PaymentSnapshot>(logEntry)\n const paymentId = after?.id ?? logEntry.resourceId ?? null\n if (!after || !paymentId) {\n throw new CrudHttpError(400, { error: '[internal] redo snapshot unavailable for sales.payments.create' })\n }\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n await restorePaymentSnapshot(em, after)\n await em.flush()\n\n const orderIds = Array.from(\n new Set(\n [\n after.orderId,\n ...after.allocations.map((allocation) => allocation.orderId),\n ].filter((value): value is string => typeof value === 'string' && value.length > 0)\n )\n )\n let totals: { paidTotalAmount: number; refundedTotalAmount: number; outstandingAmount: number } | undefined\n for (const orderId of orderIds) {\n const recomputed = await em.transactional(async (tx) => {\n const order = await findOneWithDecryption(\n tx,\n SalesOrder,\n { id: orderId },\n { lockMode: LockMode.PESSIMISTIC_WRITE },\n { tenantId: after.tenantId, organizationId: after.organizationId },\n )\n if (!order) return undefined\n if (orderId === after.orderId && after.paymentMethodId && !order.paymentMethodId) {\n const method = await findOneWithDecryption(\n tx,\n SalesPaymentMethod,\n { id: after.paymentMethodId },\n {},\n { tenantId: after.tenantId, organizationId: after.organizationId },\n )\n order.paymentMethodId = method?.id ?? after.paymentMethodId\n order.paymentMethodCode = method?.code ?? null\n order.updatedAt = new Date()\n await tx.flush()\n }\n const result = await recomputeOrderPaymentTotals(tx, order)\n await tx.flush()\n return result\n })\n if (recomputed && (!totals || orderId === after.orderId)) {\n totals = recomputed\n }\n // Raw findOne is intentional: the order is fetched only to read its id/scope\n // for cache invalidation \u2014 no encrypted field is read, so decryption is unnecessary.\n // Scope filter (#2111): never cache-invalidate a foreign tenant's order even\n // if a snapshot's orderId was somehow tampered with.\n const target = await em.findOne(SalesOrder, { id: orderId, organizationId: after.organizationId, tenantId: after.tenantId })\n if (target) {\n ensureSameScope(target, after.organizationId, after.tenantId)\n await invalidateOrderCache(ctx.container, target, ctx.auth?.tenantId ?? null)\n }\n }\n\n const payment = await findOneWithDecryption(em, SalesPayment, { id: after.id }, {}, { tenantId: after.tenantId, organizationId: after.organizationId })\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'created',\n entity: payment,\n identifiers: {\n id: after.id,\n organizationId: after.organizationId,\n tenantId: after.tenantId,\n },\n indexer: { entityType: E.sales.sales_payment },\n events: paymentCrudEvents,\n })\n\n return { paymentId: after.id, orderTotals: totals }\n },\n}\n\nconst updatePaymentCommand: CommandHandler<\n PaymentUpdateInput,\n { paymentId: string; orderTotals?: { paidTotalAmount: number; refundedTotalAmount: number; outstandingAmount: number } }\n> = {\n id: 'sales.payments.update',\n async prepare(rawInput, ctx) {\n const parsed = paymentUpdateSchema.parse(rawInput ?? {})\n if (!parsed.id) return {}\n const em = ctx.container.resolve('em') as EntityManager\n const scope = ctx.auth?.tenantId ? { tenantId: ctx.auth.tenantId, organizationId: ctx.auth?.orgId ?? null } : undefined\n const snapshot = await loadPaymentSnapshot(em, parsed.id, scope)\n if (snapshot) {\n ensureTenantScope(ctx, snapshot.tenantId)\n ensureOrganizationScope(ctx, snapshot.organizationId)\n }\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const input = paymentUpdateSchema.parse(rawInput ?? {})\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const { translate } = await resolveTranslations()\n const scopeSeed = assertFound(\n await findOneWithDecryption(em, SalesPayment, { id: input.id }, {}, { tenantId: input.tenantId, organizationId: input.organizationId }),\n 'sales.payments.not_found'\n )\n const resolvedTenantId = input.tenantId ?? scopeSeed.tenantId\n const resolvedOrganizationId = input.organizationId ?? scopeSeed.organizationId\n ensureTenantScope(ctx, resolvedTenantId)\n ensureOrganizationScope(ctx, resolvedOrganizationId)\n const payment = assertFound(\n await findOneWithDecryption(\n em,\n SalesPayment,\n { id: input.id },\n { populate: ['order'] },\n { tenantId: resolvedTenantId, organizationId: resolvedOrganizationId },\n ),\n 'sales.payments.not_found'\n )\n ensureSameScope(payment, resolvedOrganizationId, resolvedTenantId)\n const previousOrder = payment.order as SalesOrder | null\n // Apply payment scalar fields, order/line status changes and the\n // allocations rebuild in one transaction so a mid-write failure cannot\n // leave the payment and its allocations partially committed (#2336).\n await em.transactional(async (tx) => {\n if (input.orderId !== undefined) {\n if (!input.orderId) {\n payment.order = null\n } else {\n const order = assertFound(\n await findOneWithDecryption(tx, SalesOrder, { id: input.orderId }, {}, { tenantId: resolvedTenantId, organizationId: resolvedOrganizationId }),\n 'sales.payments.order_not_found'\n )\n ensureSameScope(order, resolvedOrganizationId, resolvedTenantId)\n if (\n order.currencyCode &&\n input.currencyCode &&\n order.currencyCode.toUpperCase() !== input.currencyCode.toUpperCase()\n ) {\n throw new CrudHttpError(400, {\n error: translate('sales.payments.currency_mismatch', 'Payment currency must match the order currency.'),\n })\n }\n payment.order = order\n }\n }\n if (input.paymentMethodId !== undefined) {\n if (!input.paymentMethodId) {\n payment.paymentMethod = null\n } else {\n const method = assertFound(\n await findOneWithDecryption(tx, SalesPaymentMethod, { id: input.paymentMethodId }, {}, { tenantId: resolvedTenantId, organizationId: resolvedOrganizationId }),\n 'sales.payments.method_not_found'\n )\n ensureSameScope(method, resolvedOrganizationId, resolvedTenantId)\n payment.paymentMethod = method\n }\n }\n const currentOrder = payment.order as SalesOrder | null\n if ((input.documentStatusEntryId !== undefined || input.lineStatusEntryId !== undefined) && !currentOrder) {\n throw new CrudHttpError(400, { error: translate('sales.payments.order_required', 'Order is required for payments.') })\n }\n if (currentOrder && input.documentStatusEntryId !== undefined) {\n const orderStatus = await resolveDictionaryEntryValue(tx, input.documentStatusEntryId ?? null, { tenantId: resolvedTenantId })\n if (input.documentStatusEntryId && !orderStatus) {\n throw new CrudHttpError(400, {\n error: translate('sales.documents.detail.statusInvalid', 'Selected status could not be found.'),\n })\n }\n currentOrder.statusEntryId = input.documentStatusEntryId ?? null\n currentOrder.status = orderStatus\n currentOrder.updatedAt = new Date()\n tx.persist(currentOrder)\n }\n if (currentOrder && input.lineStatusEntryId !== undefined) {\n const lineStatus = await resolveDictionaryEntryValue(tx, input.lineStatusEntryId ?? null, { tenantId: resolvedTenantId })\n if (input.lineStatusEntryId && !lineStatus) {\n throw new CrudHttpError(400, {\n error: translate('sales.documents.detail.statusInvalid', 'Selected status could not be found.'),\n })\n }\n const orderLines = await findWithDecryption(tx, SalesOrderLine, { order: currentOrder }, {}, { tenantId: resolvedTenantId, organizationId: resolvedOrganizationId })\n orderLines.forEach((line) => {\n line.statusEntryId = input.lineStatusEntryId ?? null\n line.status = lineStatus\n line.updatedAt = new Date()\n })\n orderLines.forEach((line) => tx.persist(line))\n }\n if (input.paymentReference !== undefined) payment.paymentReference = input.paymentReference ?? null\n if (input.statusEntryId !== undefined) {\n payment.statusEntryId = input.statusEntryId ?? null\n payment.status = await resolveDictionaryEntryValue(tx, input.statusEntryId ?? null, { tenantId: resolvedTenantId })\n }\n if (input.amount !== undefined) payment.amount = toNumericString(input.amount) ?? '0'\n if (input.currencyCode !== undefined) payment.currencyCode = input.currencyCode\n if (input.capturedAmount !== undefined) {\n payment.capturedAmount = toNumericString(input.capturedAmount) ?? '0'\n }\n if (input.refundedAmount !== undefined) {\n payment.refundedAmount = toNumericString(input.refundedAmount) ?? '0'\n }\n if (input.receivedAt !== undefined) payment.receivedAt = input.receivedAt ?? null\n if (input.capturedAt !== undefined) payment.capturedAt = input.capturedAt ?? null\n if (input.metadata !== undefined) {\n payment.metadata = input.metadata ? cloneJson(input.metadata) : null\n }\n if (input.customFieldSetId !== undefined) {\n payment.customFieldSetId = input.customFieldSetId ?? null\n }\n if (input.customFields !== undefined) {\n if (!payment.id) {\n await tx.flush()\n }\n await setRecordCustomFields(tx, {\n entityId: E.sales.sales_payment,\n recordId: payment.id,\n organizationId: payment.organizationId,\n tenantId: payment.tenantId,\n values: normalizeCustomFieldsInput(input.customFields),\n })\n }\n payment.updatedAt = new Date()\n\n // Persist the payment scalar changes before any allocation query below.\n // MikroORM discards pending scalar mutations when a find() runs on the\n // same EntityManager before they are flushed, which would otherwise drop\n // the updated amount/reference when allocations are (re)synced.\n await tx.flush()\n\n if (input.allocations !== undefined) {\n const existingAllocations = await findWithDecryption(tx, SalesPaymentAllocation, { payment }, {}, { tenantId: payment.tenantId, organizationId: payment.organizationId })\n existingAllocations.forEach((allocation) => tx.remove(allocation))\n const allocationInputs = Array.isArray(input.allocations) ? input.allocations : []\n const paymentOrderId =\n (typeof payment.order === 'string' ? payment.order : payment.order?.id) ?? null\n const orderCache = new Map<string, SalesOrder>()\n if (currentOrder) orderCache.set(currentOrder.id, currentOrder)\n const invoiceCache = new Map<string, SalesInvoice>()\n for (const allocation of allocationInputs) {\n const orderId = allocation.orderId ?? paymentOrderId\n let order: SalesOrder | null = null\n if (orderId && typeof orderId === 'string') {\n order = orderCache.get(orderId) ?? null\n if (!order) {\n order = assertFound(\n await findOneWithDecryption(\n tx,\n SalesOrder,\n { id: orderId },\n {},\n { tenantId: payment.tenantId, organizationId: payment.organizationId },\n ),\n 'sales.payments.order_not_found',\n )\n ensureSameScope(order, payment.organizationId, payment.tenantId)\n orderCache.set(orderId, order)\n }\n }\n let invoice: SalesInvoice | null = null\n if (allocation.invoiceId) {\n invoice = invoiceCache.get(allocation.invoiceId) ?? null\n if (!invoice) {\n invoice = assertFound(\n await findOneWithDecryption(\n tx,\n SalesInvoice,\n { id: allocation.invoiceId },\n {},\n { tenantId: payment.tenantId, organizationId: payment.organizationId },\n ),\n 'sales.payments.invoice_not_found',\n )\n ensureSameScope(invoice, payment.organizationId, payment.tenantId)\n invoiceCache.set(allocation.invoiceId, invoice)\n }\n }\n const entity = tx.create(SalesPaymentAllocation, {\n payment,\n order,\n invoice,\n organizationId: payment.organizationId,\n tenantId: payment.tenantId,\n amount: toNumericString(allocation.amount) ?? '0',\n currencyCode: allocation.currencyCode,\n metadata: allocation.metadata ? cloneJson(allocation.metadata) : null,\n })\n tx.persist(entity)\n }\n } else if (input.amount !== undefined || input.currencyCode !== undefined) {\n // The caller changed the payment amount/currency without managing\n // allocations explicitly. A simple payment carries a single\n // auto-created allocation covering the full amount (see create); keep\n // it in sync so recomputeOrderPaymentTotals \u2014 which sums allocations in\n // preference to the payment amount \u2014 does not report a stale paid total\n // after a payment edit (#2455).\n const existingAllocations = await findWithDecryption(tx, SalesPaymentAllocation, { payment }, {}, { tenantId: payment.tenantId, organizationId: payment.organizationId })\n const paymentOrderId =\n (typeof payment.order === 'string' ? payment.order : payment.order?.id) ?? null\n const isDefaultAllocation = (allocation: SalesPaymentAllocation): boolean => {\n const allocationOrderId =\n typeof allocation.order === 'string' ? allocation.order : allocation.order?.id ?? null\n const allocationInvoiceId =\n typeof allocation.invoice === 'string' ? allocation.invoice : allocation.invoice?.id ?? null\n return allocationInvoiceId === null && allocationOrderId === paymentOrderId\n }\n if (existingAllocations.length === 1 && isDefaultAllocation(existingAllocations[0])) {\n const [allocation] = existingAllocations\n allocation.amount = toNumericString(toNumber(payment.amount)) ?? '0'\n allocation.currencyCode = payment.currencyCode\n tx.persist(allocation)\n }\n }\n })\n\n const nextOrderId =\n (payment.order as SalesOrder | null)?.id ??\n (typeof payment.order === 'string' ? payment.order : null)\n let totals: { paidTotalAmount: number; refundedTotalAmount: number; outstandingAmount: number } | undefined\n if (nextOrderId) {\n totals = await em.transactional(async (tx) => {\n // Scope filter (#2111): never lock or recompute totals on a foreign\n // tenant's order, even if payment.order somehow points there.\n const lockedOrder = await tx.findOne(\n SalesOrder,\n { id: nextOrderId, organizationId: payment.organizationId, tenantId: payment.tenantId },\n { lockMode: LockMode.PESSIMISTIC_WRITE },\n )\n if (!lockedOrder) return undefined\n ensureSameScope(lockedOrder, payment.organizationId, payment.tenantId)\n const result = await recomputeOrderPaymentTotals(tx, lockedOrder)\n await tx.flush()\n return result\n })\n if (totals) {\n // Raw findOne is intentional: the order is fetched only to read its id/scope\n // for cache invalidation \u2014 no encrypted field is read, so decryption is unnecessary.\n // Scope filter (#2111): same rationale as the lock above.\n const nextOrder = await em.findOne(SalesOrder, { id: nextOrderId, organizationId: payment.organizationId, tenantId: payment.tenantId })\n if (nextOrder) {\n ensureSameScope(nextOrder, payment.organizationId, payment.tenantId)\n await invalidateOrderCache(ctx.container, nextOrder, ctx.auth?.tenantId ?? null)\n }\n }\n }\n if (previousOrder && (!nextOrderId || previousOrder.id !== nextOrderId)) {\n await em.transactional(async (tx) => {\n // Scope filter (#2111): previousOrder was already loaded via the\n // payment's scope, so its tenant/org match the payment's. Filter\n // the lock query the same way as defence-in-depth.\n const lockedOrder = await tx.findOne(\n SalesOrder,\n { id: previousOrder.id, organizationId: payment.organizationId, tenantId: payment.tenantId },\n { lockMode: LockMode.PESSIMISTIC_WRITE },\n )\n if (!lockedOrder) return\n ensureSameScope(lockedOrder, payment.organizationId, payment.tenantId)\n await recomputeOrderPaymentTotals(tx, lockedOrder)\n await tx.flush()\n })\n await invalidateOrderCache(ctx.container, previousOrder, ctx.auth?.tenantId ?? null)\n }\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'updated',\n entity: payment,\n identifiers: {\n id: payment.id,\n organizationId: payment.organizationId,\n tenantId: payment.tenantId,\n },\n indexer: { entityType: E.sales.sales_payment },\n events: paymentCrudEvents,\n })\n\n return { paymentId: payment.id, orderTotals: totals }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = ctx.auth?.tenantId ? { tenantId: ctx.auth.tenantId, organizationId: ctx.auth?.orgId ?? null } : undefined\n return result?.paymentId ? loadPaymentSnapshot(em, result.paymentId, scope) : null\n },\n buildLog: async ({ snapshots, result }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as PaymentSnapshot | undefined\n const after = snapshots.after as PaymentSnapshot | undefined\n return {\n actionLabel: translate('sales.audit.payments.update', 'Update payment'),\n resourceKind: 'sales.payment',\n resourceId: result.paymentId,\n parentResourceKind: 'sales.order',\n parentResourceId: after?.orderId ?? before?.orderId ?? null,\n tenantId: after?.tenantId ?? before?.tenantId ?? null,\n organizationId: after?.organizationId ?? before?.organizationId ?? null,\n snapshotBefore: before ?? null,\n snapshotAfter: after ?? null,\n payload: { undo: { before, after } satisfies PaymentUndoPayload },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<PaymentUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n await restorePaymentSnapshot(em, before)\n await em.flush()\n if (before.orderId) {\n await em.transactional(async (tx) => {\n const order = await findOneWithDecryption(tx, SalesOrder, { id: before.orderId! }, { lockMode: LockMode.PESSIMISTIC_WRITE }, { tenantId: before.tenantId, organizationId: before.organizationId })\n if (!order) return\n await recomputeOrderPaymentTotals(tx, order)\n await tx.flush()\n })\n }\n },\n}\n\nconst deletePaymentCommand: CommandHandler<\n { id: string; orderId?: string | null; organizationId: string; tenantId: string },\n { paymentId: string; orderTotals?: { paidTotalAmount: number; refundedTotalAmount: number; outstandingAmount: number } }\n> = {\n id: 'sales.payments.delete',\n async prepare(rawInput, ctx) {\n const parsed = paymentUpdateSchema.parse(rawInput ?? {})\n if (!parsed.id) return {}\n const em = ctx.container.resolve('em') as EntityManager\n const scope = ctx.auth?.tenantId ? { tenantId: ctx.auth.tenantId, organizationId: ctx.auth?.orgId ?? null } : undefined\n const snapshot = await loadPaymentSnapshot(em, parsed.id, scope)\n if (snapshot) {\n ensureTenantScope(ctx, snapshot.tenantId)\n ensureOrganizationScope(ctx, snapshot.organizationId)\n }\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const input = paymentUpdateSchema.parse(rawInput ?? {})\n ensureTenantScope(ctx, input.tenantId)\n ensureOrganizationScope(ctx, input.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const payment = assertFound(\n await findOneWithDecryption(\n em,\n SalesPayment,\n { id: input.id },\n { populate: ['order'] },\n { tenantId: input.tenantId, organizationId: input.organizationId },\n ),\n 'sales.payments.not_found'\n )\n ensureSameScope(payment, input.organizationId, input.tenantId)\n const order = payment.order as SalesOrder | null\n const allocations = await findWithDecryption(em, SalesPaymentAllocation, { payment }, {}, { tenantId: payment.tenantId, organizationId: payment.organizationId })\n const allocationOrders = allocations\n .map((allocation) =>\n typeof allocation.order === 'string'\n ? allocation.order\n : allocation.order?.id ?? null\n )\n .filter((value): value is string => typeof value === 'string' && value.length > 0)\n // Remove the allocations and the payment in one transaction so a failure\n // between the two deletes cannot leave orphaned allocations committed\n // without their payment (#2336).\n await em.transactional(async (tx) => {\n allocations.forEach((allocation) => tx.remove(allocation))\n tx.remove(payment)\n })\n let totals: { paidTotalAmount: number; refundedTotalAmount: number; outstandingAmount: number } | undefined\n const orderIds = Array.from(\n new Set(\n [\n order && typeof order === 'object' ? order.id : null,\n ...allocationOrders,\n ].filter((value): value is string => typeof value === 'string' && value.length > 0)\n )\n )\n const primaryOrderId = order && typeof order === 'object' ? order.id : null\n for (const orderId of orderIds) {\n const recomputed = await em.transactional(async (tx) => {\n // Scope filter (#2111): never lock or recompute totals on a foreign\n // tenant's order, even if a payment allocation somehow points there.\n const lockedOrder = await tx.findOne(\n SalesOrder,\n { id: orderId, organizationId: payment.organizationId, tenantId: payment.tenantId },\n { lockMode: LockMode.PESSIMISTIC_WRITE },\n )\n if (!lockedOrder) return undefined\n ensureSameScope(lockedOrder, payment.organizationId, payment.tenantId)\n const result = await recomputeOrderPaymentTotals(tx, lockedOrder)\n await tx.flush()\n return result\n })\n if (recomputed && (!totals || (primaryOrderId && orderId === primaryOrderId))) {\n totals = recomputed\n }\n // Raw findOne is intentional: the order is fetched only to read its id/scope\n // for cache invalidation \u2014 no encrypted field is read, so decryption is unnecessary.\n // Scope filter (#2111): same rationale as the lock above.\n const target = await em.findOne(SalesOrder, { id: orderId, organizationId: payment.organizationId, tenantId: payment.tenantId })\n if (target) {\n ensureSameScope(target, payment.organizationId, payment.tenantId)\n await invalidateOrderCache(ctx.container, target, ctx.auth?.tenantId ?? null)\n }\n }\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'deleted',\n entity: payment,\n identifiers: {\n id: payment.id,\n organizationId: payment.organizationId,\n tenantId: payment.tenantId,\n },\n indexer: { entityType: E.sales.sales_payment },\n events: paymentCrudEvents,\n })\n if (allocations.length) {\n await Promise.all(\n allocations.map((allocation) =>\n emitCrudSideEffects({\n dataEngine,\n action: 'deleted',\n entity: allocation,\n identifiers: {\n id: allocation.id,\n organizationId: allocation.organizationId ?? null,\n tenantId: allocation.tenantId ?? null,\n },\n indexer: { entityType: E.sales.sales_payment_allocation },\n })\n )\n )\n }\n return { paymentId: payment.id, orderTotals: totals }\n },\n buildLog: async ({ snapshots, result }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as PaymentSnapshot | undefined\n return {\n actionLabel: translate('sales.audit.payments.delete', 'Delete payment'),\n resourceKind: 'sales.payment',\n resourceId: result.paymentId,\n parentResourceKind: 'sales.order',\n parentResourceId: before?.orderId ?? null,\n tenantId: before?.tenantId ?? null,\n organizationId: before?.organizationId ?? null,\n snapshotBefore: before ?? null,\n payload: { undo: { before } satisfies PaymentUndoPayload },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<PaymentUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n await restorePaymentSnapshot(em, before)\n await em.flush()\n if (before.orderId) {\n await em.transactional(async (tx) => {\n const order = await findOneWithDecryption(tx, SalesOrder, { id: before.orderId! }, { lockMode: LockMode.PESSIMISTIC_WRITE }, { tenantId: before.tenantId, organizationId: before.organizationId })\n if (!order) return\n await recomputeOrderPaymentTotals(tx, order)\n await tx.flush()\n })\n }\n },\n}\n\nexport const paymentCommands = [createPaymentCommand, updatePaymentCommand, deletePaymentCommand]\n\nregisterCommand(createPaymentCommand)\nregisterCommand(updatePaymentCommand)\nregisterCommand(deletePaymentCommand)\n"],
5
+ "mappings": "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",
6
6
  "names": ["order", "orderPaymentMethodIdBefore", "orderPaymentMethodCodeBefore", "payment", "totals"]
7
7
  }
@@ -336,7 +336,7 @@ const createShipmentCommand = {
336
336
  items: input.items,
337
337
  lockOrderLines: true
338
338
  });
339
- const statusValue = await resolveDictionaryEntryValue(tx, input.statusEntryId ?? null);
339
+ const statusValue = await resolveDictionaryEntryValue(tx, input.statusEntryId ?? null, { tenantId: input.tenantId });
340
340
  const trackingNumbers = parseTrackingNumbers(input.trackingNumbers) ?? null;
341
341
  const metadata = mergeAddressSnapshot(
342
342
  input.metadata ? cloneJson(input.metadata) : null,
@@ -392,7 +392,7 @@ const createShipmentCommand = {
392
392
  });
393
393
  }
394
394
  if (input.documentStatusEntryId !== void 0) {
395
- const orderStatus = await resolveDictionaryEntryValue(tx, input.documentStatusEntryId ?? null);
395
+ const orderStatus = await resolveDictionaryEntryValue(tx, input.documentStatusEntryId ?? null, { tenantId: input.tenantId });
396
396
  if (input.documentStatusEntryId && !orderStatus) {
397
397
  throw new CrudHttpError(400, { error: translate("sales.documents.detail.statusInvalid", "Selected status could not be found.") });
398
398
  }
@@ -401,7 +401,7 @@ const createShipmentCommand = {
401
401
  order.updatedAt = /* @__PURE__ */ new Date();
402
402
  }
403
403
  if (input.lineStatusEntryId !== void 0) {
404
- const lineStatus = await resolveDictionaryEntryValue(tx, input.lineStatusEntryId ?? null);
404
+ const lineStatus = await resolveDictionaryEntryValue(tx, input.lineStatusEntryId ?? null, { tenantId: input.tenantId });
405
405
  if (input.lineStatusEntryId && !lineStatus) {
406
406
  throw new CrudHttpError(400, { error: translate("sales.documents.detail.statusInvalid", "Selected status could not be found.") });
407
407
  }
@@ -574,7 +574,7 @@ const updateShipmentCommand = {
574
574
  }) : null;
575
575
  const normalizedItems = validatedItems?.items ?? null;
576
576
  const lineMap = validatedItems?.lineMap ?? /* @__PURE__ */ new Map();
577
- const resolvedShipmentStatus = input.statusEntryId !== void 0 ? await resolveDictionaryEntryValue(tx, input.statusEntryId ?? null) : void 0;
577
+ const resolvedShipmentStatus = input.statusEntryId !== void 0 ? await resolveDictionaryEntryValue(tx, input.statusEntryId ?? null, { tenantId: shipmentEntity.tenantId }) : void 0;
578
578
  if (input.shipmentNumber !== void 0) shipmentEntity.shipmentNumber = input.shipmentNumber ?? null;
579
579
  if (input.shippingMethodId !== void 0) shipmentEntity.shippingMethodId = input.shippingMethodId ?? null;
580
580
  if (input.statusEntryId !== void 0) {
@@ -633,7 +633,7 @@ const updateShipmentCommand = {
633
633
  });
634
634
  }
635
635
  if (input.documentStatusEntryId !== void 0) {
636
- const orderStatus = await resolveDictionaryEntryValue(tx, input.documentStatusEntryId ?? null);
636
+ const orderStatus = await resolveDictionaryEntryValue(tx, input.documentStatusEntryId ?? null, { tenantId: shipmentEntity.tenantId });
637
637
  if (input.documentStatusEntryId && !orderStatus) {
638
638
  throw new CrudHttpError(400, { error: translate("sales.documents.detail.statusInvalid", "Selected status could not be found.") });
639
639
  }
@@ -642,7 +642,7 @@ const updateShipmentCommand = {
642
642
  order.updatedAt = /* @__PURE__ */ new Date();
643
643
  }
644
644
  if (input.lineStatusEntryId !== void 0) {
645
- const lineStatus = await resolveDictionaryEntryValue(tx, input.lineStatusEntryId ?? null);
645
+ const lineStatus = await resolveDictionaryEntryValue(tx, input.lineStatusEntryId ?? null, { tenantId: shipmentEntity.tenantId });
646
646
  if (input.lineStatusEntryId && !lineStatus) {
647
647
  throw new CrudHttpError(400, { error: translate("sales.documents.detail.statusInvalid", "Selected status could not be found.") });
648
648
  }