@open-mercato/core 0.4.8-develop-d16e2f51dc → 0.4.8-develop-4b58cde65d

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 (85) hide show
  1. package/dist/generated/entities/sales_return/index.js +31 -0
  2. package/dist/generated/entities/sales_return/index.js.map +7 -0
  3. package/dist/generated/entities/sales_return_line/index.js +29 -0
  4. package/dist/generated/entities/sales_return_line/index.js.map +7 -0
  5. package/dist/generated/entities.ids.generated.js +2 -0
  6. package/dist/generated/entities.ids.generated.js.map +2 -2
  7. package/dist/generated/entity-fields-registry.js +4 -0
  8. package/dist/generated/entity-fields-registry.js.map +2 -2
  9. package/dist/modules/sales/acl.js +2 -0
  10. package/dist/modules/sales/acl.js.map +2 -2
  11. package/dist/modules/sales/api/document-history/route.js +20 -2
  12. package/dist/modules/sales/api/document-history/route.js.map +2 -2
  13. package/dist/modules/sales/api/documents/factory.js +34 -0
  14. package/dist/modules/sales/api/documents/factory.js.map +2 -2
  15. package/dist/modules/sales/api/returns/[id]/route.js +147 -0
  16. package/dist/modules/sales/api/returns/[id]/route.js.map +7 -0
  17. package/dist/modules/sales/api/returns/route.js +158 -0
  18. package/dist/modules/sales/api/returns/route.js.map +7 -0
  19. package/dist/modules/sales/backend/sales/documents/[id]/page.js +20 -1
  20. package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
  21. package/dist/modules/sales/commands/index.js +1 -0
  22. package/dist/modules/sales/commands/index.js.map +2 -2
  23. package/dist/modules/sales/commands/returns.js +467 -0
  24. package/dist/modules/sales/commands/returns.js.map +7 -0
  25. package/dist/modules/sales/components/documents/ReturnDialog.js +176 -0
  26. package/dist/modules/sales/components/documents/ReturnDialog.js.map +7 -0
  27. package/dist/modules/sales/components/documents/ReturnsSection.js +188 -0
  28. package/dist/modules/sales/components/documents/ReturnsSection.js.map +7 -0
  29. package/dist/modules/sales/data/entities.js +115 -1
  30. package/dist/modules/sales/data/entities.js.map +2 -2
  31. package/dist/modules/sales/data/validators.js +13 -0
  32. package/dist/modules/sales/data/validators.js.map +2 -2
  33. package/dist/modules/sales/events.js +4 -0
  34. package/dist/modules/sales/events.js.map +2 -2
  35. package/dist/modules/sales/lib/calculations.js +7 -0
  36. package/dist/modules/sales/lib/calculations.js.map +2 -2
  37. package/dist/modules/sales/lib/dictionaries.js +1 -0
  38. package/dist/modules/sales/lib/dictionaries.js.map +2 -2
  39. package/dist/modules/sales/lib/documentNumberTokens.js +2 -0
  40. package/dist/modules/sales/lib/documentNumberTokens.js.map +2 -2
  41. package/dist/modules/sales/lib/historyHelpers.js +15 -7
  42. package/dist/modules/sales/lib/historyHelpers.js.map +2 -2
  43. package/dist/modules/sales/lib/makeSalesLineRoute.js +42 -37
  44. package/dist/modules/sales/lib/makeSalesLineRoute.js.map +2 -2
  45. package/dist/modules/sales/migrations/Migration20260309073310.js +23 -0
  46. package/dist/modules/sales/migrations/Migration20260309073310.js.map +7 -0
  47. package/dist/modules/sales/services/salesDocumentNumberGenerator.js +8 -6
  48. package/dist/modules/sales/services/salesDocumentNumberGenerator.js.map +2 -2
  49. package/dist/modules/sales/setup.js +1 -1
  50. package/dist/modules/sales/setup.js.map +2 -2
  51. package/dist/modules/sales/widgets/injection/document-history/widget.client.js +25 -16
  52. package/dist/modules/sales/widgets/injection/document-history/widget.client.js.map +2 -2
  53. package/generated/entities/sales_return/index.ts +14 -0
  54. package/generated/entities/sales_return_line/index.ts +13 -0
  55. package/generated/entities.ids.generated.ts +2 -0
  56. package/generated/entity-fields-registry.ts +4 -0
  57. package/package.json +3 -3
  58. package/src/modules/sales/AGENTS.md +1 -0
  59. package/src/modules/sales/acl.ts +2 -0
  60. package/src/modules/sales/api/document-history/route.ts +25 -1
  61. package/src/modules/sales/api/documents/factory.ts +35 -0
  62. package/src/modules/sales/api/returns/[id]/route.ts +156 -0
  63. package/src/modules/sales/api/returns/route.ts +171 -0
  64. package/src/modules/sales/backend/sales/documents/[id]/page.tsx +18 -0
  65. package/src/modules/sales/commands/index.ts +1 -0
  66. package/src/modules/sales/commands/returns.ts +540 -0
  67. package/src/modules/sales/components/documents/ReturnDialog.tsx +216 -0
  68. package/src/modules/sales/components/documents/ReturnsSection.tsx +270 -0
  69. package/src/modules/sales/data/entities.ts +99 -3
  70. package/src/modules/sales/data/validators.ts +16 -0
  71. package/src/modules/sales/events.ts +5 -0
  72. package/src/modules/sales/i18n/de.json +32 -0
  73. package/src/modules/sales/i18n/en.json +32 -0
  74. package/src/modules/sales/i18n/es.json +32 -0
  75. package/src/modules/sales/i18n/pl.json +32 -0
  76. package/src/modules/sales/lib/calculations.ts +9 -0
  77. package/src/modules/sales/lib/dictionaries.ts +1 -0
  78. package/src/modules/sales/lib/documentNumberTokens.ts +2 -1
  79. package/src/modules/sales/lib/historyHelpers.ts +20 -9
  80. package/src/modules/sales/lib/makeSalesLineRoute.ts +42 -37
  81. package/src/modules/sales/migrations/.snapshot-open-mercato.json +398 -0
  82. package/src/modules/sales/migrations/Migration20260309073310.ts +26 -0
  83. package/src/modules/sales/services/salesDocumentNumberGenerator.ts +15 -4
  84. package/src/modules/sales/setup.ts +1 -1
  85. package/src/modules/sales/widgets/injection/document-history/widget.client.tsx +26 -17
