@open-mercato/core 0.4.5-develop-3ce83a8b24 → 0.4.5-develop-539cff4960
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/dist/generated/entities/catalog_product/index.js +16 -0
- package/dist/generated/entities/catalog_product/index.js.map +2 -2
- package/dist/generated/entities/catalog_product_unit_conversion/index.js +27 -0
- package/dist/generated/entities/catalog_product_unit_conversion/index.js.map +7 -0
- package/dist/generated/entities/sales_credit_memo_line/index.js +7 -1
- package/dist/generated/entities/sales_credit_memo_line/index.js.map +2 -2
- package/dist/generated/entities/sales_invoice_line/index.js +7 -1
- package/dist/generated/entities/sales_invoice_line/index.js.map +2 -2
- package/dist/generated/entities/sales_order_line/index.js +6 -0
- package/dist/generated/entities/sales_order_line/index.js.map +2 -2
- package/dist/generated/entities/sales_quote_line/index.js +6 -0
- package/dist/generated/entities/sales_quote_line/index.js.map +2 -2
- package/dist/generated/entities.ids.generated.js +1 -0
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +2 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/catalog/api/prices/route.js +123 -8
- package/dist/modules/catalog/api/prices/route.js.map +2 -2
- package/dist/modules/catalog/api/product-unit-conversions/route.js +194 -0
- package/dist/modules/catalog/api/product-unit-conversions/route.js.map +7 -0
- package/dist/modules/catalog/api/products/route.js +351 -201
- package/dist/modules/catalog/api/products/route.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/[id]/page.js +1267 -497
- package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/create/page.js +733 -210
- package/dist/modules/catalog/backend/catalog/products/create/page.js.map +2 -2
- package/dist/modules/catalog/commands/index.js +1 -0
- package/dist/modules/catalog/commands/index.js.map +2 -2
- package/dist/modules/catalog/commands/productUnitConversions.js +503 -0
- package/dist/modules/catalog/commands/productUnitConversions.js.map +7 -0
- package/dist/modules/catalog/commands/products.js +355 -73
- package/dist/modules/catalog/commands/products.js.map +2 -2
- package/dist/modules/catalog/commands/shared.js +18 -4
- package/dist/modules/catalog/commands/shared.js.map +2 -2
- package/dist/modules/catalog/components/products/ProductUomSection.js +591 -0
- package/dist/modules/catalog/components/products/ProductUomSection.js.map +7 -0
- package/dist/modules/catalog/components/products/productForm.js +66 -5
- package/dist/modules/catalog/components/products/productForm.js.map +2 -2
- package/dist/modules/catalog/components/products/productFormUtils.js +68 -0
- package/dist/modules/catalog/components/products/productFormUtils.js.map +7 -0
- package/dist/modules/catalog/data/entities.js +86 -0
- package/dist/modules/catalog/data/entities.js.map +2 -2
- package/dist/modules/catalog/data/validators.js +65 -3
- package/dist/modules/catalog/data/validators.js.map +2 -2
- package/dist/modules/catalog/events.js +3 -0
- package/dist/modules/catalog/events.js.map +2 -2
- package/dist/modules/catalog/lib/unitCodes.js +7 -0
- package/dist/modules/catalog/lib/unitCodes.js.map +7 -0
- package/dist/modules/catalog/lib/unitResolution.js +53 -0
- package/dist/modules/catalog/lib/unitResolution.js.map +7 -0
- package/dist/modules/catalog/migrations/Migration20260218225422.js +19 -0
- package/dist/modules/catalog/migrations/Migration20260218225422.js.map +7 -0
- package/dist/modules/catalog/migrations/Migration20260219084500.js +27 -0
- package/dist/modules/catalog/migrations/Migration20260219084500.js.map +7 -0
- package/dist/modules/catalog/search.js +69 -1
- package/dist/modules/catalog/search.js.map +2 -2
- package/dist/modules/catalog/seed/examples.js +91 -42
- package/dist/modules/catalog/seed/examples.js.map +2 -2
- package/dist/modules/dashboards/seed/analytics.js +3 -0
- package/dist/modules/dashboards/seed/analytics.js.map +2 -2
- package/dist/modules/sales/api/order-lines/route.js +98 -15
- package/dist/modules/sales/api/order-lines/route.js.map +2 -2
- package/dist/modules/sales/api/quote-lines/route.js +101 -14
- package/dist/modules/sales/api/quote-lines/route.js.map +2 -2
- package/dist/modules/sales/api/quotes/public/[token]/route.js +87 -12
- package/dist/modules/sales/api/quotes/public/[token]/route.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +1424 -260
- package/dist/modules/sales/commands/documents.js.map +3 -3
- package/dist/modules/sales/commands/shared.js +6 -2
- package/dist/modules/sales/commands/shared.js.map +2 -2
- package/dist/modules/sales/components/documents/ItemsSection.js +216 -86
- package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/LineItemDialog.js +913 -241
- package/dist/modules/sales/components/documents/LineItemDialog.js.map +3 -3
- package/dist/modules/sales/components/documents/ShipmentsSection.js +15 -3
- package/dist/modules/sales/components/documents/ShipmentsSection.js.map +2 -2
- package/dist/modules/sales/data/entities.js +59 -3
- package/dist/modules/sales/data/entities.js.map +2 -2
- package/dist/modules/sales/data/validators.js +35 -0
- package/dist/modules/sales/data/validators.js.map +2 -2
- package/dist/modules/sales/frontend/quote/[token]/page.js +15 -1
- package/dist/modules/sales/frontend/quote/[token]/page.js.map +2 -2
- package/dist/modules/sales/migrations/Migration20260218225423.js +31 -0
- package/dist/modules/sales/migrations/Migration20260218225423.js.map +7 -0
- package/dist/modules/sales/migrations/Migration20260219084501.js +71 -0
- package/dist/modules/sales/migrations/Migration20260219084501.js.map +7 -0
- package/dist/modules/sales/search.js +28 -0
- package/dist/modules/sales/search.js.map +2 -2
- package/dist/modules/sales/seed/examples.js +14 -1
- package/dist/modules/sales/seed/examples.js.map +2 -2
- package/dist/modules/sales/widgets/injection/document-history/widget.client.js +1 -1
- package/dist/modules/sales/widgets/injection/document-history/widget.client.js.map +2 -2
- package/dist/modules/staff/backend/staff/team-members/[id]/page.js +28 -15
- package/dist/modules/staff/backend/staff/team-members/[id]/page.js.map +2 -2
- package/dist/modules/staff/translations.js +9 -0
- package/dist/modules/staff/translations.js.map +7 -0
- package/dist/modules/translations/components/TranslationDrawerAction.js +97 -0
- package/dist/modules/translations/components/TranslationDrawerAction.js.map +7 -0
- package/dist/modules/translations/lib/extract-record-id.js +31 -2
- package/dist/modules/translations/lib/extract-record-id.js.map +2 -2
- package/dist/modules/translations/lib/resolve-field-list.js +3 -0
- package/dist/modules/translations/lib/resolve-field-list.js.map +2 -2
- package/dist/modules/translations/widgets/injection/translation-manager/widget.client.js +105 -36
- package/dist/modules/translations/widgets/injection/translation-manager/widget.client.js.map +2 -2
- package/dist/modules/translations/widgets/injection-table.js +18 -29
- package/dist/modules/translations/widgets/injection-table.js.map +2 -2
- package/generated/entities/catalog_product/index.ts +8 -0
- package/generated/entities/catalog_product_unit_conversion/index.ts +12 -0
- package/generated/entities/sales_credit_memo_line/index.ts +3 -0
- package/generated/entities/sales_invoice_line/index.ts +3 -0
- package/generated/entities/sales_order_line/index.ts +3 -0
- package/generated/entities/sales_quote_line/index.ts +3 -0
- package/generated/entities.ids.generated.ts +1 -0
- package/generated/entity-fields-registry.ts +2 -0
- package/package.json +2 -2
- package/src/modules/auth/i18n/de.json +1 -1
- package/src/modules/auth/i18n/en.json +1 -1
- package/src/modules/auth/i18n/es.json +1 -1
- package/src/modules/auth/i18n/pl.json +1 -1
- package/src/modules/catalog/api/prices/route.ts +213 -81
- package/src/modules/catalog/api/product-unit-conversions/route.ts +195 -0
- package/src/modules/catalog/api/products/route.ts +638 -402
- package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +2085 -1072
- package/src/modules/catalog/backend/catalog/products/create/page.tsx +1288 -593
- package/src/modules/catalog/commands/index.ts +1 -0
- package/src/modules/catalog/commands/productUnitConversions.ts +626 -0
- package/src/modules/catalog/commands/products.ts +1151 -693
- package/src/modules/catalog/commands/shared.ts +19 -5
- package/src/modules/catalog/components/products/ProductUomSection.tsx +745 -0
- package/src/modules/catalog/components/products/productForm.ts +369 -256
- package/src/modules/catalog/components/products/productFormUtils.ts +82 -0
- package/src/modules/catalog/data/entities.ts +82 -1
- package/src/modules/catalog/data/validators.ts +118 -34
- package/src/modules/catalog/events.ts +3 -0
- package/src/modules/catalog/i18n/de.json +56 -0
- package/src/modules/catalog/i18n/en.json +56 -0
- package/src/modules/catalog/i18n/es.json +56 -0
- package/src/modules/catalog/i18n/pl.json +56 -0
- package/src/modules/catalog/lib/unitCodes.ts +1 -0
- package/src/modules/catalog/lib/unitResolution.ts +62 -0
- package/src/modules/catalog/migrations/.snapshot-open-mercato.json +245 -0
- package/src/modules/catalog/migrations/Migration20260218225422.ts +21 -0
- package/src/modules/catalog/migrations/Migration20260219084500.ts +26 -0
- package/src/modules/catalog/search.ts +73 -1
- package/src/modules/catalog/seed/examples.ts +552 -479
- package/src/modules/dashboards/i18n/de.json +1 -1
- package/src/modules/dashboards/i18n/en.json +1 -1
- package/src/modules/dashboards/i18n/es.json +1 -1
- package/src/modules/dashboards/i18n/pl.json +1 -1
- package/src/modules/dashboards/seed/analytics.ts +3 -0
- package/src/modules/sales/api/order-lines/route.ts +158 -68
- package/src/modules/sales/api/quote-lines/route.ts +161 -67
- package/src/modules/sales/api/quotes/public/[token]/route.ts +122 -36
- package/src/modules/sales/commands/documents.ts +4250 -2424
- package/src/modules/sales/commands/shared.ts +7 -2
- package/src/modules/sales/components/documents/ItemsSection.tsx +580 -310
- package/src/modules/sales/components/documents/LineItemDialog.tsx +1988 -833
- package/src/modules/sales/components/documents/ShipmentsSection.tsx +17 -3
- package/src/modules/sales/components/documents/lineItemTypes.ts +6 -0
- package/src/modules/sales/data/entities.ts +53 -0
- package/src/modules/sales/data/validators.ts +36 -0
- package/src/modules/sales/frontend/quote/[token]/page.tsx +25 -1
- package/src/modules/sales/i18n/de.json +23 -3
- package/src/modules/sales/i18n/en.json +23 -3
- package/src/modules/sales/i18n/es.json +23 -3
- package/src/modules/sales/i18n/pl.json +23 -3
- package/src/modules/sales/lib/types.ts +30 -0
- package/src/modules/sales/migrations/.snapshot-open-mercato.json +172 -0
- package/src/modules/sales/migrations/Migration20260218225423.ts +37 -0
- package/src/modules/sales/migrations/Migration20260219084501.ts +73 -0
- package/src/modules/sales/search.ts +28 -0
- package/src/modules/sales/seed/examples.ts +20 -1
- package/src/modules/sales/widgets/injection/document-history/widget.client.tsx +1 -1
- package/src/modules/staff/backend/staff/team-members/[id]/page.tsx +8 -0
- package/src/modules/staff/translations.ts +5 -0
- package/src/modules/translations/components/TranslationDrawerAction.tsx +107 -0
- package/src/modules/translations/lib/extract-record-id.ts +47 -3
- package/src/modules/translations/lib/resolve-field-list.ts +4 -0
- package/src/modules/translations/widgets/injection/translation-manager/widget.client.tsx +108 -36
- package/src/modules/translations/widgets/injection-table.ts +19 -33
- package/src/modules/workflows/i18n/de.json +4 -4
- package/src/modules/workflows/i18n/en.json +4 -4
- package/src/modules/workflows/i18n/es.json +4 -4
- package/src/modules/workflows/i18n/pl.json +4 -4
|
@@ -96,6 +96,7 @@
|
|
|
96
96
|
"dashboards.analytics.widgets.topProducts.empty": "Keine Produktverkaufsdaten für diesen Zeitraum",
|
|
97
97
|
"dashboards.analytics.widgets.topProducts.error": "Produktdaten konnten nicht geladen werden",
|
|
98
98
|
"dashboards.analytics.widgets.topProducts.title": "Top-Produkte nach Umsatz",
|
|
99
|
+
"dashboards.widgets.effective": "Aktive Widgets:",
|
|
99
100
|
"dashboards.widgets.error.load": "Widget-Konfiguration konnte nicht geladen werden.",
|
|
100
101
|
"dashboards.widgets.error.save": "Dashboard-Widget-Einstellungen konnten nicht gespeichert werden.",
|
|
101
102
|
"dashboards.widgets.flash.saved": "Dashboard-Widgets aktualisiert",
|
|
@@ -103,7 +104,6 @@
|
|
|
103
104
|
"dashboards.widgets.mode.hint": "Dieser Benutzer erbt derzeit Widgets von seinen Rollen. Wechseln Sie zu \"Überschreiben\", um anzupassen.",
|
|
104
105
|
"dashboards.widgets.mode.inherit": "Von Rollen übernehmen",
|
|
105
106
|
"dashboards.widgets.mode.override": "Für diesen Benutzer überschreiben",
|
|
106
|
-
"dashboards.widgets.effective": "Aktive Widgets:",
|
|
107
107
|
"dashboards.widgets.reset": "Zurücksetzen",
|
|
108
108
|
"dashboards.widgets.save": "Widgets speichern",
|
|
109
109
|
"dashboards.widgets.saving": "Speichern…"
|
|
@@ -96,6 +96,7 @@
|
|
|
96
96
|
"dashboards.analytics.widgets.topProducts.empty": "No product sales data for this period",
|
|
97
97
|
"dashboards.analytics.widgets.topProducts.error": "Failed to load top products data",
|
|
98
98
|
"dashboards.analytics.widgets.topProducts.title": "Top Products by Revenue",
|
|
99
|
+
"dashboards.widgets.effective": "Effective widgets:",
|
|
99
100
|
"dashboards.widgets.error.load": "Unable to load widget configuration.",
|
|
100
101
|
"dashboards.widgets.error.save": "Unable to save dashboard widget preferences.",
|
|
101
102
|
"dashboards.widgets.flash.saved": "Dashboard widgets updated",
|
|
@@ -103,7 +104,6 @@
|
|
|
103
104
|
"dashboards.widgets.mode.hint": "This user currently inherits widgets from their assigned roles. Switch to override to customize.",
|
|
104
105
|
"dashboards.widgets.mode.inherit": "Inherit from roles",
|
|
105
106
|
"dashboards.widgets.mode.override": "Override for this user",
|
|
106
|
-
"dashboards.widgets.effective": "Effective widgets:",
|
|
107
107
|
"dashboards.widgets.reset": "Reset",
|
|
108
108
|
"dashboards.widgets.save": "Save widgets",
|
|
109
109
|
"dashboards.widgets.saving": "Saving…"
|
|
@@ -96,6 +96,7 @@
|
|
|
96
96
|
"dashboards.analytics.widgets.topProducts.empty": "No hay datos de ventas de productos para este período",
|
|
97
97
|
"dashboards.analytics.widgets.topProducts.error": "No se pudieron cargar los datos de productos",
|
|
98
98
|
"dashboards.analytics.widgets.topProducts.title": "Productos principales por ingresos",
|
|
99
|
+
"dashboards.widgets.effective": "Widgets efectivos:",
|
|
99
100
|
"dashboards.widgets.error.load": "No se pudo cargar la configuración de widgets.",
|
|
100
101
|
"dashboards.widgets.error.save": "No se pudieron guardar las preferencias de los widgets del panel.",
|
|
101
102
|
"dashboards.widgets.flash.saved": "Widgets del panel actualizados",
|
|
@@ -103,7 +104,6 @@
|
|
|
103
104
|
"dashboards.widgets.mode.hint": "Este usuario hereda los widgets de sus roles asignados. Cambia a sobrescribir para personalizar.",
|
|
104
105
|
"dashboards.widgets.mode.inherit": "Heredar de los roles",
|
|
105
106
|
"dashboards.widgets.mode.override": "Sobrescribir para este usuario",
|
|
106
|
-
"dashboards.widgets.effective": "Widgets efectivos:",
|
|
107
107
|
"dashboards.widgets.reset": "Restablecer",
|
|
108
108
|
"dashboards.widgets.save": "Guardar widgets",
|
|
109
109
|
"dashboards.widgets.saving": "Guardando…"
|
|
@@ -96,6 +96,7 @@
|
|
|
96
96
|
"dashboards.analytics.widgets.topProducts.empty": "Brak danych o sprzedaży produktów dla tego okresu",
|
|
97
97
|
"dashboards.analytics.widgets.topProducts.error": "Nie udało się załadować danych o produktach",
|
|
98
98
|
"dashboards.analytics.widgets.topProducts.title": "Najlepsze produkty wg przychodu",
|
|
99
|
+
"dashboards.widgets.effective": "Aktywne widżety:",
|
|
99
100
|
"dashboards.widgets.error.load": "Nie udało się wczytać konfiguracji widżetów.",
|
|
100
101
|
"dashboards.widgets.error.save": "Nie udało się zapisać preferencji widżetów pulpitu.",
|
|
101
102
|
"dashboards.widgets.flash.saved": "Widżety pulpitu zostały zaktualizowane",
|
|
@@ -103,7 +104,6 @@
|
|
|
103
104
|
"dashboards.widgets.mode.hint": "Ten użytkownik dziedziczy widżety z przypisanych ról. Wybierz nadpisanie, aby je dostosować.",
|
|
104
105
|
"dashboards.widgets.mode.inherit": "Dziedzicz po rolach",
|
|
105
106
|
"dashboards.widgets.mode.override": "Nadpisz dla tego użytkownika",
|
|
106
|
-
"dashboards.widgets.effective": "Aktywne widżety:",
|
|
107
107
|
"dashboards.widgets.reset": "Resetuj",
|
|
108
108
|
"dashboards.widgets.save": "Zapisz widżety",
|
|
109
109
|
"dashboards.widgets.saving": "Zapisywanie…"
|
|
@@ -325,6 +325,9 @@ export async function seedAnalyticsData(
|
|
|
325
325
|
kind: 'product',
|
|
326
326
|
name: lineData.product.title,
|
|
327
327
|
quantity: toAmount(lineData.quantity),
|
|
328
|
+
normalizedQuantity: toAmount(lineData.quantity),
|
|
329
|
+
normalizedUnit: null,
|
|
330
|
+
uomSnapshot: null,
|
|
328
331
|
currencyCode: 'USD',
|
|
329
332
|
unitPriceNet: toAmount(lineData.unitPriceNet),
|
|
330
333
|
unitPriceGross: toAmount(lineData.unitPriceGross),
|
|
@@ -1,50 +1,69 @@
|
|
|
1
|
-
import { z } from
|
|
2
|
-
import { makeCrudRoute } from
|
|
3
|
-
import { resolveTranslations } from
|
|
4
|
-
import { CrudHttpError } from
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { makeCrudRoute } from "@open-mercato/shared/lib/crud/factory";
|
|
3
|
+
import { resolveTranslations } from "@open-mercato/shared/lib/i18n/server";
|
|
4
|
+
import { CrudHttpError } from "@open-mercato/shared/lib/crud/errors";
|
|
5
|
+
import {
|
|
6
|
+
buildCustomFieldFiltersFromQuery,
|
|
7
|
+
extractAllCustomFieldEntries,
|
|
8
|
+
} from "@open-mercato/shared/lib/crud/custom-fields";
|
|
9
|
+
import { SalesOrderLine } from "../../data/entities";
|
|
10
|
+
import { orderLineCreateSchema } from "../../data/validators";
|
|
11
|
+
import {
|
|
12
|
+
createPagedListResponseSchema,
|
|
13
|
+
createSalesCrudOpenApi,
|
|
14
|
+
defaultOkResponseSchema,
|
|
15
|
+
} from "../openapi";
|
|
16
|
+
import { withScopedPayload } from "../utils";
|
|
17
|
+
import { E } from "#generated/entities.ids.generated";
|
|
18
|
+
import * as F from "#generated/entities/sales_order_line";
|
|
19
|
+
import { canonicalizeUnitCode, REFERENCE_UNIT_CODES } from "@open-mercato/shared/lib/units/unitCodes";
|
|
12
20
|
|
|
13
|
-
const rawBodySchema = z.object({}).passthrough()
|
|
14
|
-
const resolveRawBody = (raw: unknown)
|
|
21
|
+
const rawBodySchema = z.object({}).passthrough();
|
|
22
|
+
const resolveRawBody = (raw: unknown): Record<string, unknown> => {
|
|
23
|
+
if (!raw || typeof raw !== "object") return {};
|
|
24
|
+
if ("body" in raw) {
|
|
25
|
+
const payload = raw as { body?: unknown };
|
|
26
|
+
if (payload.body && typeof payload.body === "object") {
|
|
27
|
+
return payload.body as Record<string, unknown>;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return raw as Record<string, unknown>;
|
|
31
|
+
};
|
|
15
32
|
|
|
16
33
|
const listSchema = z
|
|
17
34
|
.object({
|
|
18
35
|
page: z.coerce.number().min(1).default(1),
|
|
19
|
-
pageSize: z.coerce.number().min(1).max(
|
|
36
|
+
pageSize: z.coerce.number().min(1).max(100).default(50),
|
|
20
37
|
id: z.string().uuid().optional(),
|
|
21
38
|
orderId: z.string().uuid().optional(),
|
|
22
39
|
sortField: z.string().optional(),
|
|
23
|
-
sortDir: z.enum([
|
|
40
|
+
sortDir: z.enum(["asc", "desc"]).optional(),
|
|
24
41
|
})
|
|
25
|
-
.passthrough()
|
|
42
|
+
.passthrough();
|
|
26
43
|
|
|
27
44
|
const routeMetadata = {
|
|
28
|
-
GET: { requireAuth: true, requireFeatures: [
|
|
29
|
-
POST: { requireAuth: true, requireFeatures: [
|
|
30
|
-
PUT: { requireAuth: true, requireFeatures: [
|
|
31
|
-
DELETE: { requireAuth: true, requireFeatures: [
|
|
32
|
-
}
|
|
45
|
+
GET: { requireAuth: true, requireFeatures: ["sales.orders.view"] },
|
|
46
|
+
POST: { requireAuth: true, requireFeatures: ["sales.orders.manage"] },
|
|
47
|
+
PUT: { requireAuth: true, requireFeatures: ["sales.orders.manage"] },
|
|
48
|
+
DELETE: { requireAuth: true, requireFeatures: ["sales.orders.manage"] },
|
|
49
|
+
};
|
|
33
50
|
|
|
34
|
-
const upsertSchema = orderLineCreateSchema.extend({
|
|
51
|
+
const upsertSchema = orderLineCreateSchema.extend({
|
|
52
|
+
id: z.string().uuid().optional(),
|
|
53
|
+
});
|
|
35
54
|
const deleteSchema = z.object({
|
|
36
55
|
id: z.string().uuid(),
|
|
37
56
|
orderId: z.string().uuid(),
|
|
38
|
-
})
|
|
57
|
+
});
|
|
39
58
|
|
|
40
59
|
const crud = makeCrudRoute({
|
|
41
60
|
metadata: routeMetadata,
|
|
42
61
|
orm: {
|
|
43
62
|
entity: SalesOrderLine,
|
|
44
|
-
idField:
|
|
45
|
-
orgField:
|
|
46
|
-
tenantField:
|
|
47
|
-
softDeleteField:
|
|
63
|
+
idField: "id",
|
|
64
|
+
orgField: "organizationId",
|
|
65
|
+
tenantField: "tenantId",
|
|
66
|
+
softDeleteField: "deletedAt",
|
|
48
67
|
},
|
|
49
68
|
indexer: {
|
|
50
69
|
entityType: E.sales.sales_order_line,
|
|
@@ -54,7 +73,7 @@ const crud = makeCrudRoute({
|
|
|
54
73
|
entityId: E.sales.sales_order_line,
|
|
55
74
|
fields: [
|
|
56
75
|
F.id,
|
|
57
|
-
|
|
76
|
+
"order_id",
|
|
58
77
|
F.line_number,
|
|
59
78
|
F.kind,
|
|
60
79
|
F.status_entry_id,
|
|
@@ -69,6 +88,9 @@ const crud = makeCrudRoute({
|
|
|
69
88
|
F.tenant_id,
|
|
70
89
|
F.quantity,
|
|
71
90
|
F.quantity_unit,
|
|
91
|
+
F.normalized_quantity,
|
|
92
|
+
F.normalized_unit,
|
|
93
|
+
F.uom_snapshot,
|
|
72
94
|
F.currency_code,
|
|
73
95
|
F.unit_price_net,
|
|
74
96
|
F.unit_price_gross,
|
|
@@ -92,75 +114,134 @@ const crud = makeCrudRoute({
|
|
|
92
114
|
lineNumber: F.line_number,
|
|
93
115
|
},
|
|
94
116
|
buildFilters: async (query, ctx) => {
|
|
95
|
-
const filters: Record<string, unknown> = {}
|
|
96
|
-
if (query.id) filters.id = { $eq: query.id }
|
|
97
|
-
if (query.orderId) filters.order_id = { $eq: query.orderId }
|
|
117
|
+
const filters: Record<string, unknown> = {};
|
|
118
|
+
if (query.id) filters.id = { $eq: query.id };
|
|
119
|
+
if (query.orderId) filters.order_id = { $eq: query.orderId };
|
|
98
120
|
try {
|
|
99
|
-
const em = ctx.container.resolve(
|
|
121
|
+
const em = ctx.container.resolve("em");
|
|
100
122
|
const cfFilters = await buildCustomFieldFiltersFromQuery({
|
|
101
123
|
entityId: E.sales.sales_order_line,
|
|
102
124
|
query,
|
|
103
125
|
em,
|
|
104
126
|
tenantId: ctx.auth?.tenantId ?? null,
|
|
105
|
-
})
|
|
106
|
-
Object.assign(filters, cfFilters)
|
|
127
|
+
});
|
|
128
|
+
Object.assign(filters, cfFilters);
|
|
107
129
|
} catch {
|
|
108
130
|
// ignore
|
|
109
131
|
}
|
|
110
|
-
return filters
|
|
132
|
+
return filters;
|
|
111
133
|
},
|
|
112
|
-
transformItem: (item:
|
|
113
|
-
if (!item) return item
|
|
114
|
-
const normalized = { ...item }
|
|
115
|
-
const cfEntries = extractAllCustomFieldEntries(item)
|
|
134
|
+
transformItem: (item: Record<string, unknown> | null | undefined) => {
|
|
135
|
+
if (!item) return item;
|
|
136
|
+
const normalized = { ...item };
|
|
137
|
+
const cfEntries = extractAllCustomFieldEntries(item);
|
|
116
138
|
for (const key of Object.keys(normalized)) {
|
|
117
|
-
if (key.startsWith(
|
|
139
|
+
if (key.startsWith("cf:")) delete normalized[key];
|
|
118
140
|
}
|
|
119
|
-
|
|
141
|
+
const quantityUnit = canonicalizeUnitCode(
|
|
142
|
+
normalized["quantity_unit"] ?? normalized["quantityUnit"],
|
|
143
|
+
);
|
|
144
|
+
const normalizedUnit =
|
|
145
|
+
canonicalizeUnitCode(
|
|
146
|
+
normalized["normalized_unit"] ?? normalized["normalizedUnit"],
|
|
147
|
+
) ?? quantityUnit;
|
|
148
|
+
return {
|
|
149
|
+
...normalized,
|
|
150
|
+
quantity_unit: quantityUnit,
|
|
151
|
+
normalized_unit: normalizedUnit,
|
|
152
|
+
...cfEntries,
|
|
153
|
+
};
|
|
120
154
|
},
|
|
121
155
|
},
|
|
122
156
|
actions: {
|
|
123
157
|
create: {
|
|
124
|
-
commandId:
|
|
158
|
+
commandId: "sales.orders.lines.upsert",
|
|
125
159
|
schema: rawBodySchema,
|
|
126
160
|
mapInput: async ({ raw, ctx }) => {
|
|
127
|
-
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
161
|
+
const { translate } = await resolveTranslations();
|
|
162
|
+
const payload = upsertSchema.parse(
|
|
163
|
+
withScopedPayload(resolveRawBody(raw) ?? {}, ctx, translate),
|
|
164
|
+
);
|
|
165
|
+
return { body: payload };
|
|
131
166
|
},
|
|
132
|
-
response: ({ result }) => ({
|
|
167
|
+
response: ({ result }) => ({
|
|
168
|
+
id: result?.lineId ?? null,
|
|
169
|
+
orderId: result?.orderId ?? null,
|
|
170
|
+
}),
|
|
133
171
|
status: 201,
|
|
134
172
|
},
|
|
135
173
|
update: {
|
|
136
|
-
commandId:
|
|
174
|
+
commandId: "sales.orders.lines.upsert",
|
|
137
175
|
schema: rawBodySchema,
|
|
138
176
|
mapInput: async ({ raw, ctx }) => {
|
|
139
|
-
const { translate } = await resolveTranslations()
|
|
140
|
-
const payload = upsertSchema.parse(
|
|
141
|
-
|
|
177
|
+
const { translate } = await resolveTranslations();
|
|
178
|
+
const payload = upsertSchema.parse(
|
|
179
|
+
withScopedPayload(resolveRawBody(raw) ?? {}, ctx, translate),
|
|
180
|
+
);
|
|
181
|
+
return { body: payload };
|
|
142
182
|
},
|
|
143
|
-
response: ({ result }) => ({
|
|
183
|
+
response: ({ result }) => ({
|
|
184
|
+
id: result?.lineId ?? null,
|
|
185
|
+
orderId: result?.orderId ?? null,
|
|
186
|
+
}),
|
|
144
187
|
},
|
|
145
188
|
delete: {
|
|
146
|
-
commandId:
|
|
189
|
+
commandId: "sales.orders.lines.delete",
|
|
147
190
|
schema: rawBodySchema,
|
|
148
191
|
mapInput: async ({ raw, ctx }) => {
|
|
149
|
-
const { translate } = await resolveTranslations()
|
|
150
|
-
const payload = deleteSchema.parse(
|
|
192
|
+
const { translate } = await resolveTranslations();
|
|
193
|
+
const payload = deleteSchema.parse(
|
|
194
|
+
withScopedPayload(resolveRawBody(raw) ?? {}, ctx, translate),
|
|
195
|
+
);
|
|
151
196
|
if (!payload.id || !payload.orderId) {
|
|
152
|
-
throw new CrudHttpError(400, {
|
|
197
|
+
throw new CrudHttpError(400, {
|
|
198
|
+
error: translate(
|
|
199
|
+
"sales.documents.detail.error",
|
|
200
|
+
"Document not found or inaccessible.",
|
|
201
|
+
),
|
|
202
|
+
});
|
|
153
203
|
}
|
|
154
|
-
return { body: payload }
|
|
204
|
+
return { body: payload };
|
|
155
205
|
},
|
|
156
206
|
response: () => ({ ok: true }),
|
|
157
207
|
},
|
|
158
208
|
},
|
|
159
|
-
})
|
|
209
|
+
});
|
|
160
210
|
|
|
161
|
-
const { GET, POST, PUT, DELETE } = crud
|
|
211
|
+
const { GET, POST, PUT, DELETE } = crud;
|
|
162
212
|
|
|
163
|
-
export { GET, POST, PUT, DELETE }
|
|
213
|
+
export { GET, POST, PUT, DELETE };
|
|
214
|
+
|
|
215
|
+
const uomSnapshotOpenApiSchema = z
|
|
216
|
+
.object({
|
|
217
|
+
version: z.literal(1),
|
|
218
|
+
productId: z.string().nullable(),
|
|
219
|
+
productVariantId: z.string().nullable(),
|
|
220
|
+
baseUnitCode: z.string().nullable(),
|
|
221
|
+
enteredUnitCode: z.string().nullable(),
|
|
222
|
+
enteredQuantity: z.string(),
|
|
223
|
+
toBaseFactor: z.string(),
|
|
224
|
+
normalizedQuantity: z.string(),
|
|
225
|
+
rounding: z.object({
|
|
226
|
+
mode: z.enum(["half_up", "down", "up"]),
|
|
227
|
+
scale: z.number().int(),
|
|
228
|
+
}),
|
|
229
|
+
source: z.object({
|
|
230
|
+
conversionId: z.string().nullable(),
|
|
231
|
+
resolvedAt: z.string(),
|
|
232
|
+
}),
|
|
233
|
+
unitPriceReference: z
|
|
234
|
+
.object({
|
|
235
|
+
enabled: z.boolean(),
|
|
236
|
+
referenceUnitCode: z.enum(REFERENCE_UNIT_CODES).nullable(),
|
|
237
|
+
baseQuantity: z.string().nullable(),
|
|
238
|
+
grossPerReference: z.string().nullable().optional(),
|
|
239
|
+
netPerReference: z.string().nullable().optional(),
|
|
240
|
+
})
|
|
241
|
+
.optional(),
|
|
242
|
+
})
|
|
243
|
+
.nullable()
|
|
244
|
+
.optional();
|
|
164
245
|
|
|
165
246
|
const orderLineSchema = z.object({
|
|
166
247
|
id: z.string().uuid(),
|
|
@@ -177,6 +258,9 @@ const orderLineSchema = z.object({
|
|
|
177
258
|
comment: z.string().nullable().optional(),
|
|
178
259
|
quantity: z.number(),
|
|
179
260
|
quantity_unit: z.string().nullable().optional(),
|
|
261
|
+
normalized_quantity: z.number(),
|
|
262
|
+
normalized_unit: z.string().nullable().optional(),
|
|
263
|
+
uom_snapshot: uomSnapshotOpenApiSchema,
|
|
180
264
|
currency_code: z.string(),
|
|
181
265
|
unit_price_net: z.number(),
|
|
182
266
|
unit_price_gross: z.number(),
|
|
@@ -193,25 +277,31 @@ const orderLineSchema = z.object({
|
|
|
193
277
|
custom_field_set_id: z.string().uuid().nullable().optional(),
|
|
194
278
|
created_at: z.string(),
|
|
195
279
|
updated_at: z.string(),
|
|
196
|
-
})
|
|
280
|
+
});
|
|
197
281
|
|
|
198
282
|
export const openApi = createSalesCrudOpenApi({
|
|
199
|
-
resourceName:
|
|
283
|
+
resourceName: "Order line",
|
|
200
284
|
querySchema: listSchema,
|
|
201
285
|
listResponseSchema: createPagedListResponseSchema(orderLineSchema),
|
|
202
286
|
create: {
|
|
203
287
|
schema: upsertSchema,
|
|
204
|
-
responseSchema: z.object({
|
|
205
|
-
|
|
288
|
+
responseSchema: z.object({
|
|
289
|
+
id: z.string().uuid().nullable(),
|
|
290
|
+
orderId: z.string().uuid().nullable(),
|
|
291
|
+
}),
|
|
292
|
+
description: "Creates an order line and recalculates totals.",
|
|
206
293
|
},
|
|
207
294
|
update: {
|
|
208
295
|
schema: upsertSchema,
|
|
209
|
-
responseSchema: z.object({
|
|
210
|
-
|
|
296
|
+
responseSchema: z.object({
|
|
297
|
+
id: z.string().uuid().nullable(),
|
|
298
|
+
orderId: z.string().uuid().nullable(),
|
|
299
|
+
}),
|
|
300
|
+
description: "Updates an order line and recalculates totals.",
|
|
211
301
|
},
|
|
212
302
|
del: {
|
|
213
303
|
schema: deleteSchema,
|
|
214
304
|
responseSchema: defaultOkResponseSchema,
|
|
215
|
-
description:
|
|
305
|
+
description: "Deletes an order line and recalculates totals.",
|
|
216
306
|
},
|
|
217
|
-
})
|
|
307
|
+
});
|