@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.
- package/.turbo/turbo-build.log +1 -1
- package/dist/modules/customers/api/companies/route.js +6 -0
- package/dist/modules/customers/api/companies/route.js.map +2 -2
- package/dist/modules/customers/api/people/route.js +6 -0
- package/dist/modules/customers/api/people/route.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies/page.js +10 -9
- package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/listSorting.js +28 -0
- package/dist/modules/customers/backend/customers/listSorting.js.map +7 -0
- package/dist/modules/customers/backend/customers/people/page.js +10 -9
- package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
- package/dist/modules/sales/api/shipments/route.js +135 -131
- package/dist/modules/sales/api/shipments/route.js.map +2 -2
- package/package.json +7 -7
- package/src/modules/customers/api/companies/route.ts +6 -0
- package/src/modules/customers/api/people/route.ts +6 -0
- package/src/modules/customers/backend/customers/companies/page.tsx +12 -11
- package/src/modules/customers/backend/customers/listSorting.ts +27 -0
- package/src/modules/customers/backend/customers/people/page.tsx +12 -11
- package/src/modules/sales/api/shipments/route.ts +157 -150
|
@@ -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": "AAAA,SAAS,SAAS;AAElB,SAAS,
|
|
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.
|
|
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.
|
|
247
|
-
"@open-mercato/shared": "0.6.4-develop.
|
|
248
|
-
"@open-mercato/ui": "0.6.4-develop.
|
|
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.
|
|
254
|
-
"@open-mercato/shared": "0.6.4-develop.
|
|
255
|
-
"@open-mercato/ui": "0.6.4-develop.
|
|
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<
|
|
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
|
-
|
|
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
|
-
|
|
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={
|
|
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<
|
|
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
|
-
|
|
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
|
-
|
|
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={
|
|
919
|
+
onSortingChange={handleSortingChange}
|
|
919
920
|
bulkActions={[
|
|
920
921
|
{
|
|
921
922
|
id: 'delete',
|