@open-mercato/core 0.6.5-develop.5116.1.f0af9e5080 → 0.6.5-develop.5155.1.148d10a46d
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/communication_channels/lib/email-mime.js +18 -1
- package/dist/modules/communication_channels/lib/email-mime.js.map +2 -2
- package/dist/modules/customers/components/formConfig.js +4 -1
- package/dist/modules/customers/components/formConfig.js.map +2 -2
- package/dist/modules/customers/data/validators.js +5 -1
- package/dist/modules/customers/data/validators.js.map +2 -2
- package/dist/modules/sales/commands/configuration.js +2 -2
- package/dist/modules/sales/commands/configuration.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +17 -13
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/commands/payments.js +6 -6
- package/dist/modules/sales/commands/payments.js.map +2 -2
- package/dist/modules/sales/commands/shipments.js +6 -6
- package/dist/modules/sales/commands/shipments.js.map +2 -2
- package/dist/modules/sales/lib/dictionaries.js +2 -2
- package/dist/modules/sales/lib/dictionaries.js.map +2 -2
- package/dist/modules/staff/components/TeamMemberForm.js +5 -2
- package/dist/modules/staff/components/TeamMemberForm.js.map +2 -2
- package/package.json +14 -14
- package/src/modules/communication_channels/lib/email-mime.ts +33 -6
- package/src/modules/customers/components/formConfig.tsx +16 -1
- package/src/modules/customers/data/validators.ts +8 -1
- package/src/modules/sales/commands/configuration.ts +2 -2
- package/src/modules/sales/commands/documents.ts +13 -9
- package/src/modules/sales/commands/payments.ts +6 -6
- package/src/modules/sales/commands/shipments.ts +6 -6
- package/src/modules/sales/lib/dictionaries.ts +3 -2
- package/src/modules/staff/components/TeamMemberForm.tsx +6 -1
|
@@ -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} 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'\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 // eslint-disable-next-line no-console\n console.warn(`[sales.shipments.delete] ${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 em.findOne(SalesOrder, { id: snapshot.orderId })\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(em: EntityManager, id: string): Promise<SalesOrder> {\n const order = await em.findOne(SalesOrder, { id, deletedAt: null })\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)\n ensureSameScope(order, input.organizationId, input.tenantId)\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)\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)\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)\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 tx.findOne(SalesOrder, { id: after.orderId })\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\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)\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)\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)\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 tx.findOne(SalesOrder, { id: before.orderId })\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 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 tx.findOne(SalesOrder, { id: snapshot.orderId })\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 } 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} 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'\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 // eslint-disable-next-line no-console\n console.warn(`[sales.shipments.delete] ${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 em.findOne(SalesOrder, { id: snapshot.orderId })\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(em: EntityManager, id: string): Promise<SalesOrder> {\n const order = await em.findOne(SalesOrder, { id, deletedAt: null })\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)\n ensureSameScope(order, input.organizationId, input.tenantId)\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 tx.findOne(SalesOrder, { id: after.orderId })\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\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 tx.findOne(SalesOrder, { id: before.orderId })\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 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 tx.findOne(SalesOrder, { id: snapshot.orderId })\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
|
}
|
|
@@ -84,9 +84,9 @@ async function ensureSalesDictionary(params) {
|
|
|
84
84
|
}
|
|
85
85
|
return dictionary;
|
|
86
86
|
}
|
|
87
|
-
async function resolveDictionaryEntryValue(em, entryId) {
|
|
87
|
+
async function resolveDictionaryEntryValue(em, entryId, scope) {
|
|
88
88
|
if (!entryId) return null;
|
|
89
|
-
const entry = await em.findOne(DictionaryEntry, entryId);
|
|
89
|
+
const entry = await em.findOne(DictionaryEntry, { id: entryId, tenantId: scope.tenantId });
|
|
90
90
|
if (!entry) return null;
|
|
91
91
|
return entry.value?.trim() || null;
|
|
92
92
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/sales/lib/dictionaries.ts"],
|
|
4
|
-
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { Dictionary, DictionaryEntry } from '@open-mercato/core/modules/dictionaries/data/entities'\nimport {\n normalizeDictionaryValue,\n sanitizeDictionaryColor,\n sanitizeDictionaryIcon,\n} from '@open-mercato/core/modules/dictionaries/lib/utils'\n\nexport type SalesDictionaryKind =\n | 'order-status'\n | 'order-line-status'\n | 'shipment-status'\n | 'payment-status'\n | 'deal-loss-reasons'\n | 'adjustment-kind'\n\ntype SalesDictionaryDefinition = {\n key: string\n name: string\n singular: string\n description: string\n resourceKind: string\n commandPrefix: string\n}\n\nconst DEFINITIONS: Record<SalesDictionaryKind, SalesDictionaryDefinition> = {\n 'order-status': {\n key: 'sales.order_status',\n name: 'Sales order statuses',\n singular: 'Sales order status',\n description: 'Configurable set of statuses used by sales orders.',\n resourceKind: 'sales.order-status',\n commandPrefix: 'sales.order-statuses',\n },\n 'order-line-status': {\n key: 'sales.order_line_status',\n name: 'Sales order line statuses',\n singular: 'Sales order line status',\n description: 'Configurable set of statuses used by sales order lines.',\n resourceKind: 'sales.order-line-status',\n commandPrefix: 'sales.order-line-statuses',\n },\n 'shipment-status': {\n key: 'sales.shipment_status',\n name: 'Shipment statuses',\n singular: 'Shipment status',\n description: 'Configurable set of statuses used by shipments.',\n resourceKind: 'sales.shipment-status',\n commandPrefix: 'sales.shipment-statuses',\n },\n 'payment-status': {\n key: 'sales.payment_status',\n name: 'Payment statuses',\n singular: 'Payment status',\n description: 'Configurable set of statuses used by payments.',\n resourceKind: 'sales.payment-status',\n commandPrefix: 'sales.payment-statuses',\n },\n 'deal-loss-reasons': {\n key: 'sales.deal_loss_reason',\n name: 'Deal loss reasons',\n singular: 'Deal loss reason',\n description: 'Reusable reasons used when closing deals as lost.',\n resourceKind: 'sales.deal-loss-reason',\n commandPrefix: 'sales.deal-loss-reasons',\n },\n 'adjustment-kind': {\n key: 'sales.adjustment_kind',\n name: 'Sales adjustment kinds',\n singular: 'Sales adjustment kind',\n description: 'Reusable adjustment kinds applied to sales documents.',\n resourceKind: 'sales.adjustment-kind',\n commandPrefix: 'sales.adjustment-kinds',\n },\n}\n\nexport function getSalesDictionaryDefinition(kind: SalesDictionaryKind): SalesDictionaryDefinition {\n return DEFINITIONS[kind]\n}\n\nexport async function ensureSalesDictionary(params: {\n em: EntityManager\n tenantId: string\n organizationId: string\n kind: SalesDictionaryKind\n}): Promise<Dictionary> {\n const { em, tenantId, organizationId, kind } = params\n const def = getSalesDictionaryDefinition(kind)\n let dictionary = await em.findOne(Dictionary, {\n tenantId,\n organizationId,\n key: def.key,\n deletedAt: null,\n })\n if (!dictionary) {\n dictionary = em.create(Dictionary, {\n tenantId,\n organizationId,\n key: def.key,\n name: def.name,\n description: def.description,\n isSystem: true,\n isActive: true,\n managerVisibility: 'hidden',\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(dictionary)\n await em.flush()\n }\n return dictionary\n}\n\nexport async function resolveDictionaryEntryValue(\n em: EntityManager,\n entryId: string | null | undefined\n): Promise<string | null> {\n if (!entryId) return null\n const entry = await em.findOne(DictionaryEntry, entryId)\n if (!entry) return null\n return entry.value?.trim() || null\n}\n\nexport { normalizeDictionaryValue, sanitizeDictionaryColor, sanitizeDictionaryIcon }\n\ntype SalesDictionarySeed = {\n value: string\n label: string\n color?: string | null\n icon?: string | null\n}\n\ntype SeedScope = { tenantId: string; organizationId: string }\n\nconst ORDER_STATUS_DEFAULTS: SalesDictionarySeed[] = [\n { value: 'draft', label: 'Draft', color: '#94a3b8', icon: 'lucide:file-pen-line' },\n { value: 'pending_approval', label: 'Pending Approval', color: '#f59e0b', icon: 'lucide:hourglass' },\n { value: 'approved', label: 'Approved', color: '#16a34a', icon: 'lucide:check-circle' },\n { value: 'rejected', label: 'Rejected', color: '#ef4444', icon: 'lucide:x-circle' },\n { value: 'sent', label: 'Sent', color: '#0ea5e9', icon: 'lucide:send' },\n { value: 'confirmed', label: 'Confirmed', color: '#2563eb', icon: 'lucide:badge-check' },\n { value: 'in_fulfillment', label: 'In fulfillment', color: '#f59e0b', icon: 'lucide:loader-2' },\n { value: 'fulfilled', label: 'Fulfilled', color: '#16a34a', icon: 'lucide:check-circle-2' },\n { value: 'on_hold', label: 'On hold', color: '#a855f7', icon: 'lucide:pause-circle' },\n { value: 'canceled', label: 'Canceled', color: '#ef4444', icon: 'lucide:x-circle' },\n]\n\nconst ORDER_LINE_STATUS_DEFAULTS: SalesDictionarySeed[] = [\n { value: 'pending', label: 'Pending', color: '#94a3b8', icon: 'lucide:clock' },\n { value: 'allocated', label: 'Allocated', color: '#6366f1', icon: 'lucide:inbox' },\n { value: 'picking', label: 'Picking', color: '#f59e0b', icon: 'lucide:hand' },\n { value: 'packed', label: 'Packed', color: '#0ea5e9', icon: 'lucide:package' },\n { value: 'shipped', label: 'Shipped', color: '#2563eb', icon: 'lucide:truck' },\n { value: 'delivered', label: 'Delivered', color: '#16a34a', icon: 'lucide:check-circle-2' },\n { value: 'backordered', label: 'Backordered', color: '#d946ef', icon: 'lucide:alert-octagon' },\n { value: 'returned', label: 'Returned', color: '#0d9488', icon: 'lucide:undo-2' },\n { value: 'canceled', label: 'Canceled', color: '#ef4444', icon: 'lucide:x-circle' },\n]\n\nconst SHIPMENT_STATUS_DEFAULTS: SalesDictionarySeed[] = [\n { value: 'pending', label: 'Pending', color: '#94a3b8', icon: 'lucide:clock-3' },\n { value: 'packed', label: 'Packed', color: '#22c55e', icon: 'lucide:package-check' },\n { value: 'shipped', label: 'Shipped', color: '#2563eb', icon: 'lucide:truck' },\n { value: 'in_transit', label: 'In transit', color: '#0ea5e9', icon: 'lucide:loader' },\n { value: 'delivered', label: 'Delivered', color: '#16a34a', icon: 'lucide:check-circle-2' },\n { value: 'canceled', label: 'Canceled', color: '#ef4444', icon: 'lucide:x-circle' },\n { value: 'returned', label: 'Returned', color: '#0d9488', icon: 'lucide:undo-2' },\n]\n\nconst PAYMENT_STATUS_DEFAULTS: SalesDictionarySeed[] = [\n { value: 'pending', label: 'Pending', color: '#94a3b8', icon: 'lucide:clock-3' },\n { value: 'authorized', label: 'Authorized', color: '#6366f1', icon: 'lucide:badge-check' },\n { value: 'captured', label: 'Captured', color: '#0ea5e9', icon: 'lucide:banknote' },\n { value: 'received', label: 'Received', color: '#16a34a', icon: 'lucide:check' },\n { value: 'refunded', label: 'Refunded', color: '#f59e0b', icon: 'lucide:rotate-ccw' },\n { value: 'failed', label: 'Failed', color: '#ef4444', icon: 'lucide:triangle-alert' },\n { value: 'canceled', label: 'Canceled', color: '#ef4444', icon: 'lucide:x-circle' },\n]\n\nconst ADJUSTMENT_KIND_DEFAULTS: SalesDictionarySeed[] = [\n { value: 'discount', label: 'Discount' },\n { value: 'tax', label: 'Tax' },\n { value: 'shipping', label: 'Shipping' },\n { value: 'surcharge', label: 'Surcharge' },\n { value: 'return', label: 'Return' },\n { value: 'custom', label: 'Custom' },\n]\n\nasync function ensureSalesDictionaryEntry(\n em: EntityManager,\n scope: SeedScope,\n kind: SalesDictionaryKind,\n seed: SalesDictionarySeed\n): Promise<DictionaryEntry | null> {\n const value = seed.value?.trim()\n if (!value) return null\n const dictionary = await ensureSalesDictionary({\n em,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n kind,\n })\n const normalizedValue = normalizeDictionaryValue(value)\n const color = seed.color === undefined ? undefined : sanitizeDictionaryColor(seed.color)\n const icon = seed.icon === undefined ? undefined : sanitizeDictionaryIcon(seed.icon)\n const existing = await em.findOne(DictionaryEntry, {\n dictionary,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n normalizedValue,\n })\n if (existing) {\n let changed = false\n if (color !== undefined && existing.color !== color) {\n existing.color = color ?? null\n changed = true\n }\n if (icon !== undefined && existing.icon !== icon) {\n existing.icon = icon ?? null\n changed = true\n }\n if (changed) {\n existing.updatedAt = new Date()\n em.persist(existing)\n }\n return existing\n }\n const now = new Date()\n const entry = em.create(DictionaryEntry, {\n dictionary,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n value,\n label: seed.label?.trim() || value,\n normalizedValue,\n color: color ?? null,\n icon: icon ?? null,\n createdAt: now,\n updatedAt: now,\n })\n em.persist(entry)\n return entry\n}\n\nasync function seedSalesDictionary(\n em: EntityManager,\n scope: SeedScope,\n kind: SalesDictionaryKind,\n defaults: SalesDictionarySeed[]\n): Promise<void> {\n for (const seed of defaults) {\n await ensureSalesDictionaryEntry(em, scope, kind, seed)\n }\n}\n\nconst DEAL_LOSS_REASON_DEFAULTS: SalesDictionarySeed[] = [\n { value: 'lost_to_competitor', label: 'Lost to competitor', color: '#ef4444', icon: 'lucide:users' },\n { value: 'no_budget', label: 'No budget', color: '#f59e0b', icon: 'lucide:wallet' },\n { value: 'no_decision', label: 'No decision made', color: '#94a3b8', icon: 'lucide:help-circle' },\n { value: 'timing', label: 'Bad timing', color: '#6366f1', icon: 'lucide:clock' },\n { value: 'other', label: 'Other', color: '#71717a', icon: 'lucide:minus-circle' },\n]\n\nexport async function seedSalesStatusDictionaries(\n em: EntityManager,\n scope: SeedScope\n): Promise<void> {\n await seedSalesDictionary(em, scope, 'order-status', ORDER_STATUS_DEFAULTS)\n await seedSalesDictionary(em, scope, 'order-line-status', ORDER_LINE_STATUS_DEFAULTS)\n await seedSalesDictionary(em, scope, 'shipment-status', SHIPMENT_STATUS_DEFAULTS)\n await seedSalesDictionary(em, scope, 'payment-status', PAYMENT_STATUS_DEFAULTS)\n await seedSalesDictionary(em, scope, 'deal-loss-reasons', DEAL_LOSS_REASON_DEFAULTS)\n}\n\nexport async function seedSalesAdjustmentKinds(\n em: EntityManager,\n scope: SeedScope\n): Promise<void> {\n await seedSalesDictionary(em, scope, 'adjustment-kind', ADJUSTMENT_KIND_DEFAULTS)\n}\n\nexport async function seedSalesDictionaries(\n em: EntityManager,\n scope: SeedScope\n): Promise<void> {\n await seedSalesStatusDictionaries(em, scope)\n await seedSalesAdjustmentKinds(em, scope)\n}\n\nexport const DEFAULT_ADJUSTMENT_KIND_VALUES = ADJUSTMENT_KIND_DEFAULTS.map((entry) => entry.value)\n"],
|
|
5
|
-
"mappings": "AACA,SAAS,YAAY,uBAAuB;AAC5C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAmBP,MAAM,cAAsE;AAAA,EAC1E,gBAAgB;AAAA,IACd,KAAK;AAAA,IACL,MAAM;AAAA,IACN,UAAU;AAAA,IACV,aAAa;AAAA,IACb,cAAc;AAAA,IACd,eAAe;AAAA,EACjB;AAAA,EACA,qBAAqB;AAAA,IACnB,KAAK;AAAA,IACL,MAAM;AAAA,IACN,UAAU;AAAA,IACV,aAAa;AAAA,IACb,cAAc;AAAA,IACd,eAAe;AAAA,EACjB;AAAA,EACA,mBAAmB;AAAA,IACjB,KAAK;AAAA,IACL,MAAM;AAAA,IACN,UAAU;AAAA,IACV,aAAa;AAAA,IACb,cAAc;AAAA,IACd,eAAe;AAAA,EACjB;AAAA,EACA,kBAAkB;AAAA,IAChB,KAAK;AAAA,IACL,MAAM;AAAA,IACN,UAAU;AAAA,IACV,aAAa;AAAA,IACb,cAAc;AAAA,IACd,eAAe;AAAA,EACjB;AAAA,EACA,qBAAqB;AAAA,IACnB,KAAK;AAAA,IACL,MAAM;AAAA,IACN,UAAU;AAAA,IACV,aAAa;AAAA,IACb,cAAc;AAAA,IACd,eAAe;AAAA,EACjB;AAAA,EACA,mBAAmB;AAAA,IACjB,KAAK;AAAA,IACL,MAAM;AAAA,IACN,UAAU;AAAA,IACV,aAAa;AAAA,IACb,cAAc;AAAA,IACd,eAAe;AAAA,EACjB;AACF;AAEO,SAAS,6BAA6B,MAAsD;AACjG,SAAO,YAAY,IAAI;AACzB;AAEA,eAAsB,sBAAsB,QAKpB;AACtB,QAAM,EAAE,IAAI,UAAU,gBAAgB,KAAK,IAAI;AAC/C,QAAM,MAAM,6BAA6B,IAAI;AAC7C,MAAI,aAAa,MAAM,GAAG,QAAQ,YAAY;AAAA,IAC5C;AAAA,IACA;AAAA,IACA,KAAK,IAAI;AAAA,IACT,WAAW;AAAA,EACb,CAAC;AACD,MAAI,CAAC,YAAY;AACf,iBAAa,GAAG,OAAO,YAAY;AAAA,MACjC;AAAA,MACA;AAAA,MACA,KAAK,IAAI;AAAA,MACT,MAAM,IAAI;AAAA,MACV,aAAa,IAAI;AAAA,MACjB,UAAU;AAAA,MACV,UAAU;AAAA,MACV,mBAAmB;AAAA,MACnB,WAAW,oBAAI,KAAK;AAAA,MACpB,WAAW,oBAAI,KAAK;AAAA,IACtB,CAAC;AACD,OAAG,QAAQ,UAAU;AACrB,UAAM,GAAG,MAAM;AAAA,EACjB;AACA,SAAO;AACT;AAEA,eAAsB,4BACpB,IACA,
|
|
4
|
+
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { Dictionary, DictionaryEntry } from '@open-mercato/core/modules/dictionaries/data/entities'\nimport {\n normalizeDictionaryValue,\n sanitizeDictionaryColor,\n sanitizeDictionaryIcon,\n} from '@open-mercato/core/modules/dictionaries/lib/utils'\n\nexport type SalesDictionaryKind =\n | 'order-status'\n | 'order-line-status'\n | 'shipment-status'\n | 'payment-status'\n | 'deal-loss-reasons'\n | 'adjustment-kind'\n\ntype SalesDictionaryDefinition = {\n key: string\n name: string\n singular: string\n description: string\n resourceKind: string\n commandPrefix: string\n}\n\nconst DEFINITIONS: Record<SalesDictionaryKind, SalesDictionaryDefinition> = {\n 'order-status': {\n key: 'sales.order_status',\n name: 'Sales order statuses',\n singular: 'Sales order status',\n description: 'Configurable set of statuses used by sales orders.',\n resourceKind: 'sales.order-status',\n commandPrefix: 'sales.order-statuses',\n },\n 'order-line-status': {\n key: 'sales.order_line_status',\n name: 'Sales order line statuses',\n singular: 'Sales order line status',\n description: 'Configurable set of statuses used by sales order lines.',\n resourceKind: 'sales.order-line-status',\n commandPrefix: 'sales.order-line-statuses',\n },\n 'shipment-status': {\n key: 'sales.shipment_status',\n name: 'Shipment statuses',\n singular: 'Shipment status',\n description: 'Configurable set of statuses used by shipments.',\n resourceKind: 'sales.shipment-status',\n commandPrefix: 'sales.shipment-statuses',\n },\n 'payment-status': {\n key: 'sales.payment_status',\n name: 'Payment statuses',\n singular: 'Payment status',\n description: 'Configurable set of statuses used by payments.',\n resourceKind: 'sales.payment-status',\n commandPrefix: 'sales.payment-statuses',\n },\n 'deal-loss-reasons': {\n key: 'sales.deal_loss_reason',\n name: 'Deal loss reasons',\n singular: 'Deal loss reason',\n description: 'Reusable reasons used when closing deals as lost.',\n resourceKind: 'sales.deal-loss-reason',\n commandPrefix: 'sales.deal-loss-reasons',\n },\n 'adjustment-kind': {\n key: 'sales.adjustment_kind',\n name: 'Sales adjustment kinds',\n singular: 'Sales adjustment kind',\n description: 'Reusable adjustment kinds applied to sales documents.',\n resourceKind: 'sales.adjustment-kind',\n commandPrefix: 'sales.adjustment-kinds',\n },\n}\n\nexport function getSalesDictionaryDefinition(kind: SalesDictionaryKind): SalesDictionaryDefinition {\n return DEFINITIONS[kind]\n}\n\nexport async function ensureSalesDictionary(params: {\n em: EntityManager\n tenantId: string\n organizationId: string\n kind: SalesDictionaryKind\n}): Promise<Dictionary> {\n const { em, tenantId, organizationId, kind } = params\n const def = getSalesDictionaryDefinition(kind)\n let dictionary = await em.findOne(Dictionary, {\n tenantId,\n organizationId,\n key: def.key,\n deletedAt: null,\n })\n if (!dictionary) {\n dictionary = em.create(Dictionary, {\n tenantId,\n organizationId,\n key: def.key,\n name: def.name,\n description: def.description,\n isSystem: true,\n isActive: true,\n managerVisibility: 'hidden',\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(dictionary)\n await em.flush()\n }\n return dictionary\n}\n\nexport async function resolveDictionaryEntryValue(\n em: EntityManager,\n entryId: string | null | undefined,\n scope: { tenantId: string }\n): Promise<string | null> {\n if (!entryId) return null\n const entry = await em.findOne(DictionaryEntry, { id: entryId, tenantId: scope.tenantId })\n if (!entry) return null\n return entry.value?.trim() || null\n}\n\nexport { normalizeDictionaryValue, sanitizeDictionaryColor, sanitizeDictionaryIcon }\n\ntype SalesDictionarySeed = {\n value: string\n label: string\n color?: string | null\n icon?: string | null\n}\n\ntype SeedScope = { tenantId: string; organizationId: string }\n\nconst ORDER_STATUS_DEFAULTS: SalesDictionarySeed[] = [\n { value: 'draft', label: 'Draft', color: '#94a3b8', icon: 'lucide:file-pen-line' },\n { value: 'pending_approval', label: 'Pending Approval', color: '#f59e0b', icon: 'lucide:hourglass' },\n { value: 'approved', label: 'Approved', color: '#16a34a', icon: 'lucide:check-circle' },\n { value: 'rejected', label: 'Rejected', color: '#ef4444', icon: 'lucide:x-circle' },\n { value: 'sent', label: 'Sent', color: '#0ea5e9', icon: 'lucide:send' },\n { value: 'confirmed', label: 'Confirmed', color: '#2563eb', icon: 'lucide:badge-check' },\n { value: 'in_fulfillment', label: 'In fulfillment', color: '#f59e0b', icon: 'lucide:loader-2' },\n { value: 'fulfilled', label: 'Fulfilled', color: '#16a34a', icon: 'lucide:check-circle-2' },\n { value: 'on_hold', label: 'On hold', color: '#a855f7', icon: 'lucide:pause-circle' },\n { value: 'canceled', label: 'Canceled', color: '#ef4444', icon: 'lucide:x-circle' },\n]\n\nconst ORDER_LINE_STATUS_DEFAULTS: SalesDictionarySeed[] = [\n { value: 'pending', label: 'Pending', color: '#94a3b8', icon: 'lucide:clock' },\n { value: 'allocated', label: 'Allocated', color: '#6366f1', icon: 'lucide:inbox' },\n { value: 'picking', label: 'Picking', color: '#f59e0b', icon: 'lucide:hand' },\n { value: 'packed', label: 'Packed', color: '#0ea5e9', icon: 'lucide:package' },\n { value: 'shipped', label: 'Shipped', color: '#2563eb', icon: 'lucide:truck' },\n { value: 'delivered', label: 'Delivered', color: '#16a34a', icon: 'lucide:check-circle-2' },\n { value: 'backordered', label: 'Backordered', color: '#d946ef', icon: 'lucide:alert-octagon' },\n { value: 'returned', label: 'Returned', color: '#0d9488', icon: 'lucide:undo-2' },\n { value: 'canceled', label: 'Canceled', color: '#ef4444', icon: 'lucide:x-circle' },\n]\n\nconst SHIPMENT_STATUS_DEFAULTS: SalesDictionarySeed[] = [\n { value: 'pending', label: 'Pending', color: '#94a3b8', icon: 'lucide:clock-3' },\n { value: 'packed', label: 'Packed', color: '#22c55e', icon: 'lucide:package-check' },\n { value: 'shipped', label: 'Shipped', color: '#2563eb', icon: 'lucide:truck' },\n { value: 'in_transit', label: 'In transit', color: '#0ea5e9', icon: 'lucide:loader' },\n { value: 'delivered', label: 'Delivered', color: '#16a34a', icon: 'lucide:check-circle-2' },\n { value: 'canceled', label: 'Canceled', color: '#ef4444', icon: 'lucide:x-circle' },\n { value: 'returned', label: 'Returned', color: '#0d9488', icon: 'lucide:undo-2' },\n]\n\nconst PAYMENT_STATUS_DEFAULTS: SalesDictionarySeed[] = [\n { value: 'pending', label: 'Pending', color: '#94a3b8', icon: 'lucide:clock-3' },\n { value: 'authorized', label: 'Authorized', color: '#6366f1', icon: 'lucide:badge-check' },\n { value: 'captured', label: 'Captured', color: '#0ea5e9', icon: 'lucide:banknote' },\n { value: 'received', label: 'Received', color: '#16a34a', icon: 'lucide:check' },\n { value: 'refunded', label: 'Refunded', color: '#f59e0b', icon: 'lucide:rotate-ccw' },\n { value: 'failed', label: 'Failed', color: '#ef4444', icon: 'lucide:triangle-alert' },\n { value: 'canceled', label: 'Canceled', color: '#ef4444', icon: 'lucide:x-circle' },\n]\n\nconst ADJUSTMENT_KIND_DEFAULTS: SalesDictionarySeed[] = [\n { value: 'discount', label: 'Discount' },\n { value: 'tax', label: 'Tax' },\n { value: 'shipping', label: 'Shipping' },\n { value: 'surcharge', label: 'Surcharge' },\n { value: 'return', label: 'Return' },\n { value: 'custom', label: 'Custom' },\n]\n\nasync function ensureSalesDictionaryEntry(\n em: EntityManager,\n scope: SeedScope,\n kind: SalesDictionaryKind,\n seed: SalesDictionarySeed\n): Promise<DictionaryEntry | null> {\n const value = seed.value?.trim()\n if (!value) return null\n const dictionary = await ensureSalesDictionary({\n em,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n kind,\n })\n const normalizedValue = normalizeDictionaryValue(value)\n const color = seed.color === undefined ? undefined : sanitizeDictionaryColor(seed.color)\n const icon = seed.icon === undefined ? undefined : sanitizeDictionaryIcon(seed.icon)\n const existing = await em.findOne(DictionaryEntry, {\n dictionary,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n normalizedValue,\n })\n if (existing) {\n let changed = false\n if (color !== undefined && existing.color !== color) {\n existing.color = color ?? null\n changed = true\n }\n if (icon !== undefined && existing.icon !== icon) {\n existing.icon = icon ?? null\n changed = true\n }\n if (changed) {\n existing.updatedAt = new Date()\n em.persist(existing)\n }\n return existing\n }\n const now = new Date()\n const entry = em.create(DictionaryEntry, {\n dictionary,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n value,\n label: seed.label?.trim() || value,\n normalizedValue,\n color: color ?? null,\n icon: icon ?? null,\n createdAt: now,\n updatedAt: now,\n })\n em.persist(entry)\n return entry\n}\n\nasync function seedSalesDictionary(\n em: EntityManager,\n scope: SeedScope,\n kind: SalesDictionaryKind,\n defaults: SalesDictionarySeed[]\n): Promise<void> {\n for (const seed of defaults) {\n await ensureSalesDictionaryEntry(em, scope, kind, seed)\n }\n}\n\nconst DEAL_LOSS_REASON_DEFAULTS: SalesDictionarySeed[] = [\n { value: 'lost_to_competitor', label: 'Lost to competitor', color: '#ef4444', icon: 'lucide:users' },\n { value: 'no_budget', label: 'No budget', color: '#f59e0b', icon: 'lucide:wallet' },\n { value: 'no_decision', label: 'No decision made', color: '#94a3b8', icon: 'lucide:help-circle' },\n { value: 'timing', label: 'Bad timing', color: '#6366f1', icon: 'lucide:clock' },\n { value: 'other', label: 'Other', color: '#71717a', icon: 'lucide:minus-circle' },\n]\n\nexport async function seedSalesStatusDictionaries(\n em: EntityManager,\n scope: SeedScope\n): Promise<void> {\n await seedSalesDictionary(em, scope, 'order-status', ORDER_STATUS_DEFAULTS)\n await seedSalesDictionary(em, scope, 'order-line-status', ORDER_LINE_STATUS_DEFAULTS)\n await seedSalesDictionary(em, scope, 'shipment-status', SHIPMENT_STATUS_DEFAULTS)\n await seedSalesDictionary(em, scope, 'payment-status', PAYMENT_STATUS_DEFAULTS)\n await seedSalesDictionary(em, scope, 'deal-loss-reasons', DEAL_LOSS_REASON_DEFAULTS)\n}\n\nexport async function seedSalesAdjustmentKinds(\n em: EntityManager,\n scope: SeedScope\n): Promise<void> {\n await seedSalesDictionary(em, scope, 'adjustment-kind', ADJUSTMENT_KIND_DEFAULTS)\n}\n\nexport async function seedSalesDictionaries(\n em: EntityManager,\n scope: SeedScope\n): Promise<void> {\n await seedSalesStatusDictionaries(em, scope)\n await seedSalesAdjustmentKinds(em, scope)\n}\n\nexport const DEFAULT_ADJUSTMENT_KIND_VALUES = ADJUSTMENT_KIND_DEFAULTS.map((entry) => entry.value)\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -231,6 +231,8 @@ function TeamMemberForm(props) {
|
|
|
231
231
|
type: "custom",
|
|
232
232
|
component: ({ value, setValue, setFormValue, values, disabled }) => {
|
|
233
233
|
const currentValue = typeof value === "string" ? value : "";
|
|
234
|
+
const selectedOption = teamOptions.find((option) => option.value === currentValue);
|
|
235
|
+
const optionsKey = teamOptions.map((option) => `${option.value}:${option.label}`).join("\0");
|
|
234
236
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
235
237
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
|
|
236
238
|
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: translate("staff.teamMembers.form.fields.team", "Team") }),
|
|
@@ -268,10 +270,11 @@ function TeamMemberForm(props) {
|
|
|
268
270
|
},
|
|
269
271
|
disabled,
|
|
270
272
|
children: [
|
|
271
|
-
/* @__PURE__ */ jsx(SelectTrigger, { "data-crud-focus-target": "", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: translate("ui.forms.select.emptyOption", "\u2014") }) }),
|
|
273
|
+
/* @__PURE__ */ jsx(SelectTrigger, { "data-crud-focus-target": "", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: translate("ui.forms.select.emptyOption", "\u2014"), children: selectedOption?.label }) }),
|
|
272
274
|
/* @__PURE__ */ jsx(SelectContent, { children: teamOptions.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.value, children: option.label }, option.value)) })
|
|
273
275
|
]
|
|
274
|
-
}
|
|
276
|
+
},
|
|
277
|
+
`team:${currentValue}:${optionsKey}`
|
|
275
278
|
)
|
|
276
279
|
] });
|
|
277
280
|
}
|