@open-mercato/core 0.4.5-develop-3ce83a8b24 → 0.4.5-develop-539cff4960
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/generated/entities/catalog_product/index.js +16 -0
- package/dist/generated/entities/catalog_product/index.js.map +2 -2
- package/dist/generated/entities/catalog_product_unit_conversion/index.js +27 -0
- package/dist/generated/entities/catalog_product_unit_conversion/index.js.map +7 -0
- package/dist/generated/entities/sales_credit_memo_line/index.js +7 -1
- package/dist/generated/entities/sales_credit_memo_line/index.js.map +2 -2
- package/dist/generated/entities/sales_invoice_line/index.js +7 -1
- package/dist/generated/entities/sales_invoice_line/index.js.map +2 -2
- package/dist/generated/entities/sales_order_line/index.js +6 -0
- package/dist/generated/entities/sales_order_line/index.js.map +2 -2
- package/dist/generated/entities/sales_quote_line/index.js +6 -0
- package/dist/generated/entities/sales_quote_line/index.js.map +2 -2
- package/dist/generated/entities.ids.generated.js +1 -0
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +2 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/catalog/api/prices/route.js +123 -8
- package/dist/modules/catalog/api/prices/route.js.map +2 -2
- package/dist/modules/catalog/api/product-unit-conversions/route.js +194 -0
- package/dist/modules/catalog/api/product-unit-conversions/route.js.map +7 -0
- package/dist/modules/catalog/api/products/route.js +351 -201
- package/dist/modules/catalog/api/products/route.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/[id]/page.js +1267 -497
- package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/create/page.js +733 -210
- package/dist/modules/catalog/backend/catalog/products/create/page.js.map +2 -2
- package/dist/modules/catalog/commands/index.js +1 -0
- package/dist/modules/catalog/commands/index.js.map +2 -2
- package/dist/modules/catalog/commands/productUnitConversions.js +503 -0
- package/dist/modules/catalog/commands/productUnitConversions.js.map +7 -0
- package/dist/modules/catalog/commands/products.js +355 -73
- package/dist/modules/catalog/commands/products.js.map +2 -2
- package/dist/modules/catalog/commands/shared.js +18 -4
- package/dist/modules/catalog/commands/shared.js.map +2 -2
- package/dist/modules/catalog/components/products/ProductUomSection.js +591 -0
- package/dist/modules/catalog/components/products/ProductUomSection.js.map +7 -0
- package/dist/modules/catalog/components/products/productForm.js +66 -5
- package/dist/modules/catalog/components/products/productForm.js.map +2 -2
- package/dist/modules/catalog/components/products/productFormUtils.js +68 -0
- package/dist/modules/catalog/components/products/productFormUtils.js.map +7 -0
- package/dist/modules/catalog/data/entities.js +86 -0
- package/dist/modules/catalog/data/entities.js.map +2 -2
- package/dist/modules/catalog/data/validators.js +65 -3
- package/dist/modules/catalog/data/validators.js.map +2 -2
- package/dist/modules/catalog/events.js +3 -0
- package/dist/modules/catalog/events.js.map +2 -2
- package/dist/modules/catalog/lib/unitCodes.js +7 -0
- package/dist/modules/catalog/lib/unitCodes.js.map +7 -0
- package/dist/modules/catalog/lib/unitResolution.js +53 -0
- package/dist/modules/catalog/lib/unitResolution.js.map +7 -0
- package/dist/modules/catalog/migrations/Migration20260218225422.js +19 -0
- package/dist/modules/catalog/migrations/Migration20260218225422.js.map +7 -0
- package/dist/modules/catalog/migrations/Migration20260219084500.js +27 -0
- package/dist/modules/catalog/migrations/Migration20260219084500.js.map +7 -0
- package/dist/modules/catalog/search.js +69 -1
- package/dist/modules/catalog/search.js.map +2 -2
- package/dist/modules/catalog/seed/examples.js +91 -42
- package/dist/modules/catalog/seed/examples.js.map +2 -2
- package/dist/modules/dashboards/seed/analytics.js +3 -0
- package/dist/modules/dashboards/seed/analytics.js.map +2 -2
- package/dist/modules/sales/api/order-lines/route.js +98 -15
- package/dist/modules/sales/api/order-lines/route.js.map +2 -2
- package/dist/modules/sales/api/quote-lines/route.js +101 -14
- package/dist/modules/sales/api/quote-lines/route.js.map +2 -2
- package/dist/modules/sales/api/quotes/public/[token]/route.js +87 -12
- package/dist/modules/sales/api/quotes/public/[token]/route.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +1424 -260
- package/dist/modules/sales/commands/documents.js.map +3 -3
- package/dist/modules/sales/commands/shared.js +6 -2
- package/dist/modules/sales/commands/shared.js.map +2 -2
- package/dist/modules/sales/components/documents/ItemsSection.js +216 -86
- package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/LineItemDialog.js +913 -241
- package/dist/modules/sales/components/documents/LineItemDialog.js.map +3 -3
- package/dist/modules/sales/components/documents/ShipmentsSection.js +15 -3
- package/dist/modules/sales/components/documents/ShipmentsSection.js.map +2 -2
- package/dist/modules/sales/data/entities.js +59 -3
- package/dist/modules/sales/data/entities.js.map +2 -2
- package/dist/modules/sales/data/validators.js +35 -0
- package/dist/modules/sales/data/validators.js.map +2 -2
- package/dist/modules/sales/frontend/quote/[token]/page.js +15 -1
- package/dist/modules/sales/frontend/quote/[token]/page.js.map +2 -2
- package/dist/modules/sales/migrations/Migration20260218225423.js +31 -0
- package/dist/modules/sales/migrations/Migration20260218225423.js.map +7 -0
- package/dist/modules/sales/migrations/Migration20260219084501.js +71 -0
- package/dist/modules/sales/migrations/Migration20260219084501.js.map +7 -0
- package/dist/modules/sales/search.js +28 -0
- package/dist/modules/sales/search.js.map +2 -2
- package/dist/modules/sales/seed/examples.js +14 -1
- package/dist/modules/sales/seed/examples.js.map +2 -2
- package/dist/modules/sales/widgets/injection/document-history/widget.client.js +1 -1
- package/dist/modules/sales/widgets/injection/document-history/widget.client.js.map +2 -2
- package/dist/modules/staff/backend/staff/team-members/[id]/page.js +28 -15
- package/dist/modules/staff/backend/staff/team-members/[id]/page.js.map +2 -2
- package/dist/modules/staff/translations.js +9 -0
- package/dist/modules/staff/translations.js.map +7 -0
- package/dist/modules/translations/components/TranslationDrawerAction.js +97 -0
- package/dist/modules/translations/components/TranslationDrawerAction.js.map +7 -0
- package/dist/modules/translations/lib/extract-record-id.js +31 -2
- package/dist/modules/translations/lib/extract-record-id.js.map +2 -2
- package/dist/modules/translations/lib/resolve-field-list.js +3 -0
- package/dist/modules/translations/lib/resolve-field-list.js.map +2 -2
- package/dist/modules/translations/widgets/injection/translation-manager/widget.client.js +105 -36
- package/dist/modules/translations/widgets/injection/translation-manager/widget.client.js.map +2 -2
- package/dist/modules/translations/widgets/injection-table.js +18 -29
- package/dist/modules/translations/widgets/injection-table.js.map +2 -2
- package/generated/entities/catalog_product/index.ts +8 -0
- package/generated/entities/catalog_product_unit_conversion/index.ts +12 -0
- package/generated/entities/sales_credit_memo_line/index.ts +3 -0
- package/generated/entities/sales_invoice_line/index.ts +3 -0
- package/generated/entities/sales_order_line/index.ts +3 -0
- package/generated/entities/sales_quote_line/index.ts +3 -0
- package/generated/entities.ids.generated.ts +1 -0
- package/generated/entity-fields-registry.ts +2 -0
- package/package.json +2 -2
- package/src/modules/auth/i18n/de.json +1 -1
- package/src/modules/auth/i18n/en.json +1 -1
- package/src/modules/auth/i18n/es.json +1 -1
- package/src/modules/auth/i18n/pl.json +1 -1
- package/src/modules/catalog/api/prices/route.ts +213 -81
- package/src/modules/catalog/api/product-unit-conversions/route.ts +195 -0
- package/src/modules/catalog/api/products/route.ts +638 -402
- package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +2085 -1072
- package/src/modules/catalog/backend/catalog/products/create/page.tsx +1288 -593
- package/src/modules/catalog/commands/index.ts +1 -0
- package/src/modules/catalog/commands/productUnitConversions.ts +626 -0
- package/src/modules/catalog/commands/products.ts +1151 -693
- package/src/modules/catalog/commands/shared.ts +19 -5
- package/src/modules/catalog/components/products/ProductUomSection.tsx +745 -0
- package/src/modules/catalog/components/products/productForm.ts +369 -256
- package/src/modules/catalog/components/products/productFormUtils.ts +82 -0
- package/src/modules/catalog/data/entities.ts +82 -1
- package/src/modules/catalog/data/validators.ts +118 -34
- package/src/modules/catalog/events.ts +3 -0
- package/src/modules/catalog/i18n/de.json +56 -0
- package/src/modules/catalog/i18n/en.json +56 -0
- package/src/modules/catalog/i18n/es.json +56 -0
- package/src/modules/catalog/i18n/pl.json +56 -0
- package/src/modules/catalog/lib/unitCodes.ts +1 -0
- package/src/modules/catalog/lib/unitResolution.ts +62 -0
- package/src/modules/catalog/migrations/.snapshot-open-mercato.json +245 -0
- package/src/modules/catalog/migrations/Migration20260218225422.ts +21 -0
- package/src/modules/catalog/migrations/Migration20260219084500.ts +26 -0
- package/src/modules/catalog/search.ts +73 -1
- package/src/modules/catalog/seed/examples.ts +552 -479
- package/src/modules/dashboards/i18n/de.json +1 -1
- package/src/modules/dashboards/i18n/en.json +1 -1
- package/src/modules/dashboards/i18n/es.json +1 -1
- package/src/modules/dashboards/i18n/pl.json +1 -1
- package/src/modules/dashboards/seed/analytics.ts +3 -0
- package/src/modules/sales/api/order-lines/route.ts +158 -68
- package/src/modules/sales/api/quote-lines/route.ts +161 -67
- package/src/modules/sales/api/quotes/public/[token]/route.ts +122 -36
- package/src/modules/sales/commands/documents.ts +4250 -2424
- package/src/modules/sales/commands/shared.ts +7 -2
- package/src/modules/sales/components/documents/ItemsSection.tsx +580 -310
- package/src/modules/sales/components/documents/LineItemDialog.tsx +1988 -833
- package/src/modules/sales/components/documents/ShipmentsSection.tsx +17 -3
- package/src/modules/sales/components/documents/lineItemTypes.ts +6 -0
- package/src/modules/sales/data/entities.ts +53 -0
- package/src/modules/sales/data/validators.ts +36 -0
- package/src/modules/sales/frontend/quote/[token]/page.tsx +25 -1
- package/src/modules/sales/i18n/de.json +23 -3
- package/src/modules/sales/i18n/en.json +23 -3
- package/src/modules/sales/i18n/es.json +23 -3
- package/src/modules/sales/i18n/pl.json +23 -3
- package/src/modules/sales/lib/types.ts +30 -0
- package/src/modules/sales/migrations/.snapshot-open-mercato.json +172 -0
- package/src/modules/sales/migrations/Migration20260218225423.ts +37 -0
- package/src/modules/sales/migrations/Migration20260219084501.ts +73 -0
- package/src/modules/sales/search.ts +28 -0
- package/src/modules/sales/seed/examples.ts +20 -1
- package/src/modules/sales/widgets/injection/document-history/widget.client.tsx +1 -1
- package/src/modules/staff/backend/staff/team-members/[id]/page.tsx +8 -0
- package/src/modules/staff/translations.ts +5 -0
- package/src/modules/translations/components/TranslationDrawerAction.tsx +107 -0
- package/src/modules/translations/lib/extract-record-id.ts +47 -3
- package/src/modules/translations/lib/resolve-field-list.ts +4 -0
- package/src/modules/translations/widgets/injection/translation-manager/widget.client.tsx +108 -36
- package/src/modules/translations/widgets/injection-table.ts +19 -33
- package/src/modules/workflows/i18n/de.json +4 -4
- package/src/modules/workflows/i18n/en.json +4 -4
- package/src/modules/workflows/i18n/es.json +4 -4
- package/src/modules/workflows/i18n/pl.json +4 -4
|
@@ -0,0 +1,503 @@
|
|
|
1
|
+
import { registerCommand } from "@open-mercato/shared/lib/commands";
|
|
2
|
+
import {
|
|
3
|
+
buildChanges,
|
|
4
|
+
requireId,
|
|
5
|
+
emitCrudSideEffects,
|
|
6
|
+
emitCrudUndoSideEffects
|
|
7
|
+
} from "@open-mercato/shared/lib/commands/helpers";
|
|
8
|
+
import { UniqueConstraintViolationException } from "@mikro-orm/core";
|
|
9
|
+
import { CrudHttpError } from "@open-mercato/shared/lib/crud/errors";
|
|
10
|
+
import { resolveTranslations } from "@open-mercato/shared/lib/i18n/server";
|
|
11
|
+
import { E } from "../../../generated/entities.ids.generated.js";
|
|
12
|
+
import {
|
|
13
|
+
findOneWithDecryption
|
|
14
|
+
} from "@open-mercato/shared/lib/encryption/find";
|
|
15
|
+
import { CatalogProduct, CatalogProductUnitConversion } from "../data/entities.js";
|
|
16
|
+
import {
|
|
17
|
+
productUnitConversionCreateSchema,
|
|
18
|
+
productUnitConversionUpdateSchema,
|
|
19
|
+
productUnitConversionDeleteSchema
|
|
20
|
+
} from "../data/validators.js";
|
|
21
|
+
import {
|
|
22
|
+
ensureOrganizationScope,
|
|
23
|
+
ensureSameScope,
|
|
24
|
+
cloneJson,
|
|
25
|
+
ensureTenantScope,
|
|
26
|
+
extractUndoPayload,
|
|
27
|
+
requireProduct,
|
|
28
|
+
toNumericString,
|
|
29
|
+
getErrorConstraint,
|
|
30
|
+
getErrorMessage
|
|
31
|
+
} from "./shared.js";
|
|
32
|
+
import { toUnitLookupKey } from "../lib/unitCodes.js";
|
|
33
|
+
import { resolveCanonicalUnitCode } from "../lib/unitResolution.js";
|
|
34
|
+
const conversionCrudEvents = {
|
|
35
|
+
module: "catalog",
|
|
36
|
+
entity: "product_unit_conversion",
|
|
37
|
+
persistent: true,
|
|
38
|
+
buildPayload: (ctx) => ({
|
|
39
|
+
id: ctx.identifiers.id,
|
|
40
|
+
productId: ctx.entity.product && typeof ctx.entity.product !== "string" ? ctx.entity.product.id : null,
|
|
41
|
+
unitCode: ctx.entity.unitCode,
|
|
42
|
+
tenantId: ctx.identifiers.tenantId,
|
|
43
|
+
organizationId: ctx.identifiers.organizationId
|
|
44
|
+
})
|
|
45
|
+
};
|
|
46
|
+
const conversionCrudIndexer = {
|
|
47
|
+
entityType: E.catalog.catalog_product_unit_conversion,
|
|
48
|
+
buildUpsertPayload: (ctx) => ({
|
|
49
|
+
entityType: E.catalog.catalog_product_unit_conversion,
|
|
50
|
+
recordId: ctx.identifiers.id,
|
|
51
|
+
tenantId: ctx.identifiers.tenantId,
|
|
52
|
+
organizationId: ctx.identifiers.organizationId
|
|
53
|
+
}),
|
|
54
|
+
buildDeletePayload: (ctx) => ({
|
|
55
|
+
entityType: E.catalog.catalog_product_unit_conversion,
|
|
56
|
+
recordId: ctx.identifiers.id,
|
|
57
|
+
tenantId: ctx.identifiers.tenantId,
|
|
58
|
+
organizationId: ctx.identifiers.organizationId
|
|
59
|
+
})
|
|
60
|
+
};
|
|
61
|
+
function buildIdentifiers(record) {
|
|
62
|
+
return {
|
|
63
|
+
id: record.id,
|
|
64
|
+
organizationId: record.organizationId,
|
|
65
|
+
tenantId: record.tenantId
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
async function emitConversionCrudChange(opts) {
|
|
69
|
+
const { dataEngine, action, conversion } = opts;
|
|
70
|
+
await emitCrudSideEffects({
|
|
71
|
+
dataEngine,
|
|
72
|
+
action,
|
|
73
|
+
entity: conversion,
|
|
74
|
+
identifiers: buildIdentifiers(conversion),
|
|
75
|
+
events: conversionCrudEvents,
|
|
76
|
+
indexer: conversionCrudIndexer
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
async function emitConversionCrudUndoChange(opts) {
|
|
80
|
+
const { dataEngine, action, conversion } = opts;
|
|
81
|
+
await emitCrudUndoSideEffects({
|
|
82
|
+
dataEngine,
|
|
83
|
+
action,
|
|
84
|
+
entity: conversion,
|
|
85
|
+
identifiers: buildIdentifiers(conversion),
|
|
86
|
+
events: conversionCrudEvents,
|
|
87
|
+
indexer: conversionCrudIndexer
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
async function loadConversionSnapshot(em, id) {
|
|
91
|
+
const record = await findOneWithDecryption(
|
|
92
|
+
em,
|
|
93
|
+
CatalogProductUnitConversion,
|
|
94
|
+
{ id, deletedAt: null },
|
|
95
|
+
{ populate: ["product"] }
|
|
96
|
+
);
|
|
97
|
+
if (!record) return null;
|
|
98
|
+
const productId = typeof record.product === "string" ? record.product : record.product?.id ?? null;
|
|
99
|
+
if (!productId) return null;
|
|
100
|
+
return {
|
|
101
|
+
id: record.id,
|
|
102
|
+
productId,
|
|
103
|
+
organizationId: record.organizationId,
|
|
104
|
+
tenantId: record.tenantId,
|
|
105
|
+
unitCode: record.unitCode,
|
|
106
|
+
toBaseFactor: record.toBaseFactor,
|
|
107
|
+
sortOrder: record.sortOrder,
|
|
108
|
+
isActive: record.isActive,
|
|
109
|
+
metadata: record.metadata ? cloneJson(record.metadata) : null,
|
|
110
|
+
createdAt: record.createdAt.toISOString(),
|
|
111
|
+
updatedAt: record.updatedAt.toISOString()
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
function applyConversionSnapshot(em, record, snapshot) {
|
|
115
|
+
record.organizationId = snapshot.organizationId;
|
|
116
|
+
record.tenantId = snapshot.tenantId;
|
|
117
|
+
record.product = em.getReference(CatalogProduct, snapshot.productId);
|
|
118
|
+
record.unitCode = snapshot.unitCode;
|
|
119
|
+
record.toBaseFactor = snapshot.toBaseFactor;
|
|
120
|
+
record.sortOrder = snapshot.sortOrder;
|
|
121
|
+
record.isActive = snapshot.isActive;
|
|
122
|
+
record.metadata = snapshot.metadata ? cloneJson(snapshot.metadata) : null;
|
|
123
|
+
record.createdAt = new Date(snapshot.createdAt);
|
|
124
|
+
record.updatedAt = new Date(snapshot.updatedAt);
|
|
125
|
+
}
|
|
126
|
+
async function ensureDefaultSalesUnitIsNotRemoved(em, record, nextIsActive) {
|
|
127
|
+
if (nextIsActive) return;
|
|
128
|
+
const product = typeof record.product === "string" ? await findOneWithDecryption(em, CatalogProduct, {
|
|
129
|
+
id: record.product,
|
|
130
|
+
deletedAt: null
|
|
131
|
+
}) : record.product;
|
|
132
|
+
if (!product) return;
|
|
133
|
+
const defaultSalesUnitKey = toUnitLookupKey(product.defaultSalesUnit);
|
|
134
|
+
const conversionUnitKey = toUnitLookupKey(record.unitCode);
|
|
135
|
+
if (defaultSalesUnitKey && conversionUnitKey && defaultSalesUnitKey === conversionUnitKey) {
|
|
136
|
+
throw new CrudHttpError(409, {
|
|
137
|
+
error: "uom.default_sales_unit_conversion_required"
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
function resolveConversionUniqueConstraint(error) {
|
|
142
|
+
if (error instanceof UniqueConstraintViolationException) {
|
|
143
|
+
const constraint = getErrorConstraint(error);
|
|
144
|
+
if (constraint === "catalog_product_unit_conversions_unique") return true;
|
|
145
|
+
const message = getErrorMessage(error);
|
|
146
|
+
return message.toLowerCase().includes("catalog_product_unit_conversions_unique");
|
|
147
|
+
}
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
function rethrowConversionUniqueConstraint(error) {
|
|
151
|
+
if (resolveConversionUniqueConstraint(error)) {
|
|
152
|
+
throw new CrudHttpError(409, { error: "uom.duplicate_conversion" });
|
|
153
|
+
}
|
|
154
|
+
throw error;
|
|
155
|
+
}
|
|
156
|
+
const createProductUnitConversionCommand = {
|
|
157
|
+
id: "catalog.product-unit-conversions.create",
|
|
158
|
+
async execute(rawInput, ctx) {
|
|
159
|
+
const parsed = productUnitConversionCreateSchema.parse(rawInput);
|
|
160
|
+
ensureTenantScope(ctx, parsed.tenantId);
|
|
161
|
+
ensureOrganizationScope(ctx, parsed.organizationId);
|
|
162
|
+
const em = ctx.container.resolve("em").fork();
|
|
163
|
+
const { translate } = await resolveTranslations();
|
|
164
|
+
const product = await requireProduct(
|
|
165
|
+
em,
|
|
166
|
+
parsed.productId,
|
|
167
|
+
translate("catalog.errors.productNotFound", "Catalog product not found")
|
|
168
|
+
);
|
|
169
|
+
ensureSameScope(product, parsed.organizationId, parsed.tenantId);
|
|
170
|
+
const canonicalUnitCode = await resolveCanonicalUnitCode(em, {
|
|
171
|
+
organizationId: parsed.organizationId,
|
|
172
|
+
tenantId: parsed.tenantId,
|
|
173
|
+
unitCode: parsed.unitCode
|
|
174
|
+
});
|
|
175
|
+
const toBaseFactorStr = toNumericString(parsed.toBaseFactor);
|
|
176
|
+
if (!toBaseFactorStr) {
|
|
177
|
+
throw new CrudHttpError(400, {
|
|
178
|
+
error: "uom.conversion_factor_required"
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
const conversion = em.create(CatalogProductUnitConversion, {
|
|
182
|
+
product,
|
|
183
|
+
organizationId: parsed.organizationId,
|
|
184
|
+
tenantId: parsed.tenantId,
|
|
185
|
+
unitCode: canonicalUnitCode,
|
|
186
|
+
toBaseFactor: toBaseFactorStr,
|
|
187
|
+
sortOrder: parsed.sortOrder ?? 0,
|
|
188
|
+
isActive: parsed.isActive !== false,
|
|
189
|
+
metadata: parsed.metadata ? cloneJson(parsed.metadata) : null,
|
|
190
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
191
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
192
|
+
});
|
|
193
|
+
em.persist(conversion);
|
|
194
|
+
try {
|
|
195
|
+
await em.flush();
|
|
196
|
+
} catch (error) {
|
|
197
|
+
rethrowConversionUniqueConstraint(error);
|
|
198
|
+
}
|
|
199
|
+
const dataEngine = ctx.container.resolve("dataEngine");
|
|
200
|
+
await emitConversionCrudChange({
|
|
201
|
+
dataEngine,
|
|
202
|
+
action: "created",
|
|
203
|
+
conversion
|
|
204
|
+
});
|
|
205
|
+
return { conversionId: conversion.id };
|
|
206
|
+
},
|
|
207
|
+
captureAfter: async (_input, result, ctx) => {
|
|
208
|
+
const em = ctx.container.resolve("em").fork();
|
|
209
|
+
return loadConversionSnapshot(em, result.conversionId);
|
|
210
|
+
},
|
|
211
|
+
buildLog: async ({ snapshots }) => {
|
|
212
|
+
const after = snapshots.after;
|
|
213
|
+
if (!after) return null;
|
|
214
|
+
const { translate } = await resolveTranslations();
|
|
215
|
+
return {
|
|
216
|
+
actionLabel: translate(
|
|
217
|
+
"catalog.audit.productUnitConversions.create",
|
|
218
|
+
"Create product unit conversion"
|
|
219
|
+
),
|
|
220
|
+
resourceKind: "catalog.product_unit_conversion",
|
|
221
|
+
resourceId: after.id,
|
|
222
|
+
tenantId: after.tenantId,
|
|
223
|
+
organizationId: after.organizationId,
|
|
224
|
+
snapshotAfter: after,
|
|
225
|
+
payload: {
|
|
226
|
+
undo: {
|
|
227
|
+
after
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
},
|
|
232
|
+
undo: async ({ logEntry, ctx }) => {
|
|
233
|
+
const payload = extractUndoPayload(logEntry);
|
|
234
|
+
const after = payload?.after;
|
|
235
|
+
if (!after) return;
|
|
236
|
+
const em = ctx.container.resolve("em").fork();
|
|
237
|
+
const record = await findOneWithDecryption(
|
|
238
|
+
em,
|
|
239
|
+
CatalogProductUnitConversion,
|
|
240
|
+
{ id: after.id, deletedAt: null }
|
|
241
|
+
);
|
|
242
|
+
if (!record) return;
|
|
243
|
+
ensureTenantScope(ctx, record.tenantId);
|
|
244
|
+
ensureOrganizationScope(ctx, record.organizationId);
|
|
245
|
+
em.remove(record);
|
|
246
|
+
await em.flush();
|
|
247
|
+
const dataEngine = ctx.container.resolve("dataEngine");
|
|
248
|
+
await emitConversionCrudUndoChange({
|
|
249
|
+
dataEngine,
|
|
250
|
+
action: "deleted",
|
|
251
|
+
conversion: record
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
const updateProductUnitConversionCommand = {
|
|
256
|
+
id: "catalog.product-unit-conversions.update",
|
|
257
|
+
async prepare(input, ctx) {
|
|
258
|
+
const id = requireId(input, "Product unit conversion id is required");
|
|
259
|
+
const em = ctx.container.resolve("em");
|
|
260
|
+
const snapshot = await loadConversionSnapshot(em, id);
|
|
261
|
+
if (snapshot) {
|
|
262
|
+
ensureTenantScope(ctx, snapshot.tenantId);
|
|
263
|
+
ensureOrganizationScope(ctx, snapshot.organizationId);
|
|
264
|
+
}
|
|
265
|
+
return snapshot ? { before: snapshot } : {};
|
|
266
|
+
},
|
|
267
|
+
async execute(rawInput, ctx) {
|
|
268
|
+
const parsed = productUnitConversionUpdateSchema.parse(rawInput);
|
|
269
|
+
const em = ctx.container.resolve("em").fork();
|
|
270
|
+
const { translate } = await resolveTranslations();
|
|
271
|
+
const record = await findOneWithDecryption(
|
|
272
|
+
em,
|
|
273
|
+
CatalogProductUnitConversion,
|
|
274
|
+
{ id: parsed.id, deletedAt: null },
|
|
275
|
+
{ populate: ["product"] }
|
|
276
|
+
);
|
|
277
|
+
if (!record)
|
|
278
|
+
throw new CrudHttpError(404, {
|
|
279
|
+
error: translate("catalog.errors.conversionNotFound", "Catalog product unit conversion not found")
|
|
280
|
+
});
|
|
281
|
+
const product = typeof record.product === "string" ? await requireProduct(em, record.product, translate("catalog.errors.productNotFound", "Catalog product not found")) : record.product;
|
|
282
|
+
ensureTenantScope(ctx, record.tenantId);
|
|
283
|
+
ensureOrganizationScope(ctx, record.organizationId);
|
|
284
|
+
ensureSameScope(product, record.organizationId, record.tenantId);
|
|
285
|
+
const resolvedUnitCode = parsed.unitCode !== void 0 ? await resolveCanonicalUnitCode(em, {
|
|
286
|
+
organizationId: record.organizationId,
|
|
287
|
+
tenantId: record.tenantId,
|
|
288
|
+
unitCode: parsed.unitCode
|
|
289
|
+
}) : void 0;
|
|
290
|
+
if (parsed.isActive !== void 0) {
|
|
291
|
+
await ensureDefaultSalesUnitIsNotRemoved(em, record, parsed.isActive);
|
|
292
|
+
}
|
|
293
|
+
if (resolvedUnitCode !== void 0) {
|
|
294
|
+
record.unitCode = resolvedUnitCode;
|
|
295
|
+
}
|
|
296
|
+
if (parsed.toBaseFactor !== void 0) {
|
|
297
|
+
record.toBaseFactor = toNumericString(parsed.toBaseFactor) ?? record.toBaseFactor;
|
|
298
|
+
}
|
|
299
|
+
if (parsed.sortOrder !== void 0) {
|
|
300
|
+
record.sortOrder = parsed.sortOrder;
|
|
301
|
+
}
|
|
302
|
+
if (parsed.isActive !== void 0) {
|
|
303
|
+
record.isActive = parsed.isActive;
|
|
304
|
+
}
|
|
305
|
+
if (parsed.metadata !== void 0) {
|
|
306
|
+
record.metadata = parsed.metadata ? cloneJson(parsed.metadata) : null;
|
|
307
|
+
}
|
|
308
|
+
try {
|
|
309
|
+
await em.flush();
|
|
310
|
+
} catch (error) {
|
|
311
|
+
rethrowConversionUniqueConstraint(error);
|
|
312
|
+
}
|
|
313
|
+
const dataEngine = ctx.container.resolve("dataEngine");
|
|
314
|
+
await emitConversionCrudChange({
|
|
315
|
+
dataEngine,
|
|
316
|
+
action: "updated",
|
|
317
|
+
conversion: record
|
|
318
|
+
});
|
|
319
|
+
return { conversionId: record.id };
|
|
320
|
+
},
|
|
321
|
+
captureAfter: async (_input, result, ctx) => {
|
|
322
|
+
const em = ctx.container.resolve("em").fork();
|
|
323
|
+
return loadConversionSnapshot(em, result.conversionId);
|
|
324
|
+
},
|
|
325
|
+
buildLog: async ({ snapshots }) => {
|
|
326
|
+
const before = snapshots.before;
|
|
327
|
+
const after = snapshots.after;
|
|
328
|
+
if (!before || !after) return null;
|
|
329
|
+
const { translate } = await resolveTranslations();
|
|
330
|
+
return {
|
|
331
|
+
actionLabel: translate(
|
|
332
|
+
"catalog.audit.productUnitConversions.update",
|
|
333
|
+
"Update product unit conversion"
|
|
334
|
+
),
|
|
335
|
+
resourceKind: "catalog.product_unit_conversion",
|
|
336
|
+
resourceId: before.id,
|
|
337
|
+
tenantId: before.tenantId,
|
|
338
|
+
organizationId: before.organizationId,
|
|
339
|
+
changes: buildChanges(before, after, [
|
|
340
|
+
"unitCode",
|
|
341
|
+
"toBaseFactor",
|
|
342
|
+
"sortOrder",
|
|
343
|
+
"isActive",
|
|
344
|
+
"metadata"
|
|
345
|
+
]),
|
|
346
|
+
snapshotBefore: before,
|
|
347
|
+
snapshotAfter: after,
|
|
348
|
+
payload: {
|
|
349
|
+
undo: {
|
|
350
|
+
before,
|
|
351
|
+
after
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
},
|
|
356
|
+
undo: async ({ logEntry, ctx }) => {
|
|
357
|
+
const payload = extractUndoPayload(logEntry);
|
|
358
|
+
const before = payload?.before;
|
|
359
|
+
if (!before) return;
|
|
360
|
+
const em = ctx.container.resolve("em").fork();
|
|
361
|
+
let record = await findOneWithDecryption(
|
|
362
|
+
em,
|
|
363
|
+
CatalogProductUnitConversion,
|
|
364
|
+
{ id: before.id, deletedAt: null }
|
|
365
|
+
);
|
|
366
|
+
let undoAction = "updated";
|
|
367
|
+
if (!record) {
|
|
368
|
+
record = em.create(CatalogProductUnitConversion, {
|
|
369
|
+
id: before.id,
|
|
370
|
+
organizationId: before.organizationId,
|
|
371
|
+
tenantId: before.tenantId,
|
|
372
|
+
product: em.getReference(CatalogProduct, before.productId),
|
|
373
|
+
unitCode: before.unitCode,
|
|
374
|
+
toBaseFactor: before.toBaseFactor,
|
|
375
|
+
sortOrder: before.sortOrder,
|
|
376
|
+
isActive: before.isActive,
|
|
377
|
+
metadata: before.metadata ? cloneJson(before.metadata) : null,
|
|
378
|
+
createdAt: new Date(before.createdAt),
|
|
379
|
+
updatedAt: new Date(before.updatedAt)
|
|
380
|
+
});
|
|
381
|
+
em.persist(record);
|
|
382
|
+
undoAction = "created";
|
|
383
|
+
}
|
|
384
|
+
ensureTenantScope(ctx, before.tenantId);
|
|
385
|
+
ensureOrganizationScope(ctx, before.organizationId);
|
|
386
|
+
applyConversionSnapshot(em, record, before);
|
|
387
|
+
await em.transactional(async () => {
|
|
388
|
+
await em.flush();
|
|
389
|
+
});
|
|
390
|
+
const dataEngine = ctx.container.resolve("dataEngine");
|
|
391
|
+
await emitConversionCrudUndoChange({
|
|
392
|
+
dataEngine,
|
|
393
|
+
action: undoAction,
|
|
394
|
+
conversion: record
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
};
|
|
398
|
+
const deleteProductUnitConversionCommand = {
|
|
399
|
+
id: "catalog.product-unit-conversions.delete",
|
|
400
|
+
async prepare(input, ctx) {
|
|
401
|
+
const id = requireId(input, "Product unit conversion id is required");
|
|
402
|
+
const em = ctx.container.resolve("em");
|
|
403
|
+
const snapshot = await loadConversionSnapshot(em, id);
|
|
404
|
+
if (snapshot) {
|
|
405
|
+
ensureTenantScope(ctx, snapshot.tenantId);
|
|
406
|
+
ensureOrganizationScope(ctx, snapshot.organizationId);
|
|
407
|
+
}
|
|
408
|
+
return snapshot ? { before: snapshot } : {};
|
|
409
|
+
},
|
|
410
|
+
async execute(rawInput, ctx) {
|
|
411
|
+
const parsed = productUnitConversionDeleteSchema.parse(rawInput);
|
|
412
|
+
const em = ctx.container.resolve("em").fork();
|
|
413
|
+
const { translate } = await resolveTranslations();
|
|
414
|
+
const record = await findOneWithDecryption(
|
|
415
|
+
em,
|
|
416
|
+
CatalogProductUnitConversion,
|
|
417
|
+
{ id: parsed.id, deletedAt: null },
|
|
418
|
+
{ populate: ["product"] }
|
|
419
|
+
);
|
|
420
|
+
if (!record)
|
|
421
|
+
throw new CrudHttpError(404, {
|
|
422
|
+
error: translate("catalog.errors.conversionNotFound", "Catalog product unit conversion not found")
|
|
423
|
+
});
|
|
424
|
+
ensureTenantScope(ctx, record.tenantId);
|
|
425
|
+
ensureOrganizationScope(ctx, record.organizationId);
|
|
426
|
+
await ensureDefaultSalesUnitIsNotRemoved(em, record, false);
|
|
427
|
+
em.remove(record);
|
|
428
|
+
await em.transactional(async () => {
|
|
429
|
+
await em.flush();
|
|
430
|
+
});
|
|
431
|
+
const dataEngine = ctx.container.resolve("dataEngine");
|
|
432
|
+
await emitConversionCrudChange({
|
|
433
|
+
dataEngine,
|
|
434
|
+
action: "deleted",
|
|
435
|
+
conversion: record
|
|
436
|
+
});
|
|
437
|
+
return { conversionId: parsed.id };
|
|
438
|
+
},
|
|
439
|
+
buildLog: async ({ snapshots }) => {
|
|
440
|
+
const before = snapshots.before;
|
|
441
|
+
if (!before) return null;
|
|
442
|
+
const { translate } = await resolveTranslations();
|
|
443
|
+
return {
|
|
444
|
+
actionLabel: translate(
|
|
445
|
+
"catalog.audit.productUnitConversions.delete",
|
|
446
|
+
"Delete product unit conversion"
|
|
447
|
+
),
|
|
448
|
+
resourceKind: "catalog.product_unit_conversion",
|
|
449
|
+
resourceId: before.id,
|
|
450
|
+
tenantId: before.tenantId,
|
|
451
|
+
organizationId: before.organizationId,
|
|
452
|
+
snapshotBefore: before,
|
|
453
|
+
payload: {
|
|
454
|
+
undo: {
|
|
455
|
+
before
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
};
|
|
459
|
+
},
|
|
460
|
+
undo: async ({ logEntry, ctx }) => {
|
|
461
|
+
const payload = extractUndoPayload(logEntry);
|
|
462
|
+
const before = payload?.before;
|
|
463
|
+
if (!before) return;
|
|
464
|
+
const em = ctx.container.resolve("em").fork();
|
|
465
|
+
let record = await findOneWithDecryption(
|
|
466
|
+
em,
|
|
467
|
+
CatalogProductUnitConversion,
|
|
468
|
+
{ id: before.id, deletedAt: null }
|
|
469
|
+
);
|
|
470
|
+
if (!record) {
|
|
471
|
+
record = em.create(CatalogProductUnitConversion, {
|
|
472
|
+
id: before.id,
|
|
473
|
+
organizationId: before.organizationId,
|
|
474
|
+
tenantId: before.tenantId,
|
|
475
|
+
product: em.getReference(CatalogProduct, before.productId),
|
|
476
|
+
unitCode: before.unitCode,
|
|
477
|
+
toBaseFactor: before.toBaseFactor,
|
|
478
|
+
sortOrder: before.sortOrder,
|
|
479
|
+
isActive: before.isActive,
|
|
480
|
+
metadata: before.metadata ? cloneJson(before.metadata) : null,
|
|
481
|
+
createdAt: new Date(before.createdAt),
|
|
482
|
+
updatedAt: new Date(before.updatedAt)
|
|
483
|
+
});
|
|
484
|
+
em.persist(record);
|
|
485
|
+
}
|
|
486
|
+
ensureTenantScope(ctx, before.tenantId);
|
|
487
|
+
ensureOrganizationScope(ctx, before.organizationId);
|
|
488
|
+
applyConversionSnapshot(em, record, before);
|
|
489
|
+
await em.transactional(async () => {
|
|
490
|
+
await em.flush();
|
|
491
|
+
});
|
|
492
|
+
const dataEngine = ctx.container.resolve("dataEngine");
|
|
493
|
+
await emitConversionCrudUndoChange({
|
|
494
|
+
dataEngine,
|
|
495
|
+
action: "created",
|
|
496
|
+
conversion: record
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
};
|
|
500
|
+
registerCommand(createProductUnitConversionCommand);
|
|
501
|
+
registerCommand(updateProductUnitConversionCommand);
|
|
502
|
+
registerCommand(deleteProductUnitConversionCommand);
|
|
503
|
+
//# sourceMappingURL=productUnitConversions.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/catalog/commands/productUnitConversions.ts"],
|
|
4
|
+
"sourcesContent": ["import { registerCommand } from \"@open-mercato/shared/lib/commands\";\nimport type { CommandHandler } from \"@open-mercato/shared/lib/commands\";\nimport {\n buildChanges,\n requireId,\n emitCrudSideEffects,\n emitCrudUndoSideEffects,\n} from \"@open-mercato/shared/lib/commands/helpers\";\nimport type {\n CrudEventAction,\n CrudEventsConfig,\n CrudIndexerConfig,\n} from \"@open-mercato/shared/lib/crud/types\";\nimport type { EntityManager } from \"@mikro-orm/postgresql\";\nimport { UniqueConstraintViolationException } from \"@mikro-orm/core\";\nimport { CrudHttpError } from \"@open-mercato/shared/lib/crud/errors\";\nimport { resolveTranslations } from \"@open-mercato/shared/lib/i18n/server\";\nimport type { DataEngine } from \"@open-mercato/shared/lib/data/engine\";\nimport { E } from \"#generated/entities.ids.generated\";\nimport {\n findOneWithDecryption,\n} from \"@open-mercato/shared/lib/encryption/find\";\nimport { CatalogProduct, CatalogProductUnitConversion } from \"../data/entities\";\nimport {\n productUnitConversionCreateSchema,\n productUnitConversionUpdateSchema,\n productUnitConversionDeleteSchema,\n type ProductUnitConversionCreateInput,\n type ProductUnitConversionUpdateInput,\n type ProductUnitConversionDeleteInput,\n} from \"../data/validators\";\nimport {\n ensureOrganizationScope,\n ensureSameScope,\n cloneJson,\n ensureTenantScope,\n extractUndoPayload,\n requireProduct,\n toNumericString,\n getErrorConstraint,\n getErrorMessage,\n} from \"./shared\";\nimport { toUnitLookupKey } from \"../lib/unitCodes\";\nimport { resolveCanonicalUnitCode } from \"../lib/unitResolution\";\n\ntype ProductUnitConversionSnapshot = {\n id: string;\n productId: string;\n organizationId: string;\n tenantId: string;\n unitCode: string;\n toBaseFactor: string;\n sortOrder: number;\n isActive: boolean;\n metadata: Record<string, unknown> | null;\n createdAt: string;\n updatedAt: string;\n};\n\ntype ProductUnitConversionUndoPayload = {\n before?: ProductUnitConversionSnapshot | null;\n after?: ProductUnitConversionSnapshot | null;\n};\n\nconst conversionCrudEvents: CrudEventsConfig<CatalogProductUnitConversion> = {\n module: \"catalog\",\n entity: \"product_unit_conversion\",\n persistent: true,\n buildPayload: (ctx) => ({\n id: ctx.identifiers.id,\n productId:\n ctx.entity.product && typeof ctx.entity.product !== \"string\"\n ? ctx.entity.product.id\n : null,\n unitCode: ctx.entity.unitCode,\n tenantId: ctx.identifiers.tenantId,\n organizationId: ctx.identifiers.organizationId,\n }),\n};\n\nconst conversionCrudIndexer: CrudIndexerConfig<CatalogProductUnitConversion> = {\n entityType: E.catalog.catalog_product_unit_conversion,\n buildUpsertPayload: (ctx) => ({\n entityType: E.catalog.catalog_product_unit_conversion,\n recordId: ctx.identifiers.id,\n tenantId: ctx.identifiers.tenantId,\n organizationId: ctx.identifiers.organizationId,\n }),\n buildDeletePayload: (ctx) => ({\n entityType: E.catalog.catalog_product_unit_conversion,\n recordId: ctx.identifiers.id,\n tenantId: ctx.identifiers.tenantId,\n organizationId: ctx.identifiers.organizationId,\n }),\n};\n\nfunction buildIdentifiers(record: CatalogProductUnitConversion) {\n return {\n id: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n };\n}\n\nasync function emitConversionCrudChange(opts: {\n dataEngine: DataEngine;\n action: CrudEventAction;\n conversion: CatalogProductUnitConversion;\n}) {\n const { dataEngine, action, conversion } = opts;\n await emitCrudSideEffects({\n dataEngine,\n action,\n entity: conversion,\n identifiers: buildIdentifiers(conversion),\n events: conversionCrudEvents,\n indexer: conversionCrudIndexer,\n });\n}\n\nasync function emitConversionCrudUndoChange(opts: {\n dataEngine: DataEngine;\n action: CrudEventAction;\n conversion: CatalogProductUnitConversion;\n}) {\n const { dataEngine, action, conversion } = opts;\n await emitCrudUndoSideEffects({\n dataEngine,\n action,\n entity: conversion,\n identifiers: buildIdentifiers(conversion),\n events: conversionCrudEvents,\n indexer: conversionCrudIndexer,\n });\n}\n\nasync function loadConversionSnapshot(\n em: EntityManager,\n id: string,\n): Promise<ProductUnitConversionSnapshot | null> {\n const record = await findOneWithDecryption(\n em,\n CatalogProductUnitConversion,\n { id, deletedAt: null },\n { populate: [\"product\"] },\n );\n if (!record) return null;\n const productId =\n typeof record.product === \"string\"\n ? record.product\n : (record.product?.id ?? null);\n if (!productId) return null;\n return {\n id: record.id,\n productId,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n unitCode: record.unitCode,\n toBaseFactor: record.toBaseFactor,\n sortOrder: record.sortOrder,\n isActive: record.isActive,\n metadata: record.metadata\n ? cloneJson(record.metadata)\n : null,\n createdAt: record.createdAt.toISOString(),\n updatedAt: record.updatedAt.toISOString(),\n };\n}\n\nfunction applyConversionSnapshot(\n em: EntityManager,\n record: CatalogProductUnitConversion,\n snapshot: ProductUnitConversionSnapshot,\n): void {\n record.organizationId = snapshot.organizationId;\n record.tenantId = snapshot.tenantId;\n record.product = em.getReference(CatalogProduct, snapshot.productId);\n record.unitCode = snapshot.unitCode;\n record.toBaseFactor = snapshot.toBaseFactor;\n record.sortOrder = snapshot.sortOrder;\n record.isActive = snapshot.isActive;\n record.metadata = snapshot.metadata\n ? cloneJson(snapshot.metadata)\n : null;\n record.createdAt = new Date(snapshot.createdAt);\n record.updatedAt = new Date(snapshot.updatedAt);\n}\n\nasync function ensureDefaultSalesUnitIsNotRemoved(\n em: EntityManager,\n record: CatalogProductUnitConversion,\n nextIsActive: boolean,\n): Promise<void> {\n if (nextIsActive) return;\n const product =\n typeof record.product === \"string\"\n ? await findOneWithDecryption(em, CatalogProduct, {\n id: record.product,\n deletedAt: null,\n })\n : record.product;\n if (!product) return;\n const defaultSalesUnitKey = toUnitLookupKey(product.defaultSalesUnit);\n const conversionUnitKey = toUnitLookupKey(record.unitCode);\n if (\n defaultSalesUnitKey &&\n conversionUnitKey &&\n defaultSalesUnitKey === conversionUnitKey\n ) {\n throw new CrudHttpError(409, {\n error: \"uom.default_sales_unit_conversion_required\",\n });\n }\n}\n\nfunction resolveConversionUniqueConstraint(error: unknown): boolean {\n if (error instanceof UniqueConstraintViolationException) {\n const constraint = getErrorConstraint(error);\n if (constraint === \"catalog_product_unit_conversions_unique\") return true;\n const message = getErrorMessage(error);\n return message.toLowerCase().includes(\"catalog_product_unit_conversions_unique\");\n }\n return false;\n}\n\nfunction rethrowConversionUniqueConstraint(\n error: unknown,\n): never {\n if (resolveConversionUniqueConstraint(error)) {\n throw new CrudHttpError(409, { error: \"uom.duplicate_conversion\" });\n }\n throw error;\n}\n\nconst createProductUnitConversionCommand: CommandHandler<\n ProductUnitConversionCreateInput,\n { conversionId: string }\n> = {\n id: \"catalog.product-unit-conversions.create\",\n async execute(rawInput, ctx) {\n const parsed = productUnitConversionCreateSchema.parse(rawInput);\n ensureTenantScope(ctx, parsed.tenantId);\n ensureOrganizationScope(ctx, parsed.organizationId);\n\n const em = (ctx.container.resolve(\"em\") as EntityManager).fork();\n const { translate } = await resolveTranslations();\n const product = await requireProduct(\n em,\n parsed.productId,\n translate(\"catalog.errors.productNotFound\", \"Catalog product not found\"),\n );\n ensureSameScope(product, parsed.organizationId, parsed.tenantId);\n const canonicalUnitCode = await resolveCanonicalUnitCode(em, {\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n unitCode: parsed.unitCode,\n });\n\n const toBaseFactorStr = toNumericString(parsed.toBaseFactor);\n if (!toBaseFactorStr) {\n throw new CrudHttpError(400, {\n error: \"uom.conversion_factor_required\",\n });\n }\n\n const conversion = em.create(CatalogProductUnitConversion, {\n product,\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n unitCode: canonicalUnitCode,\n toBaseFactor: toBaseFactorStr,\n sortOrder: parsed.sortOrder ?? 0,\n isActive: parsed.isActive !== false,\n metadata: parsed.metadata\n ? cloneJson(parsed.metadata)\n : null,\n createdAt: new Date(),\n updatedAt: new Date(),\n });\n em.persist(conversion);\n try {\n await em.flush();\n } catch (error) {\n rethrowConversionUniqueConstraint(error);\n }\n\n const dataEngine = ctx.container.resolve(\"dataEngine\") as DataEngine;\n await emitConversionCrudChange({\n dataEngine,\n action: \"created\",\n conversion,\n });\n return { conversionId: conversion.id };\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve(\"em\") as EntityManager).fork();\n return loadConversionSnapshot(em, result.conversionId);\n },\n buildLog: async ({ snapshots }) => {\n const after = snapshots.after as ProductUnitConversionSnapshot | undefined;\n if (!after) return null;\n const { translate } = await resolveTranslations();\n return {\n actionLabel: translate(\n \"catalog.audit.productUnitConversions.create\",\n \"Create product unit conversion\",\n ),\n resourceKind: \"catalog.product_unit_conversion\",\n resourceId: after.id,\n tenantId: after.tenantId,\n organizationId: after.organizationId,\n snapshotAfter: after,\n payload: {\n undo: {\n after,\n } satisfies ProductUnitConversionUndoPayload,\n },\n };\n },\n undo: async ({ logEntry, ctx }) => {\n const payload =\n extractUndoPayload<ProductUnitConversionUndoPayload>(logEntry);\n const after = payload?.after;\n if (!after) return;\n const em = (ctx.container.resolve(\"em\") as EntityManager).fork();\n const record = await findOneWithDecryption(\n em,\n CatalogProductUnitConversion,\n { id: after.id, deletedAt: null },\n );\n if (!record) return;\n ensureTenantScope(ctx, record.tenantId);\n ensureOrganizationScope(ctx, record.organizationId);\n em.remove(record);\n await em.flush();\n const dataEngine = ctx.container.resolve(\"dataEngine\") as DataEngine;\n await emitConversionCrudUndoChange({\n dataEngine,\n action: \"deleted\",\n conversion: record,\n });\n },\n};\n\nconst updateProductUnitConversionCommand: CommandHandler<\n ProductUnitConversionUpdateInput,\n { conversionId: string }\n> = {\n id: \"catalog.product-unit-conversions.update\",\n async prepare(input, ctx) {\n const id = requireId(input, \"Product unit conversion id is required\");\n const em = ctx.container.resolve(\"em\") as EntityManager;\n const snapshot = await loadConversionSnapshot(em, 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 parsed = productUnitConversionUpdateSchema.parse(rawInput);\n const em = (ctx.container.resolve(\"em\") as EntityManager).fork();\n const { translate } = await resolveTranslations();\n const record = await findOneWithDecryption(\n em,\n CatalogProductUnitConversion,\n { id: parsed.id, deletedAt: null },\n { populate: [\"product\"] },\n );\n if (!record)\n throw new CrudHttpError(404, {\n error: translate(\"catalog.errors.conversionNotFound\", \"Catalog product unit conversion not found\"),\n });\n const product =\n typeof record.product === \"string\"\n ? await requireProduct(em, record.product, translate(\"catalog.errors.productNotFound\", \"Catalog product not found\"))\n : record.product;\n ensureTenantScope(ctx, record.tenantId);\n ensureOrganizationScope(ctx, record.organizationId);\n ensureSameScope(product, record.organizationId, record.tenantId);\n\n // Resolve all query-dependent values BEFORE applying scalar mutations\n const resolvedUnitCode =\n parsed.unitCode !== undefined\n ? await resolveCanonicalUnitCode(em, {\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n unitCode: parsed.unitCode,\n })\n : undefined;\n if (parsed.isActive !== undefined) {\n await ensureDefaultSalesUnitIsNotRemoved(em, record, parsed.isActive);\n }\n\n // Apply all scalar mutations after queries are complete\n if (resolvedUnitCode !== undefined) {\n record.unitCode = resolvedUnitCode;\n }\n if (parsed.toBaseFactor !== undefined) {\n record.toBaseFactor =\n toNumericString(parsed.toBaseFactor) ?? record.toBaseFactor;\n }\n if (parsed.sortOrder !== undefined) {\n record.sortOrder = parsed.sortOrder;\n }\n if (parsed.isActive !== undefined) {\n record.isActive = parsed.isActive;\n }\n if (parsed.metadata !== undefined) {\n record.metadata = parsed.metadata\n ? cloneJson(parsed.metadata)\n : null;\n }\n try {\n await em.flush();\n } catch (error) {\n rethrowConversionUniqueConstraint(error);\n }\n\n const dataEngine = ctx.container.resolve(\"dataEngine\") as DataEngine;\n await emitConversionCrudChange({\n dataEngine,\n action: \"updated\",\n conversion: record,\n });\n return { conversionId: record.id };\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve(\"em\") as EntityManager).fork();\n return loadConversionSnapshot(em, result.conversionId);\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as\n | ProductUnitConversionSnapshot\n | undefined;\n const after = snapshots.after as ProductUnitConversionSnapshot | undefined;\n if (!before || !after) return null;\n const { translate } = await resolveTranslations();\n return {\n actionLabel: translate(\n \"catalog.audit.productUnitConversions.update\",\n \"Update product unit conversion\",\n ),\n resourceKind: \"catalog.product_unit_conversion\",\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n changes: buildChanges(before, after, [\n \"unitCode\",\n \"toBaseFactor\",\n \"sortOrder\",\n \"isActive\",\n \"metadata\",\n ]),\n snapshotBefore: before,\n snapshotAfter: after,\n payload: {\n undo: {\n before,\n after,\n } satisfies ProductUnitConversionUndoPayload,\n },\n };\n },\n undo: async ({ logEntry, ctx }) => {\n const payload =\n extractUndoPayload<ProductUnitConversionUndoPayload>(logEntry);\n const before = payload?.before;\n if (!before) return;\n const em = (ctx.container.resolve(\"em\") as EntityManager).fork();\n let record = await findOneWithDecryption(\n em,\n CatalogProductUnitConversion,\n { id: before.id, deletedAt: null },\n );\n let undoAction: \"updated\" | \"created\" = \"updated\";\n if (!record) {\n record = em.create(CatalogProductUnitConversion, {\n id: before.id,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n product: em.getReference(CatalogProduct, before.productId),\n unitCode: before.unitCode,\n toBaseFactor: before.toBaseFactor,\n sortOrder: before.sortOrder,\n isActive: before.isActive,\n metadata: before.metadata\n ? cloneJson(before.metadata)\n : null,\n createdAt: new Date(before.createdAt),\n updatedAt: new Date(before.updatedAt),\n });\n em.persist(record);\n undoAction = \"created\";\n }\n ensureTenantScope(ctx, before.tenantId);\n ensureOrganizationScope(ctx, before.organizationId);\n applyConversionSnapshot(em, record, before);\n await em.transactional(async () => {\n await em.flush();\n });\n const dataEngine = ctx.container.resolve(\"dataEngine\") as DataEngine;\n await emitConversionCrudUndoChange({\n dataEngine,\n action: undoAction,\n conversion: record,\n });\n },\n};\n\nconst deleteProductUnitConversionCommand: CommandHandler<\n ProductUnitConversionDeleteInput,\n { conversionId: string }\n> = {\n id: \"catalog.product-unit-conversions.delete\",\n async prepare(input, ctx) {\n const id = requireId(input, \"Product unit conversion id is required\");\n const em = ctx.container.resolve(\"em\") as EntityManager;\n const snapshot = await loadConversionSnapshot(em, 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 parsed = productUnitConversionDeleteSchema.parse(rawInput);\n const em = (ctx.container.resolve(\"em\") as EntityManager).fork();\n const { translate } = await resolveTranslations();\n const record = await findOneWithDecryption(\n em,\n CatalogProductUnitConversion,\n { id: parsed.id, deletedAt: null },\n { populate: [\"product\"] },\n );\n if (!record)\n throw new CrudHttpError(404, {\n error: translate(\"catalog.errors.conversionNotFound\", \"Catalog product unit conversion not found\"),\n });\n ensureTenantScope(ctx, record.tenantId);\n ensureOrganizationScope(ctx, record.organizationId);\n await ensureDefaultSalesUnitIsNotRemoved(em, record, false);\n\n em.remove(record);\n await em.transactional(async () => {\n await em.flush();\n });\n\n const dataEngine = ctx.container.resolve(\"dataEngine\") as DataEngine;\n await emitConversionCrudChange({\n dataEngine,\n action: \"deleted\",\n conversion: record,\n });\n return { conversionId: parsed.id };\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as\n | ProductUnitConversionSnapshot\n | undefined;\n if (!before) return null;\n const { translate } = await resolveTranslations();\n return {\n actionLabel: translate(\n \"catalog.audit.productUnitConversions.delete\",\n \"Delete product unit conversion\",\n ),\n resourceKind: \"catalog.product_unit_conversion\",\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: {\n before,\n } satisfies ProductUnitConversionUndoPayload,\n },\n };\n },\n undo: async ({ logEntry, ctx }) => {\n const payload =\n extractUndoPayload<ProductUnitConversionUndoPayload>(logEntry);\n const before = payload?.before;\n if (!before) return;\n const em = (ctx.container.resolve(\"em\") as EntityManager).fork();\n let record = await findOneWithDecryption(\n em,\n CatalogProductUnitConversion,\n { id: before.id, deletedAt: null },\n );\n if (!record) {\n record = em.create(CatalogProductUnitConversion, {\n id: before.id,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n product: em.getReference(CatalogProduct, before.productId),\n unitCode: before.unitCode,\n toBaseFactor: before.toBaseFactor,\n sortOrder: before.sortOrder,\n isActive: before.isActive,\n metadata: before.metadata\n ? cloneJson(before.metadata)\n : null,\n createdAt: new Date(before.createdAt),\n updatedAt: new Date(before.updatedAt),\n });\n em.persist(record);\n }\n ensureTenantScope(ctx, before.tenantId);\n ensureOrganizationScope(ctx, before.organizationId);\n applyConversionSnapshot(em, record, before);\n await em.transactional(async () => {\n await em.flush();\n });\n const dataEngine = ctx.container.resolve(\"dataEngine\") as DataEngine;\n await emitConversionCrudUndoChange({\n dataEngine,\n action: \"created\",\n conversion: record,\n });\n },\n};\n\nregisterCommand(createProductUnitConversionCommand);\nregisterCommand(updateProductUnitConversionCommand);\nregisterCommand(deleteProductUnitConversionCommand);\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|