@@ -7,4 +7,5 @@ import "./documentAddresses.js";
7
7
  import "./shipments.js";
8
8
  import "./payments.js";
9
9
  import "./notes.js";
10
+ import "./returns.js";
10
11
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/sales/commands/index.ts"],
4
- "sourcesContent": ["import './configuration'\nimport './documents'\nimport './statuses'\nimport './settings'\nimport './tags'\nimport './documentAddresses'\nimport './shipments'\nimport './payments'\nimport './notes'\n"],
5
- "mappings": "AAAA,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;",
4
+ "sourcesContent": ["import './configuration'\nimport './documents'\nimport './statuses'\nimport './settings'\nimport './tags'\nimport './documentAddresses'\nimport './shipments'\nimport './payments'\nimport './notes'\nimport './returns'\n"],
5
+ "mappings": "AAAA,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,467 @@
1
+ import { randomUUID } from "crypto";
2
+ import { registerCommand } from "@open-mercato/shared/lib/commands";
3
+ import { CrudHttpError } from "@open-mercato/shared/lib/crud/errors";
4
+ import { resolveTranslations } from "@open-mercato/shared/lib/i18n/server";
5
+ import { emitCrudSideEffects } from "@open-mercato/shared/lib/commands/helpers";
6
+ import { findOneWithDecryption, findWithDecryption } from "@open-mercato/shared/lib/encryption/find";
7
+ import { SalesDocumentNumberGenerator } from "../services/salesDocumentNumberGenerator.js";
8
+ import { cloneJson, ensureOrganizationScope, ensureSameScope, ensureTenantScope, extractUndoPayload, toNumericString } from "./shared.js";
9
+ import { SalesOrder, SalesOrderAdjustment, SalesOrderLine, SalesReturn, SalesReturnLine } from "../data/entities.js";
10
+ import { returnCreateSchema } from "../data/validators.js";
11
+ import { E } from "../../../generated/entities.ids.generated.js";
12
+ const returnCrudEvents = {
13
+ module: "sales",
14
+ entity: "return",
15
+ persistent: true,
16
+ buildPayload: (ctx) => ({
17
+ id: ctx.identifiers.id,
18
+ organizationId: ctx.identifiers.organizationId,
19
+ tenantId: ctx.identifiers.tenantId
20
+ })
21
+ };
22
+ function toNumeric(value) {
23
+ if (typeof value === "number" && Number.isFinite(value)) return value;
24
+ if (typeof value === "string" && value.trim().length) {
25
+ const parsed = Number(value);
26
+ if (Number.isFinite(parsed)) return parsed;
27
+ }
28
+ return 0;
29
+ }
30
+ function round(value) {
31
+ return Math.round((value + Number.EPSILON) * 1e4) / 1e4;
32
+ }
33
+ function applyOrderTotals(order, totals, lineCount) {
34
+ order.subtotalNetAmount = toNumericString(totals.subtotalNetAmount) ?? "0";
35
+ order.subtotalGrossAmount = toNumericString(totals.subtotalGrossAmount) ?? "0";
36
+ order.discountTotalAmount = toNumericString(totals.discountTotalAmount) ?? "0";
37
+ order.taxTotalAmount = toNumericString(totals.taxTotalAmount) ?? "0";
38
+ order.shippingNetAmount = toNumericString(totals.shippingNetAmount) ?? "0";
39
+ order.shippingGrossAmount = toNumericString(totals.shippingGrossAmount) ?? "0";
40
+ order.surchargeTotalAmount = toNumericString(totals.surchargeTotalAmount) ?? "0";
41
+ order.grandTotalNetAmount = toNumericString(totals.grandTotalNetAmount) ?? "0";
42
+ order.grandTotalGrossAmount = toNumericString(totals.grandTotalGrossAmount) ?? "0";
43
+ order.paidTotalAmount = toNumericString(totals.paidTotalAmount) ?? "0";
44
+ order.refundedTotalAmount = toNumericString(totals.refundedTotalAmount) ?? "0";
45
+ order.outstandingAmount = toNumericString(totals.outstandingAmount) ?? "0";
46
+ order.totalsSnapshot = cloneJson(totals);
47
+ order.lineItemCount = lineCount;
48
+ }
49
+ function mapOrderLineEntityToSnapshot(line) {
50
+ return {
51
+ id: line.id,
52
+ lineNumber: line.lineNumber,
53
+ kind: line.kind,
54
+ productId: line.productId ?? null,
55
+ productVariantId: line.productVariantId ?? null,
56
+ name: line.name ?? null,
57
+ description: line.description ?? null,
58
+ comment: line.comment ?? null,
59
+ quantity: toNumeric(line.quantity),
60
+ quantityUnit: line.quantityUnit ?? null,
61
+ normalizedQuantity: toNumeric(line.normalizedQuantity ?? line.quantity),
62
+ normalizedUnit: line.normalizedUnit ?? line.quantityUnit ?? null,
63
+ uomSnapshot: line.uomSnapshot ? cloneJson(line.uomSnapshot) : null,
64
+ currencyCode: line.currencyCode,
65
+ unitPriceNet: toNumeric(line.unitPriceNet),
66
+ unitPriceGross: toNumeric(line.unitPriceGross),
67
+ discountAmount: toNumeric(line.discountAmount),
68
+ discountPercent: toNumeric(line.discountPercent),
69
+ taxRate: toNumeric(line.taxRate),
70
+ taxAmount: toNumeric(line.taxAmount),
71
+ totalNetAmount: toNumeric(line.totalNetAmount),
72
+ totalGrossAmount: toNumeric(line.totalGrossAmount),
73
+ configuration: line.configuration ? cloneJson(line.configuration) : null,
74
+ promotionCode: line.promotionCode ?? null,
75
+ metadata: line.metadata ? cloneJson(line.metadata) : null,
76
+ customFieldSetId: line.customFieldSetId ?? null
77
+ };
78
+ }
79
+ function mapOrderAdjustmentToDraft(adjustment) {
80
+ return {
81
+ id: adjustment.id,
82
+ scope: adjustment.scope ?? "order",
83
+ kind: adjustment.kind,
84
+ code: adjustment.code ?? null,
85
+ label: adjustment.label ?? null,
86
+ calculatorKey: adjustment.calculatorKey ?? null,
87
+ promotionId: adjustment.promotionId ?? null,
88
+ rate: toNumeric(adjustment.rate),
89
+ amountNet: toNumeric(adjustment.amountNet),
90
+ amountGross: toNumeric(adjustment.amountGross),
91
+ currencyCode: adjustment.currencyCode ?? null,
92
+ metadata: adjustment.metadata ? cloneJson(adjustment.metadata) : null,
93
+ position: adjustment.position ?? 0
94
+ };
95
+ }
96
+ function buildCalculationContext(order) {
97
+ return {
98
+ tenantId: order.tenantId,
99
+ organizationId: order.organizationId,
100
+ currencyCode: order.currencyCode,
101
+ metadata: {
102
+ shippingMethod: order.shippingMethodSnapshot ? cloneJson(order.shippingMethodSnapshot) : null,
103
+ paymentMethod: order.paymentMethodSnapshot ? cloneJson(order.paymentMethodSnapshot) : null
104
+ }
105
+ };
106
+ }
107
+ async function recalculateOrderTotalsForDisplay(em, container, orderId, scope) {
108
+ const order = await findOneWithDecryption(
109
+ em,
110
+ SalesOrder,
111
+ { id: orderId, deletedAt: null },
112
+ {},
113
+ scope
114
+ );
115
+ if (!order) return null;
116
+ const [orderLines, adjustments] = await Promise.all([
117
+ findWithDecryption(em, SalesOrderLine, { order: order.id, deletedAt: null }, {}, scope),
118
+ findWithDecryption(
119
+ em,
120
+ SalesOrderAdjustment,
121
+ { order: order.id, deletedAt: null },
122
+ { orderBy: { position: "asc" } },
123
+ scope
124
+ )
125
+ ]);
126
+ const lineSnapshots = orderLines.map(mapOrderLineEntityToSnapshot);
127
+ const adjustmentDrafts = adjustments.map(mapOrderAdjustmentToDraft);
128
+ const salesCalculationService = container.resolve("salesCalculationService");
129
+ const calculation = await salesCalculationService.calculateDocumentTotals({
130
+ documentKind: "order",
131
+ lines: lineSnapshots,
132
+ adjustments: adjustmentDrafts,
133
+ context: buildCalculationContext(order),
134
+ existingTotals: {
135
+ paidTotalAmount: toNumeric(order.paidTotalAmount),
136
+ refundedTotalAmount: toNumeric(order.refundedTotalAmount)
137
+ }
138
+ });
139
+ return calculation.totals;
140
+ }
141
+ async function loadReturnSnapshot(em, id) {
142
+ const header = await findOneWithDecryption(
143
+ em,
144
+ SalesReturn,
145
+ { id, deletedAt: null },
146
+ { populate: ["order"] },
147
+ {}
148
+ );
149
+ if (!header || !header.order) return null;
150
+ const orderId = typeof header.order === "string" ? header.order : header.order.id;
151
+ const lines = await findWithDecryption(
152
+ em,
153
+ SalesReturnLine,
154
+ { salesReturn: header.id, deletedAt: null },
155
+ { populate: ["orderLine"] },
156
+ { tenantId: header.tenantId, organizationId: header.organizationId }
157
+ );
158
+ const adjustmentIds = [];
159
+ const adjustments = await findWithDecryption(
160
+ em,
161
+ SalesOrderAdjustment,
162
+ { order: orderId, kind: "return", deletedAt: null },
163
+ {},
164
+ { tenantId: header.tenantId, organizationId: header.organizationId }
165
+ );
166
+ adjustments.forEach((adj) => {
167
+ const meta = adj.metadata;
168
+ if (meta && meta.returnId === header.id) adjustmentIds.push(adj.id);
169
+ });
170
+ return {
171
+ id: header.id,
172
+ orderId,
173
+ organizationId: header.organizationId,
174
+ tenantId: header.tenantId,
175
+ returnNumber: header.returnNumber,
176
+ returnedAt: header.returnedAt ? header.returnedAt.toISOString() : null,
177
+ reason: header.reason ?? null,
178
+ notes: header.notes ?? null,
179
+ lines: lines.map((line) => ({
180
+ id: line.id,
181
+ orderLineId: typeof line.orderLine === "string" ? line.orderLine : line.orderLine?.id ?? null,
182
+ quantityReturned: toNumeric(line.quantityReturned),
183
+ unitPriceNet: toNumeric(line.unitPriceNet),
184
+ unitPriceGross: toNumeric(line.unitPriceGross),
185
+ totalNetAmount: toNumeric(line.totalNetAmount),
186
+ totalGrossAmount: toNumeric(line.totalGrossAmount)
187
+ })),
188
+ adjustmentIds
189
+ };
190
+ }
191
+ function normalizeLinesInput(lines) {
192
+ const seen = /* @__PURE__ */ new Set();
193
+ const result = [];
194
+ for (const line of lines) {
195
+ const orderLineId = line.orderLineId;
196
+ if (!orderLineId || seen.has(orderLineId)) continue;
197
+ const quantity = toNumeric(line.quantity);
198
+ if (!Number.isFinite(quantity) || quantity <= 0) continue;
199
+ seen.add(orderLineId);
200
+ result.push({ orderLineId, quantity });
201
+ }
202
+ return result;
203
+ }
204
+ const createReturnCommand = {
205
+ id: "sales.returns.create",
206
+ async execute(rawInput, ctx) {
207
+ const input = returnCreateSchema.parse(rawInput ?? {});
208
+ ensureTenantScope(ctx, input.tenantId);
209
+ ensureOrganizationScope(ctx, input.organizationId);
210
+ const { translate } = await resolveTranslations();
211
+ const em = ctx.container.resolve("em").fork();
212
+ const order = await findOneWithDecryption(
213
+ em,
214
+ SalesOrder,
215
+ { id: input.orderId, deletedAt: null },
216
+ {},
217
+ { tenantId: input.tenantId, organizationId: input.organizationId }
218
+ );
219
+ if (!order) {
220
+ throw new CrudHttpError(404, { error: translate("sales.returns.orderMissing", "Order not found.") });
221
+ }
222
+ ensureSameScope(order, input.organizationId, input.tenantId);
223
+ const requested = normalizeLinesInput(input.lines);
224
+ if (!requested.length) {
225
+ throw new CrudHttpError(400, { error: translate("sales.returns.linesRequired", "Select at least one line to return.") });
226
+ }
227
+ const orderLines = await findWithDecryption(
228
+ em,
229
+ SalesOrderLine,
230
+ { order: order.id, deletedAt: null },
231
+ {},
232
+ { tenantId: input.tenantId, organizationId: input.organizationId }
233
+ );
234
+ const lineMap = new Map(orderLines.map((line) => [line.id, line]));
235
+ requested.forEach(({ orderLineId, quantity }) => {
236
+ const line = lineMap.get(orderLineId);
237
+ if (!line) {
238
+ throw new CrudHttpError(404, { error: translate("sales.returns.lineMissing", "Order line not found.") });
239
+ }
240
+ const available = toNumeric(line.quantity) - toNumeric(line.returnedQuantity);
241
+ if (quantity - 1e-6 > available) {
242
+ throw new CrudHttpError(400, { error: translate("sales.returns.quantityExceeded", "Cannot return more than the remaining quantity.") });
243
+ }
244
+ });
245
+ const existingAdjustments = await findWithDecryption(
246
+ em,
247
+ SalesOrderAdjustment,
248
+ { order: order.id, deletedAt: null },
249
+ { orderBy: { position: "asc" } },
250
+ { tenantId: input.tenantId, organizationId: input.organizationId }
251
+ );
252
+ const positionStart = existingAdjustments.reduce((acc, adj) => Math.max(acc, adj.position ?? 0), 0) + 1;
253
+ const numberGenerator = new SalesDocumentNumberGenerator(em);
254
+ const generated = await numberGenerator.generate({
255
+ kind: "return",
256
+ tenantId: input.tenantId,
257
+ organizationId: input.organizationId
258
+ });
259
+ const returnId = randomUUID();
260
+ const header = em.create(SalesReturn, {
261
+ id: returnId,
262
+ order,
263
+ organizationId: input.organizationId,
264
+ tenantId: input.tenantId,
265
+ returnNumber: generated.number,
266
+ reason: input.reason ?? null,
267
+ notes: input.notes ?? null,
268
+ returnedAt: input.returnedAt ?? /* @__PURE__ */ new Date(),
269
+ createdAt: /* @__PURE__ */ new Date(),
270
+ updatedAt: /* @__PURE__ */ new Date()
271
+ });
272
+ em.persist(header);
273
+ const createdAdjustments = [];
274
+ const createdLines = [];
275
+ requested.forEach((lineInput, index) => {
276
+ const line = lineMap.get(lineInput.orderLineId);
277
+ if (!line) return;
278
+ const quantity = lineInput.quantity;
279
+ const lineQuantity = Math.max(toNumeric(line.quantity), 0);
280
+ const unitNet = lineQuantity > 0 ? toNumeric(line.totalNetAmount) / lineQuantity : toNumeric(line.unitPriceNet);
281
+ const unitGross = lineQuantity > 0 ? toNumeric(line.totalGrossAmount) / lineQuantity : toNumeric(line.unitPriceGross);
282
+ const totalNet = -round(Math.max(unitNet, 0) * quantity);
283
+ const totalGross = -round(Math.max(unitGross, 0) * quantity);
284
+ const returnLineId = randomUUID();
285
+ const returnLine = em.create(SalesReturnLine, {
286
+ id: returnLineId,
287
+ salesReturn: header,
288
+ orderLine: em.getReference(SalesOrderLine, line.id),
289
+ organizationId: input.organizationId,
290
+ tenantId: input.tenantId,
291
+ quantityReturned: quantity.toString(),
292
+ unitPriceNet: round(unitNet).toString(),
293
+ unitPriceGross: round(unitGross).toString(),
294
+ totalNetAmount: totalNet.toString(),
295
+ totalGrossAmount: totalGross.toString(),
296
+ createdAt: /* @__PURE__ */ new Date(),
297
+ updatedAt: /* @__PURE__ */ new Date()
298
+ });
299
+ createdLines.push(returnLine);
300
+ em.persist(returnLine);
301
+ const adjustment = em.create(SalesOrderAdjustment, {
302
+ id: randomUUID(),
303
+ order,
304
+ orderLine: em.getReference(SalesOrderLine, line.id),
305
+ organizationId: input.organizationId,
306
+ tenantId: input.tenantId,
307
+ scope: "line",
308
+ kind: "return",
309
+ rate: "0",
310
+ amountNet: totalNet.toString(),
311
+ amountGross: totalGross.toString(),
312
+ currencyCode: order.currencyCode,
313
+ metadata: { returnId, returnLineId },
314
+ position: positionStart + index,
315
+ createdAt: /* @__PURE__ */ new Date(),
316
+ updatedAt: /* @__PURE__ */ new Date()
317
+ });
318
+ createdAdjustments.push(adjustment);
319
+ em.persist(adjustment);
320
+ line.returnedQuantity = (toNumeric(line.returnedQuantity) + quantity).toString();
321
+ line.updatedAt = /* @__PURE__ */ new Date();
322
+ em.persist(line);
323
+ });
324
+ const salesCalculationService = ctx.container.resolve("salesCalculationService");
325
+ const lineSnapshots = orderLines.map(mapOrderLineEntityToSnapshot);
326
+ const adjustmentDrafts = [...existingAdjustments, ...createdAdjustments].map(mapOrderAdjustmentToDraft);
327
+ const calculation = await salesCalculationService.calculateDocumentTotals({
328
+ documentKind: "order",
329
+ lines: lineSnapshots,
330
+ adjustments: adjustmentDrafts,
331
+ context: buildCalculationContext(order)
332
+ });
333
+ applyOrderTotals(order, calculation.totals, calculation.lines.length);
334
+ order.updatedAt = /* @__PURE__ */ new Date();
335
+ em.persist(order);
336
+ await em.flush();
337
+ const dataEngine = ctx.container.resolve("dataEngine");
338
+ await emitCrudSideEffects({
339
+ dataEngine,
340
+ action: "created",
341
+ entity: header,
342
+ identifiers: { id: header.id, organizationId: header.organizationId, tenantId: header.tenantId },
343
+ indexer: { entityType: E.sales.sales_return },
344
+ events: returnCrudEvents
345
+ });
346
+ if (createdLines.length) {
347
+ await Promise.all(
348
+ createdLines.map(
349
+ (line) => emitCrudSideEffects({
350
+ dataEngine,
351
+ action: "created",
352
+ entity: line,
353
+ identifiers: { id: line.id, organizationId: line.organizationId, tenantId: line.tenantId },
354
+ indexer: { entityType: E.sales.sales_return_line }
355
+ })
356
+ )
357
+ );
358
+ }
359
+ return { returnId };
360
+ },
361
+ captureAfter: async (_input, result, ctx) => {
362
+ const em = ctx.container.resolve("em").fork();
363
+ return loadReturnSnapshot(em, result.returnId);
364
+ },
365
+ buildLog: async ({ result, snapshots }) => {
366
+ const after = snapshots.after;
367
+ if (!after) return null;
368
+ const { translate } = await resolveTranslations();
369
+ return {
370
+ actionLabel: translate("sales.audit.returns.create", "Create return"),
371
+ resourceKind: "sales.return",
372
+ resourceId: result.returnId,
373
+ parentResourceKind: "sales.order",
374
+ parentResourceId: after.orderId ?? null,
375
+ tenantId: after.tenantId,
376
+ organizationId: after.organizationId,
377
+ snapshotAfter: after,
378
+ payload: {
379
+ undo: { after }
380
+ }
381
+ };
382
+ },
383
+ undo: async ({ logEntry, ctx }) => {
384
+ const payload = extractUndoPayload(logEntry);
385
+ const after = payload?.after;
386
+ if (!after) return;
387
+ const em = ctx.container.resolve("em").fork();
388
+ const order = await findOneWithDecryption(
389
+ em,
390
+ SalesOrder,
391
+ { id: after.orderId, deletedAt: null },
392
+ {},
393
+ { tenantId: after.tenantId, organizationId: after.organizationId }
394
+ );
395
+ if (!order) return;
396
+ const lines = await findWithDecryption(
397
+ em,
398
+ SalesOrderLine,
399
+ { order: order.id, deletedAt: null },
400
+ {},
401
+ { tenantId: after.tenantId, organizationId: after.organizationId }
402
+ );
403
+ const lineMap = new Map(lines.map((line) => [line.id, line]));
404
+ after.lines.forEach((entry) => {
405
+ const line = lineMap.get(entry.orderLineId);
406
+ if (!line) return;
407
+ const next = Math.max(0, toNumeric(line.returnedQuantity) - entry.quantityReturned);
408
+ line.returnedQuantity = next.toString();
409
+ line.updatedAt = /* @__PURE__ */ new Date();
410
+ em.persist(line);
411
+ });
412
+ if (after.adjustmentIds.length) {
413
+ const adjustments = await findWithDecryption(
414
+ em,
415
+ SalesOrderAdjustment,
416
+ { id: { $in: after.adjustmentIds }, deletedAt: null },
417
+ {},
418
+ { tenantId: after.tenantId, organizationId: after.organizationId }
419
+ );
420
+ adjustments.forEach((adj) => em.remove(adj));
421
+ }
422
+ const header = await findOneWithDecryption(
423
+ em,
424
+ SalesReturn,
425
+ { id: after.id, deletedAt: null },
426
+ {},
427
+ { tenantId: after.tenantId, organizationId: after.organizationId }
428
+ );
429
+ const returnLines = await findWithDecryption(
430
+ em,
431
+ SalesReturnLine,
432
+ { salesReturn: after.id, deletedAt: null },
433
+ {},
434
+ { tenantId: after.tenantId, organizationId: after.organizationId }
435
+ );
436
+ returnLines.forEach((line) => em.remove(line));
437
+ if (header) em.remove(header);
438
+ const existingAdjustments = await findWithDecryption(
439
+ em,
440
+ SalesOrderAdjustment,
441
+ { order: order.id, deletedAt: null },
442
+ { orderBy: { position: "asc" } },
443
+ { tenantId: after.tenantId, organizationId: after.organizationId }
444
+ );
445
+ const salesCalculationService = ctx.container.resolve("salesCalculationService");
446
+ const lineSnapshots = lines.map(mapOrderLineEntityToSnapshot);
447
+ const adjustmentDrafts = existingAdjustments.map(mapOrderAdjustmentToDraft);
448
+ const calculation = await salesCalculationService.calculateDocumentTotals({
449
+ documentKind: "order",
450
+ lines: lineSnapshots,
451
+ adjustments: adjustmentDrafts,
452
+ context: buildCalculationContext(order)
453
+ });
454
+ applyOrderTotals(order, calculation.totals, calculation.lines.length);
455
+ order.updatedAt = /* @__PURE__ */ new Date();
456
+ em.persist(order);
457
+ await em.flush();
458
+ }
459
+ };
460
+ registerCommand(createReturnCommand);
461
+ const returnCommands = [createReturnCommand];
462
+ export {
463
+ loadReturnSnapshot,
464
+ recalculateOrderTotalsForDisplay,
465
+ returnCommands
466
+ };
467
+ //# sourceMappingURL=returns.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 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 type { EntityManager } from '@mikro-orm/postgresql'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { 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, ensureOrganizationScope, ensureSameScope, ensureTenantScope, extractUndoPayload, toNumericString } from './shared'\nimport { SalesOrder, SalesOrderAdjustment, SalesOrderLine, SalesReturn, SalesReturnLine } from '../data/entities'\nimport { returnCreateSchema, type ReturnCreateInput } 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\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\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 mapOrderLineEntityToSnapshot(line: SalesOrderLine): SalesLineSnapshot {\n return {\n id: line.id,\n lineNumber: line.lineNumber,\n kind: line.kind,\n productId: line.productId ?? null,\n productVariantId: line.productVariantId ?? null,\n name: line.name ?? null,\n description: line.description ?? null,\n comment: line.comment ?? null,\n quantity: toNumeric(line.quantity),\n quantityUnit: line.quantityUnit ?? null,\n normalizedQuantity: toNumeric(line.normalizedQuantity ?? line.quantity),\n normalizedUnit: line.normalizedUnit ?? line.quantityUnit ?? null,\n uomSnapshot: line.uomSnapshot ? cloneJson(line.uomSnapshot) : null,\n currencyCode: line.currencyCode,\n unitPriceNet: toNumeric(line.unitPriceNet),\n unitPriceGross: toNumeric(line.unitPriceGross),\n discountAmount: toNumeric(line.discountAmount),\n discountPercent: toNumeric(line.discountPercent),\n taxRate: toNumeric(line.taxRate),\n taxAmount: toNumeric(line.taxAmount),\n totalNetAmount: toNumeric(line.totalNetAmount),\n totalGrossAmount: toNumeric(line.totalGrossAmount),\n configuration: line.configuration ? cloneJson(line.configuration) : null,\n promotionCode: line.promotionCode ?? null,\n metadata: line.metadata ? cloneJson(line.metadata) : null,\n customFieldSetId: line.customFieldSetId ?? 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) for display.\n * Returns the totals object to merge into an order API response, or null if order not found.\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: {\n paidTotalAmount: toNumeric(order.paidTotalAmount),\n refundedTotalAmount: toNumeric(order.refundedTotalAmount),\n },\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\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 order = await findOneWithDecryption(\n em,\n SalesOrder,\n { id: input.orderId, deletedAt: null },\n {},\n { tenantId: input.tenantId, organizationId: input.organizationId },\n )\n if (!order) {\n throw new CrudHttpError(404, { error: translate('sales.returns.orderMissing', 'Order not found.') })\n }\n ensureSameScope(order, input.organizationId, input.tenantId)\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 orderLines = await findWithDecryption(\n em,\n SalesOrderLine,\n { order: order.id, deletedAt: null },\n {},\n { tenantId: input.tenantId, organizationId: input.organizationId },\n )\n const lineMap = new Map(orderLines.map((line) => [line.id, line]))\n\n requested.forEach(({ orderLineId, quantity }) => {\n const line = lineMap.get(orderLineId)\n if (!line) {\n throw new CrudHttpError(404, { error: translate('sales.returns.lineMissing', 'Order line not found.') })\n }\n const available = toNumeric(line.quantity) - toNumeric(line.returnedQuantity)\n if (quantity - 1e-6 > available) {\n throw new CrudHttpError(400, { error: translate('sales.returns.quantityExceeded', 'Cannot return more than the remaining quantity.') })\n }\n })\n\n const existingAdjustments = await findWithDecryption(\n em,\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(em)\n const generated = await numberGenerator.generate({\n kind: 'return',\n tenantId: input.tenantId,\n organizationId: input.organizationId,\n })\n const returnId = randomUUID()\n const header = em.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 em.persist(header)\n\n const createdAdjustments: SalesOrderAdjustment[] = []\n const createdLines: 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 const unitNet = lineQuantity > 0 ? toNumeric(line.totalNetAmount) / 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 = em.create(SalesReturnLine, {\n id: returnLineId,\n salesReturn: header,\n orderLine: em.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 createdLines.push(returnLine)\n em.persist(returnLine)\n\n const adjustment = em.create(SalesOrderAdjustment, {\n id: randomUUID(),\n order,\n orderLine: em.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 em.persist(adjustment)\n\n line.returnedQuantity = (toNumeric(line.returnedQuantity) + quantity).toString()\n line.updatedAt = new Date()\n em.persist(line)\n })\n\n const salesCalculationService = ctx.container.resolve<SalesCalculationService>('salesCalculationService')\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 })\n applyOrderTotals(order, calculation.totals, calculation.lines.length)\n order.updatedAt = new Date()\n em.persist(order)\n\n await em.flush()\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'created',\n entity: 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 }\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 order = await findOneWithDecryption(\n em,\n SalesOrder,\n { id: after.orderId, deletedAt: null },\n {},\n { tenantId: after.tenantId, organizationId: after.organizationId },\n )\n if (!order) return\n\n const lines = await findWithDecryption(\n em,\n SalesOrderLine,\n { order: order.id, deletedAt: null },\n {},\n { tenantId: after.tenantId, organizationId: after.organizationId },\n )\n const lineMap = new Map(lines.map((line) => [line.id, line]))\n after.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 if (after.adjustmentIds.length) {\n const adjustments = await findWithDecryption(\n em,\n SalesOrderAdjustment,\n { id: { $in: after.adjustmentIds }, deletedAt: null },\n {},\n { tenantId: after.tenantId, organizationId: after.organizationId },\n )\n adjustments.forEach((adj) => em.remove(adj))\n }\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 const returnLines = await findWithDecryption(\n em,\n SalesReturnLine,\n { salesReturn: after.id, deletedAt: null },\n {},\n { tenantId: after.tenantId, organizationId: after.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: after.tenantId, organizationId: after.organizationId },\n )\n const salesCalculationService = ctx.container.resolve<SalesCalculationService>('salesCalculationService')\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 })\n applyOrderTotals(order, calculation.totals, calculation.lines.length)\n order.updatedAt = new Date()\n em.persist(order)\n\n await em.flush()\n },\n}\n\nregisterCommand(createReturnCommand)\n\nexport const returnCommands = [createReturnCommand]\n\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }