@open-mercato/core 0.6.4-develop.4000.1.450e315cec → 0.6.4-develop.4011.1.4f3ed9ae3e
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/dist/modules/auth/backend/users/[id]/edit/page.js +70 -57
- package/dist/modules/auth/backend/users/[id]/edit/page.js.map +2 -2
- package/dist/modules/catalog/acl.js +30 -5
- package/dist/modules/catalog/acl.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/[id]/page.js +17 -5
- package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
- package/dist/modules/catalog/commands/offers.js +26 -7
- package/dist/modules/catalog/commands/offers.js.map +2 -2
- package/dist/modules/catalog/commands/prices.js +41 -26
- package/dist/modules/catalog/commands/prices.js.map +2 -2
- package/dist/modules/catalog/commands/productUnitConversions.js +7 -1
- package/dist/modules/catalog/commands/productUnitConversions.js.map +2 -2
- package/dist/modules/catalog/commands/products.js +2 -0
- package/dist/modules/catalog/commands/products.js.map +2 -2
- package/dist/modules/catalog/commands/shared.js +58 -11
- package/dist/modules/catalog/commands/shared.js.map +2 -2
- package/dist/modules/catalog/commands/variants.js +18 -5
- package/dist/modules/catalog/commands/variants.js.map +2 -2
- package/dist/modules/resources/backend/resources/resources/[id]/page.js +17 -2
- package/dist/modules/resources/backend/resources/resources/[id]/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/documents/[id]/page.js +20 -1
- package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
- package/package.json +7 -7
- package/src/modules/auth/backend/users/[id]/edit/page.tsx +28 -6
- package/src/modules/auth/i18n/de.json +1 -0
- package/src/modules/auth/i18n/en.json +1 -0
- package/src/modules/auth/i18n/es.json +1 -0
- package/src/modules/auth/i18n/pl.json +1 -0
- package/src/modules/catalog/acl.ts +30 -5
- package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +21 -5
- package/src/modules/catalog/commands/offers.ts +26 -7
- package/src/modules/catalog/commands/prices.ts +41 -26
- package/src/modules/catalog/commands/productUnitConversions.ts +7 -1
- package/src/modules/catalog/commands/products.ts +2 -0
- package/src/modules/catalog/commands/shared.ts +70 -6
- package/src/modules/catalog/commands/variants.ts +18 -5
- package/src/modules/catalog/i18n/de.json +1 -0
- package/src/modules/catalog/i18n/en.json +1 -0
- package/src/modules/catalog/i18n/es.json +1 -0
- package/src/modules/catalog/i18n/pl.json +1 -0
- package/src/modules/resources/backend/resources/resources/[id]/page.tsx +21 -2
- package/src/modules/sales/backend/sales/documents/[id]/page.tsx +28 -1
- package/src/modules/sales/i18n/de.json +3 -0
- package/src/modules/sales/i18n/en.json +3 -0
- package/src/modules/sales/i18n/es.json +3 -0
- package/src/modules/sales/i18n/pl.json +3 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/catalog/commands/prices.ts"],
|
|
4
|
-
"sourcesContent": ["import { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { buildChanges, requireId, parseWithCustomFields, setCustomFieldsIfAny, emitCrudSideEffects } from '@open-mercato/shared/lib/commands/helpers'\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 { CatalogOffer, CatalogProduct, CatalogProductPrice, CatalogProductVariant, CatalogPriceKind } from '../data/entities'\nimport { loadCustomFieldSnapshot, buildCustomFieldResetMap } from '@open-mercato/shared/lib/commands/customFieldSnapshots'\nimport { E } from '#generated/entities.ids.generated'\nimport {\n priceCreateSchema,\n priceUpdateSchema,\n type PriceCreateInput,\n type PriceUpdateInput,\n} from '../data/validators'\nimport type { TaxCalculationService } from '@open-mercato/core/modules/sales/services/taxCalculationService'\nimport {\n cloneJson,\n ensureOrganizationScope,\n ensureSameScope,\n ensureSameTenant,\n ensureTenantScope,\n extractUndoPayload,\n requireVariant,\n requireProduct,\n requireOffer,\n requirePriceKind,\n toNumericString,\n} from './shared'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport type { CrudEventsConfig } from '@open-mercato/shared/lib/crud/types'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\n\nconst priceCrudEvents: CrudEventsConfig = {\n module: 'catalog',\n entity: 'price',\n persistent: true,\n buildPayload: (ctx) => ({\n id: ctx.identifiers.id,\n organizationId: ctx.identifiers.organizationId,\n tenantId: ctx.identifiers.tenantId,\n }),\n}\n\ntype PriceSnapshot = {\n id: string\n variantId: string | null\n productId: string | null\n offerId: string | null\n organizationId: string\n tenantId: string\n currencyCode: string\n priceKindId: string\n priceKindCode: string\n kind: string\n minQuantity: number\n maxQuantity: number | null\n unitPriceNet: string | null\n unitPriceGross: string | null\n taxRate: string | null\n taxAmount: string | null\n channelId: string | null\n userId: string | null\n userGroupId: string | null\n customerId: string | null\n customerGroupId: string | null\n metadata: Record<string, unknown> | null\n startsAt: string | null\n endsAt: string | null\n createdAt: string\n updatedAt: string\n custom: Record<string, unknown> | null\n}\n\ntype PriceUndoPayload = {\n before?: PriceSnapshot | null\n after?: PriceSnapshot | null\n}\n\nconst PRICE_CHANGE_KEYS = [\n 'currencyCode',\n 'priceKindId',\n 'kind',\n 'minQuantity',\n 'maxQuantity',\n 'unitPriceNet',\n 'unitPriceGross',\n 'taxRate',\n 'taxAmount',\n 'channelId',\n 'userId',\n 'userGroupId',\n 'customerId',\n 'customerGroupId',\n 'metadata',\n 'startsAt',\n 'endsAt',\n] as const satisfies readonly string[]\n\nasync function resolveSnapshotAssociations(\n em: EntityManager,\n snapshot: PriceSnapshot\n): Promise<{\n variant: CatalogProductVariant | null\n product: CatalogProduct\n offer: CatalogOffer | null\n}> {\n let variant: CatalogProductVariant | null = null\n if (snapshot.variantId) {\n variant = await requireVariant(em, snapshot.variantId)\n }\n let product: CatalogProduct | null = null\n if (snapshot.productId) {\n product = await requireProduct(em, snapshot.productId)\n } else if (variant) {\n product =\n typeof variant.product === 'string'\n ? await requireProduct(em, variant.product)\n : variant.product\n }\n if (!product) {\n throw new CrudHttpError(400, { error: 'Price snapshot missing product association.' })\n }\n let offer: CatalogOffer | null = null\n if (snapshot.offerId) {\n offer = await requireOffer(em, snapshot.offerId)\n }\n return { variant, product, offer }\n}\n\nasync function loadPriceSnapshot(em: EntityManager, id: string): Promise<PriceSnapshot | null> {\n const record = await findOneWithDecryption(\n em,\n CatalogProductPrice,\n { id },\n { populate: ['priceKind', 'product', 'variant', 'offer'] },\n )\n if (!record) return null\n const variantId =\n typeof record.variant === 'string'\n ? record.variant\n : record.variant\n ? record.variant.id\n : null\n const productRef = record.product\n ? record.product\n : typeof record.variant === 'object' && record.variant\n ? record.variant.product\n : null\n const productId =\n typeof productRef === 'string'\n ? productRef\n : productRef\n ? productRef.id\n : null\n const custom = await loadCustomFieldSnapshot(em, {\n entityId: E.catalog.catalog_product_price,\n recordId: record.id,\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n })\n const priceKind = record.priceKind\n const priceKindId =\n typeof priceKind === 'string'\n ? priceKind\n : priceKind\n ? priceKind.id\n : null\n if (!priceKindId) {\n throw new CrudHttpError(400, { error: 'Price is missing price kind metadata.' })\n }\n const priceKindCode =\n typeof priceKind === 'object' && priceKind ? priceKind.code : record.kind\n return {\n id: record.id,\n variantId,\n productId,\n offerId: typeof record.offer === 'string' ? record.offer : record.offer ? record.offer.id : null,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n currencyCode: record.currencyCode,\n priceKindId,\n priceKindCode,\n kind: record.kind,\n minQuantity: record.minQuantity,\n maxQuantity: record.maxQuantity ?? null,\n unitPriceNet: record.unitPriceNet ?? null,\n unitPriceGross: record.unitPriceGross ?? null,\n taxRate: record.taxRate ?? null,\n taxAmount: record.taxAmount ?? null,\n channelId: record.channelId ?? null,\n userId: record.userId ?? null,\n userGroupId: record.userGroupId ?? null,\n customerId: record.customerId ?? null,\n customerGroupId: record.customerGroupId ?? null,\n metadata: record.metadata ? cloneJson(record.metadata) : null,\n startsAt: record.startsAt ? record.startsAt.toISOString() : null,\n endsAt: record.endsAt ? record.endsAt.toISOString() : null,\n createdAt: record.createdAt.toISOString(),\n updatedAt: record.updatedAt.toISOString(),\n custom: Object.keys(custom).length ? custom : null,\n }\n}\n\nfunction applyPriceSnapshot(em: EntityManager, record: CatalogProductPrice, snapshot: PriceSnapshot): void {\n record.organizationId = snapshot.organizationId\n record.tenantId = snapshot.tenantId\n record.currencyCode = snapshot.currencyCode\n record.priceKind = em.getReference(CatalogPriceKind, snapshot.priceKindId)\n record.kind = snapshot.priceKindCode || snapshot.kind\n record.minQuantity = snapshot.minQuantity\n record.maxQuantity = snapshot.maxQuantity ?? null\n record.unitPriceNet = snapshot.unitPriceNet ?? null\n record.unitPriceGross = snapshot.unitPriceGross ?? null\n record.taxRate = snapshot.taxRate ?? null\n record.taxAmount = snapshot.taxAmount ?? null\n record.channelId = snapshot.channelId ?? null\n record.userId = snapshot.userId ?? null\n record.userGroupId = snapshot.userGroupId ?? null\n record.customerId = snapshot.customerId ?? null\n record.customerGroupId = snapshot.customerGroupId ?? null\n record.metadata = snapshot.metadata ? cloneJson(snapshot.metadata) : null\n record.startsAt = snapshot.startsAt ? new Date(snapshot.startsAt) : null\n record.endsAt = snapshot.endsAt ? new Date(snapshot.endsAt) : null\n record.createdAt = new Date(snapshot.createdAt)\n record.updatedAt = new Date(snapshot.updatedAt)\n}\n\ntype PriceAmountInput = {\n amount: number\n mode: 'net' | 'gross'\n}\n\nfunction resolveAmountInputFromParsed(\n parsed: Partial<Pick<PriceCreateInput, 'unitPriceNet' | 'unitPriceGross'>>\n): PriceAmountInput | null {\n if (typeof parsed.unitPriceNet === 'number' && Number.isFinite(parsed.unitPriceNet)) {\n return { amount: parsed.unitPriceNet, mode: 'net' }\n }\n if (typeof parsed.unitPriceGross === 'number' && Number.isFinite(parsed.unitPriceGross)) {\n return { amount: parsed.unitPriceGross, mode: 'gross' }\n }\n return null\n}\n\nfunction resolveAmountInputFromRecord(record: CatalogProductPrice): PriceAmountInput | null {\n const net = numericStringToNumber(record.unitPriceNet)\n if (net !== null) return { amount: net, mode: 'net' }\n const gross = numericStringToNumber(record.unitPriceGross)\n if (gross !== null) return { amount: gross, mode: 'gross' }\n return null\n}\n\nfunction numericStringToNumber(value: string | null | undefined): number | null {\n if (value === undefined || value === null) return null\n const numeric = Number(value)\n return Number.isFinite(numeric) ? numeric : null\n}\n\nconst createPriceCommand: CommandHandler<PriceCreateInput, { priceId: string }> = {\n id: 'catalog.prices.create',\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(priceCreateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let variant: CatalogProductVariant | null = null\n let product: CatalogProduct | null = null\n if (parsed.variantId) {\n variant = await requireVariant(em, parsed.variantId)\n product =\n typeof variant.product === 'string'\n ? await requireProduct(em, variant.product)\n : variant.product\n }\n if (parsed.productId) {\n const explicitProduct = await requireProduct(em, parsed.productId)\n if (product && explicitProduct.id !== product.id) {\n throw new CrudHttpError(400, { error: 'Variant does not belong to the provided product.' })\n }\n product = explicitProduct\n }\n if (!variant && !product) {\n throw new CrudHttpError(400, { error: 'Provide either a variantId or productId for pricing.' })\n }\n const scopeSource = variant ?? product!\n ensureTenantScope(ctx, scopeSource.tenantId)\n ensureOrganizationScope(ctx, scopeSource.organizationId)\n\n const priceKind = await requirePriceKind(em, parsed.priceKindId)\n ensureSameTenant(priceKind, scopeSource.tenantId)\n\n let offer: CatalogOffer | null = null\n if (parsed.offerId) {\n offer = await requireOffer(em, parsed.offerId)\n ensureSameScope(offer, scopeSource.organizationId, scopeSource.tenantId)\n const offerProduct =\n typeof offer.product === 'string'\n ? await requireProduct(em, offer.product)\n : offer.product\n if (product && offerProduct.id !== product.id) {\n throw new CrudHttpError(400, { error: 'Offer does not belong to the selected product.' })\n }\n product = offerProduct\n }\n const productEntity = product\n const channelId = parsed.channelId ?? (offer ? offer.channelId : null)\n const taxCalculationService = ctx.container.resolve<TaxCalculationService>('taxCalculationService')\n const amountInput = resolveAmountInputFromParsed(parsed)\n let unitPriceNetValue = toNumericString(parsed.unitPriceNet)\n let unitPriceGrossValue = toNumericString(parsed.unitPriceGross)\n let taxRateValue = toNumericString(parsed.taxRate)\n let taxAmountValue: string | null = null\n if (amountInput) {\n const calculation = await taxCalculationService.calculateUnitAmounts({\n amount: amountInput.amount,\n mode: amountInput.mode,\n organizationId: scopeSource.organizationId,\n tenantId: scopeSource.tenantId,\n taxRateId: parsed.taxRateId ?? null,\n taxRate: parsed.taxRate ?? null,\n })\n unitPriceNetValue = toNumericString(calculation.netAmount)\n unitPriceGrossValue = toNumericString(calculation.grossAmount)\n taxAmountValue = toNumericString(calculation.taxAmount)\n taxRateValue = toNumericString(calculation.taxRate)\n }\n\n const now = new Date()\n const record = em.create(CatalogProductPrice, {\n organizationId: scopeSource.organizationId,\n tenantId: scopeSource.tenantId,\n variant,\n product: productEntity ?? undefined,\n offer: offer ?? undefined,\n priceKind,\n currencyCode: parsed.currencyCode,\n kind: priceKind.code,\n minQuantity: parsed.minQuantity ?? 1,\n maxQuantity: parsed.maxQuantity ?? null,\n unitPriceNet: unitPriceNetValue,\n unitPriceGross: unitPriceGrossValue,\n taxRate: taxRateValue,\n taxAmount: taxAmountValue,\n channelId,\n userId: parsed.userId ?? null,\n userGroupId: parsed.userGroupId ?? null,\n customerId: parsed.customerId ?? null,\n customerGroupId: parsed.customerGroupId ?? null,\n metadata: parsed.metadata ? cloneJson(parsed.metadata) : null,\n startsAt: parsed.startsAt ?? null,\n endsAt: parsed.endsAt ?? null,\n createdAt: now,\n updatedAt: now,\n })\n em.persist(record)\n await em.flush()\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_product_price,\n recordId: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n values: custom,\n })\n const de = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: record,\n identifiers: {\n id: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n },\n events: priceCrudEvents,\n })\n return { priceId: record.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return loadPriceSnapshot(em, result.priceId)\n },\n buildLog: async ({ result, snapshots }) => {\n const after = snapshots.after as PriceSnapshot | undefined\n if (!after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('catalog.audit.prices.create', 'Create product price'),\n resourceKind: 'catalog.price',\n resourceId: result.priceId,\n tenantId: after.tenantId,\n organizationId: after.organizationId,\n snapshotAfter: after,\n payload: {\n undo: {\n after,\n } satisfies PriceUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<PriceUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const record = await em.findOne(CatalogProductPrice, { id: after.id })\n if (!record) return\n ensureTenantScope(ctx, record.tenantId)\n ensureOrganizationScope(ctx, record.organizationId)\n em.remove(record)\n await em.flush()\n const resetValues = buildCustomFieldResetMap(undefined, after.custom ?? undefined)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_product_price,\n recordId: after.id,\n organizationId: after.organizationId,\n tenantId: after.tenantId,\n values: resetValues,\n })\n }\n },\n}\n\nconst updatePriceCommand: CommandHandler<PriceUpdateInput, { priceId: string }> = {\n id: 'catalog.prices.update',\n async prepare(input, ctx) {\n const id = requireId(input, 'Price id is required')\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadPriceSnapshot(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, custom } = parseWithCustomFields(priceUpdateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const record = await findOneWithDecryption(\n em,\n CatalogProductPrice,\n { id: parsed.id },\n { populate: ['priceKind'] },\n { tenantId: parsed.tenantId, organizationId: parsed.organizationId },\n )\n if (!record) throw new CrudHttpError(404, { error: 'Catalog price not found' })\n const currentVariantRef = record.variant\n let targetVariant: CatalogProductVariant | null = null\n if (typeof currentVariantRef === 'string') {\n targetVariant = await requireVariant(em, currentVariantRef)\n } else if (currentVariantRef) {\n targetVariant = currentVariantRef\n }\n const currentProductRef = record.product ?? (targetVariant ? targetVariant.product : null)\n let targetProduct: CatalogProduct | null = null\n if (typeof currentProductRef === 'string') {\n targetProduct = await requireProduct(em, currentProductRef)\n } else if (currentProductRef) {\n targetProduct = currentProductRef\n }\n\n if (parsed.variantId !== undefined) {\n if (!parsed.variantId) {\n targetVariant = null\n } else {\n targetVariant = await requireVariant(em, parsed.variantId)\n targetProduct =\n typeof targetVariant.product === 'string'\n ? await requireProduct(em, targetVariant.product)\n : targetVariant.product\n }\n }\n\n if (targetVariant && (targetVariant as CatalogProductVariant | null)?.product === undefined) {\n targetVariant = await requireVariant(em, targetVariant.id)\n }\n\n if (parsed.productId !== undefined) {\n if (!parsed.productId) {\n targetProduct = null\n } else {\n const explicitProduct = await requireProduct(em, parsed.productId)\n if (targetVariant) {\n const variantProductId =\n typeof targetVariant.product === 'string'\n ? targetVariant.product\n : targetVariant.product.id\n if (variantProductId !== explicitProduct.id) {\n throw new CrudHttpError(400, { error: 'Variant does not belong to the provided product.' })\n }\n }\n targetProduct = explicitProduct\n }\n }\n\n if (!targetVariant && !targetProduct) {\n throw new CrudHttpError(400, { error: 'Price must remain associated with a product or variant.' })\n }\n if (!targetProduct && targetVariant) {\n targetProduct =\n typeof targetVariant.product === 'string'\n ? await requireProduct(em, targetVariant.product)\n : targetVariant.product\n }\n if (!targetProduct) {\n throw new CrudHttpError(400, { error: 'Unable to resolve product for price.' })\n }\n\n let targetOffer: CatalogOffer | null = null\n if (record.offer) {\n targetOffer =\n typeof record.offer === 'string'\n ? await requireOffer(em, record.offer)\n : record.offer\n }\n if (parsed.offerId !== undefined) {\n if (!parsed.offerId) {\n targetOffer = null\n } else {\n const explicitOffer = await requireOffer(em, parsed.offerId)\n ensureSameScope(explicitOffer, targetProduct.organizationId, targetProduct.tenantId)\n const offerProductId =\n typeof explicitOffer.product === 'string'\n ? explicitOffer.product\n : explicitOffer.product.id\n if (offerProductId !== targetProduct.id) {\n throw new CrudHttpError(400, { error: 'Offer does not belong to the selected product.' })\n }\n targetOffer = explicitOffer\n }\n }\n\n ensureTenantScope(ctx, targetProduct.tenantId)\n ensureOrganizationScope(ctx, targetProduct.organizationId)\n\n let targetPriceKind: CatalogPriceKind | null = null\n if (record.priceKind) {\n targetPriceKind =\n typeof record.priceKind === 'string'\n ? await requirePriceKind(em, record.priceKind)\n : record.priceKind\n }\n if (parsed.priceKindId !== undefined) {\n if (!parsed.priceKindId) {\n throw new CrudHttpError(400, { error: 'Price kind is required.' })\n }\n targetPriceKind = await requirePriceKind(em, parsed.priceKindId)\n }\n if (!targetPriceKind) {\n throw new CrudHttpError(400, { error: 'Price kind is required.' })\n }\n ensureSameTenant(targetPriceKind, targetProduct.tenantId)\n\n const taxCalculationService = ctx.container.resolve<TaxCalculationService>('taxCalculationService')\n const amountInput = resolveAmountInputFromParsed(parsed)\n const hasNetInput = Object.prototype.hasOwnProperty.call(parsed, 'unitPriceNet')\n const hasGrossInput = Object.prototype.hasOwnProperty.call(parsed, 'unitPriceGross')\n const hasTaxRateInput = Object.prototype.hasOwnProperty.call(parsed, 'taxRate')\n const hasTaxRateIdInput = Object.prototype.hasOwnProperty.call(parsed, 'taxRateId')\n let taxCalculationResult: Awaited<ReturnType<TaxCalculationService['calculateUnitAmounts']>> | null = null\n let calculationBase = amountInput\n if (!calculationBase && (hasTaxRateInput || hasTaxRateIdInput)) {\n calculationBase = resolveAmountInputFromRecord(record)\n }\n if (calculationBase) {\n const taxRateIdForCalculation = hasTaxRateIdInput ? parsed.taxRateId ?? null : undefined\n const taxRateForCalculation = hasTaxRateInput\n ? parsed.taxRate ?? null\n : taxRateIdForCalculation === null\n ? null\n : record.taxRate ?? null\n taxCalculationResult = await taxCalculationService.calculateUnitAmounts({\n amount: calculationBase.amount,\n mode: calculationBase.mode,\n organizationId: targetProduct.organizationId,\n tenantId: targetProduct.tenantId,\n taxRateId: taxRateIdForCalculation,\n taxRate: taxRateForCalculation,\n })\n }\n\n record.variant = targetVariant\n record.product = targetProduct\n record.offer = targetOffer\n record.organizationId = targetProduct.organizationId\n record.tenantId = targetProduct.tenantId\n record.priceKind = targetPriceKind\n record.kind = targetPriceKind.code\n\n if (parsed.currencyCode !== undefined) record.currencyCode = parsed.currencyCode\n if (parsed.minQuantity !== undefined) record.minQuantity = parsed.minQuantity ?? 1\n if (parsed.maxQuantity !== undefined) record.maxQuantity = parsed.maxQuantity ?? null\n if (taxCalculationResult) {\n record.unitPriceNet = toNumericString(taxCalculationResult.netAmount)\n record.unitPriceGross = toNumericString(taxCalculationResult.grossAmount)\n record.taxRate = toNumericString(taxCalculationResult.taxRate)\n record.taxAmount = toNumericString(taxCalculationResult.taxAmount)\n } else {\n if (hasNetInput) {\n record.unitPriceNet = toNumericString(parsed.unitPriceNet)\n }\n if (hasGrossInput) {\n record.unitPriceGross = toNumericString(parsed.unitPriceGross)\n }\n if (hasTaxRateInput) {\n record.taxRate = toNumericString(parsed.taxRate)\n if (parsed.taxRate == null) {\n record.taxAmount = null\n }\n } else if (hasTaxRateIdInput && parsed.taxRateId === null) {\n record.taxRate = null\n record.taxAmount = null\n }\n }\n if (parsed.channelId !== undefined) {\n record.channelId = parsed.channelId ?? null\n } else if (parsed.offerId !== undefined && targetOffer) {\n record.channelId = targetOffer.channelId\n }\n if (parsed.userId !== undefined) record.userId = parsed.userId ?? null\n if (parsed.userGroupId !== undefined) record.userGroupId = parsed.userGroupId ?? null\n if (parsed.customerId !== undefined) record.customerId = parsed.customerId ?? null\n if (parsed.customerGroupId !== undefined) record.customerGroupId = parsed.customerGroupId ?? null\n if (parsed.metadata !== undefined) {\n record.metadata = parsed.metadata ? cloneJson(parsed.metadata) : null\n }\n if (Object.prototype.hasOwnProperty.call(parsed, 'startsAt')) {\n record.startsAt = parsed.startsAt ?? null\n }\n if (Object.prototype.hasOwnProperty.call(parsed, 'endsAt')) {\n record.endsAt = parsed.endsAt ?? null\n }\n await em.flush()\n if (custom && Object.keys(custom).length) {\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_product_price,\n recordId: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n values: custom,\n })\n }\n const de = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: record,\n identifiers: {\n id: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n },\n events: priceCrudEvents,\n })\n return { priceId: record.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return loadPriceSnapshot(em, result.priceId)\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as PriceSnapshot | undefined\n const after = snapshots.after as PriceSnapshot | undefined\n if (!before || !after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('catalog.audit.prices.update', 'Update product price'),\n resourceKind: 'catalog.price',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes: buildChanges(\n before as Record<string, unknown>,\n after as Record<string, unknown>,\n PRICE_CHANGE_KEYS\n ),\n payload: {\n undo: {\n before,\n after,\n } satisfies PriceUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<PriceUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const after = payload?.after\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let record = await em.findOne(CatalogProductPrice, { id: before.id })\n if (!record) {\n const { variant, product, offer } = await resolveSnapshotAssociations(em, before)\n record = em.create(CatalogProductPrice, {\n id: before.id,\n variant,\n product,\n offer,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n currencyCode: before.currencyCode,\n priceKind: em.getReference(CatalogPriceKind, before.priceKindId),\n kind: before.priceKindCode || before.kind,\n minQuantity: before.minQuantity,\n maxQuantity: before.maxQuantity ?? null,\n unitPriceNet: before.unitPriceNet ?? null,\n unitPriceGross: before.unitPriceGross ?? null,\n taxRate: before.taxRate ?? null,\n taxAmount: before.taxAmount ?? null,\n channelId: before.channelId ?? null,\n userId: before.userId ?? null,\n userGroupId: before.userGroupId ?? null,\n customerId: before.customerId ?? null,\n customerGroupId: before.customerGroupId ?? null,\n metadata: before.metadata ? cloneJson(before.metadata) : null,\n startsAt: before.startsAt ? new Date(before.startsAt) : null,\n endsAt: before.endsAt ? new Date(before.endsAt) : 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 applyPriceSnapshot(em, record, before)\n await em.flush()\n const resetValues = buildCustomFieldResetMap(\n before.custom ?? undefined,\n after?.custom ?? undefined\n )\n if (Object.keys(resetValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_product_price,\n recordId: before.id,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n values: resetValues,\n })\n }\n },\n}\n\nconst deletePriceCommand: CommandHandler<\n { body?: Record<string, unknown>; query?: Record<string, unknown> },\n { priceId: string }\n> = {\n id: 'catalog.prices.delete',\n async prepare(input, ctx) {\n const id = requireId(input, 'Price id is required')\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadPriceSnapshot(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(input, ctx) {\n const id = requireId(input, 'Price id is required')\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const record = await em.findOne(CatalogProductPrice, { id })\n if (!record) throw new CrudHttpError(404, { error: 'Catalog price not found' })\n ensureTenantScope(ctx, record.tenantId)\n ensureOrganizationScope(ctx, record.organizationId)\n const { product } = await resolvePriceRecordAssociations(em, record)\n\n const baseEm = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadPriceSnapshot(baseEm, id)\n\n em.remove(record)\n await em.flush()\n if (snapshot?.custom && Object.keys(snapshot.custom).length) {\n const resetValues = buildCustomFieldResetMap(snapshot.custom, undefined)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_product_price,\n recordId: id,\n organizationId: snapshot.organizationId,\n tenantId: snapshot.tenantId,\n values: resetValues,\n })\n }\n }\n const de = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'deleted',\n entity: record,\n identifiers: {\n id,\n organizationId: snapshot?.organizationId ?? record.organizationId,\n tenantId: snapshot?.tenantId ?? record.tenantId,\n },\n events: priceCrudEvents,\n })\n return { priceId: id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as PriceSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('catalog.audit.prices.delete', 'Delete product price'),\n resourceKind: 'catalog.price',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: {\n before,\n } satisfies PriceUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<PriceUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let record = await em.findOne(CatalogProductPrice, { id: before.id })\n if (!record) {\n const { variant, product, offer } = await resolveSnapshotAssociations(em, before)\n record = em.create(CatalogProductPrice, {\n id: before.id,\n variant,\n product,\n offer,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n currencyCode: before.currencyCode,\n priceKind: em.getReference(CatalogPriceKind, before.priceKindId),\n kind: before.priceKindCode || before.kind,\n minQuantity: before.minQuantity,\n maxQuantity: before.maxQuantity ?? null,\n unitPriceNet: before.unitPriceNet ?? null,\n unitPriceGross: before.unitPriceGross ?? null,\n taxRate: before.taxRate ?? null,\n taxAmount: before.taxAmount ?? null,\n channelId: before.channelId ?? null,\n userId: before.userId ?? null,\n userGroupId: before.userGroupId ?? null,\n customerId: before.customerId ?? null,\n customerGroupId: before.customerGroupId ?? null,\n metadata: before.metadata ? cloneJson(before.metadata) : null,\n startsAt: before.startsAt ? new Date(before.startsAt) : null,\n endsAt: before.endsAt ? new Date(before.endsAt) : 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 applyPriceSnapshot(em, record, before)\n await em.flush()\n if (before.custom && Object.keys(before.custom).length) {\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_product_price,\n recordId: before.id,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n values: before.custom,\n })\n }\n },\n}\n\nregisterCommand(createPriceCommand)\nregisterCommand(updatePriceCommand)\nregisterCommand(deletePriceCommand)\n\nasync function resolvePriceRecordAssociations(\n em: EntityManager,\n record: CatalogProductPrice,\n): Promise<{ product: CatalogProduct; variant: CatalogProductVariant | null }> {\n const variant = record.variant\n ? (typeof record.variant === 'string'\n ? await requireVariant(em, record.variant)\n : record.variant)\n : null\n if (record.product) {\n const product =\n typeof record.product === 'string'\n ? await requireProduct(em, record.product)\n : record.product\n return { product, variant }\n }\n if (variant?.product) {\n const productRef = variant.product\n const product =\n typeof productRef === 'string'\n ? await requireProduct(em, productRef)\n : productRef\n return { product, variant }\n }\n if (record.offer) {\n const offer =\n typeof record.offer === 'string'\n ? await requireOffer(em, record.offer)\n : record.offer\n const productRef = offer?.product ?? null\n if (productRef) {\n const product =\n typeof productRef === 'string'\n ? await requireProduct(em, productRef)\n : productRef\n return { product, variant }\n }\n }\n throw new CrudHttpError(400, { error: 'Catalog price is not linked to a product.' })\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { buildChanges, requireId, parseWithCustomFields, setCustomFieldsIfAny, emitCrudSideEffects } from '@open-mercato/shared/lib/commands/helpers'\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 { CatalogOffer, CatalogProduct, CatalogProductPrice, CatalogProductVariant, CatalogPriceKind } from '../data/entities'\nimport { loadCustomFieldSnapshot, buildCustomFieldResetMap } from '@open-mercato/shared/lib/commands/customFieldSnapshots'\nimport { E } from '#generated/entities.ids.generated'\nimport {\n priceCreateSchema,\n priceUpdateSchema,\n type PriceCreateInput,\n type PriceUpdateInput,\n} from '../data/validators'\nimport type { TaxCalculationService } from '@open-mercato/core/modules/sales/services/taxCalculationService'\nimport {\n cloneJson,\n commandActorScope,\n ensureOrganizationScope,\n ensureSameScope,\n ensureSameTenant,\n ensureTenantScope,\n extractUndoPayload,\n requireVariant,\n requireProduct,\n requireOffer,\n requirePriceKind,\n toNumericString,\n} from './shared'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport type { CrudEventsConfig } from '@open-mercato/shared/lib/crud/types'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\n\nconst priceCrudEvents: CrudEventsConfig = {\n module: 'catalog',\n entity: 'price',\n persistent: true,\n buildPayload: (ctx) => ({\n id: ctx.identifiers.id,\n organizationId: ctx.identifiers.organizationId,\n tenantId: ctx.identifiers.tenantId,\n }),\n}\n\ntype PriceSnapshot = {\n id: string\n variantId: string | null\n productId: string | null\n offerId: string | null\n organizationId: string\n tenantId: string\n currencyCode: string\n priceKindId: string\n priceKindCode: string\n kind: string\n minQuantity: number\n maxQuantity: number | null\n unitPriceNet: string | null\n unitPriceGross: string | null\n taxRate: string | null\n taxAmount: string | null\n channelId: string | null\n userId: string | null\n userGroupId: string | null\n customerId: string | null\n customerGroupId: string | null\n metadata: Record<string, unknown> | null\n startsAt: string | null\n endsAt: string | null\n createdAt: string\n updatedAt: string\n custom: Record<string, unknown> | null\n}\n\ntype PriceUndoPayload = {\n before?: PriceSnapshot | null\n after?: PriceSnapshot | null\n}\n\nconst PRICE_CHANGE_KEYS = [\n 'currencyCode',\n 'priceKindId',\n 'kind',\n 'minQuantity',\n 'maxQuantity',\n 'unitPriceNet',\n 'unitPriceGross',\n 'taxRate',\n 'taxAmount',\n 'channelId',\n 'userId',\n 'userGroupId',\n 'customerId',\n 'customerGroupId',\n 'metadata',\n 'startsAt',\n 'endsAt',\n] as const satisfies readonly string[]\n\nasync function resolveSnapshotAssociations(\n em: EntityManager,\n snapshot: PriceSnapshot\n): Promise<{\n variant: CatalogProductVariant | null\n product: CatalogProduct\n offer: CatalogOffer | null\n}> {\n const scope = { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId }\n let variant: CatalogProductVariant | null = null\n if (snapshot.variantId) {\n variant = await requireVariant(em, snapshot.variantId, scope)\n }\n let product: CatalogProduct | null = null\n if (snapshot.productId) {\n product = await requireProduct(em, snapshot.productId, scope)\n } else if (variant) {\n product =\n typeof variant.product === 'string'\n ? await requireProduct(em, variant.product, scope)\n : variant.product\n }\n if (!product) {\n throw new CrudHttpError(400, { error: 'Price snapshot missing product association.' })\n }\n let offer: CatalogOffer | null = null\n if (snapshot.offerId) {\n offer = await requireOffer(em, snapshot.offerId, scope)\n }\n return { variant, product, offer }\n}\n\nasync function loadPriceSnapshot(em: EntityManager, id: string): Promise<PriceSnapshot | null> {\n const record = await findOneWithDecryption(\n em,\n CatalogProductPrice,\n { id },\n { populate: ['priceKind', 'product', 'variant', 'offer'] },\n )\n if (!record) return null\n const variantId =\n typeof record.variant === 'string'\n ? record.variant\n : record.variant\n ? record.variant.id\n : null\n const productRef = record.product\n ? record.product\n : typeof record.variant === 'object' && record.variant\n ? record.variant.product\n : null\n const productId =\n typeof productRef === 'string'\n ? productRef\n : productRef\n ? productRef.id\n : null\n const custom = await loadCustomFieldSnapshot(em, {\n entityId: E.catalog.catalog_product_price,\n recordId: record.id,\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n })\n const priceKind = record.priceKind\n const priceKindId =\n typeof priceKind === 'string'\n ? priceKind\n : priceKind\n ? priceKind.id\n : null\n if (!priceKindId) {\n throw new CrudHttpError(400, { error: 'Price is missing price kind metadata.' })\n }\n const priceKindCode =\n typeof priceKind === 'object' && priceKind ? priceKind.code : record.kind\n return {\n id: record.id,\n variantId,\n productId,\n offerId: typeof record.offer === 'string' ? record.offer : record.offer ? record.offer.id : null,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n currencyCode: record.currencyCode,\n priceKindId,\n priceKindCode,\n kind: record.kind,\n minQuantity: record.minQuantity,\n maxQuantity: record.maxQuantity ?? null,\n unitPriceNet: record.unitPriceNet ?? null,\n unitPriceGross: record.unitPriceGross ?? null,\n taxRate: record.taxRate ?? null,\n taxAmount: record.taxAmount ?? null,\n channelId: record.channelId ?? null,\n userId: record.userId ?? null,\n userGroupId: record.userGroupId ?? null,\n customerId: record.customerId ?? null,\n customerGroupId: record.customerGroupId ?? null,\n metadata: record.metadata ? cloneJson(record.metadata) : null,\n startsAt: record.startsAt ? record.startsAt.toISOString() : null,\n endsAt: record.endsAt ? record.endsAt.toISOString() : null,\n createdAt: record.createdAt.toISOString(),\n updatedAt: record.updatedAt.toISOString(),\n custom: Object.keys(custom).length ? custom : null,\n }\n}\n\nfunction applyPriceSnapshot(em: EntityManager, record: CatalogProductPrice, snapshot: PriceSnapshot): void {\n record.organizationId = snapshot.organizationId\n record.tenantId = snapshot.tenantId\n record.currencyCode = snapshot.currencyCode\n record.priceKind = em.getReference(CatalogPriceKind, snapshot.priceKindId)\n record.kind = snapshot.priceKindCode || snapshot.kind\n record.minQuantity = snapshot.minQuantity\n record.maxQuantity = snapshot.maxQuantity ?? null\n record.unitPriceNet = snapshot.unitPriceNet ?? null\n record.unitPriceGross = snapshot.unitPriceGross ?? null\n record.taxRate = snapshot.taxRate ?? null\n record.taxAmount = snapshot.taxAmount ?? null\n record.channelId = snapshot.channelId ?? null\n record.userId = snapshot.userId ?? null\n record.userGroupId = snapshot.userGroupId ?? null\n record.customerId = snapshot.customerId ?? null\n record.customerGroupId = snapshot.customerGroupId ?? null\n record.metadata = snapshot.metadata ? cloneJson(snapshot.metadata) : null\n record.startsAt = snapshot.startsAt ? new Date(snapshot.startsAt) : null\n record.endsAt = snapshot.endsAt ? new Date(snapshot.endsAt) : null\n record.createdAt = new Date(snapshot.createdAt)\n record.updatedAt = new Date(snapshot.updatedAt)\n}\n\ntype PriceAmountInput = {\n amount: number\n mode: 'net' | 'gross'\n}\n\nfunction resolveAmountInputFromParsed(\n parsed: Partial<Pick<PriceCreateInput, 'unitPriceNet' | 'unitPriceGross'>>\n): PriceAmountInput | null {\n if (typeof parsed.unitPriceNet === 'number' && Number.isFinite(parsed.unitPriceNet)) {\n return { amount: parsed.unitPriceNet, mode: 'net' }\n }\n if (typeof parsed.unitPriceGross === 'number' && Number.isFinite(parsed.unitPriceGross)) {\n return { amount: parsed.unitPriceGross, mode: 'gross' }\n }\n return null\n}\n\nfunction resolveAmountInputFromRecord(record: CatalogProductPrice): PriceAmountInput | null {\n const net = numericStringToNumber(record.unitPriceNet)\n if (net !== null) return { amount: net, mode: 'net' }\n const gross = numericStringToNumber(record.unitPriceGross)\n if (gross !== null) return { amount: gross, mode: 'gross' }\n return null\n}\n\nfunction numericStringToNumber(value: string | null | undefined): number | null {\n if (value === undefined || value === null) return null\n const numeric = Number(value)\n return Number.isFinite(numeric) ? numeric : null\n}\n\nconst createPriceCommand: CommandHandler<PriceCreateInput, { priceId: string }> = {\n id: 'catalog.prices.create',\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(priceCreateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const actorScope = commandActorScope(ctx)\n let variant: CatalogProductVariant | null = null\n let product: CatalogProduct | null = null\n if (parsed.variantId) {\n variant = await requireVariant(em, parsed.variantId, actorScope)\n product =\n typeof variant.product === 'string'\n ? await requireProduct(em, variant.product, {\n tenantId: variant.tenantId,\n organizationId: variant.organizationId,\n })\n : variant.product\n }\n if (parsed.productId) {\n const explicitProduct = await requireProduct(em, parsed.productId, actorScope)\n if (product && explicitProduct.id !== product.id) {\n throw new CrudHttpError(400, { error: 'Variant does not belong to the provided product.' })\n }\n product = explicitProduct\n }\n if (!variant && !product) {\n throw new CrudHttpError(400, { error: 'Provide either a variantId or productId for pricing.' })\n }\n const scopeSource = variant ?? product!\n ensureTenantScope(ctx, scopeSource.tenantId)\n ensureOrganizationScope(ctx, scopeSource.organizationId)\n const scopeSourceScope = {\n tenantId: scopeSource.tenantId,\n organizationId: scopeSource.organizationId,\n }\n\n const priceKind = await requirePriceKind(em, parsed.priceKindId, scopeSourceScope)\n ensureSameTenant(priceKind, scopeSource.tenantId)\n\n let offer: CatalogOffer | null = null\n if (parsed.offerId) {\n offer = await requireOffer(em, parsed.offerId, scopeSourceScope)\n ensureSameScope(offer, scopeSource.organizationId, scopeSource.tenantId)\n const offerProduct =\n typeof offer.product === 'string'\n ? await requireProduct(em, offer.product, {\n tenantId: offer.tenantId,\n organizationId: offer.organizationId,\n })\n : offer.product\n if (product && offerProduct.id !== product.id) {\n throw new CrudHttpError(400, { error: 'Offer does not belong to the selected product.' })\n }\n product = offerProduct\n }\n const productEntity = product\n const channelId = parsed.channelId ?? (offer ? offer.channelId : null)\n const taxCalculationService = ctx.container.resolve<TaxCalculationService>('taxCalculationService')\n const amountInput = resolveAmountInputFromParsed(parsed)\n let unitPriceNetValue = toNumericString(parsed.unitPriceNet)\n let unitPriceGrossValue = toNumericString(parsed.unitPriceGross)\n let taxRateValue = toNumericString(parsed.taxRate)\n let taxAmountValue: string | null = null\n if (amountInput) {\n const calculation = await taxCalculationService.calculateUnitAmounts({\n amount: amountInput.amount,\n mode: amountInput.mode,\n organizationId: scopeSource.organizationId,\n tenantId: scopeSource.tenantId,\n taxRateId: parsed.taxRateId ?? null,\n taxRate: parsed.taxRate ?? null,\n })\n unitPriceNetValue = toNumericString(calculation.netAmount)\n unitPriceGrossValue = toNumericString(calculation.grossAmount)\n taxAmountValue = toNumericString(calculation.taxAmount)\n taxRateValue = toNumericString(calculation.taxRate)\n }\n\n const now = new Date()\n const record = em.create(CatalogProductPrice, {\n organizationId: scopeSource.organizationId,\n tenantId: scopeSource.tenantId,\n variant,\n product: productEntity ?? undefined,\n offer: offer ?? undefined,\n priceKind,\n currencyCode: parsed.currencyCode,\n kind: priceKind.code,\n minQuantity: parsed.minQuantity ?? 1,\n maxQuantity: parsed.maxQuantity ?? null,\n unitPriceNet: unitPriceNetValue,\n unitPriceGross: unitPriceGrossValue,\n taxRate: taxRateValue,\n taxAmount: taxAmountValue,\n channelId,\n userId: parsed.userId ?? null,\n userGroupId: parsed.userGroupId ?? null,\n customerId: parsed.customerId ?? null,\n customerGroupId: parsed.customerGroupId ?? null,\n metadata: parsed.metadata ? cloneJson(parsed.metadata) : null,\n startsAt: parsed.startsAt ?? null,\n endsAt: parsed.endsAt ?? null,\n createdAt: now,\n updatedAt: now,\n })\n em.persist(record)\n await em.flush()\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_product_price,\n recordId: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n values: custom,\n })\n const de = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: record,\n identifiers: {\n id: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n },\n events: priceCrudEvents,\n })\n return { priceId: record.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return loadPriceSnapshot(em, result.priceId)\n },\n buildLog: async ({ result, snapshots }) => {\n const after = snapshots.after as PriceSnapshot | undefined\n if (!after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('catalog.audit.prices.create', 'Create product price'),\n resourceKind: 'catalog.price',\n resourceId: result.priceId,\n tenantId: after.tenantId,\n organizationId: after.organizationId,\n snapshotAfter: after,\n payload: {\n undo: {\n after,\n } satisfies PriceUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<PriceUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const record = await em.findOne(CatalogProductPrice, { id: after.id })\n if (!record) return\n ensureTenantScope(ctx, record.tenantId)\n ensureOrganizationScope(ctx, record.organizationId)\n em.remove(record)\n await em.flush()\n const resetValues = buildCustomFieldResetMap(undefined, after.custom ?? undefined)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_product_price,\n recordId: after.id,\n organizationId: after.organizationId,\n tenantId: after.tenantId,\n values: resetValues,\n })\n }\n },\n}\n\nconst updatePriceCommand: CommandHandler<PriceUpdateInput, { priceId: string }> = {\n id: 'catalog.prices.update',\n async prepare(input, ctx) {\n const id = requireId(input, 'Price id is required')\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadPriceSnapshot(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, custom } = parseWithCustomFields(priceUpdateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const record = await findOneWithDecryption(\n em,\n CatalogProductPrice,\n { id: parsed.id },\n { populate: ['priceKind'] },\n { tenantId: parsed.tenantId, organizationId: parsed.organizationId },\n )\n if (!record) throw new CrudHttpError(404, { error: 'Catalog price not found' })\n const recordScope = { tenantId: record.tenantId, organizationId: record.organizationId }\n const currentVariantRef = record.variant\n let targetVariant: CatalogProductVariant | null = null\n if (typeof currentVariantRef === 'string') {\n targetVariant = await requireVariant(em, currentVariantRef, recordScope)\n } else if (currentVariantRef) {\n targetVariant = currentVariantRef\n }\n const currentProductRef = record.product ?? (targetVariant ? targetVariant.product : null)\n let targetProduct: CatalogProduct | null = null\n if (typeof currentProductRef === 'string') {\n targetProduct = await requireProduct(em, currentProductRef, recordScope)\n } else if (currentProductRef) {\n targetProduct = currentProductRef\n }\n\n if (parsed.variantId !== undefined) {\n if (!parsed.variantId) {\n targetVariant = null\n } else {\n targetVariant = await requireVariant(em, parsed.variantId, recordScope)\n targetProduct =\n typeof targetVariant.product === 'string'\n ? await requireProduct(em, targetVariant.product, recordScope)\n : targetVariant.product\n }\n }\n\n if (targetVariant && (targetVariant as CatalogProductVariant | null)?.product === undefined) {\n targetVariant = await requireVariant(em, targetVariant.id, recordScope)\n }\n\n if (parsed.productId !== undefined) {\n if (!parsed.productId) {\n targetProduct = null\n } else {\n const explicitProduct = await requireProduct(em, parsed.productId, recordScope)\n if (targetVariant) {\n const variantProductId =\n typeof targetVariant.product === 'string'\n ? targetVariant.product\n : targetVariant.product.id\n if (variantProductId !== explicitProduct.id) {\n throw new CrudHttpError(400, { error: 'Variant does not belong to the provided product.' })\n }\n }\n targetProduct = explicitProduct\n }\n }\n\n if (!targetVariant && !targetProduct) {\n throw new CrudHttpError(400, { error: 'Price must remain associated with a product or variant.' })\n }\n if (!targetProduct && targetVariant) {\n targetProduct =\n typeof targetVariant.product === 'string'\n ? await requireProduct(em, targetVariant.product, recordScope)\n : targetVariant.product\n }\n if (!targetProduct) {\n throw new CrudHttpError(400, { error: 'Unable to resolve product for price.' })\n }\n\n let targetOffer: CatalogOffer | null = null\n if (record.offer) {\n targetOffer =\n typeof record.offer === 'string'\n ? await requireOffer(em, record.offer, recordScope)\n : record.offer\n }\n if (parsed.offerId !== undefined) {\n if (!parsed.offerId) {\n targetOffer = null\n } else {\n const explicitOffer = await requireOffer(em, parsed.offerId, recordScope)\n ensureSameScope(explicitOffer, targetProduct.organizationId, targetProduct.tenantId)\n const offerProductId =\n typeof explicitOffer.product === 'string'\n ? explicitOffer.product\n : explicitOffer.product.id\n if (offerProductId !== targetProduct.id) {\n throw new CrudHttpError(400, { error: 'Offer does not belong to the selected product.' })\n }\n targetOffer = explicitOffer\n }\n }\n\n ensureTenantScope(ctx, targetProduct.tenantId)\n ensureOrganizationScope(ctx, targetProduct.organizationId)\n\n let targetPriceKind: CatalogPriceKind | null = null\n if (record.priceKind) {\n targetPriceKind =\n typeof record.priceKind === 'string'\n ? await requirePriceKind(em, record.priceKind, recordScope)\n : record.priceKind\n }\n if (parsed.priceKindId !== undefined) {\n if (!parsed.priceKindId) {\n throw new CrudHttpError(400, { error: 'Price kind is required.' })\n }\n targetPriceKind = await requirePriceKind(em, parsed.priceKindId, recordScope)\n }\n if (!targetPriceKind) {\n throw new CrudHttpError(400, { error: 'Price kind is required.' })\n }\n ensureSameTenant(targetPriceKind, targetProduct.tenantId)\n\n const taxCalculationService = ctx.container.resolve<TaxCalculationService>('taxCalculationService')\n const amountInput = resolveAmountInputFromParsed(parsed)\n const hasNetInput = Object.prototype.hasOwnProperty.call(parsed, 'unitPriceNet')\n const hasGrossInput = Object.prototype.hasOwnProperty.call(parsed, 'unitPriceGross')\n const hasTaxRateInput = Object.prototype.hasOwnProperty.call(parsed, 'taxRate')\n const hasTaxRateIdInput = Object.prototype.hasOwnProperty.call(parsed, 'taxRateId')\n let taxCalculationResult: Awaited<ReturnType<TaxCalculationService['calculateUnitAmounts']>> | null = null\n let calculationBase = amountInput\n if (!calculationBase && (hasTaxRateInput || hasTaxRateIdInput)) {\n calculationBase = resolveAmountInputFromRecord(record)\n }\n if (calculationBase) {\n const taxRateIdForCalculation = hasTaxRateIdInput ? parsed.taxRateId ?? null : undefined\n const taxRateForCalculation = hasTaxRateInput\n ? parsed.taxRate ?? null\n : taxRateIdForCalculation === null\n ? null\n : record.taxRate ?? null\n taxCalculationResult = await taxCalculationService.calculateUnitAmounts({\n amount: calculationBase.amount,\n mode: calculationBase.mode,\n organizationId: targetProduct.organizationId,\n tenantId: targetProduct.tenantId,\n taxRateId: taxRateIdForCalculation,\n taxRate: taxRateForCalculation,\n })\n }\n\n record.variant = targetVariant\n record.product = targetProduct\n record.offer = targetOffer\n record.organizationId = targetProduct.organizationId\n record.tenantId = targetProduct.tenantId\n record.priceKind = targetPriceKind\n record.kind = targetPriceKind.code\n\n if (parsed.currencyCode !== undefined) record.currencyCode = parsed.currencyCode\n if (parsed.minQuantity !== undefined) record.minQuantity = parsed.minQuantity ?? 1\n if (parsed.maxQuantity !== undefined) record.maxQuantity = parsed.maxQuantity ?? null\n if (taxCalculationResult) {\n record.unitPriceNet = toNumericString(taxCalculationResult.netAmount)\n record.unitPriceGross = toNumericString(taxCalculationResult.grossAmount)\n record.taxRate = toNumericString(taxCalculationResult.taxRate)\n record.taxAmount = toNumericString(taxCalculationResult.taxAmount)\n } else {\n if (hasNetInput) {\n record.unitPriceNet = toNumericString(parsed.unitPriceNet)\n }\n if (hasGrossInput) {\n record.unitPriceGross = toNumericString(parsed.unitPriceGross)\n }\n if (hasTaxRateInput) {\n record.taxRate = toNumericString(parsed.taxRate)\n if (parsed.taxRate == null) {\n record.taxAmount = null\n }\n } else if (hasTaxRateIdInput && parsed.taxRateId === null) {\n record.taxRate = null\n record.taxAmount = null\n }\n }\n if (parsed.channelId !== undefined) {\n record.channelId = parsed.channelId ?? null\n } else if (parsed.offerId !== undefined && targetOffer) {\n record.channelId = targetOffer.channelId\n }\n if (parsed.userId !== undefined) record.userId = parsed.userId ?? null\n if (parsed.userGroupId !== undefined) record.userGroupId = parsed.userGroupId ?? null\n if (parsed.customerId !== undefined) record.customerId = parsed.customerId ?? null\n if (parsed.customerGroupId !== undefined) record.customerGroupId = parsed.customerGroupId ?? null\n if (parsed.metadata !== undefined) {\n record.metadata = parsed.metadata ? cloneJson(parsed.metadata) : null\n }\n if (Object.prototype.hasOwnProperty.call(parsed, 'startsAt')) {\n record.startsAt = parsed.startsAt ?? null\n }\n if (Object.prototype.hasOwnProperty.call(parsed, 'endsAt')) {\n record.endsAt = parsed.endsAt ?? null\n }\n await em.flush()\n if (custom && Object.keys(custom).length) {\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_product_price,\n recordId: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n values: custom,\n })\n }\n const de = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: record,\n identifiers: {\n id: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n },\n events: priceCrudEvents,\n })\n return { priceId: record.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return loadPriceSnapshot(em, result.priceId)\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as PriceSnapshot | undefined\n const after = snapshots.after as PriceSnapshot | undefined\n if (!before || !after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('catalog.audit.prices.update', 'Update product price'),\n resourceKind: 'catalog.price',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes: buildChanges(\n before as Record<string, unknown>,\n after as Record<string, unknown>,\n PRICE_CHANGE_KEYS\n ),\n payload: {\n undo: {\n before,\n after,\n } satisfies PriceUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<PriceUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const after = payload?.after\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let record = await em.findOne(CatalogProductPrice, { id: before.id })\n if (!record) {\n const { variant, product, offer } = await resolveSnapshotAssociations(em, before)\n record = em.create(CatalogProductPrice, {\n id: before.id,\n variant,\n product,\n offer,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n currencyCode: before.currencyCode,\n priceKind: em.getReference(CatalogPriceKind, before.priceKindId),\n kind: before.priceKindCode || before.kind,\n minQuantity: before.minQuantity,\n maxQuantity: before.maxQuantity ?? null,\n unitPriceNet: before.unitPriceNet ?? null,\n unitPriceGross: before.unitPriceGross ?? null,\n taxRate: before.taxRate ?? null,\n taxAmount: before.taxAmount ?? null,\n channelId: before.channelId ?? null,\n userId: before.userId ?? null,\n userGroupId: before.userGroupId ?? null,\n customerId: before.customerId ?? null,\n customerGroupId: before.customerGroupId ?? null,\n metadata: before.metadata ? cloneJson(before.metadata) : null,\n startsAt: before.startsAt ? new Date(before.startsAt) : null,\n endsAt: before.endsAt ? new Date(before.endsAt) : 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 applyPriceSnapshot(em, record, before)\n await em.flush()\n const resetValues = buildCustomFieldResetMap(\n before.custom ?? undefined,\n after?.custom ?? undefined\n )\n if (Object.keys(resetValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_product_price,\n recordId: before.id,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n values: resetValues,\n })\n }\n },\n}\n\nconst deletePriceCommand: CommandHandler<\n { body?: Record<string, unknown>; query?: Record<string, unknown> },\n { priceId: string }\n> = {\n id: 'catalog.prices.delete',\n async prepare(input, ctx) {\n const id = requireId(input, 'Price id is required')\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadPriceSnapshot(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(input, ctx) {\n const id = requireId(input, 'Price id is required')\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const record = await em.findOne(CatalogProductPrice, { id })\n if (!record) throw new CrudHttpError(404, { error: 'Catalog price not found' })\n ensureTenantScope(ctx, record.tenantId)\n ensureOrganizationScope(ctx, record.organizationId)\n const { product } = await resolvePriceRecordAssociations(em, record)\n\n const baseEm = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadPriceSnapshot(baseEm, id)\n\n em.remove(record)\n await em.flush()\n if (snapshot?.custom && Object.keys(snapshot.custom).length) {\n const resetValues = buildCustomFieldResetMap(snapshot.custom, undefined)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_product_price,\n recordId: id,\n organizationId: snapshot.organizationId,\n tenantId: snapshot.tenantId,\n values: resetValues,\n })\n }\n }\n const de = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'deleted',\n entity: record,\n identifiers: {\n id,\n organizationId: snapshot?.organizationId ?? record.organizationId,\n tenantId: snapshot?.tenantId ?? record.tenantId,\n },\n events: priceCrudEvents,\n })\n return { priceId: id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as PriceSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('catalog.audit.prices.delete', 'Delete product price'),\n resourceKind: 'catalog.price',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: {\n before,\n } satisfies PriceUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<PriceUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let record = await em.findOne(CatalogProductPrice, { id: before.id })\n if (!record) {\n const { variant, product, offer } = await resolveSnapshotAssociations(em, before)\n record = em.create(CatalogProductPrice, {\n id: before.id,\n variant,\n product,\n offer,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n currencyCode: before.currencyCode,\n priceKind: em.getReference(CatalogPriceKind, before.priceKindId),\n kind: before.priceKindCode || before.kind,\n minQuantity: before.minQuantity,\n maxQuantity: before.maxQuantity ?? null,\n unitPriceNet: before.unitPriceNet ?? null,\n unitPriceGross: before.unitPriceGross ?? null,\n taxRate: before.taxRate ?? null,\n taxAmount: before.taxAmount ?? null,\n channelId: before.channelId ?? null,\n userId: before.userId ?? null,\n userGroupId: before.userGroupId ?? null,\n customerId: before.customerId ?? null,\n customerGroupId: before.customerGroupId ?? null,\n metadata: before.metadata ? cloneJson(before.metadata) : null,\n startsAt: before.startsAt ? new Date(before.startsAt) : null,\n endsAt: before.endsAt ? new Date(before.endsAt) : 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 applyPriceSnapshot(em, record, before)\n await em.flush()\n if (before.custom && Object.keys(before.custom).length) {\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_product_price,\n recordId: before.id,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n values: before.custom,\n })\n }\n },\n}\n\nregisterCommand(createPriceCommand)\nregisterCommand(updatePriceCommand)\nregisterCommand(deletePriceCommand)\n\nasync function resolvePriceRecordAssociations(\n em: EntityManager,\n record: CatalogProductPrice,\n): Promise<{ product: CatalogProduct; variant: CatalogProductVariant | null }> {\n const scope = { tenantId: record.tenantId, organizationId: record.organizationId }\n const variant = record.variant\n ? (typeof record.variant === 'string'\n ? await requireVariant(em, record.variant, scope)\n : record.variant)\n : null\n if (record.product) {\n const product =\n typeof record.product === 'string'\n ? await requireProduct(em, record.product, scope)\n : record.product\n return { product, variant }\n }\n if (variant?.product) {\n const productRef = variant.product\n const product =\n typeof productRef === 'string'\n ? await requireProduct(em, productRef, scope)\n : productRef\n return { product, variant }\n }\n if (record.offer) {\n const offer =\n typeof record.offer === 'string'\n ? await requireOffer(em, record.offer, scope)\n : record.offer\n const productRef = offer?.product ?? null\n if (productRef) {\n const product =\n typeof productRef === 'string'\n ? await requireProduct(em, productRef, scope)\n : productRef\n return { product, variant }\n }\n }\n throw new CrudHttpError(400, { error: 'Catalog price is not linked to a product.' })\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -164,6 +164,7 @@ const createProductUnitConversionCommand = {
|
|
|
164
164
|
const product = await requireProduct(
|
|
165
165
|
em,
|
|
166
166
|
parsed.productId,
|
|
167
|
+
{ tenantId: parsed.tenantId, organizationId: parsed.organizationId },
|
|
167
168
|
translate("catalog.errors.productNotFound", "Catalog product not found")
|
|
168
169
|
);
|
|
169
170
|
ensureSameScope(product, parsed.organizationId, parsed.tenantId);
|
|
@@ -278,7 +279,12 @@ const updateProductUnitConversionCommand = {
|
|
|
278
279
|
throw new CrudHttpError(404, {
|
|
279
280
|
error: translate("catalog.errors.conversionNotFound", "Catalog product unit conversion not found")
|
|
280
281
|
});
|
|
281
|
-
const product = typeof record.product === "string" ? await requireProduct(
|
|
282
|
+
const product = typeof record.product === "string" ? await requireProduct(
|
|
283
|
+
em,
|
|
284
|
+
record.product,
|
|
285
|
+
{ tenantId: record.tenantId, organizationId: record.organizationId },
|
|
286
|
+
translate("catalog.errors.productNotFound", "Catalog product not found")
|
|
287
|
+
) : record.product;
|
|
282
288
|
ensureTenantScope(ctx, record.tenantId);
|
|
283
289
|
ensureOrganizationScope(ctx, record.organizationId);
|
|
284
290
|
ensureSameScope(product, record.organizationId, record.tenantId);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
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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",
|
|
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 { tenantId: parsed.tenantId, organizationId: parsed.organizationId },\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(\n em,\n record.product,\n { tenantId: record.tenantId, organizationId: record.organizationId },\n translate(\"catalog.errors.productNotFound\", \"Catalog product not found\"),\n )\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
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -903,6 +903,7 @@ const createProductCommand = {
|
|
|
903
903
|
optionSchemaTemplate = await requireOptionSchemaTemplate(
|
|
904
904
|
em,
|
|
905
905
|
parsed.optionSchemaId,
|
|
906
|
+
{ tenantId: parsed.tenantId, organizationId: parsed.organizationId },
|
|
906
907
|
translate("catalog.errors.optionSchemaNotFound", "Option schema not found")
|
|
907
908
|
);
|
|
908
909
|
ensureSameScope(
|
|
@@ -1149,6 +1150,7 @@ const updateProductCommand = {
|
|
|
1149
1150
|
const optionTemplate = await requireOptionSchemaTemplate(
|
|
1150
1151
|
lookupEm,
|
|
1151
1152
|
parsed.optionSchemaId,
|
|
1153
|
+
{ tenantId, organizationId },
|
|
1152
1154
|
translate("catalog.errors.optionSchemaNotFound", "Option schema not found")
|
|
1153
1155
|
);
|
|
1154
1156
|
ensureSameScope(optionTemplate, organizationId, tenantId);
|