@open-mercato/core 0.6.8-develop.6877.1.c95a715a00 → 0.6.8-develop.6879.1.9883cf6265
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.
|
@@ -165,10 +165,18 @@ function makeSalesLineRoute(config) {
|
|
|
165
165
|
return fields;
|
|
166
166
|
})(),
|
|
167
167
|
sortFieldMap: {
|
|
168
|
+
id: F.id,
|
|
168
169
|
createdAt: F.created_at,
|
|
169
170
|
updatedAt: F.updated_at,
|
|
170
171
|
lineNumber: F.line_number
|
|
171
172
|
},
|
|
173
|
+
// Line ids are random v4 UUIDs, so the factory's `id` default orders a
|
|
174
|
+
// document's lines arbitrarily and reshuffles them whenever an integration
|
|
175
|
+
// rewrites the lines (delete-and-reinsert is the normal upsert shape).
|
|
176
|
+
// `line_number` is the document's real reading order; `id` only breaks ties
|
|
177
|
+
// between legacy rows that all still sit at the column default of 0.
|
|
178
|
+
defaultSort: { field: "lineNumber", dir: "asc" },
|
|
179
|
+
tiebreakSortField: "id",
|
|
172
180
|
buildFilters: async (query, ctx) => {
|
|
173
181
|
const filters = {};
|
|
174
182
|
if (query.id) filters.id = { $eq: query.id };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/sales/lib/makeSalesLineRoute.ts"],
|
|
4
|
-
"sourcesContent": ["import { z } from 'zod'\nimport type { EntityManager } from '@mikro-orm/core'\nimport { makeCrudRoute, type CrudCtx } from '@open-mercato/shared/lib/crud/factory'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport {\n buildCustomFieldFiltersFromQuery,\n extractAllCustomFieldEntries,\n} from '@open-mercato/shared/lib/crud/custom-fields'\nimport {\n canonicalizeUnitCode,\n REFERENCE_UNIT_CODES,\n} from '@open-mercato/shared/lib/units/unitCodes'\nimport {\n createPagedListResponseSchema,\n createSalesCrudOpenApi,\n defaultOkResponseSchema,\n} from '../api/openapi'\nimport { withScopedPayload } from '../api/utils'\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- MikroORM entity class constructor\ntype EntityClass = new (...args: any[]) => unknown\n\ninterface SalesLineRouteConfig {\n entity: EntityClass\n entityId: string\n fieldConstants: Record<string, string>\n parentFkColumn: string\n parentFkParam: string\n createSchema: z.ZodObject<z.ZodRawShape>\n features: { view: string; manage: string }\n commandPrefix: string\n openApi: {\n resourceName: string\n description: string\n }\n}\n\nconst rawBodySchema = z.object({}).passthrough()\n\nfunction resolveRawBody(raw: unknown): Record<string, unknown> {\n if (!raw || typeof raw !== 'object') return {}\n if ('body' in raw) {\n const payload = raw as { body?: unknown }\n if (payload.body && typeof payload.body === 'object') {\n return payload.body as Record<string, unknown>\n }\n }\n return raw as Record<string, unknown>\n}\n\nfunction transformItem(item: Record<string, unknown> | null | undefined) {\n if (!item) return item\n const normalized = { ...item }\n const cfEntries = extractAllCustomFieldEntries(item)\n for (const key of Object.keys(normalized)) {\n if (key.startsWith('cf:')) delete normalized[key]\n }\n const quantityUnit = canonicalizeUnitCode(\n normalized['quantity_unit'] ?? normalized['quantityUnit'],\n )\n const normalizedUnit =\n canonicalizeUnitCode(\n normalized['normalized_unit'] ?? normalized['normalizedUnit'],\n ) ?? quantityUnit\n return {\n ...normalized,\n quantity_unit: quantityUnit,\n normalized_unit: normalizedUnit,\n ...cfEntries,\n }\n}\n\nconst uomSnapshotOpenApiSchema = z\n .object({\n version: z.literal(1),\n productId: z.string().nullable(),\n productVariantId: z.string().nullable(),\n baseUnitCode: z.string().nullable(),\n enteredUnitCode: z.string().nullable(),\n enteredQuantity: z.string(),\n toBaseFactor: z.string(),\n normalizedQuantity: z.string(),\n rounding: z.object({\n mode: z.enum(['half_up', 'down', 'up']),\n scale: z.number().int(),\n }),\n source: z.object({\n conversionId: z.string().nullable(),\n resolvedAt: z.string(),\n }),\n unitPriceReference: z\n .object({\n enabled: z.boolean(),\n referenceUnitCode: z.enum(REFERENCE_UNIT_CODES).nullable(),\n baseQuantity: z.string().nullable(),\n grossPerReference: z.string().nullable().optional(),\n netPerReference: z.string().nullable().optional(),\n })\n .optional(),\n })\n .nullable()\n .optional()\n\nexport function makeSalesLineRoute(config: SalesLineRouteConfig) {\n const {\n entity,\n entityId,\n fieldConstants: F,\n parentFkColumn,\n parentFkParam,\n createSchema,\n features,\n commandPrefix,\n } = config\n\n const listSchema = z\n .object({\n page: z.coerce.number().min(1).default(1),\n pageSize: z.coerce.number().min(1).max(100).default(50),\n id: z.string().uuid().optional(),\n [parentFkParam]: z.string().uuid().optional(),\n sortField: z.string().optional(),\n sortDir: z.enum(['asc', 'desc']).optional(),\n })\n .passthrough()\n\n const upsertSchema = createSchema.extend({\n id: z.string().uuid().optional(),\n })\n\n const deleteSchema = z.object({\n id: z.string().uuid(),\n [parentFkParam]: z.string().uuid(),\n })\n\n const routeMetadata = {\n GET: { requireAuth: true, requireFeatures: [features.view] },\n POST: { requireAuth: true, requireFeatures: [features.manage] },\n PUT: { requireAuth: true, requireFeatures: [features.manage] },\n DELETE: { requireAuth: true, requireFeatures: [features.manage] },\n }\n\n const crud = makeCrudRoute({\n metadata: routeMetadata,\n orm: {\n entity,\n idField: 'id',\n orgField: 'organizationId',\n tenantField: 'tenantId',\n softDeleteField: 'deletedAt',\n },\n indexer: {\n entityType: entityId,\n },\n enrichers: {\n entityId,\n },\n list: {\n schema: listSchema,\n entityId,\n fields: (() => {\n const fields: string[] = [\n F.id,\n parentFkColumn,\n F.line_number,\n F.kind,\n F.status_entry_id,\n F.status,\n F.product_id,\n F.product_variant_id,\n F.catalog_snapshot,\n F.name,\n F.description,\n F.comment,\n F.organization_id,\n F.tenant_id,\n F.quantity,\n F.quantity_unit,\n F.normalized_quantity,\n F.normalized_unit,\n F.uom_snapshot,\n F.currency_code,\n F.unit_price_net,\n F.unit_price_gross,\n F.discount_amount,\n F.discount_percent,\n F.tax_rate,\n F.tax_amount,\n F.total_net_amount,\n F.total_gross_amount,\n F.configuration,\n F.promotion_code,\n F.promotion_snapshot,\n F.metadata,\n F.custom_field_set_id,\n F.created_at,\n F.updated_at,\n ]\n const returnedQuantity = F['returned_quantity']\n if (typeof returnedQuantity === 'string') fields.push(returnedQuantity)\n return fields\n })(),\n sortFieldMap: {\n createdAt: F.created_at,\n updatedAt: F.updated_at,\n lineNumber: F.line_number,\n },\n buildFilters: async (query: Record<string, unknown>, ctx: CrudCtx) => {\n const filters: Record<string, unknown> = {}\n if (query.id) filters.id = { $eq: query.id }\n if (query[parentFkParam]) filters[parentFkColumn] = { $eq: query[parentFkParam] }\n try {\n const em = ctx.container.resolve<EntityManager>('em')\n const cfFilters = await buildCustomFieldFiltersFromQuery({\n entityId,\n query,\n em,\n tenantId: ctx.auth?.tenantId ?? null,\n })\n Object.assign(filters, cfFilters)\n } catch {\n // ignore\n }\n return filters\n },\n transformItem,\n },\n actions: {\n create: {\n commandId: `${commandPrefix}.upsert`,\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }: { raw: unknown; ctx: CrudCtx }) => {\n const { translate } = await resolveTranslations()\n const payload = upsertSchema.parse(\n withScopedPayload(resolveRawBody(raw) ?? {}, ctx, translate),\n )\n return { body: payload }\n },\n response: ({ result }: { result: Record<string, unknown> | null }) => ({\n id: result?.lineId ?? null,\n [parentFkParam]: result?.[parentFkParam] ?? null,\n }),\n status: 201,\n },\n update: {\n commandId: `${commandPrefix}.upsert`,\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }: { raw: unknown; ctx: CrudCtx }) => {\n const { translate } = await resolveTranslations()\n const payload = upsertSchema.parse(\n withScopedPayload(resolveRawBody(raw) ?? {}, ctx, translate),\n )\n return { body: payload }\n },\n response: ({ result }: { result: Record<string, unknown> | null }) => ({\n id: result?.lineId ?? null,\n [parentFkParam]: result?.[parentFkParam] ?? null,\n }),\n },\n delete: {\n commandId: `${commandPrefix}.delete`,\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }: { raw: unknown; ctx: CrudCtx }) => {\n const { translate } = await resolveTranslations()\n const payload = deleteSchema.parse(\n withScopedPayload(resolveRawBody(raw) ?? {}, ctx, translate),\n )\n if (!payload.id || !payload[parentFkParam]) {\n throw new CrudHttpError(400, {\n error: translate(\n 'sales.documents.detail.error',\n 'Document not found or inaccessible.',\n ),\n })\n }\n return { body: payload }\n },\n response: () => ({ ok: true }),\n },\n },\n })\n\n const lineItemSchema = z.object({\n id: z.string().uuid(),\n [parentFkColumn]: z.string().uuid(),\n line_number: z.number(),\n kind: z.string(),\n status_entry_id: z.string().uuid().nullable().optional(),\n status: z.string().nullable().optional(),\n product_id: z.string().uuid().nullable().optional(),\n product_variant_id: z.string().uuid().nullable().optional(),\n catalog_snapshot: z.record(z.string(), z.unknown()).nullable().optional(),\n name: z.string().nullable().optional(),\n description: z.string().nullable().optional(),\n comment: z.string().nullable().optional(),\n quantity: z.number(),\n quantity_unit: z.string().nullable().optional(),\n normalized_quantity: z.number(),\n normalized_unit: z.string().nullable().optional(),\n uom_snapshot: uomSnapshotOpenApiSchema,\n currency_code: z.string(),\n unit_price_net: z.number(),\n unit_price_gross: z.number(),\n discount_amount: z.number(),\n discount_percent: z.number(),\n tax_rate: z.number(),\n tax_amount: z.number(),\n total_net_amount: z.number(),\n total_gross_amount: z.number(),\n configuration: z.record(z.string(), z.unknown()).nullable().optional(),\n promotion_code: z.string().nullable().optional(),\n promotion_snapshot: z.record(z.string(), z.unknown()).nullable().optional(),\n metadata: z.record(z.string(), z.unknown()).nullable().optional(),\n custom_field_set_id: z.string().uuid().nullable().optional(),\n created_at: z.string(),\n updated_at: z.string(),\n })\n\n const upsertResponseSchema = z.object({\n id: z.string().uuid().nullable(),\n [parentFkParam]: z.string().uuid().nullable(),\n })\n\n const openApi = createSalesCrudOpenApi({\n resourceName: config.openApi.resourceName,\n querySchema: listSchema,\n listResponseSchema: createPagedListResponseSchema(lineItemSchema),\n create: {\n schema: upsertSchema,\n responseSchema: upsertResponseSchema,\n description: `Creates ${config.openApi.description}.`,\n },\n update: {\n schema: upsertSchema,\n responseSchema: upsertResponseSchema,\n description: `Updates ${config.openApi.description}.`,\n },\n del: {\n schema: deleteSchema,\n responseSchema: defaultOkResponseSchema,\n description: `Deletes ${config.openApi.description}.`,\n },\n })\n\n return {\n metadata: routeMetadata,\n openApi,\n GET: crud.GET,\n POST: crud.POST,\n PUT: crud.PUT,\n DELETE: crud.DELETE,\n }\n}\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["import { z } from 'zod'\nimport type { EntityManager } from '@mikro-orm/core'\nimport { makeCrudRoute, type CrudCtx } from '@open-mercato/shared/lib/crud/factory'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport {\n buildCustomFieldFiltersFromQuery,\n extractAllCustomFieldEntries,\n} from '@open-mercato/shared/lib/crud/custom-fields'\nimport {\n canonicalizeUnitCode,\n REFERENCE_UNIT_CODES,\n} from '@open-mercato/shared/lib/units/unitCodes'\nimport {\n createPagedListResponseSchema,\n createSalesCrudOpenApi,\n defaultOkResponseSchema,\n} from '../api/openapi'\nimport { withScopedPayload } from '../api/utils'\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- MikroORM entity class constructor\ntype EntityClass = new (...args: any[]) => unknown\n\ninterface SalesLineRouteConfig {\n entity: EntityClass\n entityId: string\n fieldConstants: Record<string, string>\n parentFkColumn: string\n parentFkParam: string\n createSchema: z.ZodObject<z.ZodRawShape>\n features: { view: string; manage: string }\n commandPrefix: string\n openApi: {\n resourceName: string\n description: string\n }\n}\n\nconst rawBodySchema = z.object({}).passthrough()\n\nfunction resolveRawBody(raw: unknown): Record<string, unknown> {\n if (!raw || typeof raw !== 'object') return {}\n if ('body' in raw) {\n const payload = raw as { body?: unknown }\n if (payload.body && typeof payload.body === 'object') {\n return payload.body as Record<string, unknown>\n }\n }\n return raw as Record<string, unknown>\n}\n\nfunction transformItem(item: Record<string, unknown> | null | undefined) {\n if (!item) return item\n const normalized = { ...item }\n const cfEntries = extractAllCustomFieldEntries(item)\n for (const key of Object.keys(normalized)) {\n if (key.startsWith('cf:')) delete normalized[key]\n }\n const quantityUnit = canonicalizeUnitCode(\n normalized['quantity_unit'] ?? normalized['quantityUnit'],\n )\n const normalizedUnit =\n canonicalizeUnitCode(\n normalized['normalized_unit'] ?? normalized['normalizedUnit'],\n ) ?? quantityUnit\n return {\n ...normalized,\n quantity_unit: quantityUnit,\n normalized_unit: normalizedUnit,\n ...cfEntries,\n }\n}\n\nconst uomSnapshotOpenApiSchema = z\n .object({\n version: z.literal(1),\n productId: z.string().nullable(),\n productVariantId: z.string().nullable(),\n baseUnitCode: z.string().nullable(),\n enteredUnitCode: z.string().nullable(),\n enteredQuantity: z.string(),\n toBaseFactor: z.string(),\n normalizedQuantity: z.string(),\n rounding: z.object({\n mode: z.enum(['half_up', 'down', 'up']),\n scale: z.number().int(),\n }),\n source: z.object({\n conversionId: z.string().nullable(),\n resolvedAt: z.string(),\n }),\n unitPriceReference: z\n .object({\n enabled: z.boolean(),\n referenceUnitCode: z.enum(REFERENCE_UNIT_CODES).nullable(),\n baseQuantity: z.string().nullable(),\n grossPerReference: z.string().nullable().optional(),\n netPerReference: z.string().nullable().optional(),\n })\n .optional(),\n })\n .nullable()\n .optional()\n\nexport function makeSalesLineRoute(config: SalesLineRouteConfig) {\n const {\n entity,\n entityId,\n fieldConstants: F,\n parentFkColumn,\n parentFkParam,\n createSchema,\n features,\n commandPrefix,\n } = config\n\n const listSchema = z\n .object({\n page: z.coerce.number().min(1).default(1),\n pageSize: z.coerce.number().min(1).max(100).default(50),\n id: z.string().uuid().optional(),\n [parentFkParam]: z.string().uuid().optional(),\n sortField: z.string().optional(),\n sortDir: z.enum(['asc', 'desc']).optional(),\n })\n .passthrough()\n\n const upsertSchema = createSchema.extend({\n id: z.string().uuid().optional(),\n })\n\n const deleteSchema = z.object({\n id: z.string().uuid(),\n [parentFkParam]: z.string().uuid(),\n })\n\n const routeMetadata = {\n GET: { requireAuth: true, requireFeatures: [features.view] },\n POST: { requireAuth: true, requireFeatures: [features.manage] },\n PUT: { requireAuth: true, requireFeatures: [features.manage] },\n DELETE: { requireAuth: true, requireFeatures: [features.manage] },\n }\n\n const crud = makeCrudRoute({\n metadata: routeMetadata,\n orm: {\n entity,\n idField: 'id',\n orgField: 'organizationId',\n tenantField: 'tenantId',\n softDeleteField: 'deletedAt',\n },\n indexer: {\n entityType: entityId,\n },\n enrichers: {\n entityId,\n },\n list: {\n schema: listSchema,\n entityId,\n fields: (() => {\n const fields: string[] = [\n F.id,\n parentFkColumn,\n F.line_number,\n F.kind,\n F.status_entry_id,\n F.status,\n F.product_id,\n F.product_variant_id,\n F.catalog_snapshot,\n F.name,\n F.description,\n F.comment,\n F.organization_id,\n F.tenant_id,\n F.quantity,\n F.quantity_unit,\n F.normalized_quantity,\n F.normalized_unit,\n F.uom_snapshot,\n F.currency_code,\n F.unit_price_net,\n F.unit_price_gross,\n F.discount_amount,\n F.discount_percent,\n F.tax_rate,\n F.tax_amount,\n F.total_net_amount,\n F.total_gross_amount,\n F.configuration,\n F.promotion_code,\n F.promotion_snapshot,\n F.metadata,\n F.custom_field_set_id,\n F.created_at,\n F.updated_at,\n ]\n const returnedQuantity = F['returned_quantity']\n if (typeof returnedQuantity === 'string') fields.push(returnedQuantity)\n return fields\n })(),\n sortFieldMap: {\n id: F.id,\n createdAt: F.created_at,\n updatedAt: F.updated_at,\n lineNumber: F.line_number,\n },\n // Line ids are random v4 UUIDs, so the factory's `id` default orders a\n // document's lines arbitrarily and reshuffles them whenever an integration\n // rewrites the lines (delete-and-reinsert is the normal upsert shape).\n // `line_number` is the document's real reading order; `id` only breaks ties\n // between legacy rows that all still sit at the column default of 0.\n defaultSort: { field: 'lineNumber', dir: 'asc' },\n tiebreakSortField: 'id',\n buildFilters: async (query: Record<string, unknown>, ctx: CrudCtx) => {\n const filters: Record<string, unknown> = {}\n if (query.id) filters.id = { $eq: query.id }\n if (query[parentFkParam]) filters[parentFkColumn] = { $eq: query[parentFkParam] }\n try {\n const em = ctx.container.resolve<EntityManager>('em')\n const cfFilters = await buildCustomFieldFiltersFromQuery({\n entityId,\n query,\n em,\n tenantId: ctx.auth?.tenantId ?? null,\n })\n Object.assign(filters, cfFilters)\n } catch {\n // ignore\n }\n return filters\n },\n transformItem,\n },\n actions: {\n create: {\n commandId: `${commandPrefix}.upsert`,\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }: { raw: unknown; ctx: CrudCtx }) => {\n const { translate } = await resolveTranslations()\n const payload = upsertSchema.parse(\n withScopedPayload(resolveRawBody(raw) ?? {}, ctx, translate),\n )\n return { body: payload }\n },\n response: ({ result }: { result: Record<string, unknown> | null }) => ({\n id: result?.lineId ?? null,\n [parentFkParam]: result?.[parentFkParam] ?? null,\n }),\n status: 201,\n },\n update: {\n commandId: `${commandPrefix}.upsert`,\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }: { raw: unknown; ctx: CrudCtx }) => {\n const { translate } = await resolveTranslations()\n const payload = upsertSchema.parse(\n withScopedPayload(resolveRawBody(raw) ?? {}, ctx, translate),\n )\n return { body: payload }\n },\n response: ({ result }: { result: Record<string, unknown> | null }) => ({\n id: result?.lineId ?? null,\n [parentFkParam]: result?.[parentFkParam] ?? null,\n }),\n },\n delete: {\n commandId: `${commandPrefix}.delete`,\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }: { raw: unknown; ctx: CrudCtx }) => {\n const { translate } = await resolveTranslations()\n const payload = deleteSchema.parse(\n withScopedPayload(resolveRawBody(raw) ?? {}, ctx, translate),\n )\n if (!payload.id || !payload[parentFkParam]) {\n throw new CrudHttpError(400, {\n error: translate(\n 'sales.documents.detail.error',\n 'Document not found or inaccessible.',\n ),\n })\n }\n return { body: payload }\n },\n response: () => ({ ok: true }),\n },\n },\n })\n\n const lineItemSchema = z.object({\n id: z.string().uuid(),\n [parentFkColumn]: z.string().uuid(),\n line_number: z.number(),\n kind: z.string(),\n status_entry_id: z.string().uuid().nullable().optional(),\n status: z.string().nullable().optional(),\n product_id: z.string().uuid().nullable().optional(),\n product_variant_id: z.string().uuid().nullable().optional(),\n catalog_snapshot: z.record(z.string(), z.unknown()).nullable().optional(),\n name: z.string().nullable().optional(),\n description: z.string().nullable().optional(),\n comment: z.string().nullable().optional(),\n quantity: z.number(),\n quantity_unit: z.string().nullable().optional(),\n normalized_quantity: z.number(),\n normalized_unit: z.string().nullable().optional(),\n uom_snapshot: uomSnapshotOpenApiSchema,\n currency_code: z.string(),\n unit_price_net: z.number(),\n unit_price_gross: z.number(),\n discount_amount: z.number(),\n discount_percent: z.number(),\n tax_rate: z.number(),\n tax_amount: z.number(),\n total_net_amount: z.number(),\n total_gross_amount: z.number(),\n configuration: z.record(z.string(), z.unknown()).nullable().optional(),\n promotion_code: z.string().nullable().optional(),\n promotion_snapshot: z.record(z.string(), z.unknown()).nullable().optional(),\n metadata: z.record(z.string(), z.unknown()).nullable().optional(),\n custom_field_set_id: z.string().uuid().nullable().optional(),\n created_at: z.string(),\n updated_at: z.string(),\n })\n\n const upsertResponseSchema = z.object({\n id: z.string().uuid().nullable(),\n [parentFkParam]: z.string().uuid().nullable(),\n })\n\n const openApi = createSalesCrudOpenApi({\n resourceName: config.openApi.resourceName,\n querySchema: listSchema,\n listResponseSchema: createPagedListResponseSchema(lineItemSchema),\n create: {\n schema: upsertSchema,\n responseSchema: upsertResponseSchema,\n description: `Creates ${config.openApi.description}.`,\n },\n update: {\n schema: upsertSchema,\n responseSchema: upsertResponseSchema,\n description: `Updates ${config.openApi.description}.`,\n },\n del: {\n schema: deleteSchema,\n responseSchema: defaultOkResponseSchema,\n description: `Deletes ${config.openApi.description}.`,\n },\n })\n\n return {\n metadata: routeMetadata,\n openApi,\n GET: crud.GET,\n POST: crud.POST,\n PUT: crud.PUT,\n DELETE: crud.DELETE,\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.8-develop.
|
|
3
|
+
"version": "0.6.8-develop.6879.1.9883cf6265",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -254,16 +254,16 @@
|
|
|
254
254
|
"zod": "^4.4.3"
|
|
255
255
|
},
|
|
256
256
|
"peerDependencies": {
|
|
257
|
-
"@open-mercato/ai-assistant": "0.6.8-develop.
|
|
258
|
-
"@open-mercato/shared": "0.6.8-develop.
|
|
259
|
-
"@open-mercato/ui": "0.6.8-develop.
|
|
257
|
+
"@open-mercato/ai-assistant": "0.6.8-develop.6879.1.9883cf6265",
|
|
258
|
+
"@open-mercato/shared": "0.6.8-develop.6879.1.9883cf6265",
|
|
259
|
+
"@open-mercato/ui": "0.6.8-develop.6879.1.9883cf6265",
|
|
260
260
|
"react": "^19.0.0",
|
|
261
261
|
"react-dom": "^19.0.0"
|
|
262
262
|
},
|
|
263
263
|
"devDependencies": {
|
|
264
|
-
"@open-mercato/ai-assistant": "0.6.8-develop.
|
|
265
|
-
"@open-mercato/shared": "0.6.8-develop.
|
|
266
|
-
"@open-mercato/ui": "0.6.8-develop.
|
|
264
|
+
"@open-mercato/ai-assistant": "0.6.8-develop.6879.1.9883cf6265",
|
|
265
|
+
"@open-mercato/shared": "0.6.8-develop.6879.1.9883cf6265",
|
|
266
|
+
"@open-mercato/ui": "0.6.8-develop.6879.1.9883cf6265",
|
|
267
267
|
"@testing-library/dom": "^10.4.1",
|
|
268
268
|
"@testing-library/jest-dom": "^7.0.0",
|
|
269
269
|
"@testing-library/react": "^16.3.1",
|
|
@@ -202,10 +202,18 @@ export function makeSalesLineRoute(config: SalesLineRouteConfig) {
|
|
|
202
202
|
return fields
|
|
203
203
|
})(),
|
|
204
204
|
sortFieldMap: {
|
|
205
|
+
id: F.id,
|
|
205
206
|
createdAt: F.created_at,
|
|
206
207
|
updatedAt: F.updated_at,
|
|
207
208
|
lineNumber: F.line_number,
|
|
208
209
|
},
|
|
210
|
+
// Line ids are random v4 UUIDs, so the factory's `id` default orders a
|
|
211
|
+
// document's lines arbitrarily and reshuffles them whenever an integration
|
|
212
|
+
// rewrites the lines (delete-and-reinsert is the normal upsert shape).
|
|
213
|
+
// `line_number` is the document's real reading order; `id` only breaks ties
|
|
214
|
+
// between legacy rows that all still sit at the column default of 0.
|
|
215
|
+
defaultSort: { field: 'lineNumber', dir: 'asc' },
|
|
216
|
+
tiebreakSortField: 'id',
|
|
209
217
|
buildFilters: async (query: Record<string, unknown>, ctx: CrudCtx) => {
|
|
210
218
|
const filters: Record<string, unknown> = {}
|
|
211
219
|
if (query.id) filters.id = { $eq: query.id }
|