@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.
- package/.turbo/turbo-build.log +1 -1
- package/dist/modules/communication_channels/lib/email-mime.js +18 -1
- package/dist/modules/communication_channels/lib/email-mime.js.map +2 -2
- package/dist/modules/customers/components/formConfig.js +4 -1
- package/dist/modules/customers/components/formConfig.js.map +2 -2
- package/dist/modules/customers/data/validators.js +5 -1
- package/dist/modules/customers/data/validators.js.map +2 -2
- package/dist/modules/sales/commands/configuration.js +2 -2
- package/dist/modules/sales/commands/configuration.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +17 -13
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/commands/payments.js +6 -6
- package/dist/modules/sales/commands/payments.js.map +2 -2
- package/dist/modules/sales/commands/shipments.js +6 -6
- package/dist/modules/sales/commands/shipments.js.map +2 -2
- package/dist/modules/sales/lib/dictionaries.js +2 -2
- package/dist/modules/sales/lib/dictionaries.js.map +2 -2
- package/dist/modules/staff/components/TeamMemberForm.js +5 -2
- package/dist/modules/staff/components/TeamMemberForm.js.map +2 -2
- package/package.json +14 -14
- package/src/modules/communication_channels/lib/email-mime.ts +33 -6
- package/src/modules/customers/components/formConfig.tsx +16 -1
- package/src/modules/customers/data/validators.ts +8 -1
- package/src/modules/sales/commands/configuration.ts +2 -2
- package/src/modules/sales/commands/documents.ts +13 -9
- package/src/modules/sales/commands/payments.ts +6 -6
- package/src/modules/sales/commands/shipments.ts +6 -6
- package/src/modules/sales/lib/dictionaries.ts +3 -2
- 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": "AAEA,SAAS,uBAA4C;AACrD,SAAS,gBAAgB;AAEzB,SAAS,qBAAqB;AAC9B,SAAS,2BAA2B;AACpC,SAAS,6BAA6B;AACtC,SAAS,6BAA6B;AACtC,SAAS,SAAS;AAClB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAGK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,mCAAmC;AAC5C,SAAS,2BAA2B;AACpC,SAAS,2BAA2B;AACpC,SAAS,2BAA2B;AAGpC,SAAS,uBAAuB,0BAA0B;AAC1D,SAAS,kCAAkC;AAC3C,SAAS,wCAAwC;AACjD,SAAS,yBAAyB;AAuClC,MAAM,WAAW,CAAC,UAA2B;AAC3C,MAAI,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,EAAG,QAAO;AAChE,MAAI,OAAO,UAAU,YAAY,MAAM,KAAK,EAAE,QAAQ;AACpD,UAAM,SAAS,OAAO,KAAK;AAC3B,QAAI,CAAC,OAAO,MAAM,MAAM,EAAG,QAAO;AAAA,EACpC;AACA,SAAO;AACT;AAEA,MAAM,6BAA6B,CAAC,UAClC,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,IAAK,QAAoC,CAAC;AAEtG,MAAM,oBAAsC;AAAA,EAC1C,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,cAAc,CAAC,SAAS;AAAA,IACtB,IAAI,IAAI,YAAY;AAAA,IACpB,gBAAgB,IAAI,YAAY;AAAA,IAChC,UAAU,IAAI,YAAY;AAAA,EAC5B;AACF;AAEA,MAAM,iBAAiB;AAEvB,eAAe,qBAAqB,WAAgB,OAAsC,UAAyB;AACjH,MAAI,CAAC,MAAO;AACZ,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,EAAE,IAAI,MAAM,IAAI,gBAAgB,MAAM,gBAAgB,UAAU,MAAM,SAAS;AAAA,IAC/E;AAAA,IACA;AAAA,EACF;AACF;AAEA,eAAsB,oBAAoB,IAAmB,IAAY,OAAuG;AAC9K,QAAM,UAAU,MAAM;AAAA,IACpB;AAAA,IACA;AAAA,IACA,EAAE,GAAG;AAAA,IACL,EAAE,UAAU,CAAC,SAAS,eAAe,qBAAqB,qBAAqB,EAAE;AAAA,IACjF;AAAA,EACF;AACA,MAAI,CAAC,QAAS,QAAO;AACrB,QAAM,cAA2C,MAAM,KAAK,QAAQ,eAAe,CAAC,CAAC,EAAE,IAAI,CAAC,gBAAgB;AAAA,IAC1G,IAAI,WAAW;AAAA,IACf,SACE,OAAO,WAAW,UAAU,WACxB,WAAW,QACX,WAAW,OAAO,MAAO,WAAmB,YAAY;AAAA,IAC9D,WACE,OAAO,WAAW,YAAY,WAC1B,WAAW,UACX,WAAW,SAAS,MAAO,WAAmB,cAAc;AAAA,IAClE,QAAQ,SAAS,WAAW,MAAM;AAAA,IAClC,cAAc,WAAW;AAAA,IACzB,UAAU,WAAW,WAAW,UAAU,WAAW,QAAQ,IAAI;AAAA,EACnE,EAAE;AACF,QAAM,oBAAoB,MAAM,sBAAsB;AAAA,IACpD;AAAA,IACA,UAAU,EAAE,MAAM;AAAA,IAClB,WAAW,CAAC,QAAQ,EAAE;AAAA,IACtB,kBAAkB,EAAE,CAAC,QAAQ,EAAE,GAAG,QAAQ,YAAY,KAAK;AAAA,IAC3D,wBAAwB,EAAE,CAAC,QAAQ,EAAE,GAAG,QAAQ,kBAAkB,KAAK;AAAA,EACzE,CAAC;AACD,QAAM,eAAe,kBAAkB,QAAQ,EAAE;AACjD,QAAM,yBACJ,gBAAgB,OAAO,KAAK,YAAY,EAAE,SAAS,eAAe;AACpE,SAAO;AAAA,IACL,IAAI,QAAQ;AAAA,IACZ,SAAS,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ,QAAQ,OAAO,MAAM;AAAA,IAClF,gBAAgB,QAAQ;AAAA,IACxB,UAAU,QAAQ;AAAA,IAClB,iBACE,OAAO,QAAQ,kBAAkB,WAC7B,QAAQ,gBACR,QAAQ,eAAe,MAAM;AAAA,IACnC,kBAAkB,QAAQ,oBAAoB;AAAA,IAC9C,eAAe,QAAQ,iBAAiB;AAAA,IACxC,QAAQ,QAAQ,UAAU;AAAA,IAC1B,QAAQ,SAAS,QAAQ,MAAM;AAAA,IAC/B,cAAc,QAAQ;AAAA,IACtB,gBAAgB,SAAS,QAAQ,cAAc;AAAA,IAC/C,gBAAgB,SAAS,QAAQ,cAAc;AAAA,IAC/C,YAAY,QAAQ,aAAa,QAAQ,WAAW,YAAY,IAAI;AAAA,IACpE,YAAY,QAAQ,aAAa,QAAQ,WAAW,YAAY,IAAI;AAAA,IACpE,UAAU,QAAQ,WAAW,UAAU,QAAQ,QAAQ,IAAI;AAAA,IAC3D,cAAc;AAAA,IACd,kBAAmB,QAAgB,oBAAqB,QAAgB,uBAAuB;AAAA,IAC/F;AAAA,EACF;AACF;AAEA,eAAsB,uBAAuB,IAAmB,UAA0C;AACxG,QAAM,WAAW,SAAS,UAAU,GAAG,aAAa,YAAY,SAAS,OAAO,IAAI;AACpF,QAAM,YAAY,SAAS,kBACvB,GAAG,aAAa,oBAAoB,SAAS,eAAe,IAC5D;AACJ,QAAM,SACH,MAAM,sBAAsB,IAAI,cAAc,EAAE,IAAI,SAAS,GAAG,GAAG,CAAC,GAAG,EAAE,UAAU,SAAS,UAAU,gBAAgB,SAAS,eAAe,CAAC,KAChJ,GAAG,OAAO,cAAc;AAAA,IACtB,IAAI,SAAS;AAAA,IACb,WAAW,oBAAI,KAAK;AAAA,IACpB,gBAAgB,SAAS;AAAA,IACzB,UAAU,SAAS;AAAA,EACrB,CAAC;AACH,SAAO,QAAQ;AACf,SAAO,gBAAgB;AACvB,SAAO,iBAAiB,SAAS;AACjC,SAAO,WAAW,SAAS;AAC3B,SAAO,mBAAmB,SAAS;AACnC,SAAO,gBAAgB,SAAS;AAChC,SAAO,SAAS,SAAS;AACzB,SAAO,SAAS,gBAAgB,SAAS,MAAM,KAAK;AACpD,SAAO,eAAe,SAAS;AAC/B,SAAO,iBAAiB,gBAAgB,SAAS,cAAc,KAAK;AACpE,SAAO,iBAAiB,gBAAgB,SAAS,cAAc,KAAK;AACpE,SAAO,aAAa,SAAS,aAAa,IAAI,KAAK,SAAS,UAAU,IAAI;AAC1E,SAAO,aAAa,SAAS,aAAa,IAAI,KAAK,SAAS,UAAU,IAAI;AAC1E,SAAO,WAAW,SAAS,WAAW,UAAU,SAAS,QAAQ,IAAI;AACrE,SAAO,mBACJ,SAAiB,oBAAqB,SAAiB,uBAAuB;AACjF,SAAO,YAAY,oBAAI,KAAK;AAC5B,QAAM,GAAG,MAAM;AAEf,MAAK,SAAiB,iBAAiB,QAAW;AAChD,UAAM,sBAAsB,IAAI;AAAA,MAC9B,UAAU,EAAE,MAAM;AAAA,MAClB,UAAU,OAAO;AAAA,MACjB,gBAAgB,OAAO;AAAA,MACvB,UAAU,OAAO;AAAA,MACjB,QACE,SAAS,gBAAgB,OAAO,SAAS,iBAAiB,WACrD,SAAS,eACV,CAAC;AAAA,IACT,CAAC;AAAA,EACH;AAEA,QAAM,sBAAsB,MAAM,mBAAmB,IAAI,wBAAwB,EAAE,SAAS,OAAO,GAAG,CAAC,GAAG,EAAE,UAAU,SAAS,UAAU,gBAAgB,SAAS,eAAe,CAAC;AAClL,sBAAoB,QAAQ,CAAC,eAAe,GAAG,OAAO,UAAU,CAAC;AACjE,WAAS,YAAY,QAAQ,CAAC,eAAe;AAC3C,UAAM,QACJ,WAAW,WAAW,OAAO,WAAW,YAAY,WAChD,GAAG,aAAa,YAAY,WAAW,OAAO,IAC9C;AACN,UAAM,UACJ,WAAW,aAAa,OAAO,WAAW,cAAc,WACpD,GAAG,aAAa,cAAc,WAAW,SAAS,IAClD;AACN,UAAM,gBAAgB,GAAG,OAAO,wBAAwB;AAAA,MACtD,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA,gBAAgB,SAAS;AAAA,MACzB,UAAU,SAAS;AAAA,MACnB,QAAQ,gBAAgB,WAAW,MAAM,KAAK;AAAA,MAC9C,cAAc,WAAW;AAAA,MACzB,UAAU,WAAW,WAAW,UAAU,WAAW,QAAQ,IAAI;AAAA,IACnE,CAAC;AACD,OAAG,QAAQ,aAAa;AAAA,EAC1B,CAAC;AACD,KAAG,QAAQ,MAAM;AACnB;AAEA,eAAe,4BACb,IACA,OACA,SAC8F;AAC9F,QAAM,UAAU,MAAM;AACtB,QAAM,QAAQ,EAAE,gBAAgB,MAAM,gBAAgB,UAAU,MAAM,SAAS;AAE/E,MAAI,SAAS,MAAM;AAMjB,UAAM,GAAG,QAAQ,YAAY,EAAE,IAAI,SAAS,GAAG,MAAM,GAAG,EAAE,UAAU,SAAS,kBAAkB,CAAC;AAAA,EAClG;AAEA,QAAM,cAAc,MAAM;AAAA,IACxB;AAAA,IACA;AAAA,IACA,EAAE,GAAG,OAAO,OAAO,QAAQ;AAAA,IAC3B,EAAE,UAAU,CAAC,SAAS,EAAE;AAAA,IACxB;AAAA,EACF;AAEA,QAAM,aAAa,oBAAI,IAAY;AACnC,cAAY,QAAQ,CAAC,eAAe;AAClC,UAAM,aAAa,WAAW;AAC9B,UAAM,YACJ,OAAO,eAAe,YAAY,eAAe,OAC7C,WAAW,KACX,OAAO,eAAe,WACpB,aACA;AACR,QAAI,UAAW,YAAW,IAAI,SAAS;AAAA,EACzC,CAAC;AAED,QAAM,WACJ,WAAW,OAAO,IACd,MAAM,mBAAmB,IAAI,cAAc,EAAE,IAAI,EAAE,KAAK,MAAM,KAAK,UAAU,EAAE,GAAG,WAAW,MAAM,GAAG,MAAM,GAAG,CAAC,GAAG,KAAK,IACxH,MAAM,mBAAmB,IAAI,cAAc,EAAE,OAAO,SAAS,WAAW,MAAM,GAAG,MAAM,GAAG,CAAC,GAAG,KAAK;AAEzG,QAAM,oBAAoB,CAAC,YAA0B;AACnD,UAAM,WAAW,SAAS,QAAQ,cAAc;AAChD,WAAO,WAAW,IAAI,WAAW,SAAS,QAAQ,MAAM;AAAA,EAC1D;AAEA,QAAM,mBAAmB,IAAI,IAAI,SAAS,IAAI,CAAC,YAAY,QAAQ,EAAE,CAAC;AACtE,QAAM,YACJ,YAAY,SAAS,IACjB,YAAY,OAAO,CAAC,KAAK,eAAe;AACtC,UAAM,aAAa,WAAW;AAC9B,UAAM,YACJ,OAAO,eAAe,YAAY,eAAe,OAC7C,WAAW,KACX,OAAO,eAAe,WACpB,aACA;AACR,QAAI,aAAa,CAAC,iBAAiB,IAAI,SAAS,EAAG,QAAO;AAC1D,WAAO,MAAM,SAAS,WAAW,MAAM;AAAA,EACzC,GAAG,CAAC,IACJ,SAAS,OAAO,CAAC,KAAK,YAAY,MAAM,kBAAkB,OAAO,GAAG,CAAC;AAE3E,QAAM,gBAAgB,SAAS;AAAA,IAC7B,CAAC,KAAK,YAAY,MAAM,SAAS,QAAQ,cAAc;AAAA,IACvD;AAAA,EACF;AAEA,QAAM,aAAa,SAAS,MAAM,qBAAqB;AACvD,QAAM,cAAc,KAAK,IAAI,aAAa,YAAY,eAAe,CAAC;AACtE,QAAM,kBAAkB,gBAAgB,SAAS,KAAK;AACtD,QAAM,sBAAsB,gBAAgB,aAAa,KAAK;AAC9D,QAAM,oBAAoB,gBAAgB,WAAW,KAAK;AAC1D,SAAO;AAAA,IACL,iBAAiB;AAAA,IACjB,qBAAqB;AAAA,IACrB,mBAAmB;AAAA,EACrB;AACF;AAEA,MAAM,uBAGF;AAAA,EACF,IAAI;AAAA,EACJ,MAAM,QAAQ,UAAU,KAAK;AAC3B,UAAM,QAAQ,oBAAoB,MAAM,YAAY,CAAC,CAAC;AACtD,sBAAkB,KAAK,MAAM,QAAQ;AACrC,4BAAwB,KAAK,MAAM,cAAc;AACjD,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAChD,QAAI,CAAC,MAAM,SAAS;AAClB,YAAM,IAAI,cAAc,KAAK,EAAE,OAAO,UAAU,iCAAiC,iCAAiC,EAAE,CAAC;AAAA,IACvH;AAEA,UAAM,EAAE,SAAS,OAAO,QAAQ,4BAA4B,6BAA6B,IAAI,MAAM,GAAG,cAAc,OAAO,OAAO;AAChI,YAAMA,SAAQ;AAAA,QACZ,MAAM,sBAAsB,IAAI,YAAY,EAAE,IAAI,MAAM,QAAQ,GAAG,EAAE,UAAU,SAAS,kBAAkB,GAAG,EAAE,UAAU,MAAM,UAAU,gBAAgB,MAAM,eAAe,CAAC;AAAA,QAC/K;AAAA,MACF;AACA,sBAAgBA,QAAO,MAAM,gBAAgB,MAAM,QAAQ;AAC3D,UAAIA,OAAM,WAAW;AACnB,cAAM,IAAI,cAAc,KAAK,EAAE,OAAO,iCAAiC,CAAC;AAAA,MAC1E;AACA,UACEA,OAAM,gBACN,MAAM,gBACNA,OAAM,aAAa,YAAY,MAAM,MAAM,aAAa,YAAY,GACpE;AACA,cAAM,IAAI,cAAc,KAAK;AAAA,UAC3B,OAAO,UAAU,oCAAoC,iDAAiD;AAAA,QACxG,CAAC;AAAA,MACH;AACA,UAAI,gBAAgB;AACpB,UAAI,MAAM,iBAAiB;AACzB,cAAM,SAAS;AAAA,UACb,MAAM,sBAAsB,IAAI,oBAAoB,EAAE,IAAI,MAAM,gBAAgB,GAAG,CAAC,GAAG,EAAE,UAAU,MAAM,UAAU,gBAAgB,MAAM,eAAe,CAAC;AAAA,UACzJ;AAAA,QACF;AACA,wBAAgB,QAAQ,MAAM,gBAAgB,MAAM,QAAQ;AAC5D,wBAAgB;AAAA,MAClB;AACA,YAAMC,8BAA6BD,OAAM,mBAAmB;AAC5D,YAAME,gCAA+BF,OAAM,qBAAqB;AAChE,UAAI,iBAAiB,CAACA,OAAM,iBAAiB;AAC3C,QAAAA,OAAM,kBAAkB,cAAc;AACtC,QAAAA,OAAM,oBAAoB,cAAc,QAAQ;AAChD,QAAAA,OAAM,YAAY,oBAAI,KAAK;AAC3B,WAAG,QAAQA,MAAK;AAAA,MAClB;AACA,UAAI,MAAM,0BAA0B,QAAW;AAC7C,cAAM,cAAc,MAAM,4BAA4B,IAAI,MAAM,yBAAyB,IAAI;AAC7F,YAAI,MAAM,yBAAyB,CAAC,aAAa;AAC/C,gBAAM,IAAI,cAAc,KAAK;AAAA,YAC3B,OAAO,UAAU,wCAAwC,qCAAqC;AAAA,UAChG,CAAC;AAAA,QACH;AACA,QAAAA,OAAM,gBAAgB,MAAM,yBAAyB;AACrD,QAAAA,OAAM,SAAS;AACf,QAAAA,OAAM,YAAY,oBAAI,KAAK;AAC3B,WAAG,QAAQA,MAAK;AAAA,MAClB;AACA,UAAI,MAAM,sBAAsB,QAAW;AACzC,cAAM,aAAa,MAAM,4BAA4B,IAAI,MAAM,qBAAqB,IAAI;AACxF,YAAI,MAAM,qBAAqB,CAAC,YAAY;AAC1C,gBAAM,IAAI,cAAc,KAAK;AAAA,YAC3B,OAAO,UAAU,wCAAwC,qCAAqC;AAAA,UAChG,CAAC;AAAA,QACH;AACA,cAAM,aAAa,MAAM,mBAAmB,IAAI,gBAAgB,EAAE,OAAAA,OAAM,GAAG,CAAC,GAAG,EAAE,UAAU,MAAM,UAAU,gBAAgB,MAAM,eAAe,CAAC;AACjJ,mBAAW,QAAQ,CAAC,SAAS;AAC3B,eAAK,gBAAgB,MAAM,qBAAqB;AAChD,eAAK,SAAS;AACd,eAAK,YAAY,oBAAI,KAAK;AAAA,QAC5B,CAAC;AACD,mBAAW,QAAQ,CAAC,SAAS,GAAG,QAAQ,IAAI,CAAC;AAAA,MAC/C;AACA,YAAM,SAAS,MAAM,4BAA4B,IAAI,MAAM,iBAAiB,IAAI;AAChF,YAAMG,WAAU,GAAG,OAAO,cAAc;AAAA,QACtC,gBAAgB,MAAM;AAAA,QACtB,UAAU,MAAM;AAAA,QAChB,OAAAH;AAAA,QACA;AAAA,QACA,kBAAkB,MAAM,oBAAoB;AAAA,QAC5C,eAAe,MAAM,iBAAiB;AAAA,QACtC;AAAA,QACA,QAAQ,gBAAgB,MAAM,MAAM,KAAK;AAAA,QACzC,cAAc,MAAM;AAAA,QACpB,gBAAgB,gBAAgB,MAAM,cAAc,KAAK;AAAA,QACzD,gBAAgB,gBAAgB,MAAM,cAAc,KAAK;AAAA,QACzD,YAAY,MAAM,cAAc;AAAA,QAChC,YAAY,MAAM,cAAc;AAAA,QAChC,UAAU,MAAM,WAAW,UAAU,MAAM,QAAQ,IAAI;AAAA,QACvD,kBAAkB,MAAM,oBAAoB;AAAA,MAC9C,CAAC;AACD,YAAM,mBAAmB,MAAM,QAAQ,MAAM,WAAW,IAAI,MAAM,cAAc,CAAC;AACjF,YAAM,cAAc,iBAAiB,SACjC,mBACA;AAAA,QACE;AAAA,UACE,SAAS,MAAM;AAAA,UACf,WAAW;AAAA,UACX,QAAQ,MAAM;AAAA,UACd,cAAc,MAAM;AAAA,UACpB,UAAU;AAAA,QACZ;AAAA,MACF;AACJ,YAAM,aAAa,oBAAI,IAAwB,CAAC,CAACA,OAAM,IAAIA,MAAK,CAAC,CAAC;AAClE,YAAM,eAAe,oBAAI,IAA0B;AACnD,iBAAW,cAAc,aAAa;AACpC,YAAI,kBAAqC;AACzC,YAAI,WAAW,SAAS;AACtB,4BAAkB,WAAW,IAAI,WAAW,OAAO,KAAK;AACxD,cAAI,CAAC,iBAAiB;AACpB,8BAAkB;AAAA,cAChB,MAAM;AAAA,gBACJ;AAAA,gBACA;AAAA,gBACA,EAAE,IAAI,WAAW,QAAQ;AAAA,gBACzB,CAAC;AAAA,gBACD,EAAE,UAAU,MAAM,UAAU,gBAAgB,MAAM,eAAe;AAAA,cACnE;AAAA,cACA;AAAA,YACF;AACA,4BAAgB,iBAAiB,MAAM,gBAAgB,MAAM,QAAQ;AACrE,uBAAW,IAAI,WAAW,SAAS,eAAe;AAAA,UACpD;AAAA,QACF;AACA,YAAI,oBAAyC;AAC7C,YAAI,WAAW,WAAW;AACxB,8BAAoB,aAAa,IAAI,WAAW,SAAS,KAAK;AAC9D,cAAI,CAAC,mBAAmB;AACtB,gCAAoB;AAAA,cAClB,MAAM;AAAA,gBACJ;AAAA,gBACA;AAAA,gBACA,EAAE,IAAI,WAAW,UAAU;AAAA,gBAC3B,CAAC;AAAA,gBACD,EAAE,UAAU,MAAM,UAAU,gBAAgB,MAAM,eAAe;AAAA,cACnE;AAAA,cACA;AAAA,YACF;AACA,4BAAgB,mBAAmB,MAAM,gBAAgB,MAAM,QAAQ;AACvE,yBAAa,IAAI,WAAW,WAAW,iBAAiB;AAAA,UAC1D;AAAA,QACF;AACA,cAAM,SAAS,GAAG,OAAO,wBAAwB;AAAA,UAC/C,SAAAG;AAAA,UACA,OAAO;AAAA,UACP,SAAS;AAAA,UACT,gBAAgB,MAAM;AAAA,UACtB,UAAU,MAAM;AAAA,UAChB,QAAQ,gBAAgB,WAAW,MAAM,KAAK;AAAA,UAC9C,cAAc,WAAW;AAAA,UACzB,UAAU,WAAW,WAAW,UAAU,WAAW,QAAQ,IAAI;AAAA,QACnE,CAAC;AACD,WAAG,QAAQ,MAAM;AAAA,MACnB;AACA,SAAG,QAAQA,QAAO;AAClB,UAAI,MAAM,iBAAiB,QAAW;AACpC,YAAI,CAACA,SAAQ,IAAI;AACf,gBAAM,GAAG,MAAM;AAAA,QACjB;AACA,cAAM,sBAAsB,IAAI;AAAA,UAC9B,UAAU,EAAE,MAAM;AAAA,UAClB,UAAUA,SAAQ;AAAA,UAClB,gBAAgB,MAAM;AAAA,UACtB,UAAU,MAAM;AAAA,UAChB,QAAQ,2BAA2B,MAAM,YAAY;AAAA,QACvD,CAAC;AAAA,MACH;AACA,YAAM,GAAG,MAAM;AACf,YAAMC,UAAS,MAAM,4BAA4B,IAAIJ,MAAK;AAC1D,YAAM,GAAG,MAAM;AACf,aAAO,EAAE,SAAAG,UAAS,OAAAH,QAAO,QAAAI,SAAQ,4BAAAH,6BAA4B,8BAAAC,8BAA6B;AAAA,IAC5F,CAAC;AAED,UAAM,qBAAqB,IAAI,WAAW,OAAO,IAAI,MAAM,YAAY,IAAI;AAE3E,UAAM,aAAa,IAAI,UAAU,QAAQ,YAAY;AACrD,UAAM,oBAAoB;AAAA,MACxB;AAAA,MACA,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,aAAa;AAAA,QACX,IAAI,QAAQ;AAAA,QACZ,gBAAgB,QAAQ;AAAA,QACxB,UAAU,QAAQ;AAAA,MACpB;AAAA,MACA,SAAS,EAAE,YAAY,EAAE,MAAM,cAAc;AAAA,MAC7C,QAAQ;AAAA,IACV,CAAC;AAGD,QAAI;AACF,YAAM,sBAAsB,2BAA2B,IAAI,SAAS;AACpE,YAAM,UAAU,kBAAkB,KAAK,CAAC,SAAS,KAAK,SAAS,wBAAwB;AACvF,UAAI,SAAS;AACX,cAAM,gBAAgB,QAAQ,UAAU,QAAQ,eAC5C,GAAG,QAAQ,YAAY,IAAI,QAAQ,MAAM,KACzC;AACJ,cAAM,oBAAoB,iCAAiC,SAAS;AAAA,UAClE,iBAAiB;AAAA,UACjB,eAAe;AAAA,YACb,aAAa,MAAM,eAAe;AAAA,YAClC,QAAQ;AAAA,UACV;AAAA,UACA,kBAAkB;AAAA,UAClB,gBAAgB,MAAM;AAAA,UACtB,UAAU,yBAAyB,MAAM,EAAE;AAAA,QAC7C,CAAC;AAED,cAAM,oBAAoB,iBAAiB,mBAAmB;AAAA,UAC5D,UAAU,QAAQ;AAAA,UAClB,gBAAgB,QAAQ,kBAAkB;AAAA,QAC5C,CAAC;AAAA,MACH;AAAA,IACF,SAAS,KAAK;AAEZ,cAAQ,MAAM,0DAA0D,GAAG;AAAA,IAC7E;AAEA,WAAO,EAAE,WAAW,QAAQ,IAAI,aAAa,QAAQ,4BAA4B,6BAA6B;AAAA,EAChH;AAAA,EACA,cAAc,OAAO,QAAQ,QAAQ,QAAQ;AAC3C,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,QAAQ,IAAI,MAAM,WAAW,EAAE,UAAU,IAAI,KAAK,UAAU,gBAAgB,IAAI,MAAM,SAAS,KAAK,IAAI;AAC9G,WAAO,QAAQ,YAAY,oBAAoB,IAAI,OAAO,WAAW,KAAK,IAAI;AAAA,EAChF;AAAA,EACA,UAAU,OAAO,EAAE,QAAQ,UAAU,MAAM;AACzC,UAAM,QAAQ,UAAU;AACxB,QAAI,CAAC,MAAO,QAAO;AACnB,UAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAChD,WAAO;AAAA,MACL,aAAa,UAAU,+BAA+B,gBAAgB;AAAA,MACtE,cAAc;AAAA,MACd,YAAY,OAAO;AAAA,MACnB,oBAAoB;AAAA,MACpB,kBAAkB,MAAM,WAAW;AAAA,MACnC,UAAU,MAAM;AAAA,MAChB,gBAAgB,MAAM;AAAA,MACtB,eAAe;AAAA,MACf,SAAS,EAAE,MAAM,EAAE,OAAO,4BAA4B,OAAO,8BAA8B,MAAM,8BAA8B,OAAO,gCAAgC,KAAK,EAA+B;AAAA,IAC5M;AAAA,EACF;AAAA,EACA,MAAM,OAAO,EAAE,UAAU,IAAI,MAAM;AACjC,UAAM,UAAU,mBAAuC,QAAQ;AAC/D,UAAM,QAAQ,SAAS;AACvB,QAAI,CAAC,MAAO;AACZ,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,WAAW,MAAM,sBAAsB,IAAI,cAAc,EAAE,IAAI,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,UAAU,MAAM,UAAU,gBAAgB,MAAM,eAAe,CAAC;AACvJ,QAAI,UAAU;AACZ,YAAM,WACJ,OAAO,SAAS,UAAU,WAAW,SAAS,QAAQ,SAAS,OAAO,MAAM;AAC9E,YAAM,cAAc,MAAM,mBAAmB,IAAI,wBAAwB,EAAE,SAAS,SAAS,GAAG,CAAC,GAAG,EAAE,UAAU,MAAM,UAAU,gBAAgB,MAAM,eAAe,CAAC;AACtK,YAAM,mBAAmB,YACtB;AAAA,QAAI,CAAC,eACJ,OAAO,WAAW,UAAU,WACxB,WAAW,QACX,WAAW,OAAO,MAAM;AAAA,MAC9B,EACC,OAAO,CAAC,UAA2B,OAAO,UAAU,YAAY,MAAM,SAAS,CAAC;AAEnF,kBAAY,QAAQ,CAAC,eAAe,GAAG,OAAO,UAAU,CAAC;AACzD,YAAM,GAAG,MAAM;AAEf,SAAG,OAAO,QAAQ;AAClB,YAAM,GAAG,MAAM;AAEf,YAAM,WAAW,MAAM;AAAA,QACrB,IAAI;AAAA,UACF;AAAA,YACE;AAAA,YACA,GAAG;AAAA,UACL,EAAE,OAAO,CAAC,UAA2B,OAAO,UAAU,YAAY,MAAM,SAAS,CAAC;AAAA,QACpF;AAAA,MACF;AACA,iBAAW,MAAM,UAAU;AACzB,cAAM,GAAG,cAAc,OAAO,OAAO;AACnC,gBAAM,QAAQ,MAAM,sBAAsB,IAAI,YAAY,EAAE,GAAG,GAAG,EAAE,UAAU,SAAS,kBAAkB,GAAG,EAAE,UAAU,MAAM,UAAU,gBAAgB,MAAM,eAAe,CAAC;AAC9K,cAAI,CAAC,MAAO;AACZ,cAAI,OAAO,MAAM,WAAW,iCAAiC,WAAW,CAAC,IAAI;AAC3E,kBAAM,kBAAkB,QAAQ,8BAA8B;AAC9D,kBAAM,oBAAoB,QAAQ,gCAAgC;AAClE,kBAAM,YAAY,oBAAI,KAAK;AAC3B,kBAAM,GAAG,MAAM;AAAA,UACjB;AACA,gBAAM,4BAA4B,IAAI,KAAK;AAC3C,gBAAM,GAAG,MAAM;AAAA,QACjB,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA,EACA,MAAM,OAAO,EAAE,KAAK,SAAS,MAAM;AACjC,UAAM,QAAQ,oBAAqC,QAAQ;AAC3D,UAAM,YAAY,OAAO,MAAM,SAAS,cAAc;AACtD,QAAI,CAAC,SAAS,CAAC,WAAW;AACxB,YAAM,IAAI,cAAc,KAAK,EAAE,OAAO,iEAAiE,CAAC;AAAA,IAC1G;AACA,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,uBAAuB,IAAI,KAAK;AACtC,UAAM,GAAG,MAAM;AAEf,UAAM,WAAW,MAAM;AAAA,MACrB,IAAI;AAAA,QACF;AAAA,UACE,MAAM;AAAA,UACN,GAAG,MAAM,YAAY,IAAI,CAAC,eAAe,WAAW,OAAO;AAAA,QAC7D,EAAE,OAAO,CAAC,UAA2B,OAAO,UAAU,YAAY,MAAM,SAAS,CAAC;AAAA,MACpF;AAAA,IACF;AACA,QAAI;AACJ,eAAW,WAAW,UAAU;AAC9B,YAAM,aAAa,MAAM,GAAG,cAAc,OAAO,OAAO;AACtD,cAAM,QAAQ,MAAM;AAAA,UAClB;AAAA,UACA;AAAA,UACA,EAAE,IAAI,QAAQ;AAAA,UACd,EAAE,UAAU,SAAS,kBAAkB;AAAA,UACvC,EAAE,UAAU,MAAM,UAAU,gBAAgB,MAAM,eAAe;AAAA,QACnE;AACA,YAAI,CAAC,MAAO,QAAO;AACnB,YAAI,YAAY,MAAM,WAAW,MAAM,mBAAmB,CAAC,MAAM,iBAAiB;AAChF,gBAAM,SAAS,MAAM;AAAA,YACnB;AAAA,YACA;AAAA,YACA,EAAE,IAAI,MAAM,gBAAgB;AAAA,YAC5B,CAAC;AAAA,YACD,EAAE,UAAU,MAAM,UAAU,gBAAgB,MAAM,eAAe;AAAA,UACnE;AACA,gBAAM,kBAAkB,QAAQ,MAAM,MAAM;AAC5C,gBAAM,oBAAoB,QAAQ,QAAQ;AAC1C,gBAAM,YAAY,oBAAI,KAAK;AAC3B,gBAAM,GAAG,MAAM;AAAA,QACjB;AACA,cAAM,SAAS,MAAM,4BAA4B,IAAI,KAAK;AAC1D,cAAM,GAAG,MAAM;AACf,eAAO;AAAA,MACT,CAAC;AACD,UAAI,eAAe,CAAC,UAAU,YAAY,MAAM,UAAU;AACxD,iBAAS;AAAA,MACX;AAKA,YAAM,SAAS,MAAM,GAAG,QAAQ,YAAY,EAAE,IAAI,SAAS,gBAAgB,MAAM,gBAAgB,UAAU,MAAM,SAAS,CAAC;AAC3H,UAAI,QAAQ;AACV,wBAAgB,QAAQ,MAAM,gBAAgB,MAAM,QAAQ;AAC5D,cAAM,qBAAqB,IAAI,WAAW,QAAQ,IAAI,MAAM,YAAY,IAAI;AAAA,MAC9E;AAAA,IACF;AAEA,UAAM,UAAU,MAAM,sBAAsB,IAAI,cAAc,EAAE,IAAI,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,UAAU,MAAM,UAAU,gBAAgB,MAAM,eAAe,CAAC;AACtJ,UAAM,aAAa,IAAI,UAAU,QAAQ,YAAY;AACrD,UAAM,oBAAoB;AAAA,MACxB;AAAA,MACA,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,aAAa;AAAA,QACX,IAAI,MAAM;AAAA,QACV,gBAAgB,MAAM;AAAA,QACtB,UAAU,MAAM;AAAA,MAClB;AAAA,MACA,SAAS,EAAE,YAAY,EAAE,MAAM,cAAc;AAAA,MAC7C,QAAQ;AAAA,IACV,CAAC;AAED,WAAO,EAAE,WAAW,MAAM,IAAI,aAAa,OAAO;AAAA,EACpD;AACF;AAEA,MAAM,uBAGF;AAAA,EACF,IAAI;AAAA,EACJ,MAAM,QAAQ,UAAU,KAAK;AAC3B,UAAM,SAAS,oBAAoB,MAAM,YAAY,CAAC,CAAC;AACvD,QAAI,CAAC,OAAO,GAAI,QAAO,CAAC;AACxB,UAAM,KAAK,IAAI,UAAU,QAAQ,IAAI;AACrC,UAAM,QAAQ,IAAI,MAAM,WAAW,EAAE,UAAU,IAAI,KAAK,UAAU,gBAAgB,IAAI,MAAM,SAAS,KAAK,IAAI;AAC9G,UAAM,WAAW,MAAM,oBAAoB,IAAI,OAAO,IAAI,KAAK;AAC/D,QAAI,UAAU;AACZ,wBAAkB,KAAK,SAAS,QAAQ;AACxC,8BAAwB,KAAK,SAAS,cAAc;AAAA,IACtD;AACA,WAAO,WAAW,EAAE,QAAQ,SAAS,IAAI,CAAC;AAAA,EAC5C;AAAA,EACA,MAAM,QAAQ,UAAU,KAAK;AAC3B,UAAM,QAAQ,oBAAoB,MAAM,YAAY,CAAC,CAAC;AACtD,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAChD,UAAM,YAAY;AAAA,MAChB,MAAM,sBAAsB,IAAI,cAAc,EAAE,IAAI,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,UAAU,MAAM,UAAU,gBAAgB,MAAM,eAAe,CAAC;AAAA,MACtI;AAAA,IACF;AACA,UAAM,mBAAmB,MAAM,YAAY,UAAU;AACrD,UAAM,yBAAyB,MAAM,kBAAkB,UAAU;AACjE,sBAAkB,KAAK,gBAAgB;AACvC,4BAAwB,KAAK,sBAAsB;AACnD,UAAM,UAAU;AAAA,MACd,MAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA,EAAE,IAAI,MAAM,GAAG;AAAA,QACf,EAAE,UAAU,CAAC,OAAO,EAAE;AAAA,QACtB,EAAE,UAAU,kBAAkB,gBAAgB,uBAAuB;AAAA,MACvE;AAAA,MACA;AAAA,IACF;AACA,oBAAgB,SAAS,wBAAwB,gBAAgB;AACjE,UAAM,gBAAgB,QAAQ;AAI9B,UAAM,GAAG,cAAc,OAAO,OAAO;AACnC,UAAI,MAAM,YAAY,QAAW;AAC/B,YAAI,CAAC,MAAM,SAAS;AAClB,kBAAQ,QAAQ;AAAA,QAClB,OAAO;AACL,gBAAM,QAAQ;AAAA,YACZ,MAAM,sBAAsB,IAAI,YAAY,EAAE,IAAI,MAAM,QAAQ,GAAG,CAAC,GAAG,EAAE,UAAU,kBAAkB,gBAAgB,uBAAuB,CAAC;AAAA,YAC7I;AAAA,UACF;AACA,0BAAgB,OAAO,wBAAwB,gBAAgB;AAC/D,cACE,MAAM,gBACN,MAAM,gBACN,MAAM,aAAa,YAAY,MAAM,MAAM,aAAa,YAAY,GACpE;AACA,kBAAM,IAAI,cAAc,KAAK;AAAA,cAC3B,OAAO,UAAU,oCAAoC,iDAAiD;AAAA,YACxG,CAAC;AAAA,UACH;AACA,kBAAQ,QAAQ;AAAA,QAClB;AAAA,MACF;AACA,UAAI,MAAM,oBAAoB,QAAW;AACvC,YAAI,CAAC,MAAM,iBAAiB;AAC1B,kBAAQ,gBAAgB;AAAA,QAC1B,OAAO;AACL,gBAAM,SAAS;AAAA,YACb,MAAM,sBAAsB,IAAI,oBAAoB,EAAE,IAAI,MAAM,gBAAgB,GAAG,CAAC,GAAG,EAAE,UAAU,kBAAkB,gBAAgB,uBAAuB,CAAC;AAAA,YAC7J;AAAA,UACF;AACA,0BAAgB,QAAQ,wBAAwB,gBAAgB;AAChE,kBAAQ,gBAAgB;AAAA,QAC1B;AAAA,MACF;AACA,YAAM,eAAe,QAAQ;AAC7B,WAAK,MAAM,0BAA0B,UAAa,MAAM,sBAAsB,WAAc,CAAC,cAAc;AACzG,cAAM,IAAI,cAAc,KAAK,EAAE,OAAO,UAAU,iCAAiC,iCAAiC,EAAE,CAAC;AAAA,MACvH;AACA,UAAI,gBAAgB,MAAM,0BAA0B,QAAW;AAC7D,cAAM,cAAc,MAAM,4BAA4B,IAAI,MAAM,yBAAyB,IAAI;AAC7F,YAAI,MAAM,yBAAyB,CAAC,aAAa;AAC/C,gBAAM,IAAI,cAAc,KAAK;AAAA,YAC3B,OAAO,UAAU,wCAAwC,qCAAqC;AAAA,UAChG,CAAC;AAAA,QACH;AACA,qBAAa,gBAAgB,MAAM,yBAAyB;AAC5D,qBAAa,SAAS;AACtB,qBAAa,YAAY,oBAAI,KAAK;AAClC,WAAG,QAAQ,YAAY;AAAA,MACzB;AACA,UAAI,gBAAgB,MAAM,sBAAsB,QAAW;AACzD,cAAM,aAAa,MAAM,4BAA4B,IAAI,MAAM,qBAAqB,IAAI;AACxF,YAAI,MAAM,qBAAqB,CAAC,YAAY;AAC1C,gBAAM,IAAI,cAAc,KAAK;AAAA,YAC3B,OAAO,UAAU,wCAAwC,qCAAqC;AAAA,UAChG,CAAC;AAAA,QACH;AACA,cAAM,aAAa,MAAM,mBAAmB,IAAI,gBAAgB,EAAE,OAAO,aAAa,GAAG,CAAC,GAAG,EAAE,UAAU,kBAAkB,gBAAgB,uBAAuB,CAAC;AACnK,mBAAW,QAAQ,CAAC,SAAS;AAC3B,eAAK,gBAAgB,MAAM,qBAAqB;AAChD,eAAK,SAAS;AACd,eAAK,YAAY,oBAAI,KAAK;AAAA,QAC5B,CAAC;AACD,mBAAW,QAAQ,CAAC,SAAS,GAAG,QAAQ,IAAI,CAAC;AAAA,MAC/C;AACA,UAAI,MAAM,qBAAqB,OAAW,SAAQ,mBAAmB,MAAM,oBAAoB;AAC/F,UAAI,MAAM,kBAAkB,QAAW;AACrC,gBAAQ,gBAAgB,MAAM,iBAAiB;AAC/C,gBAAQ,SAAS,MAAM,4BAA4B,IAAI,MAAM,iBAAiB,IAAI;AAAA,MACpF;AACA,UAAI,MAAM,WAAW,OAAW,SAAQ,SAAS,gBAAgB,MAAM,MAAM,KAAK;AAClF,UAAI,MAAM,iBAAiB,OAAW,SAAQ,eAAe,MAAM;AACnE,UAAI,MAAM,mBAAmB,QAAW;AACtC,gBAAQ,iBAAiB,gBAAgB,MAAM,cAAc,KAAK;AAAA,MACpE;AACA,UAAI,MAAM,mBAAmB,QAAW;AACtC,gBAAQ,iBAAiB,gBAAgB,MAAM,cAAc,KAAK;AAAA,MACpE;AACA,UAAI,MAAM,eAAe,OAAW,SAAQ,aAAa,MAAM,cAAc;AAC7E,UAAI,MAAM,eAAe,OAAW,SAAQ,aAAa,MAAM,cAAc;AAC7E,UAAI,MAAM,aAAa,QAAW;AAChC,gBAAQ,WAAW,MAAM,WAAW,UAAU,MAAM,QAAQ,IAAI;AAAA,MAClE;AACA,UAAI,MAAM,qBAAqB,QAAW;AACxC,gBAAQ,mBAAmB,MAAM,oBAAoB;AAAA,MACvD;AACA,UAAI,MAAM,iBAAiB,QAAW;AACpC,YAAI,CAAC,QAAQ,IAAI;AACf,gBAAM,GAAG,MAAM;AAAA,QACjB;AACA,cAAM,sBAAsB,IAAI;AAAA,UAC9B,UAAU,EAAE,MAAM;AAAA,UAClB,UAAU,QAAQ;AAAA,UAClB,gBAAgB,QAAQ;AAAA,UACxB,UAAU,QAAQ;AAAA,UAClB,QAAQ,2BAA2B,MAAM,YAAY;AAAA,QACvD,CAAC;AAAA,MACH;AACA,cAAQ,YAAY,oBAAI,KAAK;AAM7B,YAAM,GAAG,MAAM;AAEf,UAAI,MAAM,gBAAgB,QAAW;AACnC,cAAM,sBAAsB,MAAM,mBAAmB,IAAI,wBAAwB,EAAE,QAAQ,GAAG,CAAC,GAAG,EAAE,UAAU,QAAQ,UAAU,gBAAgB,QAAQ,eAAe,CAAC;AACxK,4BAAoB,QAAQ,CAAC,eAAe,GAAG,OAAO,UAAU,CAAC;AACjE,cAAM,mBAAmB,MAAM,QAAQ,MAAM,WAAW,IAAI,MAAM,cAAc,CAAC;AACjF,cAAM,kBACH,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ,QAAQ,OAAO,OAAO;AAC7E,cAAM,aAAa,oBAAI,IAAwB;AAC/C,YAAI,aAAc,YAAW,IAAI,aAAa,IAAI,YAAY;AAC9D,cAAM,eAAe,oBAAI,IAA0B;AACnD,mBAAW,cAAc,kBAAkB;AACzC,gBAAM,UAAU,WAAW,WAAW;AACtC,cAAI,QAA2B;AAC/B,cAAI,WAAW,OAAO,YAAY,UAAU;AAC1C,oBAAQ,WAAW,IAAI,OAAO,KAAK;AACnC,gBAAI,CAAC,OAAO;AACV,sBAAQ;AAAA,gBACN,MAAM;AAAA,kBACJ;AAAA,kBACA;AAAA,kBACA,EAAE,IAAI,QAAQ;AAAA,kBACd,CAAC;AAAA,kBACD,EAAE,UAAU,QAAQ,UAAU,gBAAgB,QAAQ,eAAe;AAAA,gBACvE;AAAA,gBACA;AAAA,cACF;AACA,8BAAgB,OAAO,QAAQ,gBAAgB,QAAQ,QAAQ;AAC/D,yBAAW,IAAI,SAAS,KAAK;AAAA,YAC/B;AAAA,UACF;AACA,cAAI,UAA+B;AACnC,cAAI,WAAW,WAAW;AACxB,sBAAU,aAAa,IAAI,WAAW,SAAS,KAAK;AACpD,gBAAI,CAAC,SAAS;AACZ,wBAAU;AAAA,gBACR,MAAM;AAAA,kBACJ;AAAA,kBACA;AAAA,kBACA,EAAE,IAAI,WAAW,UAAU;AAAA,kBAC3B,CAAC;AAAA,kBACD,EAAE,UAAU,QAAQ,UAAU,gBAAgB,QAAQ,eAAe;AAAA,gBACvE;AAAA,gBACA;AAAA,cACF;AACA,8BAAgB,SAAS,QAAQ,gBAAgB,QAAQ,QAAQ;AACjE,2BAAa,IAAI,WAAW,WAAW,OAAO;AAAA,YAChD;AAAA,UACF;AACA,gBAAM,SAAS,GAAG,OAAO,wBAAwB;AAAA,YAC/C;AAAA,YACA;AAAA,YACA;AAAA,YACA,gBAAgB,QAAQ;AAAA,YACxB,UAAU,QAAQ;AAAA,YAClB,QAAQ,gBAAgB,WAAW,MAAM,KAAK;AAAA,YAC9C,cAAc,WAAW;AAAA,YACzB,UAAU,WAAW,WAAW,UAAU,WAAW,QAAQ,IAAI;AAAA,UACnE,CAAC;AACD,aAAG,QAAQ,MAAM;AAAA,QACnB;AAAA,MACF,WAAW,MAAM,WAAW,UAAa,MAAM,iBAAiB,QAAW;AAOzE,cAAM,sBAAsB,MAAM,mBAAmB,IAAI,wBAAwB,EAAE,QAAQ,GAAG,CAAC,GAAG,EAAE,UAAU,QAAQ,UAAU,gBAAgB,QAAQ,eAAe,CAAC;AACxK,cAAM,kBACH,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ,QAAQ,OAAO,OAAO;AAC7E,cAAM,sBAAsB,CAAC,eAAgD;AAC3E,gBAAM,oBACJ,OAAO,WAAW,UAAU,WAAW,WAAW,QAAQ,WAAW,OAAO,MAAM;AACpF,gBAAM,sBACJ,OAAO,WAAW,YAAY,WAAW,WAAW,UAAU,WAAW,SAAS,MAAM;AAC1F,iBAAO,wBAAwB,QAAQ,sBAAsB;AAAA,QAC/D;AACA,YAAI,oBAAoB,WAAW,KAAK,oBAAoB,oBAAoB,CAAC,CAAC,GAAG;AACnF,gBAAM,CAAC,UAAU,IAAI;AACrB,qBAAW,SAAS,gBAAgB,SAAS,QAAQ,MAAM,CAAC,KAAK;AACjE,qBAAW,eAAe,QAAQ;AAClC,aAAG,QAAQ,UAAU;AAAA,QACvB;AAAA,MACF;AAAA,IACF,CAAC;AAED,UAAM,cACH,QAAQ,OAA6B,OACrC,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ;AACvD,QAAI;AACJ,QAAI,aAAa;AACf,eAAS,MAAM,GAAG,cAAc,OAAO,OAAO;AAG5C,cAAM,cAAc,MAAM,GAAG;AAAA,UAC3B;AAAA,UACA,EAAE,IAAI,aAAa,gBAAgB,QAAQ,gBAAgB,UAAU,QAAQ,SAAS;AAAA,UACtF,EAAE,UAAU,SAAS,kBAAkB;AAAA,QACzC;AACA,YAAI,CAAC,YAAa,QAAO;AACzB,wBAAgB,aAAa,QAAQ,gBAAgB,QAAQ,QAAQ;AACrE,cAAM,SAAS,MAAM,4BAA4B,IAAI,WAAW;AAChE,cAAM,GAAG,MAAM;AACf,eAAO;AAAA,MACT,CAAC;AACD,UAAI,QAAQ;AAIV,cAAM,YAAY,MAAM,GAAG,QAAQ,YAAY,EAAE,IAAI,aAAa,gBAAgB,QAAQ,gBAAgB,UAAU,QAAQ,SAAS,CAAC;AACtI,YAAI,WAAW;AACb,0BAAgB,WAAW,QAAQ,gBAAgB,QAAQ,QAAQ;AACnE,gBAAM,qBAAqB,IAAI,WAAW,WAAW,IAAI,MAAM,YAAY,IAAI;AAAA,QACjF;AAAA,MACF;AAAA,IACF;AACA,QAAI,kBAAkB,CAAC,eAAe,cAAc,OAAO,cAAc;AACvE,YAAM,GAAG,cAAc,OAAO,OAAO;AAInC,cAAM,cAAc,MAAM,GAAG;AAAA,UAC3B;AAAA,UACA,EAAE,IAAI,cAAc,IAAI,gBAAgB,QAAQ,gBAAgB,UAAU,QAAQ,SAAS;AAAA,UAC3F,EAAE,UAAU,SAAS,kBAAkB;AAAA,QACzC;AACA,YAAI,CAAC,YAAa;AAClB,wBAAgB,aAAa,QAAQ,gBAAgB,QAAQ,QAAQ;AACrE,cAAM,4BAA4B,IAAI,WAAW;AACjD,cAAM,GAAG,MAAM;AAAA,MACjB,CAAC;AACD,YAAM,qBAAqB,IAAI,WAAW,eAAe,IAAI,MAAM,YAAY,IAAI;AAAA,IACrF;AAEA,UAAM,aAAa,IAAI,UAAU,QAAQ,YAAY;AACrD,UAAM,oBAAoB;AAAA,MACxB;AAAA,MACA,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,aAAa;AAAA,QACX,IAAI,QAAQ;AAAA,QACZ,gBAAgB,QAAQ;AAAA,QACxB,UAAU,QAAQ;AAAA,MACpB;AAAA,MACA,SAAS,EAAE,YAAY,EAAE,MAAM,cAAc;AAAA,MAC7C,QAAQ;AAAA,IACV,CAAC;AAED,WAAO,EAAE,WAAW,QAAQ,IAAI,aAAa,OAAO;AAAA,EACtD;AAAA,EACA,cAAc,OAAO,QAAQ,QAAQ,QAAQ;AAC3C,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,QAAQ,IAAI,MAAM,WAAW,EAAE,UAAU,IAAI,KAAK,UAAU,gBAAgB,IAAI,MAAM,SAAS,KAAK,IAAI;AAC9G,WAAO,QAAQ,YAAY,oBAAoB,IAAI,OAAO,WAAW,KAAK,IAAI;AAAA,EAChF;AAAA,EACA,UAAU,OAAO,EAAE,WAAW,OAAO,MAAM;AACzC,UAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAChD,UAAM,SAAS,UAAU;AACzB,UAAM,QAAQ,UAAU;AACxB,WAAO;AAAA,MACL,aAAa,UAAU,+BAA+B,gBAAgB;AAAA,MACtE,cAAc;AAAA,MACd,YAAY,OAAO;AAAA,MACnB,oBAAoB;AAAA,MACpB,kBAAkB,OAAO,WAAW,QAAQ,WAAW;AAAA,MACvD,UAAU,OAAO,YAAY,QAAQ,YAAY;AAAA,MACjD,gBAAgB,OAAO,kBAAkB,QAAQ,kBAAkB;AAAA,MACnE,gBAAgB,UAAU;AAAA,MAC1B,eAAe,SAAS;AAAA,MACxB,SAAS,EAAE,MAAM,EAAE,QAAQ,MAAM,EAA+B;AAAA,IAClE;AAAA,EACF;AAAA,EACA,MAAM,OAAO,EAAE,UAAU,IAAI,MAAM;AACjC,UAAM,UAAU,mBAAuC,QAAQ;AAC/D,UAAM,SAAS,SAAS;AACxB,QAAI,CAAC,OAAQ;AACb,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,uBAAuB,IAAI,MAAM;AACvC,UAAM,GAAG,MAAM;AACf,QAAI,OAAO,SAAS;AAClB,YAAM,GAAG,cAAc,OAAO,OAAO;AACnC,cAAM,QAAQ,MAAM,sBAAsB,IAAI,YAAY,EAAE,IAAI,OAAO,QAAS,GAAG,EAAE,UAAU,SAAS,kBAAkB,GAAG,EAAE,UAAU,OAAO,UAAU,gBAAgB,OAAO,eAAe,CAAC;AACjM,YAAI,CAAC,MAAO;AACZ,cAAM,4BAA4B,IAAI,KAAK;AAC3C,cAAM,GAAG,MAAM;AAAA,MACjB,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEA,MAAM,uBAGF;AAAA,EACF,IAAI;AAAA,EACJ,MAAM,QAAQ,UAAU,KAAK;AAC3B,UAAM,SAAS,oBAAoB,MAAM,YAAY,CAAC,CAAC;AACvD,QAAI,CAAC,OAAO,GAAI,QAAO,CAAC;AACxB,UAAM,KAAK,IAAI,UAAU,QAAQ,IAAI;AACrC,UAAM,QAAQ,IAAI,MAAM,WAAW,EAAE,UAAU,IAAI,KAAK,UAAU,gBAAgB,IAAI,MAAM,SAAS,KAAK,IAAI;AAC9G,UAAM,WAAW,MAAM,oBAAoB,IAAI,OAAO,IAAI,KAAK;AAC/D,QAAI,UAAU;AACZ,wBAAkB,KAAK,SAAS,QAAQ;AACxC,8BAAwB,KAAK,SAAS,cAAc;AAAA,IACtD;AACA,WAAO,WAAW,EAAE,QAAQ,SAAS,IAAI,CAAC;AAAA,EAC5C;AAAA,EACA,MAAM,QAAQ,UAAU,KAAK;AAC3B,UAAM,QAAQ,oBAAoB,MAAM,YAAY,CAAC,CAAC;AACtD,sBAAkB,KAAK,MAAM,QAAQ;AACrC,4BAAwB,KAAK,MAAM,cAAc;AACjD,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,UAAU;AAAA,MACd,MAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA,EAAE,IAAI,MAAM,GAAG;AAAA,QACf,EAAE,UAAU,CAAC,OAAO,EAAE;AAAA,QACtB,EAAE,UAAU,MAAM,UAAU,gBAAgB,MAAM,eAAe;AAAA,MACnE;AAAA,MACA;AAAA,IACF;AACA,oBAAgB,SAAS,MAAM,gBAAgB,MAAM,QAAQ;AAC7D,UAAM,QAAQ,QAAQ;AACtB,UAAM,cAAc,MAAM,mBAAmB,IAAI,wBAAwB,EAAE,QAAQ,GAAG,CAAC,GAAG,EAAE,UAAU,QAAQ,UAAU,gBAAgB,QAAQ,eAAe,CAAC;AAChK,UAAM,mBAAmB,YACtB;AAAA,MAAI,CAAC,eACJ,OAAO,WAAW,UAAU,WACxB,WAAW,QACX,WAAW,OAAO,MAAM;AAAA,IAC9B,EACC,OAAO,CAAC,UAA2B,OAAO,UAAU,YAAY,MAAM,SAAS,CAAC;AAInF,UAAM,GAAG,cAAc,OAAO,OAAO;AACnC,kBAAY,QAAQ,CAAC,eAAe,GAAG,OAAO,UAAU,CAAC;AACzD,SAAG,OAAO,OAAO;AAAA,IACnB,CAAC;AACD,QAAI;AACJ,UAAM,WAAW,MAAM;AAAA,MACrB,IAAI;AAAA,QACF;AAAA,UACE,SAAS,OAAO,UAAU,WAAW,MAAM,KAAK;AAAA,UAChD,GAAG;AAAA,QACL,EAAE,OAAO,CAAC,UAA2B,OAAO,UAAU,YAAY,MAAM,SAAS,CAAC;AAAA,MACpF;AAAA,IACF;AACA,UAAM,iBAAiB,SAAS,OAAO,UAAU,WAAW,MAAM,KAAK;AACvE,eAAW,WAAW,UAAU;AAC9B,YAAM,aAAa,MAAM,GAAG,cAAc,OAAO,OAAO;AAGtD,cAAM,cAAc,MAAM,GAAG;AAAA,UAC3B;AAAA,UACA,EAAE,IAAI,SAAS,gBAAgB,QAAQ,gBAAgB,UAAU,QAAQ,SAAS;AAAA,UAClF,EAAE,UAAU,SAAS,kBAAkB;AAAA,QACzC;AACA,YAAI,CAAC,YAAa,QAAO;AACzB,wBAAgB,aAAa,QAAQ,gBAAgB,QAAQ,QAAQ;AACrE,cAAM,SAAS,MAAM,4BAA4B,IAAI,WAAW;AAChE,cAAM,GAAG,MAAM;AACf,eAAO;AAAA,MACT,CAAC;AACD,UAAI,eAAe,CAAC,UAAW,kBAAkB,YAAY,iBAAkB;AAC7E,iBAAS;AAAA,MACX;AAIA,YAAM,SAAS,MAAM,GAAG,QAAQ,YAAY,EAAE,IAAI,SAAS,gBAAgB,QAAQ,gBAAgB,UAAU,QAAQ,SAAS,CAAC;AAC/H,UAAI,QAAQ;AACV,wBAAgB,QAAQ,QAAQ,gBAAgB,QAAQ,QAAQ;AAChE,cAAM,qBAAqB,IAAI,WAAW,QAAQ,IAAI,MAAM,YAAY,IAAI;AAAA,MAC9E;AAAA,IACF;AACA,UAAM,aAAa,IAAI,UAAU,QAAQ,YAAY;AACrD,UAAM,oBAAoB;AAAA,MACxB;AAAA,MACA,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,aAAa;AAAA,QACX,IAAI,QAAQ;AAAA,QACZ,gBAAgB,QAAQ;AAAA,QACxB,UAAU,QAAQ;AAAA,MACpB;AAAA,MACA,SAAS,EAAE,YAAY,EAAE,MAAM,cAAc;AAAA,MAC7C,QAAQ;AAAA,IACV,CAAC;AACD,QAAI,YAAY,QAAQ;AACtB,YAAM,QAAQ;AAAA,QACZ,YAAY;AAAA,UAAI,CAAC,eACf,oBAAoB;AAAA,YAClB;AAAA,YACA,QAAQ;AAAA,YACR,QAAQ;AAAA,YACR,aAAa;AAAA,cACX,IAAI,WAAW;AAAA,cACf,gBAAgB,WAAW,kBAAkB;AAAA,cAC7C,UAAU,WAAW,YAAY;AAAA,YACnC;AAAA,YACA,SAAS,EAAE,YAAY,EAAE,MAAM,yBAAyB;AAAA,UAC1D,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AACA,WAAO,EAAE,WAAW,QAAQ,IAAI,aAAa,OAAO;AAAA,EACtD;AAAA,EACA,UAAU,OAAO,EAAE,WAAW,OAAO,MAAM;AACzC,UAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAChD,UAAM,SAAS,UAAU;AACzB,WAAO;AAAA,MACL,aAAa,UAAU,+BAA+B,gBAAgB;AAAA,MACtE,cAAc;AAAA,MACd,YAAY,OAAO;AAAA,MACnB,oBAAoB;AAAA,MACpB,kBAAkB,QAAQ,WAAW;AAAA,MACrC,UAAU,QAAQ,YAAY;AAAA,MAC9B,gBAAgB,QAAQ,kBAAkB;AAAA,MAC1C,gBAAgB,UAAU;AAAA,MAC1B,SAAS,EAAE,MAAM,EAAE,OAAO,EAA+B;AAAA,IAC3D;AAAA,EACF;AAAA,EACA,MAAM,OAAO,EAAE,UAAU,IAAI,MAAM;AACjC,UAAM,UAAU,mBAAuC,QAAQ;AAC/D,UAAM,SAAS,SAAS;AACxB,QAAI,CAAC,OAAQ;AACb,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,uBAAuB,IAAI,MAAM;AACvC,UAAM,GAAG,MAAM;AACf,QAAI,OAAO,SAAS;AAClB,YAAM,GAAG,cAAc,OAAO,OAAO;AACnC,cAAM,QAAQ,MAAM,sBAAsB,IAAI,YAAY,EAAE,IAAI,OAAO,QAAS,GAAG,EAAE,UAAU,SAAS,kBAAkB,GAAG,EAAE,UAAU,OAAO,UAAU,gBAAgB,OAAO,eAAe,CAAC;AACjM,YAAI,CAAC,MAAO;AACZ,cAAM,4BAA4B,IAAI,KAAK;AAC3C,cAAM,GAAG,MAAM;AAAA,MACjB,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEO,MAAM,kBAAkB,CAAC,sBAAsB,sBAAsB,oBAAoB;AAEhG,gBAAgB,oBAAoB;AACpC,gBAAgB,oBAAoB;AACpC,gBAAgB,oBAAoB;",
|
|
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
|
}
|