@open-mercato/core 0.10.1-develop.7723.1.3b2ea82ea7 → 0.10.1-develop.7726.1.a447cc5525

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/generated/entities/sales_order/index.js +2 -0
  3. package/dist/generated/entities/sales_order/index.js.map +2 -2
  4. package/dist/generated/entities/sales_order_line/index.js +2 -0
  5. package/dist/generated/entities/sales_order_line/index.js.map +2 -2
  6. package/dist/generated/entity-fields-registry.js +2 -0
  7. package/dist/generated/entity-fields-registry.js.map +2 -2
  8. package/dist/modules/planner/api/availability-date-specific.js +2 -7
  9. package/dist/modules/planner/api/availability-date-specific.js.map +2 -2
  10. package/dist/modules/planner/commands/availability-date-specific.js +14 -31
  11. package/dist/modules/planner/commands/availability-date-specific.js.map +2 -2
  12. package/dist/modules/planner/commands/availability-weekly.js +8 -22
  13. package/dist/modules/planner/commands/availability-weekly.js.map +2 -2
  14. package/dist/modules/planner/lib/availabilityMerge.js +10 -18
  15. package/dist/modules/planner/lib/availabilityMerge.js.map +2 -2
  16. package/dist/modules/planner/lib/availabilityTimezone.js +161 -0
  17. package/dist/modules/planner/lib/availabilityTimezone.js.map +7 -0
  18. package/dist/modules/sales/api/documents/factory.js +3 -0
  19. package/dist/modules/sales/api/documents/factory.js.map +2 -2
  20. package/dist/modules/sales/api/order-lines/route.js +2 -1
  21. package/dist/modules/sales/api/order-lines/route.js.map +2 -2
  22. package/dist/modules/sales/backend/sales/documents/[id]/page.js +83 -6
  23. package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
  24. package/dist/modules/sales/commands/documents.js +141 -18
  25. package/dist/modules/sales/commands/documents.js.map +2 -2
  26. package/dist/modules/sales/commands/returns.js +24 -7
  27. package/dist/modules/sales/commands/returns.js.map +2 -2
  28. package/dist/modules/sales/components/documents/AdjustmentsSection.js +17 -11
  29. package/dist/modules/sales/components/documents/AdjustmentsSection.js.map +2 -2
  30. package/dist/modules/sales/components/documents/DocumentTotals.js +21 -3
  31. package/dist/modules/sales/components/documents/DocumentTotals.js.map +2 -2
  32. package/dist/modules/sales/components/documents/ItemsSection.js +23 -12
  33. package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
  34. package/dist/modules/sales/data/entities.js +10 -0
  35. package/dist/modules/sales/data/entities.js.map +2 -2
  36. package/dist/modules/sales/data/validators.js +9 -1
  37. package/dist/modules/sales/data/validators.js.map +2 -2
  38. package/dist/modules/sales/lib/calculations.js +85 -6
  39. package/dist/modules/sales/lib/calculations.js.map +2 -2
  40. package/dist/modules/sales/lib/externalAmounts.js +143 -0
  41. package/dist/modules/sales/lib/externalAmounts.js.map +7 -0
  42. package/dist/modules/sales/lib/lineSnapshots.js +6 -1
  43. package/dist/modules/sales/lib/lineSnapshots.js.map +2 -2
  44. package/dist/modules/sales/lib/makeSalesLineRoute.js +8 -2
  45. package/dist/modules/sales/lib/makeSalesLineRoute.js.map +2 -2
  46. package/dist/modules/sales/lib/providers/totals.js +3 -2
  47. package/dist/modules/sales/lib/providers/totals.js.map +2 -2
  48. package/dist/modules/sales/migrations/Migration20260910120000_sales_external_amounts_mode.js +19 -0
  49. package/dist/modules/sales/migrations/Migration20260910120000_sales_external_amounts_mode.js.map +7 -0
  50. package/generated/entities/sales_order/index.ts +1 -0
  51. package/generated/entities/sales_order_line/index.ts +1 -0
  52. package/generated/entity-fields-registry.ts +2 -0
  53. package/package.json +8 -7
  54. package/src/modules/planner/api/availability-date-specific.ts +5 -10
  55. package/src/modules/planner/commands/availability-date-specific.ts +14 -33
  56. package/src/modules/planner/commands/availability-weekly.ts +15 -24
  57. package/src/modules/planner/lib/availabilityMerge.ts +13 -19
  58. package/src/modules/planner/lib/availabilityTimezone.ts +242 -0
  59. package/src/modules/sales/api/documents/factory.ts +3 -0
  60. package/src/modules/sales/api/order-lines/route.ts +2 -1
  61. package/src/modules/sales/backend/sales/documents/[id]/page.tsx +96 -0
  62. package/src/modules/sales/commands/documents.ts +219 -44
  63. package/src/modules/sales/commands/returns.ts +27 -3
  64. package/src/modules/sales/components/documents/AdjustmentsSection.tsx +34 -25
  65. package/src/modules/sales/components/documents/DocumentTotals.tsx +26 -2
  66. package/src/modules/sales/components/documents/ItemsSection.tsx +27 -12
  67. package/src/modules/sales/data/entities.ts +14 -0
  68. package/src/modules/sales/data/validators.ts +10 -0
  69. package/src/modules/sales/i18n/de.json +12 -0
  70. package/src/modules/sales/i18n/en.json +12 -0
  71. package/src/modules/sales/i18n/es.json +12 -0
  72. package/src/modules/sales/i18n/ko.json +12 -0
  73. package/src/modules/sales/i18n/pl.json +12 -0
  74. package/src/modules/sales/lib/calculations.ts +99 -4
  75. package/src/modules/sales/lib/externalAmounts.ts +174 -0
  76. package/src/modules/sales/lib/lineSnapshots.ts +6 -1
  77. package/src/modules/sales/lib/makeSalesLineRoute.ts +8 -0
  78. package/src/modules/sales/lib/providers/totals.ts +5 -2
  79. package/src/modules/sales/lib/types.ts +19 -2
  80. package/src/modules/sales/migrations/.snapshot-open-mercato.json +33 -1
  81. package/src/modules/sales/migrations/Migration20260910120000_sales_external_amounts_mode.ts +25 -0
@@ -8,6 +8,8 @@ import { resolveTranslations } from "@open-mercato/shared/lib/i18n/server";
8
8
  import { emitCrudSideEffects } from "@open-mercato/shared/lib/commands/helpers";
9
9
  import { findOneWithDecryption, findWithDecryption } from "@open-mercato/shared/lib/encryption/find";
10
10
  import { SalesDocumentNumberGenerator } from "../services/salesDocumentNumberGenerator.js";
11
+ import { isExternalAmountsMode } from "../lib/calculations.js";
12
+ import { readPersistedHeaderTotals } from "../lib/externalAmounts.js";
11
13
  import { cloneJson, deriveLineNetFromGross, ensureOrganizationScope, ensureSameScope, ensureTenantScope, extractUndoPayload, toNumericString, enforceSalesDocumentOptimisticLock, SALES_RESOURCE_KIND_ORDER, SALES_RESOURCE_KIND_RETURN } from "./shared.js";
12
14
  import { resolveRedoSnapshot } from "@open-mercato/shared/lib/commands/redo";
13
15
  import { SalesOrder, SalesOrderAdjustment, SalesOrderLine, SalesReturn, SalesReturnLine } from "../data/entities.js";
@@ -72,6 +74,17 @@ function applyOrderTotals(order, totals, lineCount) {
72
74
  order.totalsSnapshot = cloneJson(totals);
73
75
  order.lineItemCount = lineCount;
74
76
  }
77
+ function applyOrderTotalsUnlessExternal(order, calculation) {
78
+ if (isExternalAmountsMode(order.totalsMode ?? "computed")) return;
79
+ applyOrderTotals(order, calculation.totals, calculation.lines.length);
80
+ }
81
+ function resolveOrderCalculationMode(order) {
82
+ const totalsMode = order.totalsMode ?? "computed";
83
+ return {
84
+ totalsMode,
85
+ suppliedTotals: isExternalAmountsMode(totalsMode) ? readPersistedHeaderTotals(order) : null
86
+ };
87
+ }
75
88
  function mapOrderAdjustmentToDraft(adjustment) {
76
89
  return {
77
90
  id: adjustment.id,
@@ -127,7 +140,8 @@ async function recalculateOrderTotalsForDisplay(em, container, orderId, scope) {
127
140
  lines: lineSnapshots,
128
141
  adjustments: adjustmentDrafts,
129
142
  context: buildCalculationContext(order),
130
- existingTotals: resolveExistingPaymentTotals(order)
143
+ existingTotals: resolveExistingPaymentTotals(order),
144
+ ...resolveOrderCalculationMode(order)
131
145
  });
132
146
  return calculation.totals;
133
147
  }
@@ -267,9 +281,10 @@ async function reverseReturnEffects(em, salesCalculationService, snapshot) {
267
281
  lines: lineSnapshots,
268
282
  adjustments: adjustmentDrafts,
269
283
  context: buildCalculationContext(order),
270
- existingTotals: resolveExistingPaymentTotals(order)
284
+ existingTotals: resolveExistingPaymentTotals(order),
285
+ ...resolveOrderCalculationMode(order)
271
286
  });
272
- applyOrderTotals(order, calculation.totals, calculation.lines.length);
287
+ applyOrderTotalsUnlessExternal(order, calculation);
273
288
  order.updatedAt = /* @__PURE__ */ new Date();
274
289
  em.persist(order);
275
290
  }
@@ -422,9 +437,10 @@ async function restoreReturnEffects(em, salesCalculationService, snapshot) {
422
437
  lines: lineSnapshots,
423
438
  adjustments: adjustmentDrafts,
424
439
  context: buildCalculationContext(order),
425
- existingTotals: resolveExistingPaymentTotals(order)
440
+ existingTotals: resolveExistingPaymentTotals(order),
441
+ ...resolveOrderCalculationMode(order)
426
442
  });
427
- applyOrderTotals(order, calculation.totals, calculation.lines.length);
443
+ applyOrderTotalsUnlessExternal(order, calculation);
428
444
  order.updatedAt = /* @__PURE__ */ new Date();
429
445
  em.persist(order);
430
446
  }
@@ -585,9 +601,10 @@ const createReturnCommand = {
585
601
  lines: lineSnapshots,
586
602
  adjustments: adjustmentDrafts,
587
603
  context: buildCalculationContext(order2),
588
- existingTotals: resolveExistingPaymentTotals(order2)
604
+ existingTotals: resolveExistingPaymentTotals(order2),
605
+ ...resolveOrderCalculationMode(order2)
589
606
  });
590
- applyOrderTotals(order2, calculation.totals, calculation.lines.length);
607
+ applyOrderTotalsUnlessExternal(order2, calculation);
591
608
  order2.updatedAt = /* @__PURE__ */ new Date();
592
609
  tx.persist(order2);
