@open-mercato/core 0.6.4-develop.4011.1.4f3ed9ae3e → 0.6.4-develop.4038.1.91ce075c8a

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/sales/api/shipments/route.ts"],
4
- "sourcesContent": ["import { z } from 'zod'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { makeCrudRoute } from '@open-mercato/shared/lib/crud/factory'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { splitCustomFieldPayload } from '@open-mercato/shared/lib/crud/custom-fields'\nimport { DictionaryEntry } from '@open-mercato/core/modules/dictionaries/data/entities'\nimport { SalesOrderLine, SalesShipment, SalesShipmentItem, SalesShippingMethod } from '../../data/entities'\nimport { shipmentCreateSchema, shipmentUpdateSchema } from '../../data/validators'\nimport { withScopedPayload } from '../utils'\nimport { readShipmentItemsSnapshot } from '../../lib/shipments/snapshots'\nimport {\n createPagedListResponseSchema,\n createSalesCrudOpenApi,\n defaultOkResponseSchema,\n} from '../openapi'\nimport { E } from '#generated/entities.ids.generated'\nimport * as F from '#generated/entities/sales_shipment'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\n\nconst rawBodySchema = z.object({}).passthrough()\n\nconst listSchema = z\n .object({\n page: z.coerce.number().min(1).default(1),\n pageSize: z.coerce.number().min(1).max(200).default(50),\n orderId: z.string().uuid().optional(),\n sortField: z.string().optional(),\n sortDir: z.enum(['asc', 'desc']).optional(),\n })\n .passthrough()\n\nconst routeMetadata = {\n GET: { requireAuth: true, requireFeatures: ['sales.orders.view'] },\n POST: { requireAuth: true, requireFeatures: ['sales.shipments.manage'] },\n PUT: { requireAuth: true, requireFeatures: ['sales.shipments.manage'] },\n DELETE: { requireAuth: true, requireFeatures: ['sales.shipments.manage'] },\n}\n\nconst deleteSchema = shipmentUpdateSchema.pick({\n id: true,\n orderId: true,\n organizationId: true,\n tenantId: true,\n})\n\nconst toNumber = (value: unknown): number => {\n if (typeof value === 'number') return value\n if (typeof value === 'string') {\n const parsed = Number(value)\n if (!Number.isNaN(parsed)) return parsed\n }\n return 0\n}\n\nconst crud = makeCrudRoute({\n metadata: routeMetadata,\n orm: {\n entity: SalesShipment,\n idField: 'id',\n orgField: 'organizationId',\n tenantField: 'tenantId',\n softDeleteField: 'deletedAt',\n },\n indexer: {\n entityType: E.sales.sales_shipment,\n },\n list: {\n schema: listSchema,\n entityId: E.sales.sales_shipment,\n fields: [\n F.id,\n 'order_id',\n F.shipment_number,\n F.shipping_method_id,\n F.status_entry_id,\n F.status,\n F.carrier_name,\n F.tracking_numbers,\n F.shipped_at,\n F.delivered_at,\n F.weight_value,\n F.weight_unit,\n F.declared_value_net,\n F.declared_value_gross,\n F.currency_code,\n F.notes,\n F.metadata,\n F.items_snapshot,\n F.created_at,\n F.updated_at,\n ],\n decorateCustomFields: { entityIds: [E.sales.sales_shipment] },\n sortFieldMap: {\n createdAt: F.created_at,\n updatedAt: F.updated_at,\n shippedAt: F.shipped_at,\n },\n buildFilters: async (query: any) => {\n const filters: Record<string, any> = {}\n if (query.orderId) filters.order_id = { $eq: query.orderId }\n return filters\n },\n },\n actions: {\n create: {\n commandId: 'sales.shipments.create',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n const scoped = withScopedPayload(raw ?? {}, ctx, translate)\n const { base, custom } = splitCustomFieldPayload(scoped)\n return shipmentCreateSchema.parse({\n ...base,\n ...(Object.keys(custom).length ? { customFields: custom } : {}),\n })\n },\n response: ({ result }) => ({ id: result?.shipmentId ?? null }),\n status: 201,\n },\n update: {\n commandId: 'sales.shipments.update',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n const scoped = withScopedPayload(raw ?? {}, ctx, translate)\n const { base, custom } = splitCustomFieldPayload(scoped)\n return shipmentUpdateSchema.parse({\n ...base,\n ...(Object.keys(custom).length ? { customFields: custom } : {}),\n })\n },\n response: () => ({ ok: true }),\n },\n delete: {\n commandId: 'sales.shipments.delete',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n const merged = {\n ...(raw?.body ?? {}),\n ...(raw?.query ?? {}),\n }\n const payload = deleteSchema.parse(withScopedPayload(merged, ctx, translate))\n if (!payload.id || !payload.orderId) {\n throw new CrudHttpError(400, {\n error: translate('sales.shipments.not_found', 'Shipment not found'),\n })\n }\n return payload\n },\n response: () => ({ ok: true }),\n },\n },\n hooks: {\n afterList: async (payload, ctx) => {\n const items = Array.isArray(payload.items) ? payload.items : []\n if (!items.length) return\n const snapshotMap = new Map<string, ReturnType<typeof readShipmentItemsSnapshot>>()\n items.forEach((item: unknown) => {\n if (!item || typeof item !== 'object') return\n const id = (item as Record<string, unknown>).id\n if (typeof id !== 'string') return\n const snapshot = readShipmentItemsSnapshot(\n (item as any).items_snapshot ?? (item as any).itemsSnapshot ?? null\n )\n if (snapshot.length) {\n snapshotMap.set(id, snapshot)\n }\n })\n const shipmentIds = items\n .map((item: unknown) => (item && typeof item === 'object' ? (item as Record<string, unknown>).id : null))\n .filter((value: string | null): value is string => typeof value === 'string')\n if (!shipmentIds.length) return\n const em = ctx.container.resolve('em') as EntityManager\n const [shipmentItems, shippingMethods] = await Promise.all([\n findWithDecryption(\n em,\n SalesShipmentItem,\n { shipment: { $in: shipmentIds } },\n { populate: ['orderLine'] },\n { tenantId: ctx.auth?.tenantId ?? null, organizationId: ctx.auth?.orgId ?? null },\n ),\n (async () => {\n const ids: string[] = Array.from(\n new Set(\n items\n .map((item: unknown) => {\n if (!item || typeof item !== 'object') return null\n const raw = (item as Record<string, unknown>).shipping_method_id\n return typeof raw === 'string' ? raw : null\n })\n .filter((value: string | null): value is string => typeof value === 'string' && value.length > 0)\n )\n )\n if (!ids.length) return []\n return em.find(SalesShippingMethod, { id: { $in: ids } })\n })(),\n ])\n const orderLineIds = Array.from(\n new Set(\n shipmentItems\n .map((entry) =>\n typeof entry.orderLine === 'string'\n ? entry.orderLine\n : entry.orderLine?.id ?? (entry as any).orderLineId ?? null\n )\n .filter((value): value is string => typeof value === 'string')\n )\n )\n const orderLines = orderLineIds.length\n ? await em.find(SalesOrderLine, { id: { $in: orderLineIds } })\n : []\n const lineMap = new Map(\n orderLines.map((line) => [\n line.id,\n {\n lineNumber: line.lineNumber ?? null,\n name:\n line.name ??\n (typeof line.catalogSnapshot === 'object' && line.catalogSnapshot\n ? ((line.catalogSnapshot as any).name as string | undefined) ?? null\n : null),\n },\n ])\n )\n const grouped = shipmentItems.reduce<Map<string, Array<Record<string, unknown>>>>((acc, entry) => {\n const shipmentId =\n typeof entry.shipment === 'string'\n ? entry.shipment\n : entry.shipment?.id ?? (entry as any).shipment_id ?? null\n const lineId =\n typeof entry.orderLine === 'string'\n ? entry.orderLine\n : entry.orderLine?.id ?? (entry as any).order_line_id ?? null\n if (!shipmentId || !lineId) return acc\n const line = lineMap.get(lineId)\n const list = acc.get(shipmentId) ?? []\n list.push({\n id: entry.id,\n orderLineId: lineId,\n orderLineName: line?.name ?? null,\n orderLineNumber: line?.lineNumber ?? null,\n quantity: toNumber(entry.quantity),\n metadata: entry.metadata ?? null,\n })\n acc.set(shipmentId, list)\n return acc\n }, new Map())\n const shippingMap = new Map(\n shippingMethods.map((method) => [\n method.id,\n {\n code: method.code ?? null,\n name: method.name ?? method.code ?? null,\n },\n ])\n )\n const statusIds: string[] = Array.from(\n new Set(\n items\n .map((item: unknown) => {\n if (!item || typeof item !== 'object') return null\n const raw = (item as Record<string, unknown>).status_entry_id\n return typeof raw === 'string' ? raw : null\n })\n .filter((value: string | null): value is string => typeof value === 'string' && value.length > 0)\n )\n )\n const statusMap = new Map<string, { value: string | null; label: string | null }>()\n if (statusIds.length) {\n const entries = await em.find(DictionaryEntry, { id: { $in: statusIds } })\n entries.forEach((entry) =>\n statusMap.set(entry.id, {\n value: entry.value ?? null,\n label: entry.label ?? entry.value ?? null,\n })\n )\n }\n items.forEach((item: unknown) => {\n if (!item || typeof item !== 'object') return\n const id = (item as Record<string, unknown>).id\n if (typeof id !== 'string') return\n const snapshot = snapshotMap.get(id)\n if (snapshot?.length) {\n ;(item as Record<string, unknown>).items_snapshot = snapshot\n }\n ;(item as Record<string, unknown>).items = snapshot?.length ? snapshot : grouped.get(id) ?? []\n const shippingId = (item as Record<string, unknown>).shipping_method_id\n if (typeof shippingId === 'string' && shippingMap.has(shippingId)) {\n const method = shippingMap.get(shippingId)\n ;(item as Record<string, unknown>).shipping_method_code = method?.code ?? null\n ;(item as Record<string, unknown>).shipping_method_name = method?.name ?? null\n }\n const statusId = (item as Record<string, unknown>).status_entry_id\n if (typeof statusId === 'string' && statusMap.has(statusId)) {\n const status = statusMap.get(statusId)\n if (!(item as Record<string, unknown>).status) {\n ;(item as Record<string, unknown>).status = status?.value ?? null\n }\n ;(item as Record<string, unknown>).status_label = status?.label ?? status?.value ?? null\n }\n })\n },\n },\n})\n\nconst { GET, POST, PUT, DELETE } = crud\n\nexport const metadata = routeMetadata\nexport { GET, POST, PUT, DELETE }\n\nconst shipmentItemSchema = z.object({\n id: z.string().uuid(),\n orderLineId: z.string().uuid(),\n orderLineName: z.string().nullable().optional(),\n orderLineNumber: z.number().nullable().optional(),\n quantity: z.number(),\n metadata: z.record(z.string(), z.unknown()).nullable().optional(),\n})\n\nconst shipmentSchema = z\n .object({\n id: z.string().uuid(),\n order_id: z.string().uuid(),\n shipment_number: z.string().nullable().optional(),\n shipping_method_id: z.string().uuid().nullable().optional(),\n shipping_method_code: z.string().nullable().optional(),\n shipping_method_name: z.string().nullable().optional(),\n status_entry_id: z.string().uuid().nullable().optional(),\n status: z.string().nullable().optional(),\n status_label: z.string().nullable().optional(),\n carrier_name: z.string().nullable().optional(),\n tracking_numbers: z.array(z.string()).nullable().optional(),\n shipped_at: z.string().nullable().optional(),\n delivered_at: z.string().nullable().optional(),\n weight_value: z.number().nullable().optional(),\n weight_unit: z.string().nullable().optional(),\n declared_value_net: z.number().nullable().optional(),\n declared_value_gross: z.number().nullable().optional(),\n currency_code: z.string().nullable().optional(),\n notes: z.string().nullable().optional(),\n metadata: z.record(z.string(), z.unknown()).nullable().optional(),\n custom_values: z.record(z.string(), z.unknown()).nullable().optional(),\n customValues: z.record(z.string(), z.unknown()).nullable().optional(),\n custom_fields: z.array(z.record(z.string(), z.unknown())).nullable().optional(),\n customFields: z.array(z.record(z.string(), z.unknown())).nullable().optional(),\n items_snapshot: z.array(shipmentItemSchema).nullable().optional(),\n itemsSnapshot: z.array(shipmentItemSchema).nullable().optional(),\n created_at: z.string(),\n updated_at: z.string(),\n items: z.array(shipmentItemSchema).optional(),\n })\n .passthrough()\n\nexport const openApi = createSalesCrudOpenApi({\n resourceName: 'Shipment',\n querySchema: listSchema,\n listResponseSchema: createPagedListResponseSchema(shipmentSchema),\n create: {\n schema: shipmentCreateSchema,\n responseSchema: z.object({ id: z.string().uuid().nullable() }),\n description: 'Creates a shipment for an order.',\n },\n update: {\n schema: shipmentUpdateSchema,\n responseSchema: defaultOkResponseSchema,\n description: 'Updates a shipment.',\n },\n del: {\n schema: deleteSchema,\n responseSchema: defaultOkResponseSchema,\n description: 'Deletes a shipment.',\n },\n})\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { z } from 'zod'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { makeCrudRoute, type CrudCtx } from '@open-mercato/shared/lib/crud/factory'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { splitCustomFieldPayload } from '@open-mercato/shared/lib/crud/custom-fields'\nimport { DictionaryEntry } from '@open-mercato/core/modules/dictionaries/data/entities'\nimport { SalesOrderLine, SalesShipment, SalesShipmentItem, SalesShippingMethod } from '../../data/entities'\nimport { shipmentCreateSchema, shipmentUpdateSchema } from '../../data/validators'\nimport { withScopedPayload } from '../utils'\nimport { readShipmentItemsSnapshot } from '../../lib/shipments/snapshots'\nimport {\n createPagedListResponseSchema,\n createSalesCrudOpenApi,\n defaultOkResponseSchema,\n} from '../openapi'\nimport { E } from '#generated/entities.ids.generated'\nimport * as F from '#generated/entities/sales_shipment'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\n\nconst rawBodySchema = z.object({}).passthrough()\n\nconst listSchema = z\n .object({\n page: z.coerce.number().min(1).default(1),\n pageSize: z.coerce.number().min(1).max(200).default(50),\n orderId: z.string().uuid().optional(),\n sortField: z.string().optional(),\n sortDir: z.enum(['asc', 'desc']).optional(),\n })\n .passthrough()\n\nconst routeMetadata = {\n GET: { requireAuth: true, requireFeatures: ['sales.orders.view'] },\n POST: { requireAuth: true, requireFeatures: ['sales.shipments.manage'] },\n PUT: { requireAuth: true, requireFeatures: ['sales.shipments.manage'] },\n DELETE: { requireAuth: true, requireFeatures: ['sales.shipments.manage'] },\n}\n\nconst deleteSchema = shipmentUpdateSchema.pick({\n id: true,\n orderId: true,\n organizationId: true,\n tenantId: true,\n})\n\nconst toNumber = (value: unknown): number => {\n if (typeof value === 'number') return value\n if (typeof value === 'string') {\n const parsed = Number(value)\n if (!Number.isNaN(parsed)) return parsed\n }\n return 0\n}\n\nexport async function enrichShipmentListResponse(\n payload: { items?: unknown[] },\n ctx: CrudCtx,\n): Promise<void> {\n const items = Array.isArray(payload.items) ? payload.items : []\n if (!items.length) return\n const snapshotMap = new Map<string, ReturnType<typeof readShipmentItemsSnapshot>>()\n items.forEach((item: unknown) => {\n if (!item || typeof item !== 'object') return\n const id = (item as Record<string, unknown>).id\n if (typeof id !== 'string') return\n const snapshot = readShipmentItemsSnapshot(\n (item as any).items_snapshot ?? (item as any).itemsSnapshot ?? null\n )\n if (snapshot.length) {\n snapshotMap.set(id, snapshot)\n }\n })\n const shipmentIds = items\n .map((item: unknown) => {\n if (!item || typeof item !== 'object') return null\n const raw = (item as Record<string, unknown>).id\n return typeof raw === 'string' ? raw : null\n })\n .filter((value: string | null): value is string => typeof value === 'string')\n if (!shipmentIds.length) return\n const em = ctx.container.resolve('em') as EntityManager\n const statusIds: string[] = Array.from(\n new Set(\n items\n .map((item: unknown) => {\n if (!item || typeof item !== 'object') return null\n const raw = (item as Record<string, unknown>).status_entry_id\n return typeof raw === 'string' ? raw : null\n })\n .filter((value: string | null): value is string => typeof value === 'string' && value.length > 0)\n )\n )\n const [shipmentItems, shippingMethods, statusEntries] = await Promise.all([\n findWithDecryption(\n em,\n SalesShipmentItem,\n { shipment: { $in: shipmentIds } },\n { populate: ['orderLine'] },\n { tenantId: ctx.auth?.tenantId ?? null, organizationId: ctx.auth?.orgId ?? null },\n ),\n (async () => {\n const ids: string[] = Array.from(\n new Set(\n items\n .map((item: unknown) => {\n if (!item || typeof item !== 'object') return null\n const raw = (item as Record<string, unknown>).shipping_method_id\n return typeof raw === 'string' ? raw : null\n })\n .filter((value: string | null): value is string => typeof value === 'string' && value.length > 0)\n )\n )\n if (!ids.length) return []\n return em.find(SalesShippingMethod, { id: { $in: ids } })\n })(),\n statusIds.length ? em.find(DictionaryEntry, { id: { $in: statusIds } }) : [],\n ])\n const orderLineIds = Array.from(\n new Set(\n shipmentItems\n .map((entry) =>\n typeof entry.orderLine === 'string'\n ? entry.orderLine\n : entry.orderLine?.id ?? (entry as any).orderLineId ?? null\n )\n .filter((value): value is string => typeof value === 'string')\n )\n )\n const orderLines = orderLineIds.length\n ? await em.find(SalesOrderLine, { id: { $in: orderLineIds } })\n : []\n const lineMap = new Map(\n orderLines.map((line) => [\n line.id,\n {\n lineNumber: line.lineNumber ?? null,\n name:\n line.name ??\n (typeof line.catalogSnapshot === 'object' && line.catalogSnapshot\n ? ((line.catalogSnapshot as any).name as string | undefined) ?? null\n : null),\n },\n ])\n )\n const grouped = shipmentItems.reduce<Map<string, Array<Record<string, unknown>>>>((acc, entry) => {\n const shipmentId =\n typeof entry.shipment === 'string'\n ? entry.shipment\n : entry.shipment?.id ?? (entry as any).shipment_id ?? null\n const lineId =\n typeof entry.orderLine === 'string'\n ? entry.orderLine\n : entry.orderLine?.id ?? (entry as any).order_line_id ?? null\n if (!shipmentId || !lineId) return acc\n const line = lineMap.get(lineId)\n const list = acc.get(shipmentId) ?? []\n list.push({\n id: entry.id,\n orderLineId: lineId,\n orderLineName: line?.name ?? null,\n orderLineNumber: line?.lineNumber ?? null,\n quantity: toNumber(entry.quantity),\n metadata: entry.metadata ?? null,\n })\n acc.set(shipmentId, list)\n return acc\n }, new Map())\n const shippingMap = new Map(\n shippingMethods.map((method) => [\n method.id,\n {\n code: method.code ?? null,\n name: method.name ?? method.code ?? null,\n },\n ])\n )\n const statusMap = new Map<string, { value: string | null; label: string | null }>()\n statusEntries.forEach((entry) =>\n statusMap.set(entry.id, {\n value: entry.value ?? null,\n label: entry.label ?? entry.value ?? null,\n })\n )\n items.forEach((item: unknown) => {\n if (!item || typeof item !== 'object') return\n const id = (item as Record<string, unknown>).id\n if (typeof id !== 'string') return\n const snapshot = snapshotMap.get(id)\n if (snapshot?.length) {\n ;(item as Record<string, unknown>).items_snapshot = snapshot\n }\n ;(item as Record<string, unknown>).items = snapshot?.length ? snapshot : grouped.get(id) ?? []\n const shippingId = (item as Record<string, unknown>).shipping_method_id\n if (typeof shippingId === 'string' && shippingMap.has(shippingId)) {\n const method = shippingMap.get(shippingId)\n ;(item as Record<string, unknown>).shipping_method_code = method?.code ?? null\n ;(item as Record<string, unknown>).shipping_method_name = method?.name ?? null\n }\n const statusId = (item as Record<string, unknown>).status_entry_id\n if (typeof statusId === 'string' && statusMap.has(statusId)) {\n const status = statusMap.get(statusId)\n if (!(item as Record<string, unknown>).status) {\n ;(item as Record<string, unknown>).status = status?.value ?? null\n }\n ;(item as Record<string, unknown>).status_label = status?.label ?? status?.value ?? null\n }\n })\n}\n\nconst crud = makeCrudRoute({\n metadata: routeMetadata,\n orm: {\n entity: SalesShipment,\n idField: 'id',\n orgField: 'organizationId',\n tenantField: 'tenantId',\n softDeleteField: 'deletedAt',\n },\n indexer: {\n entityType: E.sales.sales_shipment,\n },\n list: {\n schema: listSchema,\n entityId: E.sales.sales_shipment,\n fields: [\n F.id,\n 'order_id',\n F.shipment_number,\n F.shipping_method_id,\n F.status_entry_id,\n F.status,\n F.carrier_name,\n F.tracking_numbers,\n F.shipped_at,\n F.delivered_at,\n F.weight_value,\n F.weight_unit,\n F.declared_value_net,\n F.declared_value_gross,\n F.currency_code,\n F.notes,\n F.metadata,\n F.items_snapshot,\n F.created_at,\n F.updated_at,\n ],\n decorateCustomFields: { entityIds: [E.sales.sales_shipment] },\n sortFieldMap: {\n createdAt: F.created_at,\n updatedAt: F.updated_at,\n shippedAt: F.shipped_at,\n },\n buildFilters: async (query: any) => {\n const filters: Record<string, any> = {}\n if (query.orderId) filters.order_id = { $eq: query.orderId }\n return filters\n },\n },\n actions: {\n create: {\n commandId: 'sales.shipments.create',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n const scoped = withScopedPayload(raw ?? {}, ctx, translate)\n const { base, custom } = splitCustomFieldPayload(scoped)\n return shipmentCreateSchema.parse({\n ...base,\n ...(Object.keys(custom).length ? { customFields: custom } : {}),\n })\n },\n response: ({ result }) => ({ id: result?.shipmentId ?? null }),\n status: 201,\n },\n update: {\n commandId: 'sales.shipments.update',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n const scoped = withScopedPayload(raw ?? {}, ctx, translate)\n const { base, custom } = splitCustomFieldPayload(scoped)\n return shipmentUpdateSchema.parse({\n ...base,\n ...(Object.keys(custom).length ? { customFields: custom } : {}),\n })\n },\n response: () => ({ ok: true }),\n },\n delete: {\n commandId: 'sales.shipments.delete',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n const merged = {\n ...(raw?.body ?? {}),\n ...(raw?.query ?? {}),\n }\n const payload = deleteSchema.parse(withScopedPayload(merged, ctx, translate))\n if (!payload.id || !payload.orderId) {\n throw new CrudHttpError(400, {\n error: translate('sales.shipments.not_found', 'Shipment not found'),\n })\n }\n return payload\n },\n response: () => ({ ok: true }),\n },\n },\n hooks: {\n afterList: (payload, ctx) => enrichShipmentListResponse(payload, ctx),\n },\n})\n\nconst { GET, POST, PUT, DELETE } = crud\n\nexport const metadata = routeMetadata\nexport { GET, POST, PUT, DELETE }\n\nconst shipmentItemSchema = z.object({\n id: z.string().uuid(),\n orderLineId: z.string().uuid(),\n orderLineName: z.string().nullable().optional(),\n orderLineNumber: z.number().nullable().optional(),\n quantity: z.number(),\n metadata: z.record(z.string(), z.unknown()).nullable().optional(),\n})\n\nconst shipmentSchema = z\n .object({\n id: z.string().uuid(),\n order_id: z.string().uuid(),\n shipment_number: z.string().nullable().optional(),\n shipping_method_id: z.string().uuid().nullable().optional(),\n shipping_method_code: z.string().nullable().optional(),\n shipping_method_name: z.string().nullable().optional(),\n status_entry_id: z.string().uuid().nullable().optional(),\n status: z.string().nullable().optional(),\n status_label: z.string().nullable().optional(),\n carrier_name: z.string().nullable().optional(),\n tracking_numbers: z.array(z.string()).nullable().optional(),\n shipped_at: z.string().nullable().optional(),\n delivered_at: z.string().nullable().optional(),\n weight_value: z.number().nullable().optional(),\n weight_unit: z.string().nullable().optional(),\n declared_value_net: z.number().nullable().optional(),\n declared_value_gross: z.number().nullable().optional(),\n currency_code: z.string().nullable().optional(),\n notes: z.string().nullable().optional(),\n metadata: z.record(z.string(), z.unknown()).nullable().optional(),\n custom_values: z.record(z.string(), z.unknown()).nullable().optional(),\n customValues: z.record(z.string(), z.unknown()).nullable().optional(),\n custom_fields: z.array(z.record(z.string(), z.unknown())).nullable().optional(),\n customFields: z.array(z.record(z.string(), z.unknown())).nullable().optional(),\n items_snapshot: z.array(shipmentItemSchema).nullable().optional(),\n itemsSnapshot: z.array(shipmentItemSchema).nullable().optional(),\n created_at: z.string(),\n updated_at: z.string(),\n items: z.array(shipmentItemSchema).optional(),\n })\n .passthrough()\n\nexport const openApi = createSalesCrudOpenApi({\n resourceName: 'Shipment',\n querySchema: listSchema,\n listResponseSchema: createPagedListResponseSchema(shipmentSchema),\n create: {\n schema: shipmentCreateSchema,\n responseSchema: z.object({ id: z.string().uuid().nullable() }),\n description: 'Creates a shipment for an order.',\n },\n update: {\n schema: shipmentUpdateSchema,\n responseSchema: defaultOkResponseSchema,\n description: 'Updates a shipment.',\n },\n del: {\n schema: deleteSchema,\n responseSchema: defaultOkResponseSchema,\n description: 'Deletes a shipment.',\n },\n})\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/core",
3
- "version": "0.6.4-develop.4011.1.4f3ed9ae3e",
3
+ "version": "0.6.4-develop.4038.1.91ce075c8a",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "scripts": {
@@ -243,16 +243,16 @@
243
243
  "zod": "^4.4.3"
244
244
  },
245
245
  "peerDependencies": {
246
- "@open-mercato/ai-assistant": "0.6.4-develop.4011.1.4f3ed9ae3e",
247
- "@open-mercato/shared": "0.6.4-develop.4011.1.4f3ed9ae3e",
248
- "@open-mercato/ui": "0.6.4-develop.4011.1.4f3ed9ae3e",
246
+ "@open-mercato/ai-assistant": "0.6.4-develop.4038.1.91ce075c8a",
247
+ "@open-mercato/shared": "0.6.4-develop.4038.1.91ce075c8a",
248
+ "@open-mercato/ui": "0.6.4-develop.4038.1.91ce075c8a",
249
249
  "react": "^19.0.0",
250
250
  "react-dom": "^19.0.0"
251
251
  },
252
252
  "devDependencies": {
253
- "@open-mercato/ai-assistant": "0.6.4-develop.4011.1.4f3ed9ae3e",
254
- "@open-mercato/shared": "0.6.4-develop.4011.1.4f3ed9ae3e",
255
- "@open-mercato/ui": "0.6.4-develop.4011.1.4f3ed9ae3e",
253
+ "@open-mercato/ai-assistant": "0.6.4-develop.4038.1.91ce075c8a",
254
+ "@open-mercato/shared": "0.6.4-develop.4038.1.91ce075c8a",
255
+ "@open-mercato/ui": "0.6.4-develop.4038.1.91ce075c8a",
256
256
  "@testing-library/dom": "^10.4.1",
257
257
  "@testing-library/jest-dom": "^6.9.1",
258
258
  "@testing-library/react": "^16.3.1",
@@ -114,6 +114,12 @@ const crud = makeCrudRoute({
114
114
  ],
115
115
  sortFieldMap: {
116
116
  name: 'display_name',
117
+ email: 'primary_email',
118
+ primaryEmail: 'primary_email',
119
+ status: 'status',
120
+ lifecycleStage: 'lifecycle_stage',
121
+ source: 'source',
122
+ nextInteractionAt: 'next_interaction_at',
117
123
  createdAt: 'created_at',
118
124
  updatedAt: 'updated_at',
119
125
  },
@@ -108,6 +108,12 @@ const crud = makeCrudRoute({
108
108
  ],
109
109
  sortFieldMap: {
110
110
  name: 'display_name',
111
+ email: 'primary_email',
112
+ primaryEmail: 'primary_email',
113
+ status: 'status',
114
+ lifecycleStage: 'lifecycle_stage',
115
+ source: 'source',
116
+ nextInteractionAt: 'next_interaction_at',
111
117
  createdAt: 'created_at',
112
118
  updatedAt: 'updated_at',
113
119
  },
@@ -5,7 +5,7 @@ import Link from 'next/link'
5
5
  import { usePathname, useRouter, useSearchParams } from 'next/navigation'
6
6
  import { Page, PageBody } from '@open-mercato/ui/backend/Page'
7
7
  import { DataTable, type DataTableExportFormat, withDataTableNamespaces } from '@open-mercato/ui/backend/DataTable'
8
- import type { ColumnDef } from '@tanstack/react-table'
8
+ import type { ColumnDef, SortingState } from '@tanstack/react-table'
9
9
  import { Button } from '@open-mercato/ui/primitives/button'
10
10
  import { RowActions } from '@open-mercato/ui/backend/RowActions'
11
11
  import { apiCall, apiCallOrThrow } from '@open-mercato/ui/backend/utils/apiCall'
@@ -53,6 +53,7 @@ import {
53
53
  mapAssignableStaffToFilterOptions,
54
54
  } from '../../../components/detail/assignableStaff'
55
55
  import { CollectionPreviewCell, normalizeCollectionLabels } from '../../../components/list/CollectionPreviewCell'
56
+ import { appendCustomerListSortParams } from '../listSorting'
56
57
 
57
58
  type DictionaryOptionWithTone = AdvancedFilterOption & FilterOption
58
59
 
@@ -191,7 +192,7 @@ export default function CustomersCompaniesPage() {
191
192
  const [rows, setRows] = React.useState<CompanyRow[]>([])
192
193
  const [page, setPage] = React.useState(1)
193
194
  const [pageSize, setPageSize] = React.useState(20)
194
- const [sorting, setSorting] = React.useState<import('@tanstack/react-table').SortingState>([])
195
+ const [sorting, setSorting] = React.useState<SortingState>([])
195
196
  const [total, setTotal] = React.useState(0)
196
197
  const [totalPages, setTotalPages] = React.useState(1)
197
198
  const [search, setSearch] = React.useState('')
@@ -246,6 +247,10 @@ export default function CustomersCompaniesPage() {
246
247
  setPageSize(newSize)
247
248
  setPage(1)
248
249
  }, [])
250
+ const handleSortingChange = React.useCallback((nextSorting: SortingState) => {
251
+ setSorting(nextSorting)
252
+ setPage(1)
253
+ }, [])
249
254
 
250
255
  const bulkMutationContextId = 'customers-companies-list:bulk-delete'
251
256
  const { runMutation: runBulkMutation, retryLastMutation: retryBulkMutation } = useGuardedMutation<{
@@ -350,10 +355,7 @@ export default function CustomersCompaniesPage() {
350
355
  const params = new URLSearchParams()
351
356
  params.set('page', String(page))
352
357
  params.set('pageSize', String(pageSize))
353
- if (sorting.length > 0) {
354
- params.set('sort', sorting[0].id)
355
- params.set('order', sorting[0].desc ? 'desc' : 'asc')
356
- }
358
+ appendCustomerListSortParams(params, sorting)
357
359
  if (search.trim()) params.set('search', search.trim())
358
360
  const advancedParams = serializeTree(advancedFilterState)
359
361
  for (const [key, val] of Object.entries(advancedParams)) {
@@ -374,10 +376,7 @@ export default function CustomersCompaniesPage() {
374
376
  const params = new URLSearchParams()
375
377
  if (search.trim().length) params.set('search', search.trim())
376
378
  if (page > 1) params.set('page', String(page))
377
- if (sorting.length > 0) {
378
- params.set('sort', sorting[0].id)
379
- params.set('order', sorting[0].desc ? 'desc' : 'asc')
380
- }
379
+ appendCustomerListSortParams(params, sorting)
381
380
  const advancedParams = serializeTree(advancedFilterState)
382
381
  for (const [key, val] of Object.entries(advancedParams)) {
383
382
  params.set(key, val)
@@ -820,6 +819,7 @@ export default function CustomersCompaniesPage() {
820
819
  .map<ColumnDef<CompanyRow>>((def) => ({
821
820
  accessorKey: `cf_${def.key}`,
822
821
  header: def.label || def.key,
822
+ enableSorting: true,
823
823
  meta: {
824
824
  columnChooserGroup: def.group?.title ?? 'Custom Fields',
825
825
  filterGroup: def.group?.title ?? 'Custom Fields',
@@ -887,8 +887,9 @@ export default function CustomersCompaniesPage() {
887
887
  onRowClick={(row) => router.push(`/backend/customers/companies-v2/${row.id}`)}
888
888
  perspective={{ tableId: 'customers.companies.list' }}
889
889
  sortable
890
+ manualSorting
890
891
  sorting={sorting}
891
- onSortingChange={setSorting}
892
+ onSortingChange={handleSortingChange}
892
893
  bulkActions={[
893
894
  {
894
895
  id: 'delete',
@@ -0,0 +1,27 @@
1
+ import type { SortingState } from '@tanstack/react-table'
2
+
3
+ const CUSTOMER_LIST_SORT_FIELDS: Record<string, string> = {
4
+ name: 'name',
5
+ email: 'primaryEmail',
6
+ status: 'status',
7
+ lifecycleStage: 'lifecycleStage',
8
+ source: 'source',
9
+ nextInteractionAt: 'nextInteractionAt',
10
+ }
11
+
12
+ export function resolveCustomerListSortField(columnId: string): string | null {
13
+ const normalized = columnId.trim()
14
+ if (!normalized) return null
15
+ if (normalized.startsWith('cf:')) return normalized
16
+ if (normalized.startsWith('cf_')) return `cf:${normalized.slice(3)}`
17
+ return CUSTOMER_LIST_SORT_FIELDS[normalized] ?? null
18
+ }
19
+
20
+ export function appendCustomerListSortParams(params: URLSearchParams, sorting: SortingState): void {
21
+ const activeSort = sorting[0]
22
+ if (!activeSort) return
23
+ const sortField = resolveCustomerListSortField(activeSort.id)
24
+ if (!sortField) return
25
+ params.set('sortField', sortField)
26
+ params.set('sortDir', activeSort.desc ? 'desc' : 'asc')
27
+ }
@@ -5,7 +5,7 @@ import Link from 'next/link'
5
5
  import { usePathname, useRouter, useSearchParams } from 'next/navigation'
6
6
  import { Page, PageBody } from '@open-mercato/ui/backend/Page'
7
7
  import { DataTable, type DataTableExportFormat, withDataTableNamespaces } from '@open-mercato/ui/backend/DataTable'
8
- import type { ColumnDef } from '@tanstack/react-table'
8
+ import type { ColumnDef, SortingState } from '@tanstack/react-table'
9
9
  import { Button } from '@open-mercato/ui/primitives/button'
10
10
  import { RowActions } from '@open-mercato/ui/backend/RowActions'
11
11
  import { apiCall, apiCallOrThrow } from '@open-mercato/ui/backend/utils/apiCall'
@@ -53,6 +53,7 @@ import {
53
53
  mapAssignableStaffToFilterOptions,
54
54
  } from '../../../components/detail/assignableStaff'
55
55
  import { CollectionPreviewCell, normalizeCollectionLabels } from '../../../components/list/CollectionPreviewCell'
56
+ import { appendCustomerListSortParams } from '../listSorting'
56
57
 
57
58
  type DictionaryOptionWithTone = AdvancedFilterOption & FilterOption
58
59
 
@@ -199,7 +200,7 @@ export default function CustomersPeoplePage() {
199
200
  const [rows, setRows] = React.useState<PersonRow[]>([])
200
201
  const [page, setPage] = React.useState(1)
201
202
  const [pageSize, setPageSize] = React.useState(20)
202
- const [sorting, setSorting] = React.useState<import('@tanstack/react-table').SortingState>([])
203
+ const [sorting, setSorting] = React.useState<SortingState>([])
203
204
  const [total, setTotal] = React.useState(0)
204
205
  const [totalPages, setTotalPages] = React.useState(1)
205
206
  const [search, setSearch] = React.useState('')
@@ -256,6 +257,10 @@ export default function CustomersPeoplePage() {
256
257
  setPageSize(newSize)
257
258
  setPage(1)
258
259
  }, [])
260
+ const handleSortingChange = React.useCallback((nextSorting: SortingState) => {
261
+ setSorting(nextSorting)
262
+ setPage(1)
263
+ }, [])
259
264
 
260
265
  const bulkMutationContextId = 'customers-people-list:bulk-delete'
261
266
  const { runMutation: runBulkMutation, retryLastMutation: retryBulkMutation } = useGuardedMutation<{
@@ -361,10 +366,7 @@ export default function CustomersPeoplePage() {
361
366
  const params = new URLSearchParams()
362
367
  params.set('page', String(page))
363
368
  params.set('pageSize', String(pageSize))
364
- if (sorting.length > 0) {
365
- params.set('sort', sorting[0].id)
366
- params.set('order', sorting[0].desc ? 'desc' : 'asc')
367
- }
369
+ appendCustomerListSortParams(params, sorting)
368
370
  if (search.trim()) params.set('search', search.trim())
369
371
  const advancedParams = serializeTree(advancedFilterState)
370
372
  for (const [key, val] of Object.entries(advancedParams)) {
@@ -386,10 +388,7 @@ export default function CustomersPeoplePage() {
386
388
  const params = new URLSearchParams()
387
389
  if (search.trim().length) params.set('search', search.trim())
388
390
  if (page > 1) params.set('page', String(page))
389
- if (sorting.length > 0) {
390
- params.set('sort', sorting[0].id)
391
- params.set('order', sorting[0].desc ? 'desc' : 'asc')
392
- }
391
+ appendCustomerListSortParams(params, sorting)
393
392
  const advancedParams = serializeTree(advancedFilterState)
394
393
  for (const [key, val] of Object.entries(advancedParams)) {
395
394
  params.set(key, val)
@@ -847,6 +846,7 @@ export default function CustomersPeoplePage() {
847
846
  .map<ColumnDef<PersonRow>>((def) => ({
848
847
  accessorKey: `cf_${def.key}`,
849
848
  header: def.label || def.key,
849
+ enableSorting: true,
850
850
  meta: {
851
851
  columnChooserGroup: def.group?.title ?? 'Custom Fields',
852
852
  filterGroup: def.group?.title ?? 'Custom Fields',
@@ -914,8 +914,9 @@ export default function CustomersPeoplePage() {
914
914
  perspective={{ tableId: 'customers.people.list' }}
915
915
  onRowClick={(row) => router.push(`/backend/customers/people-v2/${row.id}`)}
916
916
  sortable
917
+ manualSorting
917
918
  sorting={sorting}
918
- onSortingChange={setSorting}
919
+ onSortingChange={handleSortingChange}
919
920
  bulkActions={[
920
921
  {
921
922
  id: 'delete',