@open-mercato/core 0.6.7-develop.6553.1.2ec7246e04 → 0.6.7-develop.6566.1.15385fa179
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/attachments/api/partitions/route.js.map +1 -1
- package/dist/modules/attachments/lib/reconcileOrganization.js +9 -7
- package/dist/modules/attachments/lib/reconcileOrganization.js.map +2 -2
- package/dist/modules/catalog/api/products/route.js.map +1 -1
- package/dist/modules/customers/api/companies/[id]/people/route.js +2 -2
- package/dist/modules/customers/api/companies/[id]/people/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/companies/route.js +2 -2
- package/dist/modules/customers/api/deals/[id]/companies/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/people/route.js +2 -2
- package/dist/modules/customers/api/deals/[id]/people/route.js.map +2 -2
- package/dist/modules/customers/api/dictionaries/[kind]/[id]/route.js +4 -4
- package/dist/modules/customers/api/dictionaries/[kind]/[id]/route.js.map +2 -2
- package/dist/modules/customers/api/entity-roles-factory.js +3 -3
- package/dist/modules/customers/api/entity-roles-factory.js.map +2 -2
- package/dist/modules/customers/api/labels/assign/route.js +2 -2
- package/dist/modules/customers/api/labels/assign/route.js.map +2 -2
- package/dist/modules/customers/api/labels/unassign/route.js +2 -2
- package/dist/modules/customers/api/labels/unassign/route.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/companies/[linkId]/route.js +3 -7
- package/dist/modules/customers/api/people/[id]/companies/[linkId]/route.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/companies/context.js +3 -3
- package/dist/modules/customers/api/people/[id]/companies/context.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/companies/enriched/route.js +2 -2
- package/dist/modules/customers/api/people/[id]/companies/enriched/route.js.map +2 -2
- package/dist/modules/customers/api/todos/route.js +2 -2
- package/dist/modules/customers/api/todos/route.js.map +2 -2
- package/dist/modules/customers/commands/addresses.js +3 -3
- package/dist/modules/customers/commands/addresses.js.map +2 -2
- package/dist/modules/customers/commands/comments.js +3 -3
- package/dist/modules/customers/commands/comments.js.map +2 -2
- package/dist/modules/customers/commands/companies.js +2 -2
- package/dist/modules/customers/commands/companies.js.map +2 -2
- package/dist/modules/customers/commands/deals.js +3 -3
- package/dist/modules/customers/commands/deals.js.map +2 -2
- package/dist/modules/customers/commands/dictionaries.js +3 -3
- package/dist/modules/customers/commands/dictionaries.js.map +2 -2
- package/dist/modules/customers/commands/entity-roles.js +3 -3
- package/dist/modules/customers/commands/entity-roles.js.map +2 -2
- package/dist/modules/customers/commands/interactions.js +6 -6
- package/dist/modules/customers/commands/interactions.js.map +2 -2
- package/dist/modules/customers/commands/labels.js +7 -7
- package/dist/modules/customers/commands/labels.js.map +2 -2
- package/dist/modules/customers/commands/people.js +3 -3
- package/dist/modules/customers/commands/people.js.map +2 -2
- package/dist/modules/customers/commands/personCompanyLinks.js +6 -6
- package/dist/modules/customers/commands/personCompanyLinks.js.map +2 -2
- package/dist/modules/customers/commands/pipeline-stages.js +3 -3
- package/dist/modules/customers/commands/pipeline-stages.js.map +2 -2
- package/dist/modules/customers/commands/pipelines.js +3 -3
- package/dist/modules/customers/commands/pipelines.js.map +2 -2
- package/dist/modules/customers/commands/shared.js +3 -3
- package/dist/modules/customers/commands/shared.js.map +2 -2
- package/dist/modules/customers/commands/tags.js +7 -7
- package/dist/modules/customers/commands/tags.js.map +2 -2
- package/dist/modules/customers/commands/todos.js +3 -3
- package/dist/modules/customers/commands/todos.js.map +2 -2
- package/dist/modules/customers/lib/personCompanies.js +4 -4
- package/dist/modules/customers/lib/personCompanies.js.map +2 -2
- package/dist/modules/perspectives/data/validators.js +4 -0
- package/dist/modules/perspectives/data/validators.js.map +2 -2
- package/dist/modules/sales/api/notes/route.js +2 -4
- package/dist/modules/sales/api/notes/route.js.map +2 -2
- package/dist/modules/sales/api/quotes/accept/route.js +2 -2
- package/dist/modules/sales/api/quotes/accept/route.js.map +2 -2
- package/dist/modules/sales/api/quotes/public/[token]/route.js +3 -7
- package/dist/modules/sales/api/quotes/public/[token]/route.js.map +2 -2
- package/dist/modules/sales/api/quotes/send/route.js +2 -2
- package/dist/modules/sales/api/quotes/send/route.js.map +2 -2
- package/dist/modules/sales/api/returns/[id]/route.js +2 -2
- package/dist/modules/sales/api/returns/[id]/route.js.map +2 -2
- package/dist/modules/sales/commands/configuration.js +11 -11
- package/dist/modules/sales/commands/configuration.js.map +2 -2
- package/dist/modules/sales/commands/documentAddresses.js +3 -3
- package/dist/modules/sales/commands/documentAddresses.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +31 -39
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/commands/notes.js +7 -7
- package/dist/modules/sales/commands/notes.js.map +2 -2
- package/dist/modules/sales/commands/payments.js +2 -2
- package/dist/modules/sales/commands/payments.js.map +2 -2
- package/dist/modules/sales/commands/returns.js +8 -8
- package/dist/modules/sales/commands/returns.js.map +2 -2
- package/dist/modules/sales/commands/shared.js +2 -2
- package/dist/modules/sales/commands/shared.js.map +2 -2
- package/dist/modules/sales/commands/shipments.js +5 -5
- package/dist/modules/sales/commands/shipments.js.map +2 -2
- package/dist/modules/sales/commands/statuses.js +2 -2
- package/dist/modules/sales/commands/statuses.js.map +2 -2
- package/dist/modules/sales/commands/tags.js +3 -3
- package/dist/modules/sales/commands/tags.js.map +2 -2
- package/package.json +8 -8
- package/src/modules/attachments/api/partitions/route.ts +1 -1
- package/src/modules/attachments/lib/reconcileOrganization.ts +16 -7
- package/src/modules/catalog/api/products/route.ts +1 -1
- package/src/modules/customer_accounts/i18n/de.json +12 -0
- package/src/modules/customer_accounts/i18n/en.json +12 -0
- package/src/modules/customer_accounts/i18n/es.json +34 -22
- package/src/modules/customer_accounts/i18n/pl.json +32 -20
- package/src/modules/customers/api/companies/[id]/people/route.ts +2 -2
- package/src/modules/customers/api/deals/[id]/companies/route.ts +2 -2
- package/src/modules/customers/api/deals/[id]/people/route.ts +2 -2
- package/src/modules/customers/api/dictionaries/[kind]/[id]/route.ts +4 -4
- package/src/modules/customers/api/entity-roles-factory.ts +3 -3
- package/src/modules/customers/api/labels/assign/route.ts +2 -2
- package/src/modules/customers/api/labels/unassign/route.ts +2 -2
- package/src/modules/customers/api/people/[id]/companies/[linkId]/route.ts +3 -7
- package/src/modules/customers/api/people/[id]/companies/context.ts +3 -3
- package/src/modules/customers/api/people/[id]/companies/enriched/route.ts +2 -2
- package/src/modules/customers/api/todos/route.ts +2 -2
- package/src/modules/customers/commands/addresses.ts +3 -3
- package/src/modules/customers/commands/comments.ts +3 -3
- package/src/modules/customers/commands/companies.ts +2 -2
- package/src/modules/customers/commands/deals.ts +3 -3
- package/src/modules/customers/commands/dictionaries.ts +3 -3
- package/src/modules/customers/commands/entity-roles.ts +3 -3
- package/src/modules/customers/commands/interactions.ts +6 -6
- package/src/modules/customers/commands/labels.ts +7 -7
- package/src/modules/customers/commands/people.ts +3 -3
- package/src/modules/customers/commands/personCompanyLinks.ts +6 -6
- package/src/modules/customers/commands/pipeline-stages.ts +3 -3
- package/src/modules/customers/commands/pipelines.ts +3 -3
- package/src/modules/customers/commands/shared.ts +3 -3
- package/src/modules/customers/commands/tags.ts +7 -7
- package/src/modules/customers/commands/todos.ts +3 -3
- package/src/modules/customers/lib/personCompanies.ts +4 -4
- package/src/modules/perspectives/data/validators.ts +4 -0
- package/src/modules/sales/api/notes/route.ts +2 -4
- package/src/modules/sales/api/quotes/accept/route.ts +2 -2
- package/src/modules/sales/api/quotes/public/[token]/route.ts +3 -7
- package/src/modules/sales/api/quotes/send/route.ts +2 -2
- package/src/modules/sales/api/returns/[id]/route.ts +2 -2
- package/src/modules/sales/commands/configuration.ts +11 -11
- package/src/modules/sales/commands/documentAddresses.ts +3 -3
- package/src/modules/sales/commands/documents.ts +23 -31
- package/src/modules/sales/commands/notes.ts +7 -7
- package/src/modules/sales/commands/payments.ts +2 -2
- package/src/modules/sales/commands/returns.ts +8 -8
- package/src/modules/sales/commands/shared.ts +2 -2
- package/src/modules/sales/commands/shipments.ts +5 -5
- package/src/modules/sales/commands/statuses.ts +2 -2
- package/src/modules/sales/commands/tags.ts +3 -3
- package/tsconfig.json +0 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/sales/commands/shipments.ts"],
|
|
4
|
-
"sourcesContent": ["// @ts-nocheck\n\nimport { randomUUID } from 'crypto'\nimport { registerCommand, type CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { LockMode } from '@mikro-orm/core'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { loadCustomFieldValues } from '@open-mercato/shared/lib/crud/custom-fields'\nimport { setRecordCustomFields } from '@open-mercato/core/modules/entities/lib/helpers'\nimport { E } from '#generated/entities.ids.generated'\nimport { SalesOrder, SalesOrderLine, SalesShipment, SalesShipmentItem } from '../data/entities'\nimport {\n shipmentCreateSchema,\n shipmentUpdateSchema,\n type ShipmentCreateInput,\n type ShipmentUpdateInput,\n} from '../data/validators'\nimport {\n coerceShipmentQuantity as toNumber,\n readShipmentItemsSnapshot,\n refreshShipmentItemsSnapshot,\n type ShipmentItemSnapshot,\n buildShipmentItemSnapshots,\n} from '../lib/shipments/snapshots'\nimport {\n cloneJson,\n ensureOrganizationScope,\n ensureSameScope,\n ensureTenantScope,\n extractUndoPayload,\n enforceSalesDocumentOptimisticLock,\n SALES_RESOURCE_KIND_ORDER,\n} from './shared'\nimport { resolveDictionaryEntryValue } from '../lib/dictionaries'\nimport { resolveRedoSnapshot } from '@open-mercato/shared/lib/commands/redo'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport { emitCrudSideEffects } from '@open-mercato/shared/lib/commands/helpers'\nimport type { CrudEventsConfig } from '@open-mercato/shared/lib/crud/types'\nimport { findOneWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst fallbackShipmentLogger = createLogger('sales').child({ component: 'shipments' })\n\nconst shipmentCrudEvents: CrudEventsConfig = {\n module: 'sales',\n entity: 'shipment',\n persistent: true,\n buildPayload: (ctx) => ({\n id: ctx.identifiers.id,\n organizationId: ctx.identifiers.organizationId,\n tenantId: ctx.identifiers.tenantId,\n }),\n}\n\nconst ADDRESS_SNAPSHOT_KEY = 'shipmentAddressSnapshot'\n\nexport type ShipmentSnapshot = {\n id: string\n orderId: string\n organizationId: string\n tenantId: string\n shipmentNumber: string | null\n shippingMethodId: string | null\n statusEntryId: string | null\n status: string | null\n carrierName: string | null\n trackingNumbers: string[] | null\n shippedAt: string | null\n deliveredAt: string | null\n weightValue: number | null\n weightUnit: string | null\n declaredValueNet: number | null\n declaredValueGross: number | null\n currencyCode: string | null\n notesText: string | null\n metadata: Record<string, unknown> | null\n customFields?: Record<string, unknown> | null\n items: ShipmentItemSnapshot[]\n itemsSnapshot?: ShipmentItemSnapshot[] | null\n}\n\ntype ShipmentUndoPayload = {\n before?: ShipmentSnapshot | null\n after?: ShipmentSnapshot | null\n}\n\nconst buildShipmentCreateRedoInput = (snapshot: ShipmentSnapshot): ShipmentCreateInput => ({\n orderId: snapshot.orderId,\n organizationId: snapshot.organizationId,\n tenantId: snapshot.tenantId,\n shipmentNumber: snapshot.shipmentNumber ?? undefined,\n shippingMethodId: snapshot.shippingMethodId ?? undefined,\n statusEntryId: snapshot.statusEntryId ?? undefined,\n carrierName: snapshot.carrierName ?? undefined,\n trackingNumbers: snapshot.trackingNumbers ?? undefined,\n shippedAt: snapshot.shippedAt ? new Date(snapshot.shippedAt) : undefined,\n deliveredAt: snapshot.deliveredAt ? new Date(snapshot.deliveredAt) : undefined,\n weightValue: snapshot.weightValue ?? undefined,\n weightUnit: snapshot.weightUnit ?? undefined,\n declaredValueNet: snapshot.declaredValueNet ?? undefined,\n declaredValueGross: snapshot.declaredValueGross ?? undefined,\n currencyCode: snapshot.currencyCode ?? undefined,\n notes: snapshot.notesText ?? undefined,\n metadata: snapshot.metadata ? cloneJson(snapshot.metadata) : undefined,\n customFields: snapshot.customFields ? cloneJson(snapshot.customFields) : undefined,\n items: snapshot.items.map((item) => ({\n orderLineId: item.orderLineId,\n quantity: item.quantity,\n metadata: item.metadata ? cloneJson(item.metadata) : undefined,\n })),\n})\n\nconst parseTrackingNumbers = (input: unknown): string[] | null => {\n if (typeof input === 'string') {\n const entries = input\n .split(/[\\n,]/g)\n .map((value) => value.trim())\n .filter((value) => value.length > 0)\n return entries.length ? entries : null\n }\n if (Array.isArray(input)) {\n const entries = input\n .map((value) => (typeof value === 'string' ? value.trim() : ''))\n .filter((value) => value.length > 0)\n return entries.length ? entries : null\n }\n return null\n}\n\nconst normalizeCustomFieldsInput = (input: unknown): Record<string, unknown> =>\n input && typeof input === 'object' && !Array.isArray(input) ? (input as Record<string, unknown>) : {}\n\nconst resolveLogger = (ctx: any): { warn?: (meta: any, message?: string) => void } | null => {\n const container = ctx?.container as any\n if (!container) return null\n const cradleLogger = container?.cradle?.logger ?? null\n if (cradleLogger?.warn) return cradleLogger\n const hasRegistration = typeof container.hasRegistration === 'function' ? container.hasRegistration.bind(container) : null\n if (hasRegistration?.('logger')) {\n const logger = container.resolve('logger')\n if (logger?.warn) return logger\n }\n if (hasRegistration?.('coreLogger')) {\n const logger = container.resolve('coreLogger')\n if (logger?.warn) return logger\n }\n return null\n}\n\nconst logShipmentDeleteScopeRejection = (\n ctx: any,\n reason: string,\n meta: Record<string, unknown>\n): void => {\n const logger = resolveLogger(ctx)\n const payload = { ...meta, command: 'sales.shipments.delete' }\n if (logger?.warn) {\n logger.warn(payload, reason)\n return\n }\n fallbackShipmentLogger.warn(reason, payload)\n}\n\nexport async function loadShipmentSnapshot(em: EntityManager, id: string): Promise<ShipmentSnapshot | null> {\n const shipment = await em.findOne(\n SalesShipment,\n { id },\n { populate: ['order', 'items', 'items.orderLine'] }\n )\n if (!shipment || !shipment.order) return null\n const storedSnapshot = readShipmentItemsSnapshot(\n (shipment as any).itemsSnapshot ?? (shipment as any).items_snapshot ?? null\n )\n const lineMap = new Map(\n Array.from(shipment.items ?? [])\n .map((item) => {\n const line = typeof item.orderLine === 'string' ? null : (item.orderLine as SalesOrderLine | null)\n return line ? [line.id, line] : null\n })\n .filter((entry): entry is [string, SalesOrderLine] => Boolean(entry))\n )\n const fallbackItems = buildShipmentItemSnapshots(Array.from(shipment.items ?? []), { lineMap })\n const itemsSnapshot = storedSnapshot.length ? storedSnapshot : fallbackItems\n const customFieldValues = await loadCustomFieldValues({\n em,\n entityId: E.sales.sales_shipment,\n recordIds: [shipment.id],\n tenantIdByRecord: { [shipment.id]: shipment.tenantId ?? null },\n organizationIdByRecord: { [shipment.id]: shipment.organizationId ?? null },\n })\n const customFields = customFieldValues[shipment.id]\n return {\n id: shipment.id,\n orderId: typeof shipment.order === 'string' ? shipment.order : shipment.order.id,\n organizationId: shipment.organizationId,\n tenantId: shipment.tenantId,\n shipmentNumber: shipment.shipmentNumber ?? null,\n shippingMethodId: shipment.shippingMethodId ?? null,\n statusEntryId: shipment.statusEntryId ?? null,\n status: shipment.status ?? null,\n carrierName: shipment.carrierName ?? null,\n trackingNumbers: shipment.trackingNumbers ? [...shipment.trackingNumbers] : null,\n shippedAt: shipment.shippedAt ? shipment.shippedAt.toISOString() : null,\n deliveredAt: shipment.deliveredAt ? shipment.deliveredAt.toISOString() : null,\n weightValue: shipment.weightValue !== undefined && shipment.weightValue !== null ? Number(shipment.weightValue) : null,\n weightUnit: shipment.weightUnit ?? null,\n declaredValueNet:\n shipment.declaredValueNet !== undefined && shipment.declaredValueNet !== null\n ? Number(shipment.declaredValueNet)\n : null,\n declaredValueGross:\n shipment.declaredValueGross !== undefined && shipment.declaredValueGross !== null\n ? Number(shipment.declaredValueGross)\n : null,\n currencyCode: shipment.currencyCode ?? null,\n notesText: shipment.notesText ?? null,\n metadata: shipment.metadata ? cloneJson(shipment.metadata) : null,\n customFields: customFields && Object.keys(customFields).length ? customFields : null,\n items: itemsSnapshot,\n itemsSnapshot,\n }\n}\n\nexport async function restoreShipmentSnapshot(em: EntityManager, snapshot: ShipmentSnapshot): Promise<void> {\n const order = await findOneWithDecryption(em, SalesOrder, { id: snapshot.orderId }, {}, { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId })\n if (!order) return\n const existing = await em.findOne(SalesShipment, { id: snapshot.id })\n const entity =\n existing ??\n em.create(SalesShipment, {\n id: snapshot.id,\n createdAt: new Date(),\n organizationId: snapshot.organizationId,\n tenantId: snapshot.tenantId,\n })\n entity.order = order\n entity.organizationId = snapshot.organizationId\n entity.tenantId = snapshot.tenantId\n entity.shipmentNumber = snapshot.shipmentNumber ?? null\n entity.shippingMethodId = snapshot.shippingMethodId ?? null\n entity.statusEntryId = snapshot.statusEntryId ?? null\n entity.status = snapshot.status ?? null\n entity.carrierName = snapshot.carrierName ?? null\n entity.trackingNumbers = snapshot.trackingNumbers ? [...snapshot.trackingNumbers] : null\n entity.shippedAt = snapshot.shippedAt ? new Date(snapshot.shippedAt) : null\n entity.deliveredAt = snapshot.deliveredAt ? new Date(snapshot.deliveredAt) : null\n entity.weightValue = snapshot.weightValue !== null ? snapshot.weightValue.toString() : null\n entity.weightUnit = snapshot.weightUnit ?? null\n entity.declaredValueNet = snapshot.declaredValueNet !== null ? snapshot.declaredValueNet.toString() : null\n entity.declaredValueGross = snapshot.declaredValueGross !== null ? snapshot.declaredValueGross.toString() : null\n entity.currencyCode = snapshot.currencyCode ?? null\n entity.notesText = snapshot.notesText ?? null\n entity.metadata = snapshot.metadata ? cloneJson(snapshot.metadata) : null\n entity.updatedAt = new Date()\n em.persist(entity)\n await em.flush()\n\n const existingItems = await em.find(SalesShipmentItem, { shipment: entity })\n existingItems.forEach((item) => em.remove(item))\n const items = Array.isArray(snapshot.items) ? snapshot.items : []\n const lineIds = items\n .map((item) => item.orderLineId)\n .filter((id): id is string => typeof id === 'string' && id.length > 0)\n const lines = lineIds.length\n ? await em.find(SalesOrderLine, { id: { $in: lineIds }, order: order.id })\n : []\n const lineMap = new Map(lines.map((line) => [line.id, line]))\n const restoredItems: ShipmentItemSnapshot[] = []\n items.forEach((item) => {\n const line = lineMap.get(item.orderLineId)\n if (!line) return\n restoredItems.push(item)\n const lineRef = em.getReference(SalesOrderLine, line.id)\n const shipmentItem = em.create(SalesShipmentItem, {\n id: item.id ?? randomUUID(),\n shipment: entity,\n orderLine: lineRef,\n organizationId: snapshot.organizationId,\n tenantId: snapshot.tenantId,\n quantity: item.quantity.toString(),\n metadata: item.metadata ? cloneJson(item.metadata) : null,\n })\n em.persist(shipmentItem)\n })\n const snapshotItems = (snapshot.itemsSnapshot ?? restoredItems).filter((entry) =>\n entry?.orderLineId ? lineMap.has(entry.orderLineId) : false\n )\n entity.itemsSnapshot = snapshotItems && snapshotItems.length ? cloneJson(snapshotItems) : null\n if (!entity.itemsSnapshot) {\n await refreshShipmentItemsSnapshot(em, entity)\n }\n if ((snapshot as any).customFields !== undefined) {\n await setRecordCustomFields(em, {\n entityId: E.sales.sales_shipment,\n recordId: entity.id,\n organizationId: snapshot.organizationId,\n tenantId: snapshot.tenantId,\n values: normalizeCustomFieldsInput((snapshot as any).customFields),\n })\n }\n em.persist(entity)\n}\n\nasync function deleteShipmentWithItems(em: EntityManager, shipment: SalesShipment): Promise<void> {\n const scope = { tenantId: shipment.tenantId, organizationId: shipment.organizationId }\n const items = await findWithDecryption(em, SalesShipmentItem, { shipment }, {}, scope)\n items.forEach((item) => em.remove(item))\n em.remove(shipment)\n await em.flush()\n}\n\nasync function recomputeFulfilledQuantities(em: EntityManager, order: SalesOrder): Promise<void> {\n const scope = { tenantId: order.tenantId, organizationId: order.organizationId }\n const shipments = await findWithDecryption(em, SalesShipment, { order, deletedAt: null }, {}, scope)\n const shipmentIds = shipments.map((entry) => entry.id)\n const shipmentItems = shipmentIds.length\n ? await findWithDecryption(em, SalesShipmentItem, { shipment: { $in: shipmentIds } }, {}, scope)\n : []\n const totals = shipmentItems.reduce<Map<string, number>>((acc, item) => {\n const lineId =\n typeof item.orderLine === 'string'\n ? item.orderLine\n : item.orderLine?.id ?? (item as any).orderLineId ?? null\n if (!lineId) return acc\n const next = (acc.get(lineId) ?? 0) + toNumber(item.quantity)\n acc.set(lineId, next)\n return acc\n }, new Map())\n const lines = await findWithDecryption(em, SalesOrderLine, { order }, { lockMode: LockMode.PESSIMISTIC_WRITE }, scope)\n lines.forEach((line) => {\n const shipped = totals.get(line.id) ?? 0\n line.fulfilledQuantity = shipped.toString()\n })\n}\n\nasync function loadOrder(\n em: EntityManager,\n id: string,\n scope?: { tenantId: string; organizationId: string }\n): Promise<SalesOrder> {\n const order = await findOneWithDecryption(em, SalesOrder, { id, deletedAt: null }, {}, scope)\n if (!order) throw new CrudHttpError(404, { error: 'sales.shipments.not_found' })\n return order\n}\n\nasync function loadShippedTotals(\n em: EntityManager,\n order: SalesOrder,\n excludeShipmentId?: string | null\n): Promise<Map<string, number>> {\n const scope = { tenantId: order.tenantId, organizationId: order.organizationId }\n const shipments = await findWithDecryption(em, SalesShipment, { order, deletedAt: null }, {}, scope)\n const shipmentIds = shipments\n .map((entry) => entry.id)\n .filter((id) => !excludeShipmentId || id !== excludeShipmentId)\n if (!shipmentIds.length) return new Map()\n const items = await findWithDecryption(em, SalesShipmentItem, { shipment: { $in: shipmentIds } }, {}, scope)\n return items.reduce<Map<string, number>>((acc, item) => {\n const lineId =\n typeof item.orderLine === 'string'\n ? item.orderLine\n : item.orderLine?.id ?? (item as any).orderLineId ?? null\n if (!lineId) return acc\n const next = (acc.get(lineId) ?? 0) + toNumber(item.quantity)\n acc.set(lineId, next)\n return acc\n }, new Map())\n}\n\nasync function validateShipmentItems(params: {\n em: EntityManager\n order: SalesOrder\n items?: ShipmentCreateInput['items']\n excludeShipmentId?: string | null\n lockOrderLines?: boolean\n}): Promise<{\n items: Array<{ orderLineId: string; quantity: number; metadata: Record<string, unknown> | null }>\n lineMap: Map<string, SalesOrderLine>\n}> {\n const { em, order, items, excludeShipmentId, lockOrderLines } = params\n const { translate } = await resolveTranslations()\n if (!items || !items.length) {\n throw new CrudHttpError(400, { error: translate('sales.shipments.items_required', 'Add at least one line to ship.') })\n }\n const scope = { tenantId: order.tenantId, organizationId: order.organizationId }\n const orderLines = await findWithDecryption(\n em,\n SalesOrderLine,\n { order },\n lockOrderLines ? { lockMode: LockMode.PESSIMISTIC_WRITE } : undefined,\n scope,\n )\n const lineMap = new Map(orderLines.map((line) => [line.id, line]))\n const shippedTotals = await loadShippedTotals(em, order, excludeShipmentId)\n const requestedTotals = new Map<string, number>()\n\n for (const item of items) {\n const lineId = item.orderLineId\n const quantity = toNumber(item.quantity)\n if (!lineId || quantity <= 0) {\n throw new CrudHttpError(400, { error: translate('sales.shipments.items_required', 'Add at least one line to ship.') })\n }\n const line = lineMap.get(lineId)\n if (!line) {\n throw new CrudHttpError(404, { error: translate('sales.shipments.line_missing', 'Order line not found.') })\n }\n const lineTotal = toNumber(line.quantity)\n const alreadyShipped = shippedTotals.get(lineId) ?? 0\n const nextTotal = (requestedTotals.get(lineId) ?? 0) + quantity\n if (nextTotal + alreadyShipped - 1e-6 > lineTotal) {\n throw new CrudHttpError(400, { error: translate('sales.shipments.quantity_exceeded', 'Cannot ship more than the remaining quantity.') })\n }\n requestedTotals.set(lineId, nextTotal)\n }\n\n return {\n items: items.map((item) => ({\n orderLineId: item.orderLineId,\n quantity: toNumber(item.quantity),\n metadata: item.metadata ? cloneJson(item.metadata) : null,\n })),\n lineMap,\n }\n}\n\nfunction mergeAddressSnapshot(\n baseMetadata: Record<string, unknown> | null | undefined,\n snapshot: Record<string, unknown> | null | undefined\n): Record<string, unknown> | null {\n const metadata = baseMetadata ? { ...baseMetadata } : {}\n if (snapshot && typeof snapshot === 'object') {\n metadata[ADDRESS_SNAPSHOT_KEY] = cloneJson(snapshot)\n }\n return Object.keys(metadata).length ? metadata : null\n}\n\nconst createShipmentCommand: CommandHandler<ShipmentCreateInput, { shipmentId: string }> = {\n id: 'sales.shipments.create',\n async execute(rawInput, ctx) {\n const input = shipmentCreateSchema.parse(rawInput ?? {})\n ensureTenantScope(ctx, input.tenantId)\n ensureOrganizationScope(ctx, input.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const { translate } = await resolveTranslations()\n const shipment = await em.transactional(async (tx) => {\n const order = await loadOrder(tx, input.orderId, { tenantId: input.tenantId, organizationId: input.organizationId })\n ensureSameScope(order, input.organizationId, input.tenantId)\n // Guard the parent order's aggregate version (Gap B): a shipment mutation\n // recalculates the order's fulfilled quantities, so a stale parent must 409\n // before we touch it.\n await enforceSalesDocumentOptimisticLock(ctx, order, SALES_RESOURCE_KIND_ORDER)\n const { items: normalizedItems, lineMap } = await validateShipmentItems({\n em: tx,\n order,\n items: input.items,\n lockOrderLines: true,\n })\n const statusValue = await resolveDictionaryEntryValue(tx, input.statusEntryId ?? null, { tenantId: input.tenantId })\n const trackingNumbers = parseTrackingNumbers(input.trackingNumbers) ?? null\n const metadata =\n mergeAddressSnapshot(\n input.metadata ? cloneJson(input.metadata) : null,\n input.shipmentAddressSnapshot ?? order.shippingAddressSnapshot ?? null\n ) ?? null\n\n const shipmentId = randomUUID()\n const entity = tx.create(SalesShipment, {\n id: shipmentId,\n order,\n organizationId: input.organizationId,\n tenantId: input.tenantId,\n shipmentNumber: input.shipmentNumber ?? null,\n shippingMethodId: input.shippingMethodId ?? null,\n statusEntryId: input.statusEntryId ?? null,\n status: statusValue,\n carrierName: input.carrierName ?? null,\n trackingNumbers,\n shippedAt: input.shippedAt ?? null,\n deliveredAt: input.deliveredAt ?? null,\n weightValue: input.weightValue !== undefined ? input.weightValue.toString() : null,\n weightUnit: input.weightUnit ?? null,\n declaredValueNet: input.declaredValueNet !== undefined ? input.declaredValueNet.toString() : null,\n declaredValueGross: input.declaredValueGross !== undefined ? input.declaredValueGross.toString() : null,\n currencyCode: input.currencyCode ?? order.currencyCode ?? null,\n notesText: input.notes ?? null,\n metadata,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n const createdItems: SalesShipmentItem[] = []\n normalizedItems.forEach((item) => {\n const lineRef = tx.getReference(SalesOrderLine, item.orderLineId)\n const shipmentItem = tx.create(SalesShipmentItem, {\n id: randomUUID(),\n shipment: entity,\n orderLine: lineRef,\n organizationId: input.organizationId,\n tenantId: input.tenantId,\n quantity: item.quantity.toString(),\n metadata: item.metadata ? cloneJson(item.metadata) : null,\n })\n createdItems.push(shipmentItem)\n tx.persist(shipmentItem)\n })\n tx.persist(entity)\n if (input.customFields !== undefined) {\n await setRecordCustomFields(tx, {\n entityId: E.sales.sales_shipment,\n recordId: entity.id,\n organizationId: input.organizationId,\n tenantId: input.tenantId,\n values: normalizeCustomFieldsInput(input.customFields),\n })\n }\n if (input.documentStatusEntryId !== undefined) {\n const orderStatus = await resolveDictionaryEntryValue(tx, input.documentStatusEntryId ?? null, { tenantId: input.tenantId })\n if (input.documentStatusEntryId && !orderStatus) {\n throw new CrudHttpError(400, { error: translate('sales.documents.detail.statusInvalid', 'Selected status could not be found.') })\n }\n order.statusEntryId = input.documentStatusEntryId ?? null\n order.status = orderStatus\n order.updatedAt = new Date()\n }\n if (input.lineStatusEntryId !== undefined) {\n const lineStatus = await resolveDictionaryEntryValue(tx, input.lineStatusEntryId ?? null, { tenantId: input.tenantId })\n if (input.lineStatusEntryId && !lineStatus) {\n throw new CrudHttpError(400, { error: translate('sales.documents.detail.statusInvalid', 'Selected status could not be found.') })\n }\n const uniqueLineIds = Array.from(new Set(normalizedItems.map((item) => item.orderLineId)))\n uniqueLineIds.forEach((lineId) => {\n const line = lineMap.get(lineId)\n if (!line) return\n line.statusEntryId = input.lineStatusEntryId ?? null\n line.status = lineStatus\n line.updatedAt = new Date()\n })\n }\n await refreshShipmentItemsSnapshot(tx, entity, { items: createdItems, lineMap })\n await tx.flush()\n await recomputeFulfilledQuantities(tx, order)\n await tx.flush()\n return entity\n })\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'created',\n entity: shipment,\n identifiers: {\n id: shipment.id,\n organizationId: shipment.organizationId,\n tenantId: shipment.tenantId,\n },\n indexer: { entityType: E.sales.sales_shipment },\n events: shipmentCrudEvents,\n })\n\n return { shipmentId: shipment.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return loadShipmentSnapshot(em, result.shipmentId)\n },\n buildLog: async ({ result, snapshots }) => {\n const after = snapshots.after as ShipmentSnapshot | undefined\n if (!after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('sales.audit.shipments.create', 'Create shipment'),\n resourceKind: 'sales.shipment',\n resourceId: result.shipmentId,\n parentResourceKind: 'sales.order',\n parentResourceId: after.orderId ?? null,\n tenantId: after.tenantId,\n organizationId: after.organizationId,\n snapshotAfter: after,\n payload: {\n undo: { after } satisfies ShipmentUndoPayload,\n __redoInput: buildShipmentCreateRedoInput(after),\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<ShipmentUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n await em.transactional(async (tx) => {\n const existing = await findOneWithDecryption(\n tx,\n SalesShipment,\n { id: after.id },\n { populate: ['order'] },\n { tenantId: after.tenantId, organizationId: after.organizationId },\n )\n if (!existing) return\n const order = existing.order as SalesOrder | null\n await deleteShipmentWithItems(tx, existing)\n if (order) {\n await recomputeFulfilledQuantities(tx, order)\n await tx.flush()\n }\n })\n },\n redo: async ({ ctx, logEntry }) => {\n const after = resolveRedoSnapshot<ShipmentSnapshot>(logEntry)\n const shipmentId = after?.id ?? logEntry.resourceId ?? null\n if (!after || !shipmentId) {\n throw new CrudHttpError(400, { error: '[internal] redo snapshot unavailable for sales.shipments.create' })\n }\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n await em.transactional(async (tx) => {\n await restoreShipmentSnapshot(tx, after)\n const order = await findOneWithDecryption(tx, SalesOrder, { id: after.orderId }, {}, { tenantId: after.tenantId, organizationId: after.organizationId })\n await tx.flush()\n if (order) {\n await recomputeFulfilledQuantities(tx, order)\n await tx.flush()\n }\n })\n\n const shipment = await findOneWithDecryption(\n em,\n SalesShipment,\n { id: after.id },\n {},\n { tenantId: after.tenantId, organizationId: after.organizationId },\n )\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'created',\n entity: shipment,\n identifiers: {\n id: after.id,\n organizationId: after.organizationId,\n tenantId: after.tenantId,\n },\n indexer: { entityType: E.sales.sales_shipment },\n events: shipmentCrudEvents,\n })\n\n return { shipmentId: after.id }\n },\n}\n\nconst updateShipmentCommand: CommandHandler<ShipmentUpdateInput, { shipmentId: string }> = {\n id: 'sales.shipments.update',\n async prepare(rawInput, ctx) {\n const parsed = shipmentUpdateSchema.parse(rawInput ?? {})\n if (!parsed.id) return {}\n const em = ctx.container.resolve('em') as EntityManager\n const snapshot = await loadShipmentSnapshot(em, parsed.id)\n if (snapshot) {\n ensureTenantScope(ctx, snapshot.tenantId)\n ensureOrganizationScope(ctx, snapshot.organizationId)\n }\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const input = shipmentUpdateSchema.parse(rawInput ?? {})\n ensureTenantScope(ctx, input.tenantId)\n ensureOrganizationScope(ctx, input.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const { translate } = await resolveTranslations()\n\n const shipment = await em.transactional(async (tx) => {\n const shipmentEntity = await findOneWithDecryption(\n tx,\n SalesShipment,\n { id: input.id },\n { populate: ['order'] },\n { tenantId: input.tenantId, organizationId: input.organizationId },\n )\n if (!shipmentEntity || !shipmentEntity.order) {\n throw new CrudHttpError(404, { error: 'sales.shipments.not_found' })\n }\n ensureSameScope(shipmentEntity, input.organizationId, input.tenantId)\n const order = shipmentEntity.order as SalesOrder\n if (input.orderId && input.orderId !== order.id) {\n throw new CrudHttpError(400, { error: 'sales.shipments.invalid_order' })\n }\n // Guard the parent order's aggregate version (Gap B): updating a shipment\n // recalculates the order's fulfilled quantities, so a stale parent must 409\n // before we touch it.\n await enforceSalesDocumentOptimisticLock(ctx, order, SALES_RESOURCE_KIND_ORDER)\n\n // Check if order is financially closed - prevent modifications to shipments\n const paidAmount = parseFloat(order.paidTotalAmount || '0')\n const refundedAmount = parseFloat(order.refundedTotalAmount || '0')\n const grandTotal = parseFloat(order.grandTotalGrossAmount || '0')\n const tolerance = 1e-4 // Tolerance for floating-point comparisons\n\n // Check for full refund first (higher priority than payment)\n const isFullyRefunded = refundedAmount >= grandTotal - tolerance\n if (isFullyRefunded) {\n throw new CrudHttpError(422, { error: translate('sales.shipments.fully_returned', 'Cannot modify shipment: order is fully returned') })\n }\n\n // Check for completed payment\n const isFullyPaid = paidAmount >= grandTotal - tolerance\n if (isFullyPaid) {\n throw new CrudHttpError(422, { error: translate('sales.shipments.payment_completed', 'Cannot modify shipment: order payment is completed') })\n }\n const validatedItems = input.items\n ? await validateShipmentItems({\n em: tx,\n order,\n items: input.items,\n excludeShipmentId: shipmentEntity.id,\n })\n : null\n const normalizedItems = validatedItems?.items ?? null\n const lineMap = validatedItems?.lineMap ?? new Map<string, SalesOrderLine>()\n // Resolve the status label BEFORE mutating shipment scalars so this\n // dictionary read does not interleave with (and drop) the pending\n // shipment changeset under MikroORM v7 (SPEC-018 / #2453 class).\n const resolvedShipmentStatus = input.statusEntryId !== undefined\n ? await resolveDictionaryEntryValue(tx, input.statusEntryId ?? null, { tenantId: shipmentEntity.tenantId })\n : undefined\n if (input.shipmentNumber !== undefined) shipmentEntity.shipmentNumber = input.shipmentNumber ?? null\n if (input.shippingMethodId !== undefined) shipmentEntity.shippingMethodId = input.shippingMethodId ?? null\n if (input.statusEntryId !== undefined) {\n shipmentEntity.statusEntryId = input.statusEntryId ?? null\n shipmentEntity.status = resolvedShipmentStatus ?? null\n }\n if (input.carrierName !== undefined) shipmentEntity.carrierName = input.carrierName ?? null\n if (input.trackingNumbers !== undefined) shipmentEntity.trackingNumbers = parseTrackingNumbers(input.trackingNumbers)\n if (input.shippedAt !== undefined) shipmentEntity.shippedAt = input.shippedAt ?? null\n if (input.deliveredAt !== undefined) shipmentEntity.deliveredAt = input.deliveredAt ?? null\n if (input.weightValue !== undefined) shipmentEntity.weightValue = input.weightValue !== null ? input.weightValue.toString() : null\n if (input.weightUnit !== undefined) shipmentEntity.weightUnit = input.weightUnit ?? null\n if (input.declaredValueNet !== undefined) {\n shipmentEntity.declaredValueNet = input.declaredValueNet !== null ? input.declaredValueNet.toString() : null\n }\n if (input.declaredValueGross !== undefined) {\n shipmentEntity.declaredValueGross = input.declaredValueGross !== null ? input.declaredValueGross.toString() : null\n }\n if (input.currencyCode !== undefined) shipmentEntity.currencyCode = input.currencyCode ?? null\n if (input.notes !== undefined) shipmentEntity.notesText = input.notes ?? null\n if (input.metadata !== undefined || input.shipmentAddressSnapshot !== undefined) {\n shipmentEntity.metadata = mergeAddressSnapshot(\n input.metadata ? cloneJson(input.metadata) : shipmentEntity.metadata ?? null,\n input.shipmentAddressSnapshot\n )\n }\n shipmentEntity.updatedAt = new Date()\n\n // Persist the shipment scalar mutations before the item reads below run on\n // the same EntityManager. Under MikroORM v7 an interleaved query (the\n // findWithDecryption on SalesShipmentItem here and in the snapshot step)\n // resets the identity-map changeset, so shippingMethodId/status/carrier/etc.\n // would silently not persist even though the write returns 200 (#2453).\n await tx.flush()\n\n const shouldLoadItems = Boolean(normalizedItems || input.lineStatusEntryId !== undefined)\n const existingItems = shouldLoadItems ? await findWithDecryption(tx, SalesShipmentItem, { shipment: shipmentEntity }, {}, { tenantId: shipmentEntity.tenantId, organizationId: shipmentEntity.organizationId }) : []\n const newItems: SalesShipmentItem[] = []\n if (normalizedItems) {\n existingItems.forEach((item) => tx.remove(item))\n normalizedItems.forEach((item) => {\n const lineRef = tx.getReference(SalesOrderLine, item.orderLineId)\n const shipmentItem = tx.create(SalesShipmentItem, {\n id: randomUUID(),\n shipment: shipmentEntity,\n orderLine: lineRef,\n organizationId: shipmentEntity.organizationId,\n tenantId: shipmentEntity.tenantId,\n quantity: item.quantity.toString(),\n metadata: item.metadata ? cloneJson(item.metadata) : null,\n })\n newItems.push(shipmentItem)\n tx.persist(shipmentItem)\n })\n }\n\n if (input.customFields !== undefined) {\n await setRecordCustomFields(tx, {\n entityId: E.sales.sales_shipment,\n recordId: shipmentEntity.id,\n organizationId: shipmentEntity.organizationId,\n tenantId: shipmentEntity.tenantId,\n values: normalizeCustomFieldsInput(input.customFields),\n })\n }\n if (input.documentStatusEntryId !== undefined) {\n const orderStatus = await resolveDictionaryEntryValue(tx, input.documentStatusEntryId ?? null, { tenantId: shipmentEntity.tenantId })\n if (input.documentStatusEntryId && !orderStatus) {\n throw new CrudHttpError(400, { error: translate('sales.documents.detail.statusInvalid', 'Selected status could not be found.') })\n }\n order.statusEntryId = input.documentStatusEntryId ?? null\n order.status = orderStatus\n order.updatedAt = new Date()\n }\n if (input.lineStatusEntryId !== undefined) {\n const lineStatus = await resolveDictionaryEntryValue(tx, input.lineStatusEntryId ?? null, { tenantId: shipmentEntity.tenantId })\n if (input.lineStatusEntryId && !lineStatus) {\n throw new CrudHttpError(400, { error: translate('sales.documents.detail.statusInvalid', 'Selected status could not be found.') })\n }\n const targetLineIds = normalizedItems\n ? Array.from(new Set(normalizedItems.map((item) => item.orderLineId)))\n : Array.from(\n new Set(\n existingItems\n .map((item) =>\n typeof item.orderLine === 'string'\n ? item.orderLine\n : (item.orderLine as SalesOrderLine | null)?.id ?? null\n )\n .filter((id): id is string => Boolean(id))\n )\n )\n if (targetLineIds.length) {\n const missing = targetLineIds.filter((id) => !lineMap.has(id))\n if (missing.length) {\n const fetched = await tx.find(SalesOrderLine, { id: { $in: missing } })\n fetched.forEach((line) => lineMap.set(line.id, line))\n }\n targetLineIds.forEach((lineId) => {\n const line = lineMap.get(lineId)\n if (!line) return\n line.statusEntryId = input.lineStatusEntryId ?? null\n line.status = lineStatus\n line.updatedAt = new Date()\n })\n }\n }\n\n // Flush any order/line status mutations applied above before the snapshot\n // read below queries the same EntityManager (same interleaved-read hazard).\n await tx.flush()\n const itemsForSnapshot =\n normalizedItems || shouldLoadItems\n ? (normalizedItems ? newItems : existingItems)\n : await findWithDecryption(tx, SalesShipmentItem, { shipment: shipmentEntity }, {}, { tenantId: shipmentEntity.tenantId, organizationId: shipmentEntity.organizationId })\n await refreshShipmentItemsSnapshot(tx, shipmentEntity, { items: itemsForSnapshot, lineMap })\n await tx.flush()\n await recomputeFulfilledQuantities(tx, order)\n await tx.flush()\n return shipmentEntity\n })\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'updated',\n entity: shipment,\n identifiers: {\n id: shipment.id,\n organizationId: shipment.organizationId,\n tenantId: shipment.tenantId,\n },\n indexer: { entityType: E.sales.sales_shipment },\n events: shipmentCrudEvents,\n })\n\n return { shipmentId: shipment.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return loadShipmentSnapshot(em, result.shipmentId)\n },\n buildLog: async ({ snapshots, result }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as ShipmentSnapshot | undefined\n const after = snapshots.after as ShipmentSnapshot | undefined\n return {\n actionLabel: translate('sales.audit.shipments.update', 'Update shipment'),\n resourceKind: 'sales.shipment',\n resourceId: result.shipmentId,\n parentResourceKind: 'sales.order',\n parentResourceId: after?.orderId ?? before?.orderId ?? null,\n tenantId: after?.tenantId ?? before?.tenantId ?? null,\n organizationId: after?.organizationId ?? before?.organizationId ?? null,\n snapshotBefore: before ?? null,\n snapshotAfter: after ?? null,\n payload: {\n undo: { before, after } satisfies ShipmentUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<ShipmentUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n await em.transactional(async (tx) => {\n await restoreShipmentSnapshot(tx, before)\n const order = await findOneWithDecryption(tx, SalesOrder, { id: before.orderId }, {}, { tenantId: before.tenantId, organizationId: before.organizationId })\n await tx.flush()\n if (order) {\n await recomputeFulfilledQuantities(tx, order)\n await tx.flush()\n }\n })\n },\n}\n\nconst deleteShipmentCommand: CommandHandler<\n { id: string; orderId: string; organizationId: string; tenantId: string },\n { shipmentId: string }\n> = {\n id: 'sales.shipments.delete',\n async prepare(rawInput, ctx) {\n const parsed = shipmentUpdateSchema.parse(rawInput ?? {})\n if (!parsed.id) return {}\n const em = ctx.container.resolve('em') as EntityManager\n const snapshot = await loadShipmentSnapshot(em, parsed.id)\n if (snapshot) {\n try {\n ensureTenantScope(ctx, snapshot.tenantId)\n } catch (error) {\n logShipmentDeleteScopeRejection(ctx, 'Tenant mismatch while preparing shipment delete', {\n shipmentId: snapshot.id,\n snapshotTenantId: snapshot.tenantId,\n authTenantId: ctx.auth?.tenantId ?? null,\n })\n throw error\n }\n try {\n ensureOrganizationScope(ctx, snapshot.organizationId)\n } catch (error) {\n logShipmentDeleteScopeRejection(ctx, 'Organization mismatch while preparing shipment delete', {\n shipmentId: snapshot.id,\n snapshotOrganizationId: snapshot.organizationId,\n selectedOrganizationId: ctx.selectedOrganizationId ?? null,\n authOrganizationId: ctx.auth?.orgId ?? null,\n })\n throw error\n }\n }\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const { translate } = await resolveTranslations()\n const payload = shipmentUpdateSchema\n .pick({ id: true, orderId: true, organizationId: true, tenantId: true })\n .parse(rawInput ?? {})\n try {\n ensureTenantScope(ctx, payload.tenantId)\n } catch (error) {\n logShipmentDeleteScopeRejection(ctx, 'Tenant mismatch while executing shipment delete', {\n shipmentId: payload.id,\n payloadTenantId: payload.tenantId,\n authTenantId: ctx.auth?.tenantId ?? null,\n })\n throw error\n }\n try {\n ensureOrganizationScope(ctx, payload.organizationId)\n } catch (error) {\n logShipmentDeleteScopeRejection(ctx, 'Organization mismatch while executing shipment delete', {\n shipmentId: payload.id,\n payloadOrganizationId: payload.organizationId,\n selectedOrganizationId: ctx.selectedOrganizationId ?? null,\n authOrganizationId: ctx.auth?.orgId ?? null,\n })\n throw error\n }\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n\n const { shipment, shipmentItems } = await em.transactional(async (tx) => {\n const shipmentEntity = await findOneWithDecryption(\n tx,\n SalesShipment,\n { id: payload.id },\n { populate: ['order'] },\n { tenantId: payload.tenantId, organizationId: payload.organizationId },\n )\n if (!shipmentEntity || !shipmentEntity.order) {\n throw new CrudHttpError(404, { error: translate('sales.shipments.not_found', 'Shipment not found') })\n }\n try {\n ensureSameScope(shipmentEntity, payload.organizationId, payload.tenantId)\n } catch (error) {\n logShipmentDeleteScopeRejection(ctx, 'Shipment scope mismatch against payload', {\n shipmentId: payload.id,\n shipmentOrganizationId: shipmentEntity.organizationId,\n shipmentTenantId: shipmentEntity.tenantId,\n payloadOrganizationId: payload.organizationId,\n payloadTenantId: payload.tenantId,\n })\n throw error\n }\n const order = shipmentEntity.order as SalesOrder\n if (order.id !== payload.orderId) {\n throw new CrudHttpError(400, { error: translate('sales.shipments.invalid_order', 'Shipment does not belong to this order') })\n }\n // Guard the parent order's aggregate version (Gap B): deleting a shipment\n // recalculates the order's fulfilled quantities, so a stale parent must 409\n // before we touch it.\n await enforceSalesDocumentOptimisticLock(ctx, order, SALES_RESOURCE_KIND_ORDER)\n const scope = { tenantId: shipmentEntity.tenantId, organizationId: shipmentEntity.organizationId }\n const items = await findWithDecryption(tx, SalesShipmentItem, { shipment: shipmentEntity }, {}, scope)\n items.forEach((item) => tx.remove(item))\n tx.remove(shipmentEntity)\n await tx.flush()\n await recomputeFulfilledQuantities(tx, order)\n await tx.flush()\n return { shipment: shipmentEntity, shipmentItems: items }\n })\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'deleted',\n entity: shipment,\n identifiers: {\n id: shipment.id,\n organizationId: shipment.organizationId,\n tenantId: shipment.tenantId,\n },\n indexer: { entityType: E.sales.sales_shipment },\n events: shipmentCrudEvents,\n })\n if (shipmentItems.length) {\n await Promise.all(\n shipmentItems.map((item) =>\n emitCrudSideEffects({\n dataEngine,\n action: 'deleted',\n entity: item,\n identifiers: {\n id: item.id,\n organizationId: item.organizationId ?? null,\n tenantId: item.tenantId ?? null,\n },\n indexer: { entityType: E.sales.sales_shipment_item },\n })\n )\n )\n }\n return { shipmentId: shipment.id }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<ShipmentUndoPayload>(logEntry)\n const snapshot = payload?.before ?? null\n if (!snapshot) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n await em.transactional(async (tx) => {\n await restoreShipmentSnapshot(tx, snapshot)\n const order = await findOneWithDecryption(tx, SalesOrder, { id: snapshot.orderId }, {}, { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId })\n await tx.flush()\n if (order) {\n await recomputeFulfilledQuantities(tx, order)\n await tx.flush()\n }\n })\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as ShipmentSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('sales.audit.shipments.delete', 'Delete shipment'),\n resourceKind: 'sales.shipment',\n resourceId: before.id ?? null,\n parentResourceKind: 'sales.order',\n parentResourceId: before.orderId ?? null,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: { before } satisfies ShipmentUndoPayload,\n },\n }\n },\n}\n\nregisterCommand(createShipmentCommand)\nregisterCommand(updateShipmentCommand)\nregisterCommand(deleteShipmentCommand)\n\nexport const shipmentCommands = [createShipmentCommand, updateShipmentCommand, deleteShipmentCommand]\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["// @ts-nocheck\n\nimport { randomUUID } from 'crypto'\nimport { registerCommand, type CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { LockMode } from '@mikro-orm/core'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { CrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { loadCustomFieldValues } from '@open-mercato/shared/lib/crud/custom-fields'\nimport { setRecordCustomFields } from '@open-mercato/core/modules/entities/lib/helpers'\nimport { E } from '#generated/entities.ids.generated'\nimport { SalesOrder, SalesOrderLine, SalesShipment, SalesShipmentItem } from '../data/entities'\nimport {\n shipmentCreateSchema,\n shipmentUpdateSchema,\n type ShipmentCreateInput,\n type ShipmentUpdateInput,\n} from '../data/validators'\nimport {\n coerceShipmentQuantity as toNumber,\n readShipmentItemsSnapshot,\n refreshShipmentItemsSnapshot,\n type ShipmentItemSnapshot,\n buildShipmentItemSnapshots,\n} from '../lib/shipments/snapshots'\nimport {\n cloneJson,\n ensureOrganizationScope,\n ensureSameScope,\n ensureTenantScope,\n extractUndoPayload,\n enforceSalesDocumentOptimisticLock,\n SALES_RESOURCE_KIND_ORDER,\n} from './shared'\nimport { resolveDictionaryEntryValue } from '../lib/dictionaries'\nimport { resolveRedoSnapshot } from '@open-mercato/shared/lib/commands/redo'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport { emitCrudSideEffects } from '@open-mercato/shared/lib/commands/helpers'\nimport type { CrudEventsConfig } from '@open-mercato/shared/lib/crud/types'\nimport { findOneWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst fallbackShipmentLogger = createLogger('sales').child({ component: 'shipments' })\n\nconst shipmentCrudEvents: CrudEventsConfig = {\n module: 'sales',\n entity: 'shipment',\n persistent: true,\n buildPayload: (ctx) => ({\n id: ctx.identifiers.id,\n organizationId: ctx.identifiers.organizationId,\n tenantId: ctx.identifiers.tenantId,\n }),\n}\n\nconst ADDRESS_SNAPSHOT_KEY = 'shipmentAddressSnapshot'\n\nexport type ShipmentSnapshot = {\n id: string\n orderId: string\n organizationId: string\n tenantId: string\n shipmentNumber: string | null\n shippingMethodId: string | null\n statusEntryId: string | null\n status: string | null\n carrierName: string | null\n trackingNumbers: string[] | null\n shippedAt: string | null\n deliveredAt: string | null\n weightValue: number | null\n weightUnit: string | null\n declaredValueNet: number | null\n declaredValueGross: number | null\n currencyCode: string | null\n notesText: string | null\n metadata: Record<string, unknown> | null\n customFields?: Record<string, unknown> | null\n items: ShipmentItemSnapshot[]\n itemsSnapshot?: ShipmentItemSnapshot[] | null\n}\n\ntype ShipmentUndoPayload = {\n before?: ShipmentSnapshot | null\n after?: ShipmentSnapshot | null\n}\n\nconst buildShipmentCreateRedoInput = (snapshot: ShipmentSnapshot): ShipmentCreateInput => ({\n orderId: snapshot.orderId,\n organizationId: snapshot.organizationId,\n tenantId: snapshot.tenantId,\n shipmentNumber: snapshot.shipmentNumber ?? undefined,\n shippingMethodId: snapshot.shippingMethodId ?? undefined,\n statusEntryId: snapshot.statusEntryId ?? undefined,\n carrierName: snapshot.carrierName ?? undefined,\n trackingNumbers: snapshot.trackingNumbers ?? undefined,\n shippedAt: snapshot.shippedAt ? new Date(snapshot.shippedAt) : undefined,\n deliveredAt: snapshot.deliveredAt ? new Date(snapshot.deliveredAt) : undefined,\n weightValue: snapshot.weightValue ?? undefined,\n weightUnit: snapshot.weightUnit ?? undefined,\n declaredValueNet: snapshot.declaredValueNet ?? undefined,\n declaredValueGross: snapshot.declaredValueGross ?? undefined,\n currencyCode: snapshot.currencyCode ?? undefined,\n notes: snapshot.notesText ?? undefined,\n metadata: snapshot.metadata ? cloneJson(snapshot.metadata) : undefined,\n customFields: snapshot.customFields ? cloneJson(snapshot.customFields) : undefined,\n items: snapshot.items.map((item) => ({\n orderLineId: item.orderLineId,\n quantity: item.quantity,\n metadata: item.metadata ? cloneJson(item.metadata) : undefined,\n })),\n})\n\nconst parseTrackingNumbers = (input: unknown): string[] | null => {\n if (typeof input === 'string') {\n const entries = input\n .split(/[\\n,]/g)\n .map((value) => value.trim())\n .filter((value) => value.length > 0)\n return entries.length ? entries : null\n }\n if (Array.isArray(input)) {\n const entries = input\n .map((value) => (typeof value === 'string' ? value.trim() : ''))\n .filter((value) => value.length > 0)\n return entries.length ? entries : null\n }\n return null\n}\n\nconst normalizeCustomFieldsInput = (input: unknown): Record<string, unknown> =>\n input && typeof input === 'object' && !Array.isArray(input) ? (input as Record<string, unknown>) : {}\n\nconst resolveLogger = (ctx: any): { warn?: (meta: any, message?: string) => void } | null => {\n const container = ctx?.container as any\n if (!container) return null\n const cradleLogger = container?.cradle?.logger ?? null\n if (cradleLogger?.warn) return cradleLogger\n const hasRegistration = typeof container.hasRegistration === 'function' ? container.hasRegistration.bind(container) : null\n if (hasRegistration?.('logger')) {\n const logger = container.resolve('logger')\n if (logger?.warn) return logger\n }\n if (hasRegistration?.('coreLogger')) {\n const logger = container.resolve('coreLogger')\n if (logger?.warn) return logger\n }\n return null\n}\n\nconst logShipmentDeleteScopeRejection = (\n ctx: any,\n reason: string,\n meta: Record<string, unknown>\n): void => {\n const logger = resolveLogger(ctx)\n const payload = { ...meta, command: 'sales.shipments.delete' }\n if (logger?.warn) {\n logger.warn(payload, reason)\n return\n }\n fallbackShipmentLogger.warn(reason, payload)\n}\n\nexport async function loadShipmentSnapshot(em: EntityManager, id: string): Promise<ShipmentSnapshot | null> {\n const shipment = await em.findOne(\n SalesShipment,\n { id },\n { populate: ['order', 'items', 'items.orderLine'] }\n )\n if (!shipment || !shipment.order) return null\n const storedSnapshot = readShipmentItemsSnapshot(\n (shipment as any).itemsSnapshot ?? (shipment as any).items_snapshot ?? null\n )\n const lineMap = new Map(\n Array.from(shipment.items ?? [])\n .map((item) => {\n const line = typeof item.orderLine === 'string' ? null : (item.orderLine as SalesOrderLine | null)\n return line ? [line.id, line] : null\n })\n .filter((entry): entry is [string, SalesOrderLine] => Boolean(entry))\n )\n const fallbackItems = buildShipmentItemSnapshots(Array.from(shipment.items ?? []), { lineMap })\n const itemsSnapshot = storedSnapshot.length ? storedSnapshot : fallbackItems\n const customFieldValues = await loadCustomFieldValues({\n em,\n entityId: E.sales.sales_shipment,\n recordIds: [shipment.id],\n tenantIdByRecord: { [shipment.id]: shipment.tenantId ?? null },\n organizationIdByRecord: { [shipment.id]: shipment.organizationId ?? null },\n })\n const customFields = customFieldValues[shipment.id]\n return {\n id: shipment.id,\n orderId: typeof shipment.order === 'string' ? shipment.order : shipment.order.id,\n organizationId: shipment.organizationId,\n tenantId: shipment.tenantId,\n shipmentNumber: shipment.shipmentNumber ?? null,\n shippingMethodId: shipment.shippingMethodId ?? null,\n statusEntryId: shipment.statusEntryId ?? null,\n status: shipment.status ?? null,\n carrierName: shipment.carrierName ?? null,\n trackingNumbers: shipment.trackingNumbers ? [...shipment.trackingNumbers] : null,\n shippedAt: shipment.shippedAt ? shipment.shippedAt.toISOString() : null,\n deliveredAt: shipment.deliveredAt ? shipment.deliveredAt.toISOString() : null,\n weightValue: shipment.weightValue !== undefined && shipment.weightValue !== null ? Number(shipment.weightValue) : null,\n weightUnit: shipment.weightUnit ?? null,\n declaredValueNet:\n shipment.declaredValueNet !== undefined && shipment.declaredValueNet !== null\n ? Number(shipment.declaredValueNet)\n : null,\n declaredValueGross:\n shipment.declaredValueGross !== undefined && shipment.declaredValueGross !== null\n ? Number(shipment.declaredValueGross)\n : null,\n currencyCode: shipment.currencyCode ?? null,\n notesText: shipment.notesText ?? null,\n metadata: shipment.metadata ? cloneJson(shipment.metadata) : null,\n customFields: customFields && Object.keys(customFields).length ? customFields : null,\n items: itemsSnapshot,\n itemsSnapshot,\n }\n}\n\nexport async function restoreShipmentSnapshot(em: EntityManager, snapshot: ShipmentSnapshot): Promise<void> {\n const order = await findOneWithDecryption(em, SalesOrder, { id: snapshot.orderId }, {}, { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId })\n if (!order) return\n const existing = await em.findOne(SalesShipment, { id: snapshot.id })\n const entity =\n existing ??\n em.create(SalesShipment, {\n id: snapshot.id,\n createdAt: new Date(),\n organizationId: snapshot.organizationId,\n tenantId: snapshot.tenantId,\n })\n entity.order = order\n entity.organizationId = snapshot.organizationId\n entity.tenantId = snapshot.tenantId\n entity.shipmentNumber = snapshot.shipmentNumber ?? null\n entity.shippingMethodId = snapshot.shippingMethodId ?? null\n entity.statusEntryId = snapshot.statusEntryId ?? null\n entity.status = snapshot.status ?? null\n entity.carrierName = snapshot.carrierName ?? null\n entity.trackingNumbers = snapshot.trackingNumbers ? [...snapshot.trackingNumbers] : null\n entity.shippedAt = snapshot.shippedAt ? new Date(snapshot.shippedAt) : null\n entity.deliveredAt = snapshot.deliveredAt ? new Date(snapshot.deliveredAt) : null\n entity.weightValue = snapshot.weightValue !== null ? snapshot.weightValue.toString() : null\n entity.weightUnit = snapshot.weightUnit ?? null\n entity.declaredValueNet = snapshot.declaredValueNet !== null ? snapshot.declaredValueNet.toString() : null\n entity.declaredValueGross = snapshot.declaredValueGross !== null ? snapshot.declaredValueGross.toString() : null\n entity.currencyCode = snapshot.currencyCode ?? null\n entity.notesText = snapshot.notesText ?? null\n entity.metadata = snapshot.metadata ? cloneJson(snapshot.metadata) : null\n entity.updatedAt = new Date()\n em.persist(entity)\n await em.flush()\n\n const existingItems = await em.find(SalesShipmentItem, { shipment: entity })\n existingItems.forEach((item) => em.remove(item))\n const items = Array.isArray(snapshot.items) ? snapshot.items : []\n const lineIds = items\n .map((item) => item.orderLineId)\n .filter((id): id is string => typeof id === 'string' && id.length > 0)\n const lines = lineIds.length\n ? await em.find(SalesOrderLine, { id: { $in: lineIds }, order: order.id })\n : []\n const lineMap = new Map(lines.map((line) => [line.id, line]))\n const restoredItems: ShipmentItemSnapshot[] = []\n items.forEach((item) => {\n const line = lineMap.get(item.orderLineId)\n if (!line) return\n restoredItems.push(item)\n const lineRef = em.getReference(SalesOrderLine, line.id)\n const shipmentItem = em.create(SalesShipmentItem, {\n id: item.id ?? randomUUID(),\n shipment: entity,\n orderLine: lineRef,\n organizationId: snapshot.organizationId,\n tenantId: snapshot.tenantId,\n quantity: item.quantity.toString(),\n metadata: item.metadata ? cloneJson(item.metadata) : null,\n })\n em.persist(shipmentItem)\n })\n const snapshotItems = (snapshot.itemsSnapshot ?? restoredItems).filter((entry) =>\n entry?.orderLineId ? lineMap.has(entry.orderLineId) : false\n )\n entity.itemsSnapshot = snapshotItems && snapshotItems.length ? cloneJson(snapshotItems) : null\n if (!entity.itemsSnapshot) {\n await refreshShipmentItemsSnapshot(em, entity)\n }\n if ((snapshot as any).customFields !== undefined) {\n await setRecordCustomFields(em, {\n entityId: E.sales.sales_shipment,\n recordId: entity.id,\n organizationId: snapshot.organizationId,\n tenantId: snapshot.tenantId,\n values: normalizeCustomFieldsInput((snapshot as any).customFields),\n })\n }\n em.persist(entity)\n}\n\nasync function deleteShipmentWithItems(em: EntityManager, shipment: SalesShipment): Promise<void> {\n const scope = { tenantId: shipment.tenantId, organizationId: shipment.organizationId }\n const items = await findWithDecryption(em, SalesShipmentItem, { shipment }, {}, scope)\n items.forEach((item) => em.remove(item))\n em.remove(shipment)\n await em.flush()\n}\n\nasync function recomputeFulfilledQuantities(em: EntityManager, order: SalesOrder): Promise<void> {\n const scope = { tenantId: order.tenantId, organizationId: order.organizationId }\n const shipments = await findWithDecryption(em, SalesShipment, { order, deletedAt: null }, {}, scope)\n const shipmentIds = shipments.map((entry) => entry.id)\n const shipmentItems = shipmentIds.length\n ? await findWithDecryption(em, SalesShipmentItem, { shipment: { $in: shipmentIds } }, {}, scope)\n : []\n const totals = shipmentItems.reduce<Map<string, number>>((acc, item) => {\n const lineId =\n typeof item.orderLine === 'string'\n ? item.orderLine\n : item.orderLine?.id ?? (item as any).orderLineId ?? null\n if (!lineId) return acc\n const next = (acc.get(lineId) ?? 0) + toNumber(item.quantity)\n acc.set(lineId, next)\n return acc\n }, new Map())\n const lines = await findWithDecryption(em, SalesOrderLine, { order }, { lockMode: LockMode.PESSIMISTIC_WRITE }, scope)\n lines.forEach((line) => {\n const shipped = totals.get(line.id) ?? 0\n line.fulfilledQuantity = shipped.toString()\n })\n}\n\nasync function loadOrder(\n em: EntityManager,\n id: string,\n scope?: { tenantId: string; organizationId: string }\n): Promise<SalesOrder> {\n const order = await findOneWithDecryption(em, SalesOrder, { id, deletedAt: null }, {}, scope)\n if (!order) throw notFound('sales.shipments.not_found')\n return order\n}\n\nasync function loadShippedTotals(\n em: EntityManager,\n order: SalesOrder,\n excludeShipmentId?: string | null\n): Promise<Map<string, number>> {\n const scope = { tenantId: order.tenantId, organizationId: order.organizationId }\n const shipments = await findWithDecryption(em, SalesShipment, { order, deletedAt: null }, {}, scope)\n const shipmentIds = shipments\n .map((entry) => entry.id)\n .filter((id) => !excludeShipmentId || id !== excludeShipmentId)\n if (!shipmentIds.length) return new Map()\n const items = await findWithDecryption(em, SalesShipmentItem, { shipment: { $in: shipmentIds } }, {}, scope)\n return items.reduce<Map<string, number>>((acc, item) => {\n const lineId =\n typeof item.orderLine === 'string'\n ? item.orderLine\n : item.orderLine?.id ?? (item as any).orderLineId ?? null\n if (!lineId) return acc\n const next = (acc.get(lineId) ?? 0) + toNumber(item.quantity)\n acc.set(lineId, next)\n return acc\n }, new Map())\n}\n\nasync function validateShipmentItems(params: {\n em: EntityManager\n order: SalesOrder\n items?: ShipmentCreateInput['items']\n excludeShipmentId?: string | null\n lockOrderLines?: boolean\n}): Promise<{\n items: Array<{ orderLineId: string; quantity: number; metadata: Record<string, unknown> | null }>\n lineMap: Map<string, SalesOrderLine>\n}> {\n const { em, order, items, excludeShipmentId, lockOrderLines } = params\n const { translate } = await resolveTranslations()\n if (!items || !items.length) {\n throw new CrudHttpError(400, { error: translate('sales.shipments.items_required', 'Add at least one line to ship.') })\n }\n const scope = { tenantId: order.tenantId, organizationId: order.organizationId }\n const orderLines = await findWithDecryption(\n em,\n SalesOrderLine,\n { order },\n lockOrderLines ? { lockMode: LockMode.PESSIMISTIC_WRITE } : undefined,\n scope,\n )\n const lineMap = new Map(orderLines.map((line) => [line.id, line]))\n const shippedTotals = await loadShippedTotals(em, order, excludeShipmentId)\n const requestedTotals = new Map<string, number>()\n\n for (const item of items) {\n const lineId = item.orderLineId\n const quantity = toNumber(item.quantity)\n if (!lineId || quantity <= 0) {\n throw new CrudHttpError(400, { error: translate('sales.shipments.items_required', 'Add at least one line to ship.') })\n }\n const line = lineMap.get(lineId)\n if (!line) {\n throw notFound(translate('sales.shipments.line_missing', 'Order line not found.'))\n }\n const lineTotal = toNumber(line.quantity)\n const alreadyShipped = shippedTotals.get(lineId) ?? 0\n const nextTotal = (requestedTotals.get(lineId) ?? 0) + quantity\n if (nextTotal + alreadyShipped - 1e-6 > lineTotal) {\n throw new CrudHttpError(400, { error: translate('sales.shipments.quantity_exceeded', 'Cannot ship more than the remaining quantity.') })\n }\n requestedTotals.set(lineId, nextTotal)\n }\n\n return {\n items: items.map((item) => ({\n orderLineId: item.orderLineId,\n quantity: toNumber(item.quantity),\n metadata: item.metadata ? cloneJson(item.metadata) : null,\n })),\n lineMap,\n }\n}\n\nfunction mergeAddressSnapshot(\n baseMetadata: Record<string, unknown> | null | undefined,\n snapshot: Record<string, unknown> | null | undefined\n): Record<string, unknown> | null {\n const metadata = baseMetadata ? { ...baseMetadata } : {}\n if (snapshot && typeof snapshot === 'object') {\n metadata[ADDRESS_SNAPSHOT_KEY] = cloneJson(snapshot)\n }\n return Object.keys(metadata).length ? metadata : null\n}\n\nconst createShipmentCommand: CommandHandler<ShipmentCreateInput, { shipmentId: string }> = {\n id: 'sales.shipments.create',\n async execute(rawInput, ctx) {\n const input = shipmentCreateSchema.parse(rawInput ?? {})\n ensureTenantScope(ctx, input.tenantId)\n ensureOrganizationScope(ctx, input.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const { translate } = await resolveTranslations()\n const shipment = await em.transactional(async (tx) => {\n const order = await loadOrder(tx, input.orderId, { tenantId: input.tenantId, organizationId: input.organizationId })\n ensureSameScope(order, input.organizationId, input.tenantId)\n // Guard the parent order's aggregate version (Gap B): a shipment mutation\n // recalculates the order's fulfilled quantities, so a stale parent must 409\n // before we touch it.\n await enforceSalesDocumentOptimisticLock(ctx, order, SALES_RESOURCE_KIND_ORDER)\n const { items: normalizedItems, lineMap } = await validateShipmentItems({\n em: tx,\n order,\n items: input.items,\n lockOrderLines: true,\n })\n const statusValue = await resolveDictionaryEntryValue(tx, input.statusEntryId ?? null, { tenantId: input.tenantId })\n const trackingNumbers = parseTrackingNumbers(input.trackingNumbers) ?? null\n const metadata =\n mergeAddressSnapshot(\n input.metadata ? cloneJson(input.metadata) : null,\n input.shipmentAddressSnapshot ?? order.shippingAddressSnapshot ?? null\n ) ?? null\n\n const shipmentId = randomUUID()\n const entity = tx.create(SalesShipment, {\n id: shipmentId,\n order,\n organizationId: input.organizationId,\n tenantId: input.tenantId,\n shipmentNumber: input.shipmentNumber ?? null,\n shippingMethodId: input.shippingMethodId ?? null,\n statusEntryId: input.statusEntryId ?? null,\n status: statusValue,\n carrierName: input.carrierName ?? null,\n trackingNumbers,\n shippedAt: input.shippedAt ?? null,\n deliveredAt: input.deliveredAt ?? null,\n weightValue: input.weightValue !== undefined ? input.weightValue.toString() : null,\n weightUnit: input.weightUnit ?? null,\n declaredValueNet: input.declaredValueNet !== undefined ? input.declaredValueNet.toString() : null,\n declaredValueGross: input.declaredValueGross !== undefined ? input.declaredValueGross.toString() : null,\n currencyCode: input.currencyCode ?? order.currencyCode ?? null,\n notesText: input.notes ?? null,\n metadata,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n const createdItems: SalesShipmentItem[] = []\n normalizedItems.forEach((item) => {\n const lineRef = tx.getReference(SalesOrderLine, item.orderLineId)\n const shipmentItem = tx.create(SalesShipmentItem, {\n id: randomUUID(),\n shipment: entity,\n orderLine: lineRef,\n organizationId: input.organizationId,\n tenantId: input.tenantId,\n quantity: item.quantity.toString(),\n metadata: item.metadata ? cloneJson(item.metadata) : null,\n })\n createdItems.push(shipmentItem)\n tx.persist(shipmentItem)\n })\n tx.persist(entity)\n if (input.customFields !== undefined) {\n await setRecordCustomFields(tx, {\n entityId: E.sales.sales_shipment,\n recordId: entity.id,\n organizationId: input.organizationId,\n tenantId: input.tenantId,\n values: normalizeCustomFieldsInput(input.customFields),\n })\n }\n if (input.documentStatusEntryId !== undefined) {\n const orderStatus = await resolveDictionaryEntryValue(tx, input.documentStatusEntryId ?? null, { tenantId: input.tenantId })\n if (input.documentStatusEntryId && !orderStatus) {\n throw new CrudHttpError(400, { error: translate('sales.documents.detail.statusInvalid', 'Selected status could not be found.') })\n }\n order.statusEntryId = input.documentStatusEntryId ?? null\n order.status = orderStatus\n order.updatedAt = new Date()\n }\n if (input.lineStatusEntryId !== undefined) {\n const lineStatus = await resolveDictionaryEntryValue(tx, input.lineStatusEntryId ?? null, { tenantId: input.tenantId })\n if (input.lineStatusEntryId && !lineStatus) {\n throw new CrudHttpError(400, { error: translate('sales.documents.detail.statusInvalid', 'Selected status could not be found.') })\n }\n const uniqueLineIds = Array.from(new Set(normalizedItems.map((item) => item.orderLineId)))\n uniqueLineIds.forEach((lineId) => {\n const line = lineMap.get(lineId)\n if (!line) return\n line.statusEntryId = input.lineStatusEntryId ?? null\n line.status = lineStatus\n line.updatedAt = new Date()\n })\n }\n await refreshShipmentItemsSnapshot(tx, entity, { items: createdItems, lineMap })\n await tx.flush()\n await recomputeFulfilledQuantities(tx, order)\n await tx.flush()\n return entity\n })\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'created',\n entity: shipment,\n identifiers: {\n id: shipment.id,\n organizationId: shipment.organizationId,\n tenantId: shipment.tenantId,\n },\n indexer: { entityType: E.sales.sales_shipment },\n events: shipmentCrudEvents,\n })\n\n return { shipmentId: shipment.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return loadShipmentSnapshot(em, result.shipmentId)\n },\n buildLog: async ({ result, snapshots }) => {\n const after = snapshots.after as ShipmentSnapshot | undefined\n if (!after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('sales.audit.shipments.create', 'Create shipment'),\n resourceKind: 'sales.shipment',\n resourceId: result.shipmentId,\n parentResourceKind: 'sales.order',\n parentResourceId: after.orderId ?? null,\n tenantId: after.tenantId,\n organizationId: after.organizationId,\n snapshotAfter: after,\n payload: {\n undo: { after } satisfies ShipmentUndoPayload,\n __redoInput: buildShipmentCreateRedoInput(after),\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<ShipmentUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n await em.transactional(async (tx) => {\n const existing = await findOneWithDecryption(\n tx,\n SalesShipment,\n { id: after.id },\n { populate: ['order'] },\n { tenantId: after.tenantId, organizationId: after.organizationId },\n )\n if (!existing) return\n const order = existing.order as SalesOrder | null\n await deleteShipmentWithItems(tx, existing)\n if (order) {\n await recomputeFulfilledQuantities(tx, order)\n await tx.flush()\n }\n })\n },\n redo: async ({ ctx, logEntry }) => {\n const after = resolveRedoSnapshot<ShipmentSnapshot>(logEntry)\n const shipmentId = after?.id ?? logEntry.resourceId ?? null\n if (!after || !shipmentId) {\n throw new CrudHttpError(400, { error: '[internal] redo snapshot unavailable for sales.shipments.create' })\n }\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n await em.transactional(async (tx) => {\n await restoreShipmentSnapshot(tx, after)\n const order = await findOneWithDecryption(tx, SalesOrder, { id: after.orderId }, {}, { tenantId: after.tenantId, organizationId: after.organizationId })\n await tx.flush()\n if (order) {\n await recomputeFulfilledQuantities(tx, order)\n await tx.flush()\n }\n })\n\n const shipment = await findOneWithDecryption(\n em,\n SalesShipment,\n { id: after.id },\n {},\n { tenantId: after.tenantId, organizationId: after.organizationId },\n )\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'created',\n entity: shipment,\n identifiers: {\n id: after.id,\n organizationId: after.organizationId,\n tenantId: after.tenantId,\n },\n indexer: { entityType: E.sales.sales_shipment },\n events: shipmentCrudEvents,\n })\n\n return { shipmentId: after.id }\n },\n}\n\nconst updateShipmentCommand: CommandHandler<ShipmentUpdateInput, { shipmentId: string }> = {\n id: 'sales.shipments.update',\n async prepare(rawInput, ctx) {\n const parsed = shipmentUpdateSchema.parse(rawInput ?? {})\n if (!parsed.id) return {}\n const em = ctx.container.resolve('em') as EntityManager\n const snapshot = await loadShipmentSnapshot(em, parsed.id)\n if (snapshot) {\n ensureTenantScope(ctx, snapshot.tenantId)\n ensureOrganizationScope(ctx, snapshot.organizationId)\n }\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const input = shipmentUpdateSchema.parse(rawInput ?? {})\n ensureTenantScope(ctx, input.tenantId)\n ensureOrganizationScope(ctx, input.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const { translate } = await resolveTranslations()\n\n const shipment = await em.transactional(async (tx) => {\n const shipmentEntity = await findOneWithDecryption(\n tx,\n SalesShipment,\n { id: input.id },\n { populate: ['order'] },\n { tenantId: input.tenantId, organizationId: input.organizationId },\n )\n if (!shipmentEntity || !shipmentEntity.order) {\n throw notFound('sales.shipments.not_found')\n }\n ensureSameScope(shipmentEntity, input.organizationId, input.tenantId)\n const order = shipmentEntity.order as SalesOrder\n if (input.orderId && input.orderId !== order.id) {\n throw new CrudHttpError(400, { error: 'sales.shipments.invalid_order' })\n }\n // Guard the parent order's aggregate version (Gap B): updating a shipment\n // recalculates the order's fulfilled quantities, so a stale parent must 409\n // before we touch it.\n await enforceSalesDocumentOptimisticLock(ctx, order, SALES_RESOURCE_KIND_ORDER)\n\n // Check if order is financially closed - prevent modifications to shipments\n const paidAmount = parseFloat(order.paidTotalAmount || '0')\n const refundedAmount = parseFloat(order.refundedTotalAmount || '0')\n const grandTotal = parseFloat(order.grandTotalGrossAmount || '0')\n const tolerance = 1e-4 // Tolerance for floating-point comparisons\n\n // Check for full refund first (higher priority than payment)\n const isFullyRefunded = refundedAmount >= grandTotal - tolerance\n if (isFullyRefunded) {\n throw new CrudHttpError(422, { error: translate('sales.shipments.fully_returned', 'Cannot modify shipment: order is fully returned') })\n }\n\n // Check for completed payment\n const isFullyPaid = paidAmount >= grandTotal - tolerance\n if (isFullyPaid) {\n throw new CrudHttpError(422, { error: translate('sales.shipments.payment_completed', 'Cannot modify shipment: order payment is completed') })\n }\n const validatedItems = input.items\n ? await validateShipmentItems({\n em: tx,\n order,\n items: input.items,\n excludeShipmentId: shipmentEntity.id,\n })\n : null\n const normalizedItems = validatedItems?.items ?? null\n const lineMap = validatedItems?.lineMap ?? new Map<string, SalesOrderLine>()\n // Resolve the status label BEFORE mutating shipment scalars so this\n // dictionary read does not interleave with (and drop) the pending\n // shipment changeset under MikroORM v7 (SPEC-018 / #2453 class).\n const resolvedShipmentStatus = input.statusEntryId !== undefined\n ? await resolveDictionaryEntryValue(tx, input.statusEntryId ?? null, { tenantId: shipmentEntity.tenantId })\n : undefined\n if (input.shipmentNumber !== undefined) shipmentEntity.shipmentNumber = input.shipmentNumber ?? null\n if (input.shippingMethodId !== undefined) shipmentEntity.shippingMethodId = input.shippingMethodId ?? null\n if (input.statusEntryId !== undefined) {\n shipmentEntity.statusEntryId = input.statusEntryId ?? null\n shipmentEntity.status = resolvedShipmentStatus ?? null\n }\n if (input.carrierName !== undefined) shipmentEntity.carrierName = input.carrierName ?? null\n if (input.trackingNumbers !== undefined) shipmentEntity.trackingNumbers = parseTrackingNumbers(input.trackingNumbers)\n if (input.shippedAt !== undefined) shipmentEntity.shippedAt = input.shippedAt ?? null\n if (input.deliveredAt !== undefined) shipmentEntity.deliveredAt = input.deliveredAt ?? null\n if (input.weightValue !== undefined) shipmentEntity.weightValue = input.weightValue !== null ? input.weightValue.toString() : null\n if (input.weightUnit !== undefined) shipmentEntity.weightUnit = input.weightUnit ?? null\n if (input.declaredValueNet !== undefined) {\n shipmentEntity.declaredValueNet = input.declaredValueNet !== null ? input.declaredValueNet.toString() : null\n }\n if (input.declaredValueGross !== undefined) {\n shipmentEntity.declaredValueGross = input.declaredValueGross !== null ? input.declaredValueGross.toString() : null\n }\n if (input.currencyCode !== undefined) shipmentEntity.currencyCode = input.currencyCode ?? null\n if (input.notes !== undefined) shipmentEntity.notesText = input.notes ?? null\n if (input.metadata !== undefined || input.shipmentAddressSnapshot !== undefined) {\n shipmentEntity.metadata = mergeAddressSnapshot(\n input.metadata ? cloneJson(input.metadata) : shipmentEntity.metadata ?? null,\n input.shipmentAddressSnapshot\n )\n }\n shipmentEntity.updatedAt = new Date()\n\n // Persist the shipment scalar mutations before the item reads below run on\n // the same EntityManager. Under MikroORM v7 an interleaved query (the\n // findWithDecryption on SalesShipmentItem here and in the snapshot step)\n // resets the identity-map changeset, so shippingMethodId/status/carrier/etc.\n // would silently not persist even though the write returns 200 (#2453).\n await tx.flush()\n\n const shouldLoadItems = Boolean(normalizedItems || input.lineStatusEntryId !== undefined)\n const existingItems = shouldLoadItems ? await findWithDecryption(tx, SalesShipmentItem, { shipment: shipmentEntity }, {}, { tenantId: shipmentEntity.tenantId, organizationId: shipmentEntity.organizationId }) : []\n const newItems: SalesShipmentItem[] = []\n if (normalizedItems) {\n existingItems.forEach((item) => tx.remove(item))\n normalizedItems.forEach((item) => {\n const lineRef = tx.getReference(SalesOrderLine, item.orderLineId)\n const shipmentItem = tx.create(SalesShipmentItem, {\n id: randomUUID(),\n shipment: shipmentEntity,\n orderLine: lineRef,\n organizationId: shipmentEntity.organizationId,\n tenantId: shipmentEntity.tenantId,\n quantity: item.quantity.toString(),\n metadata: item.metadata ? cloneJson(item.metadata) : null,\n })\n newItems.push(shipmentItem)\n tx.persist(shipmentItem)\n })\n }\n\n if (input.customFields !== undefined) {\n await setRecordCustomFields(tx, {\n entityId: E.sales.sales_shipment,\n recordId: shipmentEntity.id,\n organizationId: shipmentEntity.organizationId,\n tenantId: shipmentEntity.tenantId,\n values: normalizeCustomFieldsInput(input.customFields),\n })\n }\n if (input.documentStatusEntryId !== undefined) {\n const orderStatus = await resolveDictionaryEntryValue(tx, input.documentStatusEntryId ?? null, { tenantId: shipmentEntity.tenantId })\n if (input.documentStatusEntryId && !orderStatus) {\n throw new CrudHttpError(400, { error: translate('sales.documents.detail.statusInvalid', 'Selected status could not be found.') })\n }\n order.statusEntryId = input.documentStatusEntryId ?? null\n order.status = orderStatus\n order.updatedAt = new Date()\n }\n if (input.lineStatusEntryId !== undefined) {\n const lineStatus = await resolveDictionaryEntryValue(tx, input.lineStatusEntryId ?? null, { tenantId: shipmentEntity.tenantId })\n if (input.lineStatusEntryId && !lineStatus) {\n throw new CrudHttpError(400, { error: translate('sales.documents.detail.statusInvalid', 'Selected status could not be found.') })\n }\n const targetLineIds = normalizedItems\n ? Array.from(new Set(normalizedItems.map((item) => item.orderLineId)))\n : Array.from(\n new Set(\n existingItems\n .map((item) =>\n typeof item.orderLine === 'string'\n ? item.orderLine\n : (item.orderLine as SalesOrderLine | null)?.id ?? null\n )\n .filter((id): id is string => Boolean(id))\n )\n )\n if (targetLineIds.length) {\n const missing = targetLineIds.filter((id) => !lineMap.has(id))\n if (missing.length) {\n const fetched = await tx.find(SalesOrderLine, { id: { $in: missing } })\n fetched.forEach((line) => lineMap.set(line.id, line))\n }\n targetLineIds.forEach((lineId) => {\n const line = lineMap.get(lineId)\n if (!line) return\n line.statusEntryId = input.lineStatusEntryId ?? null\n line.status = lineStatus\n line.updatedAt = new Date()\n })\n }\n }\n\n // Flush any order/line status mutations applied above before the snapshot\n // read below queries the same EntityManager (same interleaved-read hazard).\n await tx.flush()\n const itemsForSnapshot =\n normalizedItems || shouldLoadItems\n ? (normalizedItems ? newItems : existingItems)\n : await findWithDecryption(tx, SalesShipmentItem, { shipment: shipmentEntity }, {}, { tenantId: shipmentEntity.tenantId, organizationId: shipmentEntity.organizationId })\n await refreshShipmentItemsSnapshot(tx, shipmentEntity, { items: itemsForSnapshot, lineMap })\n await tx.flush()\n await recomputeFulfilledQuantities(tx, order)\n await tx.flush()\n return shipmentEntity\n })\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'updated',\n entity: shipment,\n identifiers: {\n id: shipment.id,\n organizationId: shipment.organizationId,\n tenantId: shipment.tenantId,\n },\n indexer: { entityType: E.sales.sales_shipment },\n events: shipmentCrudEvents,\n })\n\n return { shipmentId: shipment.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return loadShipmentSnapshot(em, result.shipmentId)\n },\n buildLog: async ({ snapshots, result }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as ShipmentSnapshot | undefined\n const after = snapshots.after as ShipmentSnapshot | undefined\n return {\n actionLabel: translate('sales.audit.shipments.update', 'Update shipment'),\n resourceKind: 'sales.shipment',\n resourceId: result.shipmentId,\n parentResourceKind: 'sales.order',\n parentResourceId: after?.orderId ?? before?.orderId ?? null,\n tenantId: after?.tenantId ?? before?.tenantId ?? null,\n organizationId: after?.organizationId ?? before?.organizationId ?? null,\n snapshotBefore: before ?? null,\n snapshotAfter: after ?? null,\n payload: {\n undo: { before, after } satisfies ShipmentUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<ShipmentUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n await em.transactional(async (tx) => {\n await restoreShipmentSnapshot(tx, before)\n const order = await findOneWithDecryption(tx, SalesOrder, { id: before.orderId }, {}, { tenantId: before.tenantId, organizationId: before.organizationId })\n await tx.flush()\n if (order) {\n await recomputeFulfilledQuantities(tx, order)\n await tx.flush()\n }\n })\n },\n}\n\nconst deleteShipmentCommand: CommandHandler<\n { id: string; orderId: string; organizationId: string; tenantId: string },\n { shipmentId: string }\n> = {\n id: 'sales.shipments.delete',\n async prepare(rawInput, ctx) {\n const parsed = shipmentUpdateSchema.parse(rawInput ?? {})\n if (!parsed.id) return {}\n const em = ctx.container.resolve('em') as EntityManager\n const snapshot = await loadShipmentSnapshot(em, parsed.id)\n if (snapshot) {\n try {\n ensureTenantScope(ctx, snapshot.tenantId)\n } catch (error) {\n logShipmentDeleteScopeRejection(ctx, 'Tenant mismatch while preparing shipment delete', {\n shipmentId: snapshot.id,\n snapshotTenantId: snapshot.tenantId,\n authTenantId: ctx.auth?.tenantId ?? null,\n })\n throw error\n }\n try {\n ensureOrganizationScope(ctx, snapshot.organizationId)\n } catch (error) {\n logShipmentDeleteScopeRejection(ctx, 'Organization mismatch while preparing shipment delete', {\n shipmentId: snapshot.id,\n snapshotOrganizationId: snapshot.organizationId,\n selectedOrganizationId: ctx.selectedOrganizationId ?? null,\n authOrganizationId: ctx.auth?.orgId ?? null,\n })\n throw error\n }\n }\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const { translate } = await resolveTranslations()\n const payload = shipmentUpdateSchema\n .pick({ id: true, orderId: true, organizationId: true, tenantId: true })\n .parse(rawInput ?? {})\n try {\n ensureTenantScope(ctx, payload.tenantId)\n } catch (error) {\n logShipmentDeleteScopeRejection(ctx, 'Tenant mismatch while executing shipment delete', {\n shipmentId: payload.id,\n payloadTenantId: payload.tenantId,\n authTenantId: ctx.auth?.tenantId ?? null,\n })\n throw error\n }\n try {\n ensureOrganizationScope(ctx, payload.organizationId)\n } catch (error) {\n logShipmentDeleteScopeRejection(ctx, 'Organization mismatch while executing shipment delete', {\n shipmentId: payload.id,\n payloadOrganizationId: payload.organizationId,\n selectedOrganizationId: ctx.selectedOrganizationId ?? null,\n authOrganizationId: ctx.auth?.orgId ?? null,\n })\n throw error\n }\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n\n const { shipment, shipmentItems } = await em.transactional(async (tx) => {\n const shipmentEntity = await findOneWithDecryption(\n tx,\n SalesShipment,\n { id: payload.id },\n { populate: ['order'] },\n { tenantId: payload.tenantId, organizationId: payload.organizationId },\n )\n if (!shipmentEntity || !shipmentEntity.order) {\n throw notFound(translate('sales.shipments.not_found', 'Shipment not found'))\n }\n try {\n ensureSameScope(shipmentEntity, payload.organizationId, payload.tenantId)\n } catch (error) {\n logShipmentDeleteScopeRejection(ctx, 'Shipment scope mismatch against payload', {\n shipmentId: payload.id,\n shipmentOrganizationId: shipmentEntity.organizationId,\n shipmentTenantId: shipmentEntity.tenantId,\n payloadOrganizationId: payload.organizationId,\n payloadTenantId: payload.tenantId,\n })\n throw error\n }\n const order = shipmentEntity.order as SalesOrder\n if (order.id !== payload.orderId) {\n throw new CrudHttpError(400, { error: translate('sales.shipments.invalid_order', 'Shipment does not belong to this order') })\n }\n // Guard the parent order's aggregate version (Gap B): deleting a shipment\n // recalculates the order's fulfilled quantities, so a stale parent must 409\n // before we touch it.\n await enforceSalesDocumentOptimisticLock(ctx, order, SALES_RESOURCE_KIND_ORDER)\n const scope = { tenantId: shipmentEntity.tenantId, organizationId: shipmentEntity.organizationId }\n const items = await findWithDecryption(tx, SalesShipmentItem, { shipment: shipmentEntity }, {}, scope)\n items.forEach((item) => tx.remove(item))\n tx.remove(shipmentEntity)\n await tx.flush()\n await recomputeFulfilledQuantities(tx, order)\n await tx.flush()\n return { shipment: shipmentEntity, shipmentItems: items }\n })\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'deleted',\n entity: shipment,\n identifiers: {\n id: shipment.id,\n organizationId: shipment.organizationId,\n tenantId: shipment.tenantId,\n },\n indexer: { entityType: E.sales.sales_shipment },\n events: shipmentCrudEvents,\n })\n if (shipmentItems.length) {\n await Promise.all(\n shipmentItems.map((item) =>\n emitCrudSideEffects({\n dataEngine,\n action: 'deleted',\n entity: item,\n identifiers: {\n id: item.id,\n organizationId: item.organizationId ?? null,\n tenantId: item.tenantId ?? null,\n },\n indexer: { entityType: E.sales.sales_shipment_item },\n })\n )\n )\n }\n return { shipmentId: shipment.id }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<ShipmentUndoPayload>(logEntry)\n const snapshot = payload?.before ?? null\n if (!snapshot) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n await em.transactional(async (tx) => {\n await restoreShipmentSnapshot(tx, snapshot)\n const order = await findOneWithDecryption(tx, SalesOrder, { id: snapshot.orderId }, {}, { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId })\n await tx.flush()\n if (order) {\n await recomputeFulfilledQuantities(tx, order)\n await tx.flush()\n }\n })\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as ShipmentSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('sales.audit.shipments.delete', 'Delete shipment'),\n resourceKind: 'sales.shipment',\n resourceId: before.id ?? null,\n parentResourceKind: 'sales.order',\n parentResourceId: before.orderId ?? null,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: { before } satisfies ShipmentUndoPayload,\n },\n }\n },\n}\n\nregisterCommand(createShipmentCommand)\nregisterCommand(updateShipmentCommand)\nregisterCommand(deleteShipmentCommand)\n\nexport const shipmentCommands = [createShipmentCommand, updateShipmentCommand, deleteShipmentCommand]\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DictionaryEntry } from "@open-mercato/core/modules/dictionaries/data/entities";
|
|
2
2
|
import { registerDictionaryEntryCommands } from "@open-mercato/core/modules/dictionaries/commands/factory";
|
|
3
|
-
import { CrudHttpError } from "@open-mercato/shared/lib/crud/errors";
|
|
3
|
+
import { CrudHttpError, notFound } from "@open-mercato/shared/lib/crud/errors";
|
|
4
4
|
import {
|
|
5
5
|
ensureSalesDictionary,
|
|
6
6
|
getSalesDictionaryDefinition
|
|
@@ -65,7 +65,7 @@ function registerStatusDictionaryCommands(kind) {
|
|
|
65
65
|
resolveEntry: async ({ em, ctx, id }) => {
|
|
66
66
|
const entry = await findOneWithDecryption(em, DictionaryEntry, id, { populate: ["dictionary"] });
|
|
67
67
|
if (!entry) {
|
|
68
|
-
throw
|
|
68
|
+
throw notFound("Dictionary entry not found");
|
|
69
69
|
}
|
|
70
70
|
if (entry.dictionary.key !== definition.key) {
|
|
71
71
|
throw new CrudHttpError(400, { error: "Entry does not belong to this dictionary." });
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/sales/commands/statuses.ts"],
|
|
4
|
-
"sourcesContent": ["import { DictionaryEntry } from '@open-mercato/core/modules/dictionaries/data/entities'\nimport { registerDictionaryEntryCommands } from '@open-mercato/core/modules/dictionaries/commands/factory'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport {\n ensureSalesDictionary,\n getSalesDictionaryDefinition,\n type SalesDictionaryKind,\n} from '../lib/dictionaries'\nimport {\n ensureOrganizationScope,\n ensureTenantScope,\n} from './shared'\nimport {\n statusDictionaryCreateSchema,\n statusDictionaryUpdateSchema,\n} from '../data/validators'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\n\nexport const commandIds = [\n 'sales.order-statuses.create',\n 'sales.order-statuses.update',\n 'sales.order-statuses.delete',\n 'sales.order-line-statuses.create',\n 'sales.order-line-statuses.update',\n 'sales.order-line-statuses.delete',\n 'sales.shipment-statuses.create',\n 'sales.shipment-statuses.update',\n 'sales.shipment-statuses.delete',\n 'sales.payment-statuses.create',\n 'sales.payment-statuses.update',\n 'sales.payment-statuses.delete',\n 'sales.adjustment-kinds.create',\n 'sales.adjustment-kinds.update',\n 'sales.adjustment-kinds.delete',\n] as const\n\nfunction ensureScope(ctx: Parameters<typeof ensureTenantScope>[0], scope: { tenantId: string; organizationId: string }): void {\n ensureTenantScope(ctx, scope.tenantId)\n ensureOrganizationScope(ctx, scope.organizationId)\n}\n\nfunction registerStatusDictionaryCommands(kind: SalesDictionaryKind): void {\n const definition = getSalesDictionaryDefinition(kind)\n\n registerDictionaryEntryCommands({\n commandPrefix: definition.commandPrefix,\n resourceKind: definition.resourceKind,\n translationKeyPrefix: definition.commandPrefix,\n createSchema: statusDictionaryCreateSchema,\n updateSchema: statusDictionaryUpdateSchema,\n ensureScope,\n duplicateError: 'Value already exists in this dictionary.',\n labels: {\n singular: definition.singular,\n create: `Create ${definition.singular}`,\n update: `Update ${definition.singular}`,\n delete: `Delete ${definition.singular}`,\n },\n resolveDictionaryForCreate: async ({ em, ctx, parsed }) => {\n const dictionary = await ensureSalesDictionary({\n em,\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n kind,\n })\n const scope = { tenantId: parsed.tenantId, organizationId: parsed.organizationId }\n ensureScope(ctx, scope)\n return { dictionary, scope }\n },\n resolveEntry: async ({ em, ctx, id }) => {\n const entry = await findOneWithDecryption(em, DictionaryEntry, id, { populate: ['dictionary'] })\n if (!entry) {\n throw
|
|
5
|
-
"mappings": "AAAA,SAAS,uBAAuB;AAChC,SAAS,uCAAuC;AAChD,SAAS,
|
|
4
|
+
"sourcesContent": ["import { DictionaryEntry } from '@open-mercato/core/modules/dictionaries/data/entities'\nimport { registerDictionaryEntryCommands } from '@open-mercato/core/modules/dictionaries/commands/factory'\nimport { CrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'\nimport {\n ensureSalesDictionary,\n getSalesDictionaryDefinition,\n type SalesDictionaryKind,\n} from '../lib/dictionaries'\nimport {\n ensureOrganizationScope,\n ensureTenantScope,\n} from './shared'\nimport {\n statusDictionaryCreateSchema,\n statusDictionaryUpdateSchema,\n} from '../data/validators'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\n\nexport const commandIds = [\n 'sales.order-statuses.create',\n 'sales.order-statuses.update',\n 'sales.order-statuses.delete',\n 'sales.order-line-statuses.create',\n 'sales.order-line-statuses.update',\n 'sales.order-line-statuses.delete',\n 'sales.shipment-statuses.create',\n 'sales.shipment-statuses.update',\n 'sales.shipment-statuses.delete',\n 'sales.payment-statuses.create',\n 'sales.payment-statuses.update',\n 'sales.payment-statuses.delete',\n 'sales.adjustment-kinds.create',\n 'sales.adjustment-kinds.update',\n 'sales.adjustment-kinds.delete',\n] as const\n\nfunction ensureScope(ctx: Parameters<typeof ensureTenantScope>[0], scope: { tenantId: string; organizationId: string }): void {\n ensureTenantScope(ctx, scope.tenantId)\n ensureOrganizationScope(ctx, scope.organizationId)\n}\n\nfunction registerStatusDictionaryCommands(kind: SalesDictionaryKind): void {\n const definition = getSalesDictionaryDefinition(kind)\n\n registerDictionaryEntryCommands({\n commandPrefix: definition.commandPrefix,\n resourceKind: definition.resourceKind,\n translationKeyPrefix: definition.commandPrefix,\n createSchema: statusDictionaryCreateSchema,\n updateSchema: statusDictionaryUpdateSchema,\n ensureScope,\n duplicateError: 'Value already exists in this dictionary.',\n labels: {\n singular: definition.singular,\n create: `Create ${definition.singular}`,\n update: `Update ${definition.singular}`,\n delete: `Delete ${definition.singular}`,\n },\n resolveDictionaryForCreate: async ({ em, ctx, parsed }) => {\n const dictionary = await ensureSalesDictionary({\n em,\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n kind,\n })\n const scope = { tenantId: parsed.tenantId, organizationId: parsed.organizationId }\n ensureScope(ctx, scope)\n return { dictionary, scope }\n },\n resolveEntry: async ({ em, ctx, id }) => {\n const entry = await findOneWithDecryption(em, DictionaryEntry, id, { populate: ['dictionary'] })\n if (!entry) {\n throw notFound('Dictionary entry not found')\n }\n if (entry.dictionary.key !== definition.key) {\n throw new CrudHttpError(400, { error: 'Entry does not belong to this dictionary.' })\n }\n const scope = { tenantId: entry.tenantId, organizationId: entry.organizationId }\n ensureScope(ctx, scope)\n return { entry, dictionary: entry.dictionary, scope }\n },\n ensureDictionaryForUndo: async ({ em, snapshot }) => {\n return ensureSalesDictionary({\n em,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n kind,\n })\n },\n })\n}\n\nregisterStatusDictionaryCommands('order-status')\nregisterStatusDictionaryCommands('order-line-status')\nregisterStatusDictionaryCommands('shipment-status')\nregisterStatusDictionaryCommands('payment-status')\nregisterStatusDictionaryCommands('adjustment-kind')\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,uBAAuB;AAChC,SAAS,uCAAuC;AAChD,SAAS,eAAe,gBAAgB;AACxC;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP,SAAS,6BAA6B;AAE/B,MAAM,aAAa;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,SAAS,YAAY,KAA8C,OAA2D;AAC5H,oBAAkB,KAAK,MAAM,QAAQ;AACrC,0BAAwB,KAAK,MAAM,cAAc;AACnD;AAEA,SAAS,iCAAiC,MAAiC;AACzE,QAAM,aAAa,6BAA6B,IAAI;AAEpD,kCAAgC;AAAA,IAC9B,eAAe,WAAW;AAAA,IAC1B,cAAc,WAAW;AAAA,IACzB,sBAAsB,WAAW;AAAA,IACjC,cAAc;AAAA,IACd,cAAc;AAAA,IACd;AAAA,IACA,gBAAgB;AAAA,IAChB,QAAQ;AAAA,MACN,UAAU,WAAW;AAAA,MACrB,QAAQ,UAAU,WAAW,QAAQ;AAAA,MACrC,QAAQ,UAAU,WAAW,QAAQ;AAAA,MACrC,QAAQ,UAAU,WAAW,QAAQ;AAAA,IACvC;AAAA,IACA,4BAA4B,OAAO,EAAE,IAAI,KAAK,OAAO,MAAM;AACzD,YAAM,aAAa,MAAM,sBAAsB;AAAA,QAC7C;AAAA,QACA,UAAU,OAAO;AAAA,QACjB,gBAAgB,OAAO;AAAA,QACvB;AAAA,MACF,CAAC;AACD,YAAM,QAAQ,EAAE,UAAU,OAAO,UAAU,gBAAgB,OAAO,eAAe;AACjF,kBAAY,KAAK,KAAK;AACtB,aAAO,EAAE,YAAY,MAAM;AAAA,IAC7B;AAAA,IACA,cAAc,OAAO,EAAE,IAAI,KAAK,GAAG,MAAM;AACvC,YAAM,QAAQ,MAAM,sBAAsB,IAAI,iBAAiB,IAAI,EAAE,UAAU,CAAC,YAAY,EAAE,CAAC;AAC/F,UAAI,CAAC,OAAO;AACV,cAAM,SAAS,4BAA4B;AAAA,MAC7C;AACA,UAAI,MAAM,WAAW,QAAQ,WAAW,KAAK;AAC3C,cAAM,IAAI,cAAc,KAAK,EAAE,OAAO,4CAA4C,CAAC;AAAA,MACrF;AACA,YAAM,QAAQ,EAAE,UAAU,MAAM,UAAU,gBAAgB,MAAM,eAAe;AAC/E,kBAAY,KAAK,KAAK;AACtB,aAAO,EAAE,OAAO,YAAY,MAAM,YAAY,MAAM;AAAA,IACtD;AAAA,IACA,yBAAyB,OAAO,EAAE,IAAI,SAAS,MAAM;AACnD,aAAO,sBAAsB;AAAA,QAC3B;AAAA,QACA,UAAU,SAAS;AAAA,QACnB,gBAAgB,SAAS;AAAA,QACzB;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AACH;AAEA,iCAAiC,cAAc;AAC/C,iCAAiC,mBAAmB;AACpD,iCAAiC,iBAAiB;AAClD,iCAAiC,gBAAgB;AACjD,iCAAiC,iBAAiB;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { registerCommand } from "@open-mercato/shared/lib/commands";
|
|
2
|
-
import { CrudHttpError } from "@open-mercato/shared/lib/crud/errors";
|
|
2
|
+
import { CrudHttpError, notFound } from "@open-mercato/shared/lib/crud/errors";
|
|
3
3
|
import { SalesDocumentTag, SalesDocumentTagAssignment } from "../data/entities.js";
|
|
4
4
|
import { ensureTenantScope } from "./shared.js";
|
|
5
5
|
import {
|
|
@@ -36,7 +36,7 @@ const updateTagCommand = {
|
|
|
36
36
|
const parsed = salesTagUpdateSchema.parse(rawInput ?? {});
|
|
37
37
|
const em = ctx.container.resolve("em").fork();
|
|
38
38
|
const tag = await em.findOne(SalesDocumentTag, { id: parsed.id });
|
|
39
|
-
if (!tag) throw
|
|
39
|
+
if (!tag) throw notFound("Tag not found");
|
|
40
40
|
ensureTenantScope(ctx, parsed.tenantId ?? tag.tenantId);
|
|
41
41
|
if (parsed.slug && parsed.slug !== tag.slug) {
|
|
42
42
|
const conflict = await em.findOne(SalesDocumentTag, {
|
|
@@ -65,7 +65,7 @@ const deleteTagCommand = {
|
|
|
65
65
|
if (!id) throw new CrudHttpError(400, { error: "Tag id is required" });
|
|
66
66
|
const em = ctx.container.resolve("em").fork();
|
|
67
67
|
const tag = await em.findOne(SalesDocumentTag, { id });
|
|
68
|
-
if (!tag) throw
|
|
68
|
+
if (!tag) throw notFound("Tag not found");
|
|
69
69
|
ensureTenantScope(ctx, tag.tenantId);
|
|
70
70
|
await em.nativeDelete(SalesDocumentTagAssignment, { tag: tag.id });
|
|
71
71
|
em.remove(tag);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/sales/commands/tags.ts"],
|
|
4
|
-
"sourcesContent": ["// @ts-nocheck\n\nimport { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { SalesDocumentTag, SalesDocumentTagAssignment } from '../data/entities'\nimport { ensureTenantScope } from './shared'\nimport {\n salesTagCreateSchema,\n salesTagUpdateSchema,\n type SalesTagCreateInput,\n type SalesTagUpdateInput,\n} from '../data/validators'\n\nconst createTagCommand: CommandHandler<SalesTagCreateInput, { tagId: string }> = {\n id: 'sales.tags.create',\n async execute(rawInput, ctx) {\n const parsed = salesTagCreateSchema.parse(rawInput ?? {})\n ensureTenantScope(ctx, parsed.tenantId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const conflict = await em.findOne(SalesDocumentTag, {\n slug: parsed.slug,\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n })\n if (conflict) throw new CrudHttpError(409, { error: 'Tag slug already exists for this scope' })\n const tag = em.create(SalesDocumentTag, {\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n slug: parsed.slug,\n label: parsed.label,\n color: parsed.color ?? null,\n description: parsed.description ?? null,\n })\n await em.persist(tag).flush()\n return { tagId: tag.id }\n },\n}\n\nconst updateTagCommand: CommandHandler<SalesTagUpdateInput, { tagId: string }> = {\n id: 'sales.tags.update',\n async execute(rawInput, ctx) {\n const parsed = salesTagUpdateSchema.parse(rawInput ?? {})\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const tag = await em.findOne(SalesDocumentTag, { id: parsed.id })\n if (!tag) throw
|
|
5
|
-
"mappings": "AAEA,SAAS,uBAAuB;AAGhC,SAAS,
|
|
4
|
+
"sourcesContent": ["// @ts-nocheck\n\nimport { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { CrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'\nimport { SalesDocumentTag, SalesDocumentTagAssignment } from '../data/entities'\nimport { ensureTenantScope } from './shared'\nimport {\n salesTagCreateSchema,\n salesTagUpdateSchema,\n type SalesTagCreateInput,\n type SalesTagUpdateInput,\n} from '../data/validators'\n\nconst createTagCommand: CommandHandler<SalesTagCreateInput, { tagId: string }> = {\n id: 'sales.tags.create',\n async execute(rawInput, ctx) {\n const parsed = salesTagCreateSchema.parse(rawInput ?? {})\n ensureTenantScope(ctx, parsed.tenantId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const conflict = await em.findOne(SalesDocumentTag, {\n slug: parsed.slug,\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n })\n if (conflict) throw new CrudHttpError(409, { error: 'Tag slug already exists for this scope' })\n const tag = em.create(SalesDocumentTag, {\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n slug: parsed.slug,\n label: parsed.label,\n color: parsed.color ?? null,\n description: parsed.description ?? null,\n })\n await em.persist(tag).flush()\n return { tagId: tag.id }\n },\n}\n\nconst updateTagCommand: CommandHandler<SalesTagUpdateInput, { tagId: string }> = {\n id: 'sales.tags.update',\n async execute(rawInput, ctx) {\n const parsed = salesTagUpdateSchema.parse(rawInput ?? {})\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const tag = await em.findOne(SalesDocumentTag, { id: parsed.id })\n if (!tag) throw notFound('Tag not found')\n ensureTenantScope(ctx, parsed.tenantId ?? tag.tenantId)\n if (parsed.slug && parsed.slug !== tag.slug) {\n const conflict = await em.findOne(SalesDocumentTag, {\n slug: parsed.slug,\n organizationId: parsed.organizationId ?? tag.organizationId,\n tenantId: parsed.tenantId ?? tag.tenantId,\n })\n if (conflict && conflict.id !== tag.id) {\n throw new CrudHttpError(409, { error: 'Tag slug already exists for this scope' })\n }\n tag.slug = parsed.slug\n }\n if (parsed.label !== undefined) tag.label = parsed.label\n if (parsed.color !== undefined) tag.color = parsed.color ?? null\n if (parsed.description !== undefined) tag.description = parsed.description ?? null\n if (parsed.organizationId) tag.organizationId = parsed.organizationId\n if (parsed.tenantId) tag.tenantId = parsed.tenantId\n await em.flush()\n return { tagId: tag.id }\n },\n}\n\nconst deleteTagCommand: CommandHandler<{ id?: string }, { tagId: string }> = {\n id: 'sales.tags.delete',\n async execute(input, ctx) {\n const id = typeof input?.id === 'string' ? input.id : null\n if (!id) throw new CrudHttpError(400, { error: 'Tag id is required' })\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const tag = await em.findOne(SalesDocumentTag, { id })\n if (!tag) throw notFound('Tag not found')\n ensureTenantScope(ctx, tag.tenantId)\n await em.nativeDelete(SalesDocumentTagAssignment, { tag: tag.id })\n em.remove(tag)\n await em.flush()\n return { tagId: id }\n },\n}\n\nregisterCommand(createTagCommand)\nregisterCommand(updateTagCommand)\nregisterCommand(deleteTagCommand)\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-mercato/core",
|
|
3
|
-
"version": "0.6.7-develop.
|
|
3
|
+
"version": "0.6.7-develop.6566.1.15385fa179",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -253,16 +253,16 @@
|
|
|
253
253
|
"zod": "^4.4.3"
|
|
254
254
|
},
|
|
255
255
|
"peerDependencies": {
|
|
256
|
-
"@open-mercato/ai-assistant": "0.6.7-develop.
|
|
257
|
-
"@open-mercato/shared": "0.6.7-develop.
|
|
258
|
-
"@open-mercato/ui": "0.6.7-develop.
|
|
256
|
+
"@open-mercato/ai-assistant": "0.6.7-develop.6566.1.15385fa179",
|
|
257
|
+
"@open-mercato/shared": "0.6.7-develop.6566.1.15385fa179",
|
|
258
|
+
"@open-mercato/ui": "0.6.7-develop.6566.1.15385fa179",
|
|
259
259
|
"react": "^19.0.0",
|
|
260
260
|
"react-dom": "^19.0.0"
|
|
261
261
|
},
|
|
262
262
|
"devDependencies": {
|
|
263
|
-
"@open-mercato/ai-assistant": "0.6.7-develop.
|
|
264
|
-
"@open-mercato/shared": "0.6.7-develop.
|
|
265
|
-
"@open-mercato/ui": "0.6.7-develop.
|
|
263
|
+
"@open-mercato/ai-assistant": "0.6.7-develop.6566.1.15385fa179",
|
|
264
|
+
"@open-mercato/shared": "0.6.7-develop.6566.1.15385fa179",
|
|
265
|
+
"@open-mercato/ui": "0.6.7-develop.6566.1.15385fa179",
|
|
266
266
|
"@testing-library/dom": "^10.4.1",
|
|
267
267
|
"@testing-library/jest-dom": "^6.9.1",
|
|
268
268
|
"@testing-library/react": "^16.3.1",
|
|
@@ -276,7 +276,7 @@
|
|
|
276
276
|
"react": "19.2.7",
|
|
277
277
|
"react-dom": "19.2.7",
|
|
278
278
|
"ts-jest": "^29.4.11",
|
|
279
|
-
"typescript": "
|
|
279
|
+
"typescript": "7.0.2"
|
|
280
280
|
},
|
|
281
281
|
"publishConfig": {
|
|
282
282
|
"access": "public"
|
|
@@ -78,7 +78,7 @@ export async function GET(req: Request) {
|
|
|
78
78
|
}
|
|
79
79
|
const em = await resolveEm()
|
|
80
80
|
await ensureDefaultPartitions(em)
|
|
81
|
-
const rows = await findWithDecryption(
|
|
81
|
+
const rows = await findWithDecryption<AttachmentPartition>(
|
|
82
82
|
em,
|
|
83
83
|
AttachmentPartition,
|
|
84
84
|
partitionVisibilityFilter(auth),
|
|
@@ -132,13 +132,22 @@ export async function reconcileAttachmentOrganizations(opts: {
|
|
|
132
132
|
for (let index = 0; index < recordIds.length; index += batchSize) {
|
|
133
133
|
const chunk = recordIds.slice(index, index + batchSize)
|
|
134
134
|
try {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
135
|
+
// An unregistrable entity id makes the Query Engine emit SQL against a
|
|
136
|
+
// non-existent relation, and a failed statement aborts the surrounding
|
|
137
|
+
// Postgres transaction the caller runs this reconcile in — poisoning
|
|
138
|
+
// the whole backfill (#4145). Running each resolution query inside a
|
|
139
|
+
// nested transaction scopes the failure to a savepoint, so the catch
|
|
140
|
+
// below can mark just this group unresolved while every other group
|
|
141
|
+
// and the final flush keep working.
|
|
142
|
+
const result = await em.transactional(async () =>
|
|
143
|
+
queryEngine.query(entityId as any, {
|
|
144
|
+
fields: ['id', 'organization_id'],
|
|
145
|
+
filters: { id: chunk.length === 1 ? { $eq: chunk[0] } : { $in: chunk } },
|
|
146
|
+
tenantId,
|
|
147
|
+
withDeleted: true,
|
|
148
|
+
page: { pageSize: Math.max(chunk.length, 1) },
|
|
149
|
+
}),
|
|
150
|
+
)
|
|
142
151
|
for (const item of result.items ?? []) {
|
|
143
152
|
const record = item as Record<string, unknown>
|
|
144
153
|
const recordId = record.id != null ? String(record.id) : null
|
|
@@ -585,7 +585,7 @@ async function decorateProductsAfterList(
|
|
|
585
585
|
],
|
|
586
586
|
}
|
|
587
587
|
: { product: { $in: productIds } };
|
|
588
|
-
const priceRows = await findWithDecryption(
|
|
588
|
+
const priceRows = await findWithDecryption<CatalogProductPrice>(
|
|
589
589
|
em,
|
|
590
590
|
CatalogProductPrice,
|
|
591
591
|
{ ...priceWhere, ...scope },
|
|
@@ -104,7 +104,9 @@
|
|
|
104
104
|
"customer_accounts.admin.flash.deleted": "User deleted",
|
|
105
105
|
"customer_accounts.admin.inactive": "Inactive",
|
|
106
106
|
"customer_accounts.admin.portalFeatures.addresses.manage": "Adressen verwalten",
|
|
107
|
+
"customer_accounts.admin.portalFeatures.addresses.manage.description": "Ermöglicht das Hinzufügen, Bearbeiten und Entfernen von Adressen",
|
|
107
108
|
"customer_accounts.admin.portalFeatures.addresses.view": "Adressen anzeigen",
|
|
109
|
+
"customer_accounts.admin.portalFeatures.addresses.view.description": "Ermöglicht das Anzeigen gespeicherter Liefer- und Rechnungsadressen",
|
|
108
110
|
"customer_accounts.admin.portalFeatures.groups.addresses": "Adressen",
|
|
109
111
|
"customer_accounts.admin.portalFeatures.groups.invoices": "Rechnungen",
|
|
110
112
|
"customer_accounts.admin.portalFeatures.groups.orders": "Bestellungen",
|
|
@@ -112,15 +114,25 @@
|
|
|
112
114
|
"customer_accounts.admin.portalFeatures.groups.quotes": "Angebote",
|
|
113
115
|
"customer_accounts.admin.portalFeatures.groups.users": "Benutzer",
|
|
114
116
|
"customer_accounts.admin.portalFeatures.invoices.view": "Rechnungen anzeigen",
|
|
117
|
+
"customer_accounts.admin.portalFeatures.invoices.view.description": "Ermöglicht das Anzeigen von Rechnungen und der Zahlungshistorie",
|
|
115
118
|
"customer_accounts.admin.portalFeatures.orders.create": "Bestellungen erstellen",
|
|
119
|
+
"customer_accounts.admin.portalFeatures.orders.create.description": "Ermöglicht das Aufgeben neuer Bestellungen über das Portal",
|
|
116
120
|
"customer_accounts.admin.portalFeatures.orders.view": "Bestellungen anzeigen",
|
|
121
|
+
"customer_accounts.admin.portalFeatures.orders.view.description": "Ermöglicht das Anzeigen des Bestellverlaufs und der Bestelldetails",
|
|
117
122
|
"customer_accounts.admin.portalFeatures.profile.edit": "Profil bearbeiten",
|
|
123
|
+
"customer_accounts.admin.portalFeatures.profile.edit.description": "Ermöglicht das Bearbeiten des Anzeigenamens und anderer Profileinstellungen",
|
|
118
124
|
"customer_accounts.admin.portalFeatures.profile.view": "Profil anzeigen",
|
|
125
|
+
"customer_accounts.admin.portalFeatures.profile.view.description": "Ermöglicht das Anzeigen der eigenen Profilinformationen und Kontodetails",
|
|
119
126
|
"customer_accounts.admin.portalFeatures.quotes.request": "Angebote anfordern",
|
|
127
|
+
"customer_accounts.admin.portalFeatures.quotes.request.description": "Ermöglicht das Anfordern neuer Angebote vom Unternehmen",
|
|
120
128
|
"customer_accounts.admin.portalFeatures.quotes.view": "Angebote anzeigen",
|
|
129
|
+
"customer_accounts.admin.portalFeatures.quotes.view.description": "Ermöglicht das Anzeigen erhaltener Angebote und deren Details",
|
|
121
130
|
"customer_accounts.admin.portalFeatures.users.invite": "Teammitglieder einladen",
|
|
131
|
+
"customer_accounts.admin.portalFeatures.users.invite.description": "Ermöglicht das Senden von Portaleinladungen an neue Teammitglieder",
|
|
122
132
|
"customer_accounts.admin.portalFeatures.users.manage": "Teammitglieder verwalten",
|
|
133
|
+
"customer_accounts.admin.portalFeatures.users.manage.description": "Ermöglicht das Bearbeiten von Rollen und das Entfernen von Teammitgliedern",
|
|
123
134
|
"customer_accounts.admin.portalFeatures.users.view": "Teammitglieder anzeigen",
|
|
135
|
+
"customer_accounts.admin.portalFeatures.users.view.description": "Ermöglicht das Anzeigen anderer Teammitglieder in der Organisation",
|
|
124
136
|
"customer_accounts.admin.portalInfo.credentials": "Demo credentials: alice.johnson@example.com / Password123!",
|
|
125
137
|
"customer_accounts.admin.portalInfo.description": "Manage customer portal accounts. Customers can self-register, log in, and access orders, quotes, and invoices through the portal.",
|
|
126
138
|
"customer_accounts.admin.portalInfo.open": "Open Portal",
|