593
610
  await tx.flush();
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/sales/commands/returns.ts"],
4
- "sourcesContent": ["import { randomUUID } from 'crypto'\nimport { registerCommand, type CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'\nimport { LockMode } from '@mikro-orm/core'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { CrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'\nimport { invalidateCrudCache } from '@open-mercato/shared/lib/crud/cache'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\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 { SalesDocumentNumberGenerator } from '../services/salesDocumentNumberGenerator'\nimport type { SalesCalculationService } from '../services/salesCalculationService'\nimport type { SalesAdjustmentDraft, SalesLineSnapshot, SalesDocumentCalculationResult } from '../lib/types'\nimport { cloneJson, deriveLineNetFromGross, ensureOrganizationScope, ensureSameScope, ensureTenantScope, extractUndoPayload, toNumericString, enforceSalesDocumentOptimisticLock, SALES_RESOURCE_KIND_ORDER, SALES_RESOURCE_KIND_RETURN } from './shared'\nimport { resolveRedoSnapshot } from '@open-mercato/shared/lib/commands/redo'\nimport { SalesOrder, SalesOrderAdjustment, SalesOrderLine, SalesReturn, SalesReturnLine } from '../data/entities'\nimport { mapOrderLineEntityToSnapshot } from '../lib/lineSnapshots'\nimport { loadShippedQuantityByLine } from '../lib/shipments/snapshots'\nimport { computeAvailableReturnQuantity } from '../lib/returnQuantity'\nimport {\n returnCreateSchema,\n returnUpdateSchema,\n returnDeleteSchema,\n type ReturnCreateInput,\n type ReturnUpdateInput,\n type ReturnDeleteInput,\n} from '../data/validators'\nimport { E } from '#generated/entities.ids.generated'\n\ntype ReturnLineInput = { orderLineId: string; quantity: number }\n\ntype ReturnSnapshot = {\n id: string\n orderId: string\n organizationId: string\n tenantId: string\n returnNumber: string\n returnedAt: string | null\n reason: string | null\n notes: string | null\n lines: Array<{\n id: string\n orderLineId: string\n quantityReturned: number\n unitPriceNet: number\n unitPriceGross: number\n totalNetAmount: number\n totalGrossAmount: number\n }>\n adjustmentIds: string[]\n}\n\ntype ReturnUndoPayload = {\n after?: ReturnSnapshot | null\n}\n\nconst returnCrudEvents: CrudEventsConfig = {\n module: 'sales',\n entity: 'return',\n persistent: true,\n buildPayload: (ctx) => ({\n id: ctx.identifiers.id,\n organizationId: ctx.identifiers.organizationId,\n tenantId: ctx.identifiers.tenantId,\n }),\n}\n\ntype OrderCacheRecord = Pick<SalesOrder, 'id' | 'organizationId' | 'tenantId'>\n\n/**\n * Return mutations update the order aggregate, which is also the cache resource\n * used by the order-lines and order-adjustments routes. Invalidate it after\n * each committed return lifecycle change so reloads receive its fresh\n * `updatedAt` optimistic-lock token.\n */\nasync function invalidateOrderCache(\n container: Parameters<typeof invalidateCrudCache>[0],\n order: OrderCacheRecord,\n fallbackTenant: string | null,\n): Promise<void> {\n await invalidateCrudCache(\n container,\n SALES_RESOURCE_KIND_ORDER,\n { id: order.id, organizationId: order.organizationId, tenantId: order.tenantId },\n fallbackTenant,\n 'updated',\n )\n}\n\nfunction toNumeric(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.isFinite(parsed)) return parsed\n }\n return 0\n}\n\nfunction round(value: number): number {\n return Math.round((value + Number.EPSILON) * 1e4) / 1e4\n}\n\n/**\n * Payment totals live on the order, not in the line/adjustment math a return\n * recalculates. Every `calculateDocumentTotals` call that writes order totals\n * back to the order MUST seed these so `buildBaseDocumentResult` preserves the\n * recorded `paidTotalAmount` / `refundedTotalAmount` instead of defaulting them\n * to 0 \u2014 otherwise creating/undoing/redoing a return silently zeroes the paid\n * amount and the order's outstanding balance goes wrong on any paid order\n * (#3756). Mirrors `resolveExistingPaymentTotals` in `commands/documents.ts`.\n */\nfunction resolveExistingPaymentTotals(order: SalesOrder): { paidTotalAmount: number; refundedTotalAmount: number } {\n return {\n paidTotalAmount: toNumeric(order.paidTotalAmount),\n refundedTotalAmount: toNumeric(order.refundedTotalAmount),\n }\n}\n\nfunction applyOrderTotals(order: SalesOrder, totals: SalesDocumentCalculationResult['totals'], lineCount: number): void {\n order.subtotalNetAmount = toNumericString(totals.subtotalNetAmount) ?? '0'\n order.subtotalGrossAmount = toNumericString(totals.subtotalGrossAmount) ?? '0'\n order.discountTotalAmount = toNumericString(totals.discountTotalAmount) ?? '0'\n order.taxTotalAmount = toNumericString(totals.taxTotalAmount) ?? '0'\n order.shippingNetAmount = toNumericString(totals.shippingNetAmount) ?? '0'\n order.shippingGrossAmount = toNumericString(totals.shippingGrossAmount) ?? '0'\n order.surchargeTotalAmount = toNumericString(totals.surchargeTotalAmount) ?? '0'\n order.grandTotalNetAmount = toNumericString(totals.grandTotalNetAmount) ?? '0'\n order.grandTotalGrossAmount = toNumericString(totals.grandTotalGrossAmount) ?? '0'\n order.paidTotalAmount = toNumericString(totals.paidTotalAmount) ?? '0'\n order.refundedTotalAmount = toNumericString(totals.refundedTotalAmount) ?? '0'\n order.outstandingAmount = toNumericString(totals.outstandingAmount) ?? '0'\n order.totalsSnapshot = cloneJson(totals)\n order.lineItemCount = lineCount\n}\n\nfunction mapOrderAdjustmentToDraft(adjustment: SalesOrderAdjustment): SalesAdjustmentDraft {\n return {\n id: adjustment.id,\n scope: adjustment.scope ?? 'order',\n kind: adjustment.kind,\n code: adjustment.code ?? null,\n label: adjustment.label ?? null,\n calculatorKey: adjustment.calculatorKey ?? null,\n promotionId: adjustment.promotionId ?? null,\n rate: toNumeric(adjustment.rate),\n amountNet: toNumeric(adjustment.amountNet),\n amountGross: toNumeric(adjustment.amountGross),\n currencyCode: adjustment.currencyCode ?? null,\n metadata: adjustment.metadata ? cloneJson(adjustment.metadata) : null,\n position: adjustment.position ?? 0,\n }\n}\n\nfunction buildCalculationContext(order: SalesOrder) {\n return {\n tenantId: order.tenantId,\n organizationId: order.organizationId,\n currencyCode: order.currencyCode,\n metadata: {\n shippingMethod: order.shippingMethodSnapshot\n ? cloneJson(order.shippingMethodSnapshot as Record<string, unknown>)\n : null,\n paymentMethod: order.paymentMethodSnapshot ? cloneJson(order.paymentMethodSnapshot as Record<string, unknown>) : null,\n },\n }\n}\n\n/**\n * Recalculates order totals (including line-scoped return adjustments) from lines and\n * adjustments. Do not merge this into GET /api/sales/orders responses: provider\n * calculators re-emit shipping/payment fees on top of already-persisted adjustments\n * and make list vs detail totals diverge (#5438). Persist via commands instead.\n */\nexport async function recalculateOrderTotalsForDisplay(\n em: EntityManager,\n container: { resolve: (key: string) => unknown },\n orderId: string,\n scope: { tenantId: string; organizationId: string },\n): Promise<SalesDocumentCalculationResult['totals'] | null> {\n const order = await findOneWithDecryption(\n em,\n SalesOrder,\n { id: orderId, deletedAt: null },\n {},\n scope,\n )\n if (!order) return null\n const [orderLines, adjustments] = await Promise.all([\n findWithDecryption(em, SalesOrderLine, { order: order.id, deletedAt: null }, {}, scope),\n findWithDecryption(\n em,\n SalesOrderAdjustment,\n { order: order.id, deletedAt: null },\n { orderBy: { position: 'asc' } },\n scope,\n ),\n ])\n const lineSnapshots: SalesLineSnapshot[] = orderLines.map(mapOrderLineEntityToSnapshot)\n const adjustmentDrafts: SalesAdjustmentDraft[] = adjustments.map(mapOrderAdjustmentToDraft)\n const salesCalculationService = container.resolve('salesCalculationService') as SalesCalculationService\n const calculation = await salesCalculationService.calculateDocumentTotals({\n documentKind: 'order',\n lines: lineSnapshots,\n adjustments: adjustmentDrafts,\n context: buildCalculationContext(order),\n existingTotals: resolveExistingPaymentTotals(order),\n })\n return calculation.totals\n}\n\nexport async function loadReturnSnapshot(em: EntityManager, id: string): Promise<ReturnSnapshot | null> {\n const header = await findOneWithDecryption(\n em,\n SalesReturn,\n { id, deletedAt: null },\n { populate: ['order'] },\n {},\n )\n if (!header || !header.order) return null\n const orderId = typeof header.order === 'string' ? header.order : header.order.id\n const lines = await findWithDecryption(\n em,\n SalesReturnLine,\n { salesReturn: header.id, deletedAt: null },\n { populate: ['orderLine'] },\n { tenantId: header.tenantId, organizationId: header.organizationId },\n )\n const adjustmentIds: string[] = []\n const adjustments = await findWithDecryption(\n em,\n SalesOrderAdjustment,\n { order: orderId, kind: 'return', deletedAt: null },\n {},\n { tenantId: header.tenantId, organizationId: header.organizationId },\n )\n adjustments.forEach((adj) => {\n const meta = adj.metadata as Record<string, unknown> | null | undefined\n if (meta && meta.returnId === header.id) adjustmentIds.push(adj.id)\n })\n\n return {\n id: header.id,\n orderId,\n organizationId: header.organizationId,\n tenantId: header.tenantId,\n returnNumber: header.returnNumber,\n returnedAt: header.returnedAt ? header.returnedAt.toISOString() : null,\n reason: header.reason ?? null,\n notes: header.notes ?? null,\n lines: lines.map((line) => ({\n id: line.id,\n orderLineId: typeof line.orderLine === 'string' ? line.orderLine : line.orderLine?.id ?? null,\n quantityReturned: toNumeric(line.quantityReturned),\n unitPriceNet: toNumeric(line.unitPriceNet),\n unitPriceGross: toNumeric(line.unitPriceGross),\n totalNetAmount: toNumeric(line.totalNetAmount),\n totalGrossAmount: toNumeric(line.totalGrossAmount),\n })),\n adjustmentIds,\n }\n}\n\ntype ReturnHeaderSnapshot = {\n id: string\n orderId: string\n organizationId: string\n tenantId: string\n reason: string | null\n notes: string | null\n returnedAt: string | null\n}\n\ntype ReturnHeaderUndoPayload = {\n before?: ReturnHeaderSnapshot | null\n after?: ReturnHeaderSnapshot | null\n}\n\ntype ReturnDeleteUndoPayload = {\n before?: ReturnSnapshot | null\n}\n\nasync function loadReturnHeaderSnapshot(em: EntityManager, id: string): Promise<ReturnHeaderSnapshot | null> {\n const header = await findOneWithDecryption(em, SalesReturn, { id, deletedAt: null }, { populate: ['order'] }, {})\n if (!header || !header.order) return null\n const orderId = typeof header.order === 'string' ? header.order : header.order.id\n return {\n id: header.id,\n orderId,\n organizationId: header.organizationId,\n tenantId: header.tenantId,\n reason: header.reason ?? null,\n notes: header.notes ?? null,\n returnedAt: header.returnedAt ? header.returnedAt.toISOString() : null,\n }\n}\n\n/**\n * Reverse the order-level effects of a return: restore each order line's\n * `returnedQuantity`, drop the return's line-scoped credit adjustments, remove\n * the return header + lines, and recalculate the order totals. Shared by the\n * create command's undo and the delete command's execute \u2014 both need the exact\n * same teardown. No-op when the order is gone.\n *\n * The line reversals, adjustment/return removals, and the order-total recompute\n * interleave queries on the same EntityManager with scalar mutations, so they\n * run inside an atomic flush to avoid lost updates and partial commits\n * (SPEC-018): the per-phase flush boundary persists the line `returnedQuantity`\n * reversals before the adjustment/header/return-line lookups in the next phase\n * run any query, which under MikroORM v7 would otherwise silently discard the\n * pending scalar changes on the managed lines.\n */\nasync function reverseReturnEffects(\n em: EntityManager,\n salesCalculationService: SalesCalculationService,\n snapshot: ReturnSnapshot,\n): Promise<void> {\n const order = await findOneWithDecryption(\n em,\n SalesOrder,\n { id: snapshot.orderId, deletedAt: null },\n {},\n { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId },\n )\n if (!order) return\n\n let lines: SalesOrderLine[] = []\n await withAtomicFlush(\n em,\n [\n async () => {\n lines = await findWithDecryption(\n em,\n SalesOrderLine,\n { order: order.id, deletedAt: null },\n {},\n { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId },\n )\n const lineMap = new Map(lines.map((line) => [line.id, line]))\n snapshot.lines.forEach((entry) => {\n const line = lineMap.get(entry.orderLineId)\n if (!line) return\n const next = Math.max(0, toNumeric(line.returnedQuantity) - entry.quantityReturned)\n line.returnedQuantity = next.toString()\n line.updatedAt = new Date()\n em.persist(line)\n })\n },\n async () => {\n if (snapshot.adjustmentIds.length) {\n const adjustments = await findWithDecryption(\n em,\n SalesOrderAdjustment,\n { id: { $in: snapshot.adjustmentIds }, deletedAt: null },\n {},\n { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId },\n )\n adjustments.forEach((adj) => em.remove(adj))\n }\n\n const header = await findOneWithDecryption(\n em,\n SalesReturn,\n { id: snapshot.id, deletedAt: null },\n {},\n { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId },\n )\n const returnLines = await findWithDecryption(\n em,\n SalesReturnLine,\n { salesReturn: snapshot.id, deletedAt: null },\n {},\n { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId },\n )\n returnLines.forEach((line) => em.remove(line))\n if (header) em.remove(header)\n\n const existingAdjustments = await findWithDecryption(\n em,\n SalesOrderAdjustment,\n { order: order.id, deletedAt: null },\n { orderBy: { position: 'asc' } },\n { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId },\n )\n const lineSnapshots: SalesLineSnapshot[] = lines.map(mapOrderLineEntityToSnapshot)\n const adjustmentDrafts: SalesAdjustmentDraft[] = existingAdjustments.map(mapOrderAdjustmentToDraft)\n const calculation = await salesCalculationService.calculateDocumentTotals({\n documentKind: 'order',\n lines: lineSnapshots,\n adjustments: adjustmentDrafts,\n context: buildCalculationContext(order),\n existingTotals: resolveExistingPaymentTotals(order),\n })\n applyOrderTotals(order, calculation.totals, calculation.lines.length)\n order.updatedAt = new Date()\n em.persist(order)\n },\n ],\n { transaction: true },\n )\n}\n\n/**\n * Re-apply a return from a snapshot: recreate the return header + lines and the\n * line-scoped credit adjustments, bump each order line's `returnedQuantity`, and\n * recalculate the order totals. Shared by the create command's redo and the\n * delete command's undo. Returns the recreated return lines so callers can emit\n * index side effects. Throws a 404 when the order is gone.\n *\n * The order may have changed since the snapshot was taken (another return\n * consumed the shipped quantity, a shipment was removed, an order line was\n * deleted), so the snapshot quantities are re-checked against the currently\n * returnable quantity \u2014 the same rule `sales.returns.create` enforces \u2014 under\n * the order-line lock and before any write. A stale restore is refused with a\n * 409 instead of returning and crediting the same shipped units twice.\n */\nasync function restoreReturnEffects(\n em: EntityManager,\n salesCalculationService: SalesCalculationService,\n snapshot: ReturnSnapshot,\n): Promise<SalesReturnLine[]> {\n const returnId = snapshot.id\n const createdLines: SalesReturnLine[] = []\n const { translate } = await resolveTranslations()\n\n await withAtomicFlush(\n em,\n [\n async () => {\n const order = await findOneWithDecryption(\n em,\n SalesOrder,\n { id: snapshot.orderId, deletedAt: null },\n {},\n { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId },\n )\n if (!order) {\n throw notFound(translate('sales.returns.orderMissing', 'Order not found.'))\n }\n ensureSameScope(order, snapshot.organizationId, snapshot.tenantId)\n\n const orderLines = await findWithDecryption(\n em,\n SalesOrderLine,\n { order: order.id, deletedAt: null },\n { lockMode: LockMode.PESSIMISTIC_WRITE },\n { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId },\n )\n const lineMap = new Map(orderLines.map((line) => [line.id, line]))\n\n const shippedByLine = await loadShippedQuantityByLine(em, order.id, {\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n })\n const restoredByLine = new Map<string, { line: SalesOrderLine; quantity: number }>()\n snapshot.lines.forEach((lineSnapshot) => {\n const line = lineSnapshot.orderLineId ? lineMap.get(lineSnapshot.orderLineId) : undefined\n if (!line) {\n throw new CrudHttpError(409, {\n error: translate('sales.returns.restoreLineMissing', 'This return cannot be restored: one of its order lines no longer exists.'),\n })\n }\n const restored = restoredByLine.get(line.id)\n restoredByLine.set(line.id, { line, quantity: (restored?.quantity ?? 0) + lineSnapshot.quantityReturned })\n })\n restoredByLine.forEach(({ line, quantity }, orderLineId) => {\n const available = computeAvailableReturnQuantity({\n quantity: toNumeric(line.quantity),\n returnedQuantity: toNumeric(line.returnedQuantity),\n shippedQuantity: shippedByLine.get(orderLineId) ?? 0,\n })\n if (quantity - 1e-6 > available) {\n throw new CrudHttpError(409, {\n error: translate('sales.returns.restoreQuantityUnavailable', 'This return cannot be restored: the order no longer has enough shipped quantity left to return.'),\n })\n }\n })\n\n const existingAdjustments = await findWithDecryption(\n em,\n SalesOrderAdjustment,\n { order: order.id, deletedAt: null },\n { orderBy: { position: 'asc' } },\n { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId },\n )\n const positionStart = existingAdjustments.reduce((acc, adj) => Math.max(acc, adj.position ?? 0), 0) + 1\n\n const restoredHeader =\n (await findOneWithDecryption(\n em,\n SalesReturn,\n { id: snapshot.id },\n {},\n { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId },\n )) ??\n em.create(SalesReturn, {\n id: snapshot.id,\n order,\n organizationId: snapshot.organizationId,\n tenantId: snapshot.tenantId,\n returnNumber: snapshot.returnNumber,\n reason: snapshot.reason ?? null,\n notes: snapshot.notes ?? null,\n returnedAt: snapshot.returnedAt ? new Date(snapshot.returnedAt) : new Date(),\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n restoredHeader.order = order\n restoredHeader.deletedAt = null\n restoredHeader.organizationId = snapshot.organizationId\n restoredHeader.tenantId = snapshot.tenantId\n restoredHeader.returnNumber = snapshot.returnNumber\n restoredHeader.reason = snapshot.reason ?? null\n restoredHeader.notes = snapshot.notes ?? null\n restoredHeader.returnedAt = snapshot.returnedAt ? new Date(snapshot.returnedAt) : new Date()\n restoredHeader.updatedAt = new Date()\n em.persist(restoredHeader)\n\n const createdAdjustments: SalesOrderAdjustment[] = []\n snapshot.lines.forEach((lineSnapshot, index) => {\n const line = lineMap.get(lineSnapshot.orderLineId)\n if (!line) return\n const totalNet = lineSnapshot.totalNetAmount\n const totalGross = lineSnapshot.totalGrossAmount\n const adjustmentId = snapshot.adjustmentIds[index] ?? randomUUID()\n\n const returnLine = em.create(SalesReturnLine, {\n id: lineSnapshot.id,\n salesReturn: restoredHeader,\n orderLine: em.getReference(SalesOrderLine, line.id),\n organizationId: snapshot.organizationId,\n tenantId: snapshot.tenantId,\n quantityReturned: lineSnapshot.quantityReturned.toString(),\n unitPriceNet: lineSnapshot.unitPriceNet.toString(),\n unitPriceGross: lineSnapshot.unitPriceGross.toString(),\n totalNetAmount: totalNet.toString(),\n totalGrossAmount: totalGross.toString(),\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n createdLines.push(returnLine)\n em.persist(returnLine)\n\n const adjustment = em.create(SalesOrderAdjustment, {\n id: adjustmentId,\n order,\n orderLine: em.getReference(SalesOrderLine, line.id),\n organizationId: snapshot.organizationId,\n tenantId: snapshot.tenantId,\n scope: 'line',\n kind: 'return',\n rate: '0',\n amountNet: totalNet.toString(),\n amountGross: totalGross.toString(),\n currencyCode: order.currencyCode,\n metadata: { returnId, returnLineId: lineSnapshot.id },\n position: positionStart + index,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n createdAdjustments.push(adjustment)\n em.persist(adjustment)\n\n line.returnedQuantity = (toNumeric(line.returnedQuantity) + lineSnapshot.quantityReturned).toString()\n line.updatedAt = new Date()\n em.persist(line)\n })\n\n const lineSnapshots: SalesLineSnapshot[] = orderLines.map(mapOrderLineEntityToSnapshot)\n const adjustmentDrafts: SalesAdjustmentDraft[] = [...existingAdjustments, ...createdAdjustments].map(\n mapOrderAdjustmentToDraft,\n )\n const calculation = await salesCalculationService.calculateDocumentTotals({\n documentKind: 'order',\n lines: lineSnapshots,\n adjustments: adjustmentDrafts,\n context: buildCalculationContext(order),\n existingTotals: resolveExistingPaymentTotals(order),\n })\n applyOrderTotals(order, calculation.totals, calculation.lines.length)\n order.updatedAt = new Date()\n em.persist(order)\n },\n ],\n { transaction: true },\n )\n\n return createdLines\n}\n\nfunction normalizeLinesInput(lines: ReturnCreateInput['lines']): ReturnLineInput[] {\n const seen = new Set<string>()\n const result: ReturnLineInput[] = []\n for (const line of lines) {\n const orderLineId = line.orderLineId\n if (!orderLineId || seen.has(orderLineId)) continue\n const quantity = toNumeric(line.quantity)\n if (!Number.isFinite(quantity) || quantity <= 0) continue\n seen.add(orderLineId)\n result.push({ orderLineId, quantity })\n }\n return result\n}\n\nconst createReturnCommand: CommandHandler<ReturnCreateInput, { returnId: string }> = {\n id: 'sales.returns.create',\n async execute(rawInput, ctx) {\n const input = returnCreateSchema.parse(rawInput ?? {})\n ensureTenantScope(ctx, input.tenantId)\n ensureOrganizationScope(ctx, input.organizationId)\n\n const { translate } = await resolveTranslations()\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n\n const requested = normalizeLinesInput(input.lines)\n if (!requested.length) {\n throw new CrudHttpError(400, { error: translate('sales.returns.linesRequired', 'Select at least one line to return.') })\n }\n\n const salesCalculationService = ctx.container.resolve<SalesCalculationService>('salesCalculationService')\n const { header, createdLines, order } = await em.transactional(async (tx) => {\n const order = await findOneWithDecryption(\n tx,\n SalesOrder,\n { id: input.orderId, deletedAt: null },\n {},\n { tenantId: input.tenantId, organizationId: input.organizationId },\n )\n if (!order) {\n throw notFound(translate('sales.returns.orderMissing', 'Order not found.'))\n }\n ensureSameScope(order, input.organizationId, input.tenantId)\n await enforceSalesDocumentOptimisticLock(ctx, order, SALES_RESOURCE_KIND_ORDER)\n\n const orderLines = await findWithDecryption(\n tx,\n SalesOrderLine,\n { order: order.id, deletedAt: null },\n { lockMode: LockMode.PESSIMISTIC_WRITE },\n { tenantId: input.tenantId, organizationId: input.organizationId },\n )\n const lineMap = new Map(orderLines.map((line) => [line.id, line]))\n\n const shippedByLine = await loadShippedQuantityByLine(tx, order.id, {\n tenantId: input.tenantId,\n organizationId: input.organizationId,\n })\n\n requested.forEach(({ orderLineId, quantity }) => {\n const line = lineMap.get(orderLineId)\n if (!line) {\n throw notFound(translate('sales.returns.lineMissing', 'Order line not found.'))\n }\n const available = computeAvailableReturnQuantity({\n quantity: toNumeric(line.quantity),\n returnedQuantity: toNumeric(line.returnedQuantity),\n shippedQuantity: shippedByLine.get(orderLineId) ?? 0,\n })\n if (quantity - 1e-6 > available) {\n throw new CrudHttpError(400, { error: translate('sales.returns.quantityExceedsShipped', 'Cannot return more than the shipped quantity. Ship the items before recording a return.') })\n }\n })\n\n const existingAdjustments = await findWithDecryption(\n tx,\n SalesOrderAdjustment,\n { order: order.id, deletedAt: null },\n { orderBy: { position: 'asc' } },\n { tenantId: input.tenantId, organizationId: input.organizationId },\n )\n const positionStart = existingAdjustments.reduce((acc, adj) => Math.max(acc, adj.position ?? 0), 0) + 1\n\n const numberGenerator = new SalesDocumentNumberGenerator(tx)\n const generated = await numberGenerator.generate({\n kind: 'return',\n tenantId: input.tenantId,\n organizationId: input.organizationId,\n })\n const returnId = randomUUID()\n const entity = tx.create(SalesReturn, {\n id: returnId,\n order,\n organizationId: input.organizationId,\n tenantId: input.tenantId,\n returnNumber: generated.number,\n reason: input.reason ?? null,\n notes: input.notes ?? null,\n returnedAt: input.returnedAt ?? new Date(),\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n tx.persist(entity)\n\n const createdAdjustments: SalesOrderAdjustment[] = []\n const createdReturnLines: SalesReturnLine[] = []\n requested.forEach((lineInput, index) => {\n const line = lineMap.get(lineInput.orderLineId)\n if (!line) return\n const quantity = lineInput.quantity\n const lineQuantity = Math.max(toNumeric(line.quantity), 0)\n // `total_net_amount = 0` while `total_gross_amount > 0` is not a representable\n // priced state (gross = net * (1 + taxRate) \u21D2 net = 0 \u21D2 gross = 0). When a line\n // carries a positive gross but a zeroed/missing net, reconstruct the net from the\n // line's gross and tax rate so the return credits both sides and the order's net\n // grand total moves in lockstep with gross (#3036). A genuinely free line\n // (gross = 0, e.g. a 100% discount / comp) keeps net 0, so the return is not\n // over-credited at the discount-ignoring unit price (#3521).\n const lineTotalNet = deriveLineNetFromGross(line.totalNetAmount, line.totalGrossAmount, line.taxRate)\n const unitNet = lineQuantity > 0 ? lineTotalNet / lineQuantity : toNumeric(line.unitPriceNet)\n const unitGross = lineQuantity > 0 ? toNumeric(line.totalGrossAmount) / lineQuantity : toNumeric(line.unitPriceGross)\n const totalNet = -round(Math.max(unitNet, 0) * quantity)\n const totalGross = -round(Math.max(unitGross, 0) * quantity)\n\n const returnLineId = randomUUID()\n const returnLine = tx.create(SalesReturnLine, {\n id: returnLineId,\n salesReturn: entity,\n orderLine: tx.getReference(SalesOrderLine, line.id),\n organizationId: input.organizationId,\n tenantId: input.tenantId,\n quantityReturned: quantity.toString(),\n unitPriceNet: round(unitNet).toString(),\n unitPriceGross: round(unitGross).toString(),\n totalNetAmount: totalNet.toString(),\n totalGrossAmount: totalGross.toString(),\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n createdReturnLines.push(returnLine)\n tx.persist(returnLine)\n\n const adjustment = tx.create(SalesOrderAdjustment, {\n id: randomUUID(),\n order,\n orderLine: tx.getReference(SalesOrderLine, line.id),\n organizationId: input.organizationId,\n tenantId: input.tenantId,\n scope: 'line',\n kind: 'return',\n rate: '0',\n amountNet: totalNet.toString(),\n amountGross: totalGross.toString(),\n currencyCode: order.currencyCode,\n metadata: { returnId, returnLineId },\n position: positionStart + index,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n createdAdjustments.push(adjustment)\n tx.persist(adjustment)\n\n line.returnedQuantity = (toNumeric(line.returnedQuantity) + quantity).toString()\n line.updatedAt = new Date()\n tx.persist(line)\n })\n\n const lineSnapshots: SalesLineSnapshot[] = orderLines.map(mapOrderLineEntityToSnapshot)\n const adjustmentDrafts: SalesAdjustmentDraft[] = [...existingAdjustments, ...createdAdjustments].map(mapOrderAdjustmentToDraft)\n const calculation = await salesCalculationService.calculateDocumentTotals({\n documentKind: 'order',\n lines: lineSnapshots,\n adjustments: adjustmentDrafts,\n context: buildCalculationContext(order),\n existingTotals: resolveExistingPaymentTotals(order),\n })\n applyOrderTotals(order, calculation.totals, calculation.lines.length)\n order.updatedAt = new Date()\n tx.persist(order)\n\n await tx.flush()\n\n return { header: entity, createdLines: createdReturnLines, order }\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: header,\n identifiers: { id: header.id, organizationId: header.organizationId, tenantId: header.tenantId },\n indexer: { entityType: E.sales.sales_return },\n events: returnCrudEvents,\n })\n\n if (createdLines.length) {\n await Promise.all(\n createdLines.map((line) =>\n emitCrudSideEffects({\n dataEngine,\n action: 'created',\n entity: line,\n identifiers: { id: line.id, organizationId: line.organizationId, tenantId: line.tenantId },\n indexer: { entityType: E.sales.sales_return_line },\n }),\n ),\n )\n }\n\n return { returnId: header.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return loadReturnSnapshot(em, result.returnId)\n },\n buildLog: async ({ result, snapshots }) => {\n const after = snapshots.after as ReturnSnapshot | undefined\n if (!after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('sales.audit.returns.create', 'Create return'),\n resourceKind: 'sales.return',\n resourceId: result.returnId,\n parentResourceKind: 'sales.order',\n parentResourceId: after.orderId ?? null,\n tenantId: after.tenantId,\n organizationId: after.organizationId,\n snapshotAfter: after,\n payload: {\n undo: { after } satisfies ReturnUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<ReturnUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const salesCalculationService = ctx.container.resolve<SalesCalculationService>('salesCalculationService')\n await reverseReturnEffects(em, salesCalculationService, after)\n await invalidateOrderCache(ctx.container, {\n id: after.orderId,\n organizationId: after.organizationId,\n tenantId: after.tenantId,\n }, ctx.auth?.tenantId ?? null)\n },\n redo: async ({ ctx, logEntry }) => {\n const after = resolveRedoSnapshot<ReturnSnapshot>(logEntry)\n if (!after || !after.id) {\n throw new CrudHttpError(400, { error: '[internal] redo snapshot unavailable for sales.returns.create' })\n }\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const salesCalculationService = ctx.container.resolve<SalesCalculationService>('salesCalculationService')\n\n const createdLines = await restoreReturnEffects(em, salesCalculationService, after)\n\n const header = await findOneWithDecryption(\n em,\n SalesReturn,\n { id: after.id, deletedAt: null },\n {},\n { tenantId: after.tenantId, organizationId: after.organizationId },\n )\n if (!header) {\n const { translate } = await resolveTranslations()\n throw notFound(translate('sales.returns.orderMissing', 'Order not found.'))\n }\n\n await invalidateOrderCache(ctx.container, {\n id: after.orderId,\n organizationId: after.organizationId,\n tenantId: after.tenantId,\n }, ctx.auth?.tenantId ?? null)\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'created',\n entity: header,\n identifiers: { id: header.id, organizationId: header.organizationId, tenantId: header.tenantId },\n indexer: { entityType: E.sales.sales_return },\n events: returnCrudEvents,\n })\n\n if (createdLines.length) {\n await Promise.all(\n createdLines.map((line) =>\n emitCrudSideEffects({\n dataEngine,\n action: 'created',\n entity: line,\n identifiers: { id: line.id, organizationId: line.organizationId, tenantId: line.tenantId },\n indexer: { entityType: E.sales.sales_return_line },\n }),\n ),\n )\n }\n\n return { returnId: header.id }\n },\n}\n\nconst updateReturnCommand: CommandHandler<ReturnUpdateInput, { returnId: string }> = {\n id: 'sales.returns.update',\n async prepare(rawInput, ctx) {\n const parsed = returnUpdateSchema.parse(rawInput ?? {})\n const em = ctx.container.resolve('em') as EntityManager\n const snapshot = await loadReturnHeaderSnapshot(em, parsed.id)\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 = returnUpdateSchema.parse(rawInput ?? {})\n ensureTenantScope(ctx, input.tenantId)\n ensureOrganizationScope(ctx, input.organizationId)\n const { translate } = await resolveTranslations()\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n\n const header = await em.transactional(async (tx) => {\n const entity = await findOneWithDecryption(\n tx,\n SalesReturn,\n { id: input.id, deletedAt: null },\n { populate: ['order'] },\n { tenantId: input.tenantId, organizationId: input.organizationId },\n )\n if (!entity || !entity.order) {\n throw notFound(translate('sales.returns.notFound', 'Return not found.'))\n }\n ensureSameScope(entity, input.organizationId, input.tenantId)\n const orderId = typeof entity.order === 'string' ? entity.order : entity.order.id\n if (input.orderId !== orderId) {\n throw new CrudHttpError(400, { error: translate('sales.returns.orderMismatch', 'Return does not belong to this order.') })\n }\n // Lock on the return's own version \u2014 editing header fields (reason / notes /\n // returnedAt) only touches the return, not the order totals.\n await enforceSalesDocumentOptimisticLock(ctx, entity, SALES_RESOURCE_KIND_RETURN)\n\n if (input.reason !== undefined) entity.reason = input.reason.length ? input.reason : null\n if (input.notes !== undefined) entity.notes = input.notes.length ? input.notes : null\n if (input.returnedAt !== undefined) entity.returnedAt = input.returnedAt ?? null\n entity.updatedAt = new Date()\n tx.persist(entity)\n await tx.flush()\n return entity\n })\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'updated',\n entity: header,\n identifiers: { id: header.id, organizationId: header.organizationId, tenantId: header.tenantId },\n indexer: { entityType: E.sales.sales_return },\n events: returnCrudEvents,\n })\n\n return { returnId: header.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return loadReturnHeaderSnapshot(em, result.returnId)\n },\n buildLog: async ({ snapshots, result }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as ReturnHeaderSnapshot | undefined\n const after = snapshots.after as ReturnHeaderSnapshot | undefined\n return {\n actionLabel: translate('sales.audit.returns.update', 'Update return'),\n resourceKind: 'sales.return',\n resourceId: result.returnId,\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: {\n undo: { before, after } satisfies ReturnHeaderUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<ReturnHeaderUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n await em.transactional(async (tx) => {\n const entity = await findOneWithDecryption(\n tx,\n SalesReturn,\n { id: before.id, deletedAt: null },\n {},\n { tenantId: before.tenantId, organizationId: before.organizationId },\n )\n if (!entity) return\n entity.reason = before.reason\n entity.notes = before.notes\n entity.returnedAt = before.returnedAt ? new Date(before.returnedAt) : null\n entity.updatedAt = new Date()\n tx.persist(entity)\n await tx.flush()\n })\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n const restored = await findOneWithDecryption(\n em,\n SalesReturn,\n { id: before.id, deletedAt: null },\n {},\n { tenantId: before.tenantId, organizationId: before.organizationId },\n )\n if (restored) {\n await emitCrudSideEffects({\n dataEngine,\n action: 'updated',\n entity: restored,\n identifiers: { id: restored.id, organizationId: restored.organizationId, tenantId: restored.tenantId },\n indexer: { entityType: E.sales.sales_return },\n events: returnCrudEvents,\n })\n }\n },\n}\n\nconst deleteReturnCommand: CommandHandler<ReturnDeleteInput, { returnId: string }> = {\n id: 'sales.returns.delete',\n async prepare(rawInput, ctx) {\n const parsed = returnDeleteSchema.parse(rawInput ?? {})\n const em = ctx.container.resolve('em') as EntityManager\n const snapshot = await loadReturnSnapshot(em, parsed.id)\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 = returnDeleteSchema.parse(rawInput ?? {})\n ensureTenantScope(ctx, input.tenantId)\n ensureOrganizationScope(ctx, input.organizationId)\n const { translate } = await resolveTranslations()\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const salesCalculationService = ctx.container.resolve<SalesCalculationService>('salesCalculationService')\n\n const snapshot = await loadReturnSnapshot(em, input.id)\n if (!snapshot) {\n throw notFound(translate('sales.returns.notFound', 'Return not found.'))\n }\n ensureSameScope(snapshot, input.organizationId, input.tenantId)\n if (input.orderId !== snapshot.orderId) {\n throw new CrudHttpError(400, { error: translate('sales.returns.orderMismatch', 'Return does not belong to this order.') })\n }\n\n const header = await findOneWithDecryption(\n em,\n SalesReturn,\n { id: input.id, deletedAt: null },\n {},\n { tenantId: input.tenantId, organizationId: input.organizationId },\n )\n if (!header) {\n throw notFound(translate('sales.returns.notFound', 'Return not found.'))\n }\n ensureSameScope(header, input.organizationId, input.tenantId)\n // Lock on the return's own version, captured before any mutation.\n await enforceSalesDocumentOptimisticLock(ctx, header, SALES_RESOURCE_KIND_RETURN)\n\n await reverseReturnEffects(em, salesCalculationService, snapshot)\n await invalidateOrderCache(ctx.container, {\n id: snapshot.orderId,\n organizationId: snapshot.organizationId,\n tenantId: snapshot.tenantId,\n }, ctx.auth?.tenantId ?? null)\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'deleted',\n entity: header,\n identifiers: { id: snapshot.id, organizationId: snapshot.organizationId, tenantId: snapshot.tenantId },\n indexer: { entityType: E.sales.sales_return },\n events: returnCrudEvents,\n })\n\n if (snapshot.lines.length) {\n await Promise.all(\n snapshot.lines.map((line) =>\n emitCrudSideEffects({\n dataEngine,\n action: 'deleted',\n entity: { id: line.id, organizationId: snapshot.organizationId, tenantId: snapshot.tenantId },\n identifiers: { id: line.id, organizationId: snapshot.organizationId, tenantId: snapshot.tenantId },\n indexer: { entityType: E.sales.sales_return_line },\n }),\n ),\n )\n }\n\n return { returnId: snapshot.id }\n },\n buildLog: async ({ snapshots, result }) => {\n const before = snapshots.before as ReturnSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('sales.audit.returns.delete', 'Delete return'),\n resourceKind: 'sales.return',\n resourceId: result.returnId,\n parentResourceKind: 'sales.order',\n parentResourceId: before.orderId ?? null,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: { before } satisfies ReturnDeleteUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<ReturnDeleteUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const salesCalculationService = ctx.container.resolve<SalesCalculationService>('salesCalculationService')\n\n const createdLines = await restoreReturnEffects(em, salesCalculationService, before)\n\n const header = await findOneWithDecryption(\n em,\n SalesReturn,\n { id: before.id, deletedAt: null },\n {},\n { tenantId: before.tenantId, organizationId: before.organizationId },\n )\n if (!header) return\n\n await invalidateOrderCache(ctx.container, {\n id: before.orderId,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n }, ctx.auth?.tenantId ?? null)\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'created',\n entity: header,\n identifiers: { id: header.id, organizationId: header.organizationId, tenantId: header.tenantId },\n indexer: { entityType: E.sales.sales_return },\n events: returnCrudEvents,\n })\n\n if (createdLines.length) {\n await Promise.all(\n createdLines.map((line) =>\n emitCrudSideEffects({\n dataEngine,\n action: 'created',\n entity: line,\n identifiers: { id: line.id, organizationId: line.organizationId, tenantId: line.tenantId },\n indexer: { entityType: E.sales.sales_return_line },\n }),\n ),\n )\n }\n },\n}\n\nregisterCommand(createReturnCommand)\nregisterCommand(updateReturnCommand)\nregisterCommand(deleteReturnCommand)\n\nexport const returnCommands = [createReturnCommand, updateReturnCommand, deleteReturnCommand]\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { randomUUID } from 'crypto'\nimport { registerCommand, type CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'\nimport { LockMode } from '@mikro-orm/core'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { CrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'\nimport { invalidateCrudCache } from '@open-mercato/shared/lib/crud/cache'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\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 { SalesDocumentNumberGenerator } from '../services/salesDocumentNumberGenerator'\nimport type { SalesCalculationService } from '../services/salesCalculationService'\nimport type { SalesAdjustmentDraft, SalesLineSnapshot, SalesDocumentCalculationResult } from '../lib/types'\nimport { isExternalAmountsMode } from '../lib/calculations'\nimport { readPersistedHeaderTotals } from '../lib/externalAmounts'\nimport { cloneJson, deriveLineNetFromGross, ensureOrganizationScope, ensureSameScope, ensureTenantScope, extractUndoPayload, toNumericString, enforceSalesDocumentOptimisticLock, SALES_RESOURCE_KIND_ORDER, SALES_RESOURCE_KIND_RETURN } from './shared'\nimport { resolveRedoSnapshot } from '@open-mercato/shared/lib/commands/redo'\nimport { SalesOrder, SalesOrderAdjustment, SalesOrderLine, SalesReturn, SalesReturnLine } from '../data/entities'\nimport { mapOrderLineEntityToSnapshot } from '../lib/lineSnapshots'\nimport { loadShippedQuantityByLine } from '../lib/shipments/snapshots'\nimport { computeAvailableReturnQuantity } from '../lib/returnQuantity'\nimport {\n returnCreateSchema,\n returnUpdateSchema,\n returnDeleteSchema,\n type ReturnCreateInput,\n type ReturnUpdateInput,\n type ReturnDeleteInput,\n} from '../data/validators'\nimport { E } from '#generated/entities.ids.generated'\n\ntype ReturnLineInput = { orderLineId: string; quantity: number }\n\ntype ReturnSnapshot = {\n id: string\n orderId: string\n organizationId: string\n tenantId: string\n returnNumber: string\n returnedAt: string | null\n reason: string | null\n notes: string | null\n lines: Array<{\n id: string\n orderLineId: string\n quantityReturned: number\n unitPriceNet: number\n unitPriceGross: number\n totalNetAmount: number\n totalGrossAmount: number\n }>\n adjustmentIds: string[]\n}\n\ntype ReturnUndoPayload = {\n after?: ReturnSnapshot | null\n}\n\nconst returnCrudEvents: CrudEventsConfig = {\n module: 'sales',\n entity: 'return',\n persistent: true,\n buildPayload: (ctx) => ({\n id: ctx.identifiers.id,\n organizationId: ctx.identifiers.organizationId,\n tenantId: ctx.identifiers.tenantId,\n }),\n}\n\ntype OrderCacheRecord = Pick<SalesOrder, 'id' | 'organizationId' | 'tenantId'>\n\n/**\n * Return mutations update the order aggregate, which is also the cache resource\n * used by the order-lines and order-adjustments routes. Invalidate it after\n * each committed return lifecycle change so reloads receive its fresh\n * `updatedAt` optimistic-lock token.\n */\nasync function invalidateOrderCache(\n container: Parameters<typeof invalidateCrudCache>[0],\n order: OrderCacheRecord,\n fallbackTenant: string | null,\n): Promise<void> {\n await invalidateCrudCache(\n container,\n SALES_RESOURCE_KIND_ORDER,\n { id: order.id, organizationId: order.organizationId, tenantId: order.tenantId },\n fallbackTenant,\n 'updated',\n )\n}\n\nfunction toNumeric(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.isFinite(parsed)) return parsed\n }\n return 0\n}\n\nfunction round(value: number): number {\n return Math.round((value + Number.EPSILON) * 1e4) / 1e4\n}\n\n/**\n * Payment totals live on the order, not in the line/adjustment math a return\n * recalculates. Every `calculateDocumentTotals` call that writes order totals\n * back to the order MUST seed these so `buildBaseDocumentResult` preserves the\n * recorded `paidTotalAmount` / `refundedTotalAmount` instead of defaulting them\n * to 0 \u2014 otherwise creating/undoing/redoing a return silently zeroes the paid\n * amount and the order's outstanding balance goes wrong on any paid order\n * (#3756). Mirrors `resolveExistingPaymentTotals` in `commands/documents.ts`.\n */\nfunction resolveExistingPaymentTotals(order: SalesOrder): { paidTotalAmount: number; refundedTotalAmount: number } {\n return {\n paidTotalAmount: toNumeric(order.paidTotalAmount),\n refundedTotalAmount: toNumeric(order.refundedTotalAmount),\n }\n}\n\nfunction applyOrderTotals(order: SalesOrder, totals: SalesDocumentCalculationResult['totals'], lineCount: number): void {\n order.subtotalNetAmount = toNumericString(totals.subtotalNetAmount) ?? '0'\n order.subtotalGrossAmount = toNumericString(totals.subtotalGrossAmount) ?? '0'\n order.discountTotalAmount = toNumericString(totals.discountTotalAmount) ?? '0'\n order.taxTotalAmount = toNumericString(totals.taxTotalAmount) ?? '0'\n order.shippingNetAmount = toNumericString(totals.shippingNetAmount) ?? '0'\n order.shippingGrossAmount = toNumericString(totals.shippingGrossAmount) ?? '0'\n order.surchargeTotalAmount = toNumericString(totals.surchargeTotalAmount) ?? '0'\n order.grandTotalNetAmount = toNumericString(totals.grandTotalNetAmount) ?? '0'\n order.grandTotalGrossAmount = toNumericString(totals.grandTotalGrossAmount) ?? '0'\n order.paidTotalAmount = toNumericString(totals.paidTotalAmount) ?? '0'\n order.refundedTotalAmount = toNumericString(totals.refundedTotalAmount) ?? '0'\n order.outstandingAmount = toNumericString(totals.outstandingAmount) ?? '0'\n order.totalsSnapshot = cloneJson(totals)\n order.lineItemCount = lineCount\n}\n\n// Deliberate, not an omission: an external order's header belongs to the source\n// system, which issues its own credit document. The return itself is still recorded.\nfunction applyOrderTotalsUnlessExternal(\n order: SalesOrder,\n calculation: SalesDocumentCalculationResult,\n): void {\n if (isExternalAmountsMode(order.totalsMode ?? 'computed')) return\n applyOrderTotals(order, calculation.totals, calculation.lines.length)\n}\n\nfunction resolveOrderCalculationMode(order: SalesOrder) {\n const totalsMode = order.totalsMode ?? 'computed'\n return {\n totalsMode,\n suppliedTotals: isExternalAmountsMode(totalsMode) ? readPersistedHeaderTotals(order) : null,\n }\n}\n\nfunction mapOrderAdjustmentToDraft(adjustment: SalesOrderAdjustment): SalesAdjustmentDraft {\n return {\n id: adjustment.id,\n scope: adjustment.scope ?? 'order',\n kind: adjustment.kind,\n code: adjustment.code ?? null,\n label: adjustment.label ?? null,\n calculatorKey: adjustment.calculatorKey ?? null,\n promotionId: adjustment.promotionId ?? null,\n rate: toNumeric(adjustment.rate),\n amountNet: toNumeric(adjustment.amountNet),\n amountGross: toNumeric(adjustment.amountGross),\n currencyCode: adjustment.currencyCode ?? null,\n metadata: adjustment.metadata ? cloneJson(adjustment.metadata) : null,\n position: adjustment.position ?? 0,\n }\n}\n\nfunction buildCalculationContext(order: SalesOrder) {\n return {\n tenantId: order.tenantId,\n organizationId: order.organizationId,\n currencyCode: order.currencyCode,\n metadata: {\n shippingMethod: order.shippingMethodSnapshot\n ? cloneJson(order.shippingMethodSnapshot as Record<string, unknown>)\n : null,\n paymentMethod: order.paymentMethodSnapshot ? cloneJson(order.paymentMethodSnapshot as Record<string, unknown>) : null,\n },\n }\n}\n\n/**\n * Recalculates order totals (including line-scoped return adjustments) from lines and\n * adjustments. Do not merge this into GET /api/sales/orders responses: provider\n * calculators re-emit shipping/payment fees on top of already-persisted adjustments\n * and make list vs detail totals diverge (#5438). Persist via commands instead.\n */\nexport async function recalculateOrderTotalsForDisplay(\n em: EntityManager,\n container: { resolve: (key: string) => unknown },\n orderId: string,\n scope: { tenantId: string; organizationId: string },\n): Promise<SalesDocumentCalculationResult['totals'] | null> {\n const order = await findOneWithDecryption(\n em,\n SalesOrder,\n { id: orderId, deletedAt: null },\n {},\n scope,\n )\n if (!order) return null\n const [orderLines, adjustments] = await Promise.all([\n findWithDecryption(em, SalesOrderLine, { order: order.id, deletedAt: null }, {}, scope),\n findWithDecryption(\n em,\n SalesOrderAdjustment,\n { order: order.id, deletedAt: null },\n { orderBy: { position: 'asc' } },\n scope,\n ),\n ])\n const lineSnapshots: SalesLineSnapshot[] = orderLines.map(mapOrderLineEntityToSnapshot)\n const adjustmentDrafts: SalesAdjustmentDraft[] = adjustments.map(mapOrderAdjustmentToDraft)\n const salesCalculationService = container.resolve('salesCalculationService') as SalesCalculationService\n const calculation = await salesCalculationService.calculateDocumentTotals({\n documentKind: 'order',\n lines: lineSnapshots,\n adjustments: adjustmentDrafts,\n context: buildCalculationContext(order),\n existingTotals: resolveExistingPaymentTotals(order),\n ...resolveOrderCalculationMode(order),\n })\n return calculation.totals\n}\n\nexport async function loadReturnSnapshot(em: EntityManager, id: string): Promise<ReturnSnapshot | null> {\n const header = await findOneWithDecryption(\n em,\n SalesReturn,\n { id, deletedAt: null },\n { populate: ['order'] },\n {},\n )\n if (!header || !header.order) return null\n const orderId = typeof header.order === 'string' ? header.order : header.order.id\n const lines = await findWithDecryption(\n em,\n SalesReturnLine,\n { salesReturn: header.id, deletedAt: null },\n { populate: ['orderLine'] },\n { tenantId: header.tenantId, organizationId: header.organizationId },\n )\n const adjustmentIds: string[] = []\n const adjustments = await findWithDecryption(\n em,\n SalesOrderAdjustment,\n { order: orderId, kind: 'return', deletedAt: null },\n {},\n { tenantId: header.tenantId, organizationId: header.organizationId },\n )\n adjustments.forEach((adj) => {\n const meta = adj.metadata as Record<string, unknown> | null | undefined\n if (meta && meta.returnId === header.id) adjustmentIds.push(adj.id)\n })\n\n return {\n id: header.id,\n orderId,\n organizationId: header.organizationId,\n tenantId: header.tenantId,\n returnNumber: header.returnNumber,\n returnedAt: header.returnedAt ? header.returnedAt.toISOString() : null,\n reason: header.reason ?? null,\n notes: header.notes ?? null,\n lines: lines.map((line) => ({\n id: line.id,\n orderLineId: typeof line.orderLine === 'string' ? line.orderLine : line.orderLine?.id ?? null,\n quantityReturned: toNumeric(line.quantityReturned),\n unitPriceNet: toNumeric(line.unitPriceNet),\n unitPriceGross: toNumeric(line.unitPriceGross),\n totalNetAmount: toNumeric(line.totalNetAmount),\n totalGrossAmount: toNumeric(line.totalGrossAmount),\n })),\n adjustmentIds,\n }\n}\n\ntype ReturnHeaderSnapshot = {\n id: string\n orderId: string\n organizationId: string\n tenantId: string\n reason: string | null\n notes: string | null\n returnedAt: string | null\n}\n\ntype ReturnHeaderUndoPayload = {\n before?: ReturnHeaderSnapshot | null\n after?: ReturnHeaderSnapshot | null\n}\n\ntype ReturnDeleteUndoPayload = {\n before?: ReturnSnapshot | null\n}\n\nasync function loadReturnHeaderSnapshot(em: EntityManager, id: string): Promise<ReturnHeaderSnapshot | null> {\n const header = await findOneWithDecryption(em, SalesReturn, { id, deletedAt: null }, { populate: ['order'] }, {})\n if (!header || !header.order) return null\n const orderId = typeof header.order === 'string' ? header.order : header.order.id\n return {\n id: header.id,\n orderId,\n organizationId: header.organizationId,\n tenantId: header.tenantId,\n reason: header.reason ?? null,\n notes: header.notes ?? null,\n returnedAt: header.returnedAt ? header.returnedAt.toISOString() : null,\n }\n}\n\n/**\n * Reverse the order-level effects of a return: restore each order line's\n * `returnedQuantity`, drop the return's line-scoped credit adjustments, remove\n * the return header + lines, and recalculate the order totals. Shared by the\n * create command's undo and the delete command's execute \u2014 both need the exact\n * same teardown. No-op when the order is gone.\n *\n * The line reversals, adjustment/return removals, and the order-total recompute\n * interleave queries on the same EntityManager with scalar mutations, so they\n * run inside an atomic flush to avoid lost updates and partial commits\n * (SPEC-018): the per-phase flush boundary persists the line `returnedQuantity`\n * reversals before the adjustment/header/return-line lookups in the next phase\n * run any query, which under MikroORM v7 would otherwise silently discard the\n * pending scalar changes on the managed lines.\n */\nasync function reverseReturnEffects(\n em: EntityManager,\n salesCalculationService: SalesCalculationService,\n snapshot: ReturnSnapshot,\n): Promise<void> {\n const order = await findOneWithDecryption(\n em,\n SalesOrder,\n { id: snapshot.orderId, deletedAt: null },\n {},\n { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId },\n )\n if (!order) return\n\n let lines: SalesOrderLine[] = []\n await withAtomicFlush(\n em,\n [\n async () => {\n lines = await findWithDecryption(\n em,\n SalesOrderLine,\n { order: order.id, deletedAt: null },\n {},\n { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId },\n )\n const lineMap = new Map(lines.map((line) => [line.id, line]))\n snapshot.lines.forEach((entry) => {\n const line = lineMap.get(entry.orderLineId)\n if (!line) return\n const next = Math.max(0, toNumeric(line.returnedQuantity) - entry.quantityReturned)\n line.returnedQuantity = next.toString()\n line.updatedAt = new Date()\n em.persist(line)\n })\n },\n async () => {\n if (snapshot.adjustmentIds.length) {\n const adjustments = await findWithDecryption(\n em,\n SalesOrderAdjustment,\n { id: { $in: snapshot.adjustmentIds }, deletedAt: null },\n {},\n { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId },\n )\n adjustments.forEach((adj) => em.remove(adj))\n }\n\n const header = await findOneWithDecryption(\n em,\n SalesReturn,\n { id: snapshot.id, deletedAt: null },\n {},\n { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId },\n )\n const returnLines = await findWithDecryption(\n em,\n SalesReturnLine,\n { salesReturn: snapshot.id, deletedAt: null },\n {},\n { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId },\n )\n returnLines.forEach((line) => em.remove(line))\n if (header) em.remove(header)\n\n const existingAdjustments = await findWithDecryption(\n em,\n SalesOrderAdjustment,\n { order: order.id, deletedAt: null },\n { orderBy: { position: 'asc' } },\n { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId },\n )\n const lineSnapshots: SalesLineSnapshot[] = lines.map(mapOrderLineEntityToSnapshot)\n const adjustmentDrafts: SalesAdjustmentDraft[] = existingAdjustments.map(mapOrderAdjustmentToDraft)\n const calculation = await salesCalculationService.calculateDocumentTotals({\n documentKind: 'order',\n lines: lineSnapshots,\n adjustments: adjustmentDrafts,\n context: buildCalculationContext(order),\n existingTotals: resolveExistingPaymentTotals(order),\n ...resolveOrderCalculationMode(order),\n })\n applyOrderTotalsUnlessExternal(order, calculation)\n order.updatedAt = new Date()\n em.persist(order)\n },\n ],\n { transaction: true },\n )\n}\n\n/**\n * Re-apply a return from a snapshot: recreate the return header + lines and the\n * line-scoped credit adjustments, bump each order line's `returnedQuantity`, and\n * recalculate the order totals. Shared by the create command's redo and the\n * delete command's undo. Returns the recreated return lines so callers can emit\n * index side effects. Throws a 404 when the order is gone.\n *\n * The order may have changed since the snapshot was taken (another return\n * consumed the shipped quantity, a shipment was removed, an order line was\n * deleted), so the snapshot quantities are re-checked against the currently\n * returnable quantity \u2014 the same rule `sales.returns.create` enforces \u2014 under\n * the order-line lock and before any write. A stale restore is refused with a\n * 409 instead of returning and crediting the same shipped units twice.\n */\nasync function restoreReturnEffects(\n em: EntityManager,\n salesCalculationService: SalesCalculationService,\n snapshot: ReturnSnapshot,\n): Promise<SalesReturnLine[]> {\n const returnId = snapshot.id\n const createdLines: SalesReturnLine[] = []\n const { translate } = await resolveTranslations()\n\n await withAtomicFlush(\n em,\n [\n async () => {\n const order = await findOneWithDecryption(\n em,\n SalesOrder,\n { id: snapshot.orderId, deletedAt: null },\n {},\n { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId },\n )\n if (!order) {\n throw notFound(translate('sales.returns.orderMissing', 'Order not found.'))\n }\n ensureSameScope(order, snapshot.organizationId, snapshot.tenantId)\n\n const orderLines = await findWithDecryption(\n em,\n SalesOrderLine,\n { order: order.id, deletedAt: null },\n { lockMode: LockMode.PESSIMISTIC_WRITE },\n { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId },\n )\n const lineMap = new Map(orderLines.map((line) => [line.id, line]))\n\n const shippedByLine = await loadShippedQuantityByLine(em, order.id, {\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n })\n const restoredByLine = new Map<string, { line: SalesOrderLine; quantity: number }>()\n snapshot.lines.forEach((lineSnapshot) => {\n const line = lineSnapshot.orderLineId ? lineMap.get(lineSnapshot.orderLineId) : undefined\n if (!line) {\n throw new CrudHttpError(409, {\n error: translate('sales.returns.restoreLineMissing', 'This return cannot be restored: one of its order lines no longer exists.'),\n })\n }\n const restored = restoredByLine.get(line.id)\n restoredByLine.set(line.id, { line, quantity: (restored?.quantity ?? 0) + lineSnapshot.quantityReturned })\n })\n restoredByLine.forEach(({ line, quantity }, orderLineId) => {\n const available = computeAvailableReturnQuantity({\n quantity: toNumeric(line.quantity),\n returnedQuantity: toNumeric(line.returnedQuantity),\n shippedQuantity: shippedByLine.get(orderLineId) ?? 0,\n })\n if (quantity - 1e-6 > available) {\n throw new CrudHttpError(409, {\n error: translate('sales.returns.restoreQuantityUnavailable', 'This return cannot be restored: the order no longer has enough shipped quantity left to return.'),\n })\n }\n })\n\n const existingAdjustments = await findWithDecryption(\n em,\n SalesOrderAdjustment,\n { order: order.id, deletedAt: null },\n { orderBy: { position: 'asc' } },\n { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId },\n )\n const positionStart = existingAdjustments.reduce((acc, adj) => Math.max(acc, adj.position ?? 0), 0) + 1\n\n const restoredHeader =\n (await findOneWithDecryption(\n em,\n SalesReturn,\n { id: snapshot.id },\n {},\n { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId },\n )) ??\n em.create(SalesReturn, {\n id: snapshot.id,\n order,\n organizationId: snapshot.organizationId,\n tenantId: snapshot.tenantId,\n returnNumber: snapshot.returnNumber,\n reason: snapshot.reason ?? null,\n notes: snapshot.notes ?? null,\n returnedAt: snapshot.returnedAt ? new Date(snapshot.returnedAt) : new Date(),\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n restoredHeader.order = order\n restoredHeader.deletedAt = null\n restoredHeader.organizationId = snapshot.organizationId\n restoredHeader.tenantId = snapshot.tenantId\n restoredHeader.returnNumber = snapshot.returnNumber\n restoredHeader.reason = snapshot.reason ?? null\n restoredHeader.notes = snapshot.notes ?? null\n restoredHeader.returnedAt = snapshot.returnedAt ? new Date(snapshot.returnedAt) : new Date()\n restoredHeader.updatedAt = new Date()\n em.persist(restoredHeader)\n\n const createdAdjustments: SalesOrderAdjustment[] = []\n snapshot.lines.forEach((lineSnapshot, index) => {\n const line = lineMap.get(lineSnapshot.orderLineId)\n if (!line) return\n const totalNet = lineSnapshot.totalNetAmount\n const totalGross = lineSnapshot.totalGrossAmount\n const adjustmentId = snapshot.adjustmentIds[index] ?? randomUUID()\n\n const returnLine = em.create(SalesReturnLine, {\n id: lineSnapshot.id,\n salesReturn: restoredHeader,\n orderLine: em.getReference(SalesOrderLine, line.id),\n organizationId: snapshot.organizationId,\n tenantId: snapshot.tenantId,\n quantityReturned: lineSnapshot.quantityReturned.toString(),\n unitPriceNet: lineSnapshot.unitPriceNet.toString(),\n unitPriceGross: lineSnapshot.unitPriceGross.toString(),\n totalNetAmount: totalNet.toString(),\n totalGrossAmount: totalGross.toString(),\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n createdLines.push(returnLine)\n em.persist(returnLine)\n\n const adjustment = em.create(SalesOrderAdjustment, {\n id: adjustmentId,\n order,\n orderLine: em.getReference(SalesOrderLine, line.id),\n organizationId: snapshot.organizationId,\n tenantId: snapshot.tenantId,\n scope: 'line',\n kind: 'return',\n rate: '0',\n amountNet: totalNet.toString(),\n amountGross: totalGross.toString(),\n currencyCode: order.currencyCode,\n metadata: { returnId, returnLineId: lineSnapshot.id },\n position: positionStart + index,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n createdAdjustments.push(adjustment)\n em.persist(adjustment)\n\n line.returnedQuantity = (toNumeric(line.returnedQuantity) + lineSnapshot.quantityReturned).toString()\n line.updatedAt = new Date()\n em.persist(line)\n })\n\n const lineSnapshots: SalesLineSnapshot[] = orderLines.map(mapOrderLineEntityToSnapshot)\n const adjustmentDrafts: SalesAdjustmentDraft[] = [...existingAdjustments, ...createdAdjustments].map(\n mapOrderAdjustmentToDraft,\n )\n const calculation = await salesCalculationService.calculateDocumentTotals({\n documentKind: 'order',\n lines: lineSnapshots,\n adjustments: adjustmentDrafts,\n context: buildCalculationContext(order),\n existingTotals: resolveExistingPaymentTotals(order),\n ...resolveOrderCalculationMode(order),\n })\n applyOrderTotalsUnlessExternal(order, calculation)\n order.updatedAt = new Date()\n em.persist(order)\n },\n ],\n { transaction: true },\n )\n\n return createdLines\n}\n\nfunction normalizeLinesInput(lines: ReturnCreateInput['lines']): ReturnLineInput[] {\n const seen = new Set<string>()\n const result: ReturnLineInput[] = []\n for (const line of lines) {\n const orderLineId = line.orderLineId\n if (!orderLineId || seen.has(orderLineId)) continue\n const quantity = toNumeric(line.quantity)\n if (!Number.isFinite(quantity) || quantity <= 0) continue\n seen.add(orderLineId)\n result.push({ orderLineId, quantity })\n }\n return result\n}\n\nconst createReturnCommand: CommandHandler<ReturnCreateInput, { returnId: string }> = {\n id: 'sales.returns.create',\n async execute(rawInput, ctx) {\n const input = returnCreateSchema.parse(rawInput ?? {})\n ensureTenantScope(ctx, input.tenantId)\n ensureOrganizationScope(ctx, input.organizationId)\n\n const { translate } = await resolveTranslations()\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n\n const requested = normalizeLinesInput(input.lines)\n if (!requested.length) {\n throw new CrudHttpError(400, { error: translate('sales.returns.linesRequired', 'Select at least one line to return.') })\n }\n\n const salesCalculationService = ctx.container.resolve<SalesCalculationService>('salesCalculationService')\n const { header, createdLines, order } = await em.transactional(async (tx) => {\n const order = await findOneWithDecryption(\n tx,\n SalesOrder,\n { id: input.orderId, deletedAt: null },\n {},\n { tenantId: input.tenantId, organizationId: input.organizationId },\n )\n if (!order) {\n throw notFound(translate('sales.returns.orderMissing', 'Order not found.'))\n }\n ensureSameScope(order, input.organizationId, input.tenantId)\n await enforceSalesDocumentOptimisticLock(ctx, order, SALES_RESOURCE_KIND_ORDER)\n\n const orderLines = await findWithDecryption(\n tx,\n SalesOrderLine,\n { order: order.id, deletedAt: null },\n { lockMode: LockMode.PESSIMISTIC_WRITE },\n { tenantId: input.tenantId, organizationId: input.organizationId },\n )\n const lineMap = new Map(orderLines.map((line) => [line.id, line]))\n\n const shippedByLine = await loadShippedQuantityByLine(tx, order.id, {\n tenantId: input.tenantId,\n organizationId: input.organizationId,\n })\n\n requested.forEach(({ orderLineId, quantity }) => {\n const line = lineMap.get(orderLineId)\n if (!line) {\n throw notFound(translate('sales.returns.lineMissing', 'Order line not found.'))\n }\n const available = computeAvailableReturnQuantity({\n quantity: toNumeric(line.quantity),\n returnedQuantity: toNumeric(line.returnedQuantity),\n shippedQuantity: shippedByLine.get(orderLineId) ?? 0,\n })\n if (quantity - 1e-6 > available) {\n throw new CrudHttpError(400, { error: translate('sales.returns.quantityExceedsShipped', 'Cannot return more than the shipped quantity. Ship the items before recording a return.') })\n }\n })\n\n const existingAdjustments = await findWithDecryption(\n tx,\n SalesOrderAdjustment,\n { order: order.id, deletedAt: null },\n { orderBy: { position: 'asc' } },\n { tenantId: input.tenantId, organizationId: input.organizationId },\n )\n const positionStart = existingAdjustments.reduce((acc, adj) => Math.max(acc, adj.position ?? 0), 0) + 1\n\n const numberGenerator = new SalesDocumentNumberGenerator(tx)\n const generated = await numberGenerator.generate({\n kind: 'return',\n tenantId: input.tenantId,\n organizationId: input.organizationId,\n })\n const returnId = randomUUID()\n const entity = tx.create(SalesReturn, {\n id: returnId,\n order,\n organizationId: input.organizationId,\n tenantId: input.tenantId,\n returnNumber: generated.number,\n reason: input.reason ?? null,\n notes: input.notes ?? null,\n returnedAt: input.returnedAt ?? new Date(),\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n tx.persist(entity)\n\n const createdAdjustments: SalesOrderAdjustment[] = []\n const createdReturnLines: SalesReturnLine[] = []\n requested.forEach((lineInput, index) => {\n const line = lineMap.get(lineInput.orderLineId)\n if (!line) return\n const quantity = lineInput.quantity\n const lineQuantity = Math.max(toNumeric(line.quantity), 0)\n // `total_net_amount = 0` while `total_gross_amount > 0` is not a representable\n // priced state (gross = net * (1 + taxRate) \u21D2 net = 0 \u21D2 gross = 0). When a line\n // carries a positive gross but a zeroed/missing net, reconstruct the net from the\n // line's gross and tax rate so the return credits both sides and the order's net\n // grand total moves in lockstep with gross (#3036). A genuinely free line\n // (gross = 0, e.g. a 100% discount / comp) keeps net 0, so the return is not\n // over-credited at the discount-ignoring unit price (#3521).\n const lineTotalNet = deriveLineNetFromGross(line.totalNetAmount, line.totalGrossAmount, line.taxRate)\n const unitNet = lineQuantity > 0 ? lineTotalNet / lineQuantity : toNumeric(line.unitPriceNet)\n const unitGross = lineQuantity > 0 ? toNumeric(line.totalGrossAmount) / lineQuantity : toNumeric(line.unitPriceGross)\n const totalNet = -round(Math.max(unitNet, 0) * quantity)\n const totalGross = -round(Math.max(unitGross, 0) * quantity)\n\n const returnLineId = randomUUID()\n const returnLine = tx.create(SalesReturnLine, {\n id: returnLineId,\n salesReturn: entity,\n orderLine: tx.getReference(SalesOrderLine, line.id),\n organizationId: input.organizationId,\n tenantId: input.tenantId,\n quantityReturned: quantity.toString(),\n unitPriceNet: round(unitNet).toString(),\n unitPriceGross: round(unitGross).toString(),\n totalNetAmount: totalNet.toString(),\n totalGrossAmount: totalGross.toString(),\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n createdReturnLines.push(returnLine)\n tx.persist(returnLine)\n\n const adjustment = tx.create(SalesOrderAdjustment, {\n id: randomUUID(),\n order,\n orderLine: tx.getReference(SalesOrderLine, line.id),\n organizationId: input.organizationId,\n tenantId: input.tenantId,\n scope: 'line',\n kind: 'return',\n rate: '0',\n amountNet: totalNet.toString(),\n amountGross: totalGross.toString(),\n currencyCode: order.currencyCode,\n metadata: { returnId, returnLineId },\n position: positionStart + index,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n createdAdjustments.push(adjustment)\n tx.persist(adjustment)\n\n line.returnedQuantity = (toNumeric(line.returnedQuantity) + quantity).toString()\n line.updatedAt = new Date()\n tx.persist(line)\n })\n\n const lineSnapshots: SalesLineSnapshot[] = orderLines.map(mapOrderLineEntityToSnapshot)\n const adjustmentDrafts: SalesAdjustmentDraft[] = [...existingAdjustments, ...createdAdjustments].map(mapOrderAdjustmentToDraft)\n const calculation = await salesCalculationService.calculateDocumentTotals({\n documentKind: 'order',\n lines: lineSnapshots,\n adjustments: adjustmentDrafts,\n context: buildCalculationContext(order),\n existingTotals: resolveExistingPaymentTotals(order),\n ...resolveOrderCalculationMode(order),\n })\n applyOrderTotalsUnlessExternal(order, calculation)\n order.updatedAt = new Date()\n tx.persist(order)\n\n await tx.flush()\n\n return { header: entity, createdLines: createdReturnLines, order }\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: header,\n identifiers: { id: header.id, organizationId: header.organizationId, tenantId: header.tenantId },\n indexer: { entityType: E.sales.sales_return },\n events: returnCrudEvents,\n })\n\n if (createdLines.length) {\n await Promise.all(\n createdLines.map((line) =>\n emitCrudSideEffects({\n dataEngine,\n action: 'created',\n entity: line,\n identifiers: { id: line.id, organizationId: line.organizationId, tenantId: line.tenantId },\n indexer: { entityType: E.sales.sales_return_line },\n }),\n ),\n )\n }\n\n return { returnId: header.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return loadReturnSnapshot(em, result.returnId)\n },\n buildLog: async ({ result, snapshots }) => {\n const after = snapshots.after as ReturnSnapshot | undefined\n if (!after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('sales.audit.returns.create', 'Create return'),\n resourceKind: 'sales.return',\n resourceId: result.returnId,\n parentResourceKind: 'sales.order',\n parentResourceId: after.orderId ?? null,\n tenantId: after.tenantId,\n organizationId: after.organizationId,\n snapshotAfter: after,\n payload: {\n undo: { after } satisfies ReturnUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<ReturnUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const salesCalculationService = ctx.container.resolve<SalesCalculationService>('salesCalculationService')\n await reverseReturnEffects(em, salesCalculationService, after)\n await invalidateOrderCache(ctx.container, {\n id: after.orderId,\n organizationId: after.organizationId,\n tenantId: after.tenantId,\n }, ctx.auth?.tenantId ?? null)\n },\n redo: async ({ ctx, logEntry }) => {\n const after = resolveRedoSnapshot<ReturnSnapshot>(logEntry)\n if (!after || !after.id) {\n throw new CrudHttpError(400, { error: '[internal] redo snapshot unavailable for sales.returns.create' })\n }\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const salesCalculationService = ctx.container.resolve<SalesCalculationService>('salesCalculationService')\n\n const createdLines = await restoreReturnEffects(em, salesCalculationService, after)\n\n const header = await findOneWithDecryption(\n em,\n SalesReturn,\n { id: after.id, deletedAt: null },\n {},\n { tenantId: after.tenantId, organizationId: after.organizationId },\n )\n if (!header) {\n const { translate } = await resolveTranslations()\n throw notFound(translate('sales.returns.orderMissing', 'Order not found.'))\n }\n\n await invalidateOrderCache(ctx.container, {\n id: after.orderId,\n organizationId: after.organizationId,\n tenantId: after.tenantId,\n }, ctx.auth?.tenantId ?? null)\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'created',\n entity: header,\n identifiers: { id: header.id, organizationId: header.organizationId, tenantId: header.tenantId },\n indexer: { entityType: E.sales.sales_return },\n events: returnCrudEvents,\n })\n\n if (createdLines.length) {\n await Promise.all(\n createdLines.map((line) =>\n emitCrudSideEffects({\n dataEngine,\n action: 'created',\n entity: line,\n identifiers: { id: line.id, organizationId: line.organizationId, tenantId: line.tenantId },\n indexer: { entityType: E.sales.sales_return_line },\n }),\n ),\n )\n }\n\n return { returnId: header.id }\n },\n}\n\nconst updateReturnCommand: CommandHandler<ReturnUpdateInput, { returnId: string }> = {\n id: 'sales.returns.update',\n async prepare(rawInput, ctx) {\n const parsed = returnUpdateSchema.parse(rawInput ?? {})\n const em = ctx.container.resolve('em') as EntityManager\n const snapshot = await loadReturnHeaderSnapshot(em, parsed.id)\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 = returnUpdateSchema.parse(rawInput ?? {})\n ensureTenantScope(ctx, input.tenantId)\n ensureOrganizationScope(ctx, input.organizationId)\n const { translate } = await resolveTranslations()\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n\n const header = await em.transactional(async (tx) => {\n const entity = await findOneWithDecryption(\n tx,\n SalesReturn,\n { id: input.id, deletedAt: null },\n { populate: ['order'] },\n { tenantId: input.tenantId, organizationId: input.organizationId },\n )\n if (!entity || !entity.order) {\n throw notFound(translate('sales.returns.notFound', 'Return not found.'))\n }\n ensureSameScope(entity, input.organizationId, input.tenantId)\n const orderId = typeof entity.order === 'string' ? entity.order : entity.order.id\n if (input.orderId !== orderId) {\n throw new CrudHttpError(400, { error: translate('sales.returns.orderMismatch', 'Return does not belong to this order.') })\n }\n // Lock on the return's own version \u2014 editing header fields (reason / notes /\n // returnedAt) only touches the return, not the order totals.\n await enforceSalesDocumentOptimisticLock(ctx, entity, SALES_RESOURCE_KIND_RETURN)\n\n if (input.reason !== undefined) entity.reason = input.reason.length ? input.reason : null\n if (input.notes !== undefined) entity.notes = input.notes.length ? input.notes : null\n if (input.returnedAt !== undefined) entity.returnedAt = input.returnedAt ?? null\n entity.updatedAt = new Date()\n tx.persist(entity)\n await tx.flush()\n return entity\n })\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'updated',\n entity: header,\n identifiers: { id: header.id, organizationId: header.organizationId, tenantId: header.tenantId },\n indexer: { entityType: E.sales.sales_return },\n events: returnCrudEvents,\n })\n\n return { returnId: header.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return loadReturnHeaderSnapshot(em, result.returnId)\n },\n buildLog: async ({ snapshots, result }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as ReturnHeaderSnapshot | undefined\n const after = snapshots.after as ReturnHeaderSnapshot | undefined\n return {\n actionLabel: translate('sales.audit.returns.update', 'Update return'),\n resourceKind: 'sales.return',\n resourceId: result.returnId,\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: {\n undo: { before, after } satisfies ReturnHeaderUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<ReturnHeaderUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n await em.transactional(async (tx) => {\n const entity = await findOneWithDecryption(\n tx,\n SalesReturn,\n { id: before.id, deletedAt: null },\n {},\n { tenantId: before.tenantId, organizationId: before.organizationId },\n )\n if (!entity) return\n entity.reason = before.reason\n entity.notes = before.notes\n entity.returnedAt = before.returnedAt ? new Date(before.returnedAt) : null\n entity.updatedAt = new Date()\n tx.persist(entity)\n await tx.flush()\n })\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n const restored = await findOneWithDecryption(\n em,\n SalesReturn,\n { id: before.id, deletedAt: null },\n {},\n { tenantId: before.tenantId, organizationId: before.organizationId },\n )\n if (restored) {\n await emitCrudSideEffects({\n dataEngine,\n action: 'updated',\n entity: restored,\n identifiers: { id: restored.id, organizationId: restored.organizationId, tenantId: restored.tenantId },\n indexer: { entityType: E.sales.sales_return },\n events: returnCrudEvents,\n })\n }\n },\n}\n\nconst deleteReturnCommand: CommandHandler<ReturnDeleteInput, { returnId: string }> = {\n id: 'sales.returns.delete',\n async prepare(rawInput, ctx) {\n const parsed = returnDeleteSchema.parse(rawInput ?? {})\n const em = ctx.container.resolve('em') as EntityManager\n const snapshot = await loadReturnSnapshot(em, parsed.id)\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 = returnDeleteSchema.parse(rawInput ?? {})\n ensureTenantScope(ctx, input.tenantId)\n ensureOrganizationScope(ctx, input.organizationId)\n const { translate } = await resolveTranslations()\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const salesCalculationService = ctx.container.resolve<SalesCalculationService>('salesCalculationService')\n\n const snapshot = await loadReturnSnapshot(em, input.id)\n if (!snapshot) {\n throw notFound(translate('sales.returns.notFound', 'Return not found.'))\n }\n ensureSameScope(snapshot, input.organizationId, input.tenantId)\n if (input.orderId !== snapshot.orderId) {\n throw new CrudHttpError(400, { error: translate('sales.returns.orderMismatch', 'Return does not belong to this order.') })\n }\n\n const header = await findOneWithDecryption(\n em,\n SalesReturn,\n { id: input.id, deletedAt: null },\n {},\n { tenantId: input.tenantId, organizationId: input.organizationId },\n )\n if (!header) {\n throw notFound(translate('sales.returns.notFound', 'Return not found.'))\n }\n ensureSameScope(header, input.organizationId, input.tenantId)\n // Lock on the return's own version, captured before any mutation.\n await enforceSalesDocumentOptimisticLock(ctx, header, SALES_RESOURCE_KIND_RETURN)\n\n await reverseReturnEffects(em, salesCalculationService, snapshot)\n await invalidateOrderCache(ctx.container, {\n id: snapshot.orderId,\n organizationId: snapshot.organizationId,\n tenantId: snapshot.tenantId,\n }, ctx.auth?.tenantId ?? null)\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'deleted',\n entity: header,\n identifiers: { id: snapshot.id, organizationId: snapshot.organizationId, tenantId: snapshot.tenantId },\n indexer: { entityType: E.sales.sales_return },\n events: returnCrudEvents,\n })\n\n if (snapshot.lines.length) {\n await Promise.all(\n snapshot.lines.map((line) =>\n emitCrudSideEffects({\n dataEngine,\n action: 'deleted',\n entity: { id: line.id, organizationId: snapshot.organizationId, tenantId: snapshot.tenantId },\n identifiers: { id: line.id, organizationId: snapshot.organizationId, tenantId: snapshot.tenantId },\n indexer: { entityType: E.sales.sales_return_line },\n }),\n ),\n )\n }\n\n return { returnId: snapshot.id }\n },\n buildLog: async ({ snapshots, result }) => {\n const before = snapshots.before as ReturnSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('sales.audit.returns.delete', 'Delete return'),\n resourceKind: 'sales.return',\n resourceId: result.returnId,\n parentResourceKind: 'sales.order',\n parentResourceId: before.orderId ?? null,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: { before } satisfies ReturnDeleteUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<ReturnDeleteUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const salesCalculationService = ctx.container.resolve<SalesCalculationService>('salesCalculationService')\n\n const createdLines = await restoreReturnEffects(em, salesCalculationService, before)\n\n const header = await findOneWithDecryption(\n em,\n SalesReturn,\n { id: before.id, deletedAt: null },\n {},\n { tenantId: before.tenantId, organizationId: before.organizationId },\n )\n if (!header) return\n\n await invalidateOrderCache(ctx.container, {\n id: before.orderId,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n }, ctx.auth?.tenantId ?? null)\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'created',\n entity: header,\n identifiers: { id: header.id, organizationId: header.organizationId, tenantId: header.tenantId },\n indexer: { entityType: E.sales.sales_return },\n events: returnCrudEvents,\n })\n\n if (createdLines.length) {\n await Promise.all(\n createdLines.map((line) =>\n emitCrudSideEffects({\n dataEngine,\n action: 'created',\n entity: line,\n identifiers: { id: line.id, organizationId: line.organizationId, tenantId: line.tenantId },\n indexer: { entityType: E.sales.sales_return_line },\n }),\n ),\n )\n }\n },\n}\n\nregisterCommand(createReturnCommand)\nregisterCommand(updateReturnCommand)\nregisterCommand(deleteReturnCommand)\n\nexport const returnCommands = [createReturnCommand, updateReturnCommand, deleteReturnCommand]\n"],
5
+ "mappings": "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",
6
6
  "names": ["order"]
7
7
  }
@@ -51,7 +51,8 @@ function SalesDocumentAdjustmentsSection({
51
51
  organizationId: orgFromProps,
52
52
  tenantId: tenantFromProps,
53
53
  onActionChange,
54
- onRowsChange
54
+ onRowsChange,
55
+ amountsReadOnly = false
55
56
  }) {
56
57
  const t = useT();
57
58
  const runDocumentMutation = useSalesDocumentMutation(kind, documentId);
@@ -208,10 +209,14 @@ function SalesDocumentAdjustmentsSection({
208
209
  setActiveAdjustment(null);
209
210
  setDialogOpen(true);
210
211
  }, []);
211
- const handleEdit = React.useCallback((row) => {
212
- setActiveAdjustment(row);
213
- setDialogOpen(true);
214
- }, []);
212
+ const handleEdit = React.useCallback(
213
+ (row) => {
214
+ if (amountsReadOnly) return;
215
+ setActiveAdjustment(row);
216
+ setDialogOpen(true);
217
+ },
218
+ [amountsReadOnly]
219
+ );
215
220
  const handleCloseDialog = React.useCallback(() => {
216
221
  setDialogOpen(false);
217
222
  setActiveAdjustment(null);
@@ -221,10 +226,10 @@ function SalesDocumentAdjustmentsSection({
221
226
  onActionChange({
222
227
  label: t("sales.documents.adjustments.add", "Add adjustment"),
223
228
  onClick: handleOpenCreate,
224
- disabled: false
229
+ disabled: amountsReadOnly
225
230
  });
226
231
  return () => onActionChange(null);
227
- }, [handleOpenCreate, onActionChange, t]);
232
+ }, [amountsReadOnly, handleOpenCreate, onActionChange, t]);
228
233
  const handleFormSubmit = React.useCallback(
229
234
  async (values) => {
230
235
  if (!resolvedOrganizationId || !resolvedTenantId) {
@@ -358,7 +363,7 @@ function SalesDocumentAdjustmentsSection({
358
363
  );
359
364
  const showLoadingState = loading && rows.length === 0;
360
365
  const renderRowActions = React.useCallback(
361
- (row) => /* @__PURE__ */ jsx(
366
+ (row) => amountsReadOnly ? null : /* @__PURE__ */ jsx(
362
367
  RowActions,
363
368
  {
364
369
  items: [
@@ -376,7 +381,7 @@ function SalesDocumentAdjustmentsSection({
376
381
  ]
377
382
  }
378
383
  ),
379
- [handleDelete, handleEdit, t]
384
+ [amountsReadOnly, handleDelete, handleEdit, t]
380
385
  );
381
386
  return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
382
387
  error ? /* @__PURE__ */ jsx(ErrorMessage, { title: t("sales.documents.adjustments.errorLoad", "Failed to load adjustments."), description: error, onRetry: () => void loadAdjustments() }) : null,
@@ -393,7 +398,7 @@ function SalesDocumentAdjustmentsSection({
393
398
  columns,
394
399
  isLoading: loading && rows.length > 0,
395
400
  embedded: true,
396
- onRowClick: handleEdit,
401
+ onRowClick: amountsReadOnly ? void 0 : handleEdit,
397
402
  rowActions: renderRowActions,
398
403
  emptyState: /* @__PURE__ */ jsx(
399
404
  TabEmptyState,
@@ -401,7 +406,8 @@ function SalesDocumentAdjustmentsSection({
401
406
  title: t("sales.documents.empty.adjustments.title", "No adjustments yet."),
402
407
  description: t("sales.documents.empty.adjustments.description", "Add discounts, fees, or taxes to refine totals."),
403
408
  actionLabel: t("sales.documents.adjustments.add", "Add adjustment"),
404
- onAction: handleOpenCreate
409
+ onAction: handleOpenCreate,
410
+ disabled: amountsReadOnly
405
411
  }
406
412
  )
407
413
  }