@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.
Files changed (184) hide show
  1. package/dist/generated/entities/catalog_product/index.js +16 -0
  2. package/dist/generated/entities/catalog_product/index.js.map +2 -2
  3. package/dist/generated/entities/catalog_product_unit_conversion/index.js +27 -0
  4. package/dist/generated/entities/catalog_product_unit_conversion/index.js.map +7 -0
  5. package/dist/generated/entities/sales_credit_memo_line/index.js +7 -1
  6. package/dist/generated/entities/sales_credit_memo_line/index.js.map +2 -2
  7. package/dist/generated/entities/sales_invoice_line/index.js +7 -1
  8. package/dist/generated/entities/sales_invoice_line/index.js.map +2 -2
  9. package/dist/generated/entities/sales_order_line/index.js +6 -0
  10. package/dist/generated/entities/sales_order_line/index.js.map +2 -2
  11. package/dist/generated/entities/sales_quote_line/index.js +6 -0
  12. package/dist/generated/entities/sales_quote_line/index.js.map +2 -2
  13. package/dist/generated/entities.ids.generated.js +1 -0
  14. package/dist/generated/entities.ids.generated.js.map +2 -2
  15. package/dist/generated/entity-fields-registry.js +2 -0
  16. package/dist/generated/entity-fields-registry.js.map +2 -2
  17. package/dist/modules/catalog/api/prices/route.js +123 -8
  18. package/dist/modules/catalog/api/prices/route.js.map +2 -2
  19. package/dist/modules/catalog/api/product-unit-conversions/route.js +194 -0
  20. package/dist/modules/catalog/api/product-unit-conversions/route.js.map +7 -0
  21. package/dist/modules/catalog/api/products/route.js +351 -201
  22. package/dist/modules/catalog/api/products/route.js.map +2 -2
  23. package/dist/modules/catalog/backend/catalog/products/[id]/page.js +1267 -497
  24. package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
  25. package/dist/modules/catalog/backend/catalog/products/create/page.js +733 -210
  26. package/dist/modules/catalog/backend/catalog/products/create/page.js.map +2 -2
  27. package/dist/modules/catalog/commands/index.js +1 -0
  28. package/dist/modules/catalog/commands/index.js.map +2 -2
  29. package/dist/modules/catalog/commands/productUnitConversions.js +503 -0
  30. package/dist/modules/catalog/commands/productUnitConversions.js.map +7 -0
  31. package/dist/modules/catalog/commands/products.js +355 -73
  32. package/dist/modules/catalog/commands/products.js.map +2 -2
  33. package/dist/modules/catalog/commands/shared.js +18 -4
  34. package/dist/modules/catalog/commands/shared.js.map +2 -2
  35. package/dist/modules/catalog/components/products/ProductUomSection.js +591 -0
  36. package/dist/modules/catalog/components/products/ProductUomSection.js.map +7 -0
  37. package/dist/modules/catalog/components/products/productForm.js +66 -5
  38. package/dist/modules/catalog/components/products/productForm.js.map +2 -2
  39. package/dist/modules/catalog/components/products/productFormUtils.js +68 -0
  40. package/dist/modules/catalog/components/products/productFormUtils.js.map +7 -0
  41. package/dist/modules/catalog/data/entities.js +86 -0
  42. package/dist/modules/catalog/data/entities.js.map +2 -2
  43. package/dist/modules/catalog/data/validators.js +65 -3
  44. package/dist/modules/catalog/data/validators.js.map +2 -2
  45. package/dist/modules/catalog/events.js +3 -0
  46. package/dist/modules/catalog/events.js.map +2 -2
  47. package/dist/modules/catalog/lib/unitCodes.js +7 -0
  48. package/dist/modules/catalog/lib/unitCodes.js.map +7 -0
  49. package/dist/modules/catalog/lib/unitResolution.js +53 -0
  50. package/dist/modules/catalog/lib/unitResolution.js.map +7 -0
  51. package/dist/modules/catalog/migrations/Migration20260218225422.js +19 -0
  52. package/dist/modules/catalog/migrations/Migration20260218225422.js.map +7 -0
  53. package/dist/modules/catalog/migrations/Migration20260219084500.js +27 -0
  54. package/dist/modules/catalog/migrations/Migration20260219084500.js.map +7 -0
  55. package/dist/modules/catalog/search.js +69 -1
  56. package/dist/modules/catalog/search.js.map +2 -2
  57. package/dist/modules/catalog/seed/examples.js +91 -42
  58. package/dist/modules/catalog/seed/examples.js.map +2 -2
  59. package/dist/modules/dashboards/seed/analytics.js +3 -0
  60. package/dist/modules/dashboards/seed/analytics.js.map +2 -2
  61. package/dist/modules/sales/api/order-lines/route.js +98 -15
  62. package/dist/modules/sales/api/order-lines/route.js.map +2 -2
  63. package/dist/modules/sales/api/quote-lines/route.js +101 -14
  64. package/dist/modules/sales/api/quote-lines/route.js.map +2 -2
  65. package/dist/modules/sales/api/quotes/public/[token]/route.js +87 -12
  66. package/dist/modules/sales/api/quotes/public/[token]/route.js.map +2 -2
  67. package/dist/modules/sales/commands/documents.js +1424 -260
  68. package/dist/modules/sales/commands/documents.js.map +3 -3
  69. package/dist/modules/sales/commands/shared.js +6 -2
  70. package/dist/modules/sales/commands/shared.js.map +2 -2
  71. package/dist/modules/sales/components/documents/ItemsSection.js +216 -86
  72. package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
  73. package/dist/modules/sales/components/documents/LineItemDialog.js +913 -241
  74. package/dist/modules/sales/components/documents/LineItemDialog.js.map +3 -3
  75. package/dist/modules/sales/components/documents/ShipmentsSection.js +15 -3
  76. package/dist/modules/sales/components/documents/ShipmentsSection.js.map +2 -2
  77. package/dist/modules/sales/data/entities.js +59 -3
  78. package/dist/modules/sales/data/entities.js.map +2 -2
  79. package/dist/modules/sales/data/validators.js +35 -0
  80. package/dist/modules/sales/data/validators.js.map +2 -2
  81. package/dist/modules/sales/frontend/quote/[token]/page.js +15 -1
  82. package/dist/modules/sales/frontend/quote/[token]/page.js.map +2 -2
  83. package/dist/modules/sales/migrations/Migration20260218225423.js +31 -0
  84. package/dist/modules/sales/migrations/Migration20260218225423.js.map +7 -0
  85. package/dist/modules/sales/migrations/Migration20260219084501.js +71 -0
  86. package/dist/modules/sales/migrations/Migration20260219084501.js.map +7 -0
  87. package/dist/modules/sales/search.js +28 -0
  88. package/dist/modules/sales/search.js.map +2 -2
  89. package/dist/modules/sales/seed/examples.js +14 -1
  90. package/dist/modules/sales/seed/examples.js.map +2 -2
  91. package/dist/modules/sales/widgets/injection/document-history/widget.client.js +1 -1
  92. package/dist/modules/sales/widgets/injection/document-history/widget.client.js.map +2 -2
  93. package/dist/modules/staff/backend/staff/team-members/[id]/page.js +28 -15
  94. package/dist/modules/staff/backend/staff/team-members/[id]/page.js.map +2 -2
  95. package/dist/modules/staff/translations.js +9 -0
  96. package/dist/modules/staff/translations.js.map +7 -0
  97. package/dist/modules/translations/components/TranslationDrawerAction.js +97 -0
  98. package/dist/modules/translations/components/TranslationDrawerAction.js.map +7 -0
  99. package/dist/modules/translations/lib/extract-record-id.js +31 -2
  100. package/dist/modules/translations/lib/extract-record-id.js.map +2 -2
  101. package/dist/modules/translations/lib/resolve-field-list.js +3 -0
  102. package/dist/modules/translations/lib/resolve-field-list.js.map +2 -2
  103. package/dist/modules/translations/widgets/injection/translation-manager/widget.client.js +105 -36
  104. package/dist/modules/translations/widgets/injection/translation-manager/widget.client.js.map +2 -2
  105. package/dist/modules/translations/widgets/injection-table.js +18 -29
  106. package/dist/modules/translations/widgets/injection-table.js.map +2 -2
  107. package/generated/entities/catalog_product/index.ts +8 -0
  108. package/generated/entities/catalog_product_unit_conversion/index.ts +12 -0
  109. package/generated/entities/sales_credit_memo_line/index.ts +3 -0
  110. package/generated/entities/sales_invoice_line/index.ts +3 -0
  111. package/generated/entities/sales_order_line/index.ts +3 -0
  112. package/generated/entities/sales_quote_line/index.ts +3 -0
  113. package/generated/entities.ids.generated.ts +1 -0
  114. package/generated/entity-fields-registry.ts +2 -0
  115. package/package.json +2 -2
  116. package/src/modules/auth/i18n/de.json +1 -1
  117. package/src/modules/auth/i18n/en.json +1 -1
  118. package/src/modules/auth/i18n/es.json +1 -1
  119. package/src/modules/auth/i18n/pl.json +1 -1
  120. package/src/modules/catalog/api/prices/route.ts +213 -81
  121. package/src/modules/catalog/api/product-unit-conversions/route.ts +195 -0
  122. package/src/modules/catalog/api/products/route.ts +638 -402
  123. package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +2085 -1072
  124. package/src/modules/catalog/backend/catalog/products/create/page.tsx +1288 -593
  125. package/src/modules/catalog/commands/index.ts +1 -0
  126. package/src/modules/catalog/commands/productUnitConversions.ts +626 -0
  127. package/src/modules/catalog/commands/products.ts +1151 -693
  128. package/src/modules/catalog/commands/shared.ts +19 -5
  129. package/src/modules/catalog/components/products/ProductUomSection.tsx +745 -0
  130. package/src/modules/catalog/components/products/productForm.ts +369 -256
  131. package/src/modules/catalog/components/products/productFormUtils.ts +82 -0
  132. package/src/modules/catalog/data/entities.ts +82 -1
  133. package/src/modules/catalog/data/validators.ts +118 -34
  134. package/src/modules/catalog/events.ts +3 -0
  135. package/src/modules/catalog/i18n/de.json +56 -0
  136. package/src/modules/catalog/i18n/en.json +56 -0
  137. package/src/modules/catalog/i18n/es.json +56 -0
  138. package/src/modules/catalog/i18n/pl.json +56 -0
  139. package/src/modules/catalog/lib/unitCodes.ts +1 -0
  140. package/src/modules/catalog/lib/unitResolution.ts +62 -0
  141. package/src/modules/catalog/migrations/.snapshot-open-mercato.json +245 -0
  142. package/src/modules/catalog/migrations/Migration20260218225422.ts +21 -0
  143. package/src/modules/catalog/migrations/Migration20260219084500.ts +26 -0
  144. package/src/modules/catalog/search.ts +73 -1
  145. package/src/modules/catalog/seed/examples.ts +552 -479
  146. package/src/modules/dashboards/i18n/de.json +1 -1
  147. package/src/modules/dashboards/i18n/en.json +1 -1
  148. package/src/modules/dashboards/i18n/es.json +1 -1
  149. package/src/modules/dashboards/i18n/pl.json +1 -1
  150. package/src/modules/dashboards/seed/analytics.ts +3 -0
  151. package/src/modules/sales/api/order-lines/route.ts +158 -68
  152. package/src/modules/sales/api/quote-lines/route.ts +161 -67
  153. package/src/modules/sales/api/quotes/public/[token]/route.ts +122 -36
  154. package/src/modules/sales/commands/documents.ts +4250 -2424
  155. package/src/modules/sales/commands/shared.ts +7 -2
  156. package/src/modules/sales/components/documents/ItemsSection.tsx +580 -310
  157. package/src/modules/sales/components/documents/LineItemDialog.tsx +1988 -833
  158. package/src/modules/sales/components/documents/ShipmentsSection.tsx +17 -3
  159. package/src/modules/sales/components/documents/lineItemTypes.ts +6 -0
  160. package/src/modules/sales/data/entities.ts +53 -0
  161. package/src/modules/sales/data/validators.ts +36 -0
  162. package/src/modules/sales/frontend/quote/[token]/page.tsx +25 -1
  163. package/src/modules/sales/i18n/de.json +23 -3
  164. package/src/modules/sales/i18n/en.json +23 -3
  165. package/src/modules/sales/i18n/es.json +23 -3
  166. package/src/modules/sales/i18n/pl.json +23 -3
  167. package/src/modules/sales/lib/types.ts +30 -0
  168. package/src/modules/sales/migrations/.snapshot-open-mercato.json +172 -0
  169. package/src/modules/sales/migrations/Migration20260218225423.ts +37 -0
  170. package/src/modules/sales/migrations/Migration20260219084501.ts +73 -0
  171. package/src/modules/sales/search.ts +28 -0
  172. package/src/modules/sales/seed/examples.ts +20 -1
  173. package/src/modules/sales/widgets/injection/document-history/widget.client.tsx +1 -1
  174. package/src/modules/staff/backend/staff/team-members/[id]/page.tsx +8 -0
  175. package/src/modules/staff/translations.ts +5 -0
  176. package/src/modules/translations/components/TranslationDrawerAction.tsx +107 -0
  177. package/src/modules/translations/lib/extract-record-id.ts +47 -3
  178. package/src/modules/translations/lib/resolve-field-list.ts +4 -0
  179. package/src/modules/translations/widgets/injection/translation-manager/widget.client.tsx +108 -36
  180. package/src/modules/translations/widgets/injection-table.ts +19 -33
  181. package/src/modules/workflows/i18n/de.json +4 -4
  182. package/src/modules/workflows/i18n/en.json +4 -4
  183. package/src/modules/workflows/i18n/es.json +4 -4
  184. package/src/modules/workflows/i18n/pl.json +4 -4
@@ -1,9 +1,17 @@
1
1
  import { z } from "zod";
2
2
  import { makeCrudRoute } from "@open-mercato/shared/lib/crud/factory";
3
3
  import { CrudHttpError } from "@open-mercato/shared/lib/crud/errors";
4
- import { buildCustomFieldFiltersFromQuery, extractAllCustomFieldEntries } from "@open-mercato/shared/lib/crud/custom-fields";
4
+ import {
5
+ buildCustomFieldFiltersFromQuery,
6
+ extractAllCustomFieldEntries
7
+ } from "@open-mercato/shared/lib/crud/custom-fields";
5
8
  import { resolveTranslations } from "@open-mercato/shared/lib/i18n/server";
6
- import { CatalogProductPrice } from "../../data/entities.js";
9
+ import {
10
+ CatalogProduct,
11
+ CatalogProductPrice,
12
+ CatalogProductUnitConversion,
13
+ CatalogProductVariant
14
+ } from "../../data/entities.js";
7
15
  import { priceCreateSchema, priceUpdateSchema } from "../../data/validators.js";
8
16
  import { parseScopedCommandInput, resolveCrudRecordId } from "../utils.js";
9
17
  import { E } from "../../../../generated/entities.ids.generated.js";
@@ -13,6 +21,11 @@ import {
13
21
  createPagedListResponseSchema,
14
22
  defaultOkResponseSchema
15
23
  } from "../openapi.js";
24
+ import { toUnitLookupKey } from "../../lib/unitCodes.js";
25
+ import {
26
+ findWithDecryption,
27
+ findOneWithDecryption
28
+ } from "@open-mercato/shared/lib/encryption/find";
16
29
  const rawBodySchema = z.object({}).passthrough();
17
30
  const listSchema = z.object({
18
31
  page: z.coerce.number().min(1).default(1),
@@ -28,6 +41,8 @@ const listSchema = z.object({
28
41
  userGroupId: z.string().uuid().optional(),
29
42
  customerId: z.string().uuid().optional(),
30
43
  customerGroupId: z.string().uuid().optional(),
44
+ quantity: z.coerce.number().min(1).max(1e5).optional(),
45
+ quantityUnit: z.string().trim().max(50).optional(),
31
46
  withDeleted: z.coerce.boolean().optional(),
32
47
  sortField: z.string().optional(),
33
48
  sortDir: z.enum(["asc", "desc"]).optional()
@@ -39,6 +54,68 @@ const routeMetadata = {
39
54
  DELETE: { requireAuth: true, requireFeatures: ["catalog.pricing.manage"] }
40
55
  };
41
56
  const metadata = routeMetadata;
57
+ async function resolveNormalizedQuantityForFilter(params) {
58
+ const quantity = params.quantity;
59
+ const quantityUnitKey = toUnitLookupKey(params.quantityUnit);
60
+ if (!params.productId && !params.variantId || !quantityUnitKey)
61
+ return quantity;
62
+ if (!params.organizationId || !params.tenantId) return quantity;
63
+ let targetProductId = params.productId;
64
+ if (!targetProductId && params.variantId) {
65
+ const variant = await findOneWithDecryption(
66
+ params.em,
67
+ CatalogProductVariant,
68
+ {
69
+ id: params.variantId,
70
+ organizationId: params.organizationId,
71
+ tenantId: params.tenantId,
72
+ deletedAt: null
73
+ },
74
+ { fields: ["id", "product"] }
75
+ );
76
+ if (variant) {
77
+ targetProductId = typeof variant.product === "string" ? variant.product : variant.product?.id ?? null;
78
+ }
79
+ }
80
+ if (!targetProductId) return quantity;
81
+ const product = await findOneWithDecryption(
82
+ params.em,
83
+ CatalogProduct,
84
+ {
85
+ id: targetProductId,
86
+ organizationId: params.organizationId,
87
+ tenantId: params.tenantId,
88
+ deletedAt: null
89
+ },
90
+ { fields: ["id", "defaultUnit", "uomRoundingScale"] }
91
+ );
92
+ if (!product) return quantity;
93
+ const baseUnitKey = toUnitLookupKey(product.defaultUnit);
94
+ if (!baseUnitKey || baseUnitKey === quantityUnitKey) return quantity;
95
+ const conversions = await findWithDecryption(
96
+ params.em,
97
+ CatalogProductUnitConversion,
98
+ {
99
+ product: product.id,
100
+ organizationId: params.organizationId,
101
+ tenantId: params.tenantId,
102
+ isActive: true,
103
+ deletedAt: null
104
+ },
105
+ { fields: ["id", "unitCode", "toBaseFactor"] }
106
+ );
107
+ const conversion = conversions.find(
108
+ (entry) => toUnitLookupKey(entry.unitCode) === quantityUnitKey
109
+ );
110
+ if (!conversion) return quantity;
111
+ const factor = Number(conversion.toBaseFactor);
112
+ if (!Number.isFinite(factor) || factor <= 0) return quantity;
113
+ const rawNormalized = quantity * factor;
114
+ const scale = Number(product.uomRoundingScale ?? 4);
115
+ const pow = Math.pow(10, scale);
116
+ const normalized = Math.round(rawNormalized * pow) / pow;
117
+ return Number.isFinite(normalized) && normalized > 0 ? normalized : quantity;
118
+ }
42
119
  async function buildPriceFilters(query) {
43
120
  const filters = {};
44
121
  if (query.productId) {
@@ -65,7 +142,8 @@ async function buildPriceFilters(query) {
65
142
  if (query.userId) filters.user_id = { $eq: query.userId };
66
143
  if (query.userGroupId) filters.user_group_id = { $eq: query.userGroupId };
67
144
  if (query.customerId) filters.customer_id = { $eq: query.customerId };
68
- if (query.customerGroupId) filters.customer_group_id = { $eq: query.customerGroupId };
145
+ if (query.customerGroupId)
146
+ filters.customer_group_id = { $eq: query.customerGroupId };
69
147
  return filters;
70
148
  }
71
149
  const crud = makeCrudRoute({
@@ -77,6 +155,9 @@ const crud = makeCrudRoute({
77
155
  tenantField: "tenantId",
78
156
  softDeleteField: null
79
157
  },
158
+ indexer: {
159
+ entityType: E.catalog.catalog_product_price
160
+ },
80
161
  list: {
81
162
  schema: listSchema,
82
163
  entityId: E.catalog.catalog_product_price,
@@ -116,8 +197,9 @@ const crud = makeCrudRoute({
116
197
  buildFilters: async (query, ctx) => {
117
198
  const filters = await buildPriceFilters(query);
118
199
  const tenantId = ctx.auth?.tenantId ?? null;
200
+ const organizationId = ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null;
201
+ const em = ctx.container.resolve("em");
119
202
  try {
120
- const em = ctx.container.resolve("em");
121
203
  const cfFilters = await buildCustomFieldFiltersFromQuery({
122
204
  entityIds: [E.catalog.catalog_product_price],
123
205
  query,
@@ -125,7 +207,24 @@ const crud = makeCrudRoute({
125
207
  tenantId
126
208
  });
127
209
  Object.assign(filters, cfFilters);
128
- } catch {
210
+ } catch (err) {
211
+ if (process.env.NODE_ENV === "development") console.warn("[catalog:prices] custom field filter error", err);
212
+ }
213
+ if (typeof query.quantity === "number" && Number.isFinite(query.quantity) && query.quantity > 0) {
214
+ const normalizedQuantity = await resolveNormalizedQuantityForFilter({
215
+ em,
216
+ organizationId,
217
+ tenantId,
218
+ productId: query.productId,
219
+ variantId: query.variantId,
220
+ quantity: query.quantity,
221
+ quantityUnit: query.quantityUnit
222
+ });
223
+ filters.min_quantity = { $lte: normalizedQuantity };
224
+ filters.$or = [
225
+ { max_quantity: null },
226
+ { max_quantity: { $gte: normalizedQuantity } }
227
+ ];
129
228
  }
130
229
  return filters;
131
230
  },
@@ -145,7 +244,12 @@ const crud = makeCrudRoute({
145
244
  schema: rawBodySchema,
146
245
  mapInput: async ({ raw, ctx }) => {
147
246
  const { translate } = await resolveTranslations();
148
- return parseScopedCommandInput(priceCreateSchema, raw ?? {}, ctx, translate);
247
+ return parseScopedCommandInput(
248
+ priceCreateSchema,
249
+ raw ?? {},
250
+ ctx,
251
+ translate
252
+ );
149
253
  },
150
254
  response: ({ result }) => ({ id: result?.priceId ?? result?.id ?? null }),
151
255
  status: 201
@@ -155,7 +259,12 @@ const crud = makeCrudRoute({
155
259
  schema: rawBodySchema,
156
260
  mapInput: async ({ raw, ctx }) => {
157
261
  const { translate } = await resolveTranslations();
158
- return parseScopedCommandInput(priceUpdateSchema, raw ?? {}, ctx, translate);
262
+ return parseScopedCommandInput(
263
+ priceUpdateSchema,
264
+ raw ?? {},
265
+ ctx,
266
+ translate
267
+ );
159
268
  },
160
269
  response: () => ({ ok: true })
161
270
  },
@@ -165,7 +274,13 @@ const crud = makeCrudRoute({
165
274
  mapInput: async ({ parsed, ctx }) => {
166
275
  const { translate } = await resolveTranslations();
167
276
  const id = resolveCrudRecordId(parsed, ctx, translate);
168
- if (!id) throw new CrudHttpError(400, { error: translate("catalog.errors.id_required", "Price id is required.") });
277
+ if (!id)
278
+ throw new CrudHttpError(400, {
279
+ error: translate(
280
+ "catalog.errors.id_required",
281
+ "Price id is required."
282
+ )
283
+ });
169
284
  return { id };
170
285
  },
171
286
  response: () => ({ ok: true })
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/catalog/api/prices/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 { buildCustomFieldFiltersFromQuery, extractAllCustomFieldEntries } from '@open-mercato/shared/lib/crud/custom-fields'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { CatalogProductPrice } from '../../data/entities'\nimport { priceCreateSchema, priceUpdateSchema } from '../../data/validators'\nimport { parseScopedCommandInput, resolveCrudRecordId } from '../utils'\nimport { E } from '#generated/entities.ids.generated'\nimport * as FP from '#generated/entities/catalog_product_price'\nimport {\n createCatalogCrudOpenApi,\n createPagedListResponseSchema,\n defaultOkResponseSchema,\n} from '../openapi'\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(100).default(50),\n productId: z.string().uuid().optional(),\n variantId: z.string().uuid().optional(),\n offerId: z.string().uuid().optional(),\n channelId: z.string().uuid().optional(),\n currencyCode: z.string().optional(),\n priceKindId: z.string().uuid().optional(),\n kind: z.string().optional(),\n userId: z.string().uuid().optional(),\n userGroupId: z.string().uuid().optional(),\n customerId: z.string().uuid().optional(),\n customerGroupId: z.string().uuid().optional(),\n withDeleted: z.coerce.boolean().optional(),\n sortField: z.string().optional(),\n sortDir: z.enum(['asc', 'desc']).optional(),\n })\n .passthrough()\n\ntype PriceQuery = z.infer<typeof listSchema>\n\nconst routeMetadata = {\n GET: { requireAuth: true, requireFeatures: ['catalog.products.view'] },\n POST: { requireAuth: true, requireFeatures: ['catalog.pricing.manage'] },\n PUT: { requireAuth: true, requireFeatures: ['catalog.pricing.manage'] },\n DELETE: { requireAuth: true, requireFeatures: ['catalog.pricing.manage'] },\n}\n\nexport const metadata = routeMetadata\n\nexport async function buildPriceFilters(\n query: PriceQuery\n): Promise<Record<string, unknown>> {\n const filters: Record<string, unknown> = {}\n if (query.productId) {\n filters.product_id = { $eq: query.productId }\n }\n if (query.variantId) {\n filters.variant_id = { $eq: query.variantId }\n }\n if (query.offerId) {\n filters.offer_id = { $eq: query.offerId }\n }\n if (query.channelId) {\n filters.channel_id = { $eq: query.channelId }\n }\n if (query.currencyCode) {\n filters.currency_code = { $eq: query.currencyCode.trim().toUpperCase() }\n }\n if (query.priceKindId) {\n filters.price_kind_id = { $eq: query.priceKindId }\n }\n if (query.kind) {\n filters.kind = { $eq: query.kind }\n }\n if (query.userId) filters.user_id = { $eq: query.userId }\n if (query.userGroupId) filters.user_group_id = { $eq: query.userGroupId }\n if (query.customerId) filters.customer_id = { $eq: query.customerId }\n if (query.customerGroupId) filters.customer_group_id = { $eq: query.customerGroupId }\n return filters\n}\n\nconst crud = makeCrudRoute({\n metadata: routeMetadata,\n orm: {\n entity: CatalogProductPrice,\n idField: 'id',\n orgField: 'organizationId',\n tenantField: 'tenantId',\n softDeleteField: null,\n },\n list: {\n schema: listSchema,\n entityId: E.catalog.catalog_product_price,\n fields: [\n FP.id,\n 'product_id',\n 'variant_id',\n 'offer_id',\n FP.currency_code,\n 'price_kind_id',\n FP.kind,\n FP.min_quantity,\n FP.max_quantity,\n FP.unit_price_net,\n FP.unit_price_gross,\n FP.tax_rate,\n FP.tax_amount,\n FP.channel_id,\n FP.user_id,\n FP.user_group_id,\n FP.customer_id,\n FP.customer_group_id,\n FP.metadata,\n FP.starts_at,\n FP.ends_at,\n FP.created_at,\n FP.updated_at,\n ],\n sortFieldMap: {\n currencyCode: FP.currency_code,\n priceKindId: 'price_kind_id',\n kind: FP.kind,\n minQuantity: FP.min_quantity,\n createdAt: FP.created_at,\n updatedAt: FP.updated_at,\n },\n buildFilters: async (query, ctx) => {\n const filters = await buildPriceFilters(query)\n const tenantId = ctx.auth?.tenantId ?? null\n try {\n const em = ctx.container.resolve('em') as EntityManager\n const cfFilters = await buildCustomFieldFiltersFromQuery({\n entityIds: [E.catalog.catalog_product_price],\n query,\n em,\n tenantId,\n })\n Object.assign(filters, cfFilters)\n } catch {\n // ignore\n }\n return filters\n },\n transformItem: (item: any) => {\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 return { ...normalized, ...cfEntries }\n },\n },\n actions: {\n create: {\n commandId: 'catalog.prices.create',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n return parseScopedCommandInput(priceCreateSchema, raw ?? {}, ctx, translate)\n },\n response: ({ result }) => ({ id: result?.priceId ?? result?.id ?? null }),\n status: 201,\n },\n update: {\n commandId: 'catalog.prices.update',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n return parseScopedCommandInput(priceUpdateSchema, raw ?? {}, ctx, translate)\n },\n response: () => ({ ok: true }),\n },\n delete: {\n commandId: 'catalog.prices.delete',\n schema: rawBodySchema,\n mapInput: async ({ parsed, ctx }) => {\n const { translate } = await resolveTranslations()\n const id = resolveCrudRecordId(parsed, ctx, translate)\n if (!id) throw new CrudHttpError(400, { error: translate('catalog.errors.id_required', 'Price id is required.') })\n return { id }\n },\n response: () => ({ ok: true }),\n },\n },\n})\n\nexport const GET = crud.GET\nexport const POST = crud.POST\nexport const PUT = crud.PUT\nexport const DELETE = crud.DELETE\n\nconst priceListItemSchema = z.object({\n id: z.string().uuid(),\n product_id: z.string().uuid().nullable().optional(),\n variant_id: z.string().uuid().nullable().optional(),\n offer_id: z.string().uuid().nullable().optional(),\n currency_code: z.string().nullable().optional(),\n price_kind_id: z.string().uuid().nullable().optional(),\n kind: z.string().nullable().optional(),\n min_quantity: z.number().nullable().optional(),\n max_quantity: z.number().nullable().optional(),\n unit_price_net: z.number().nullable().optional(),\n unit_price_gross: z.number().nullable().optional(),\n tax_rate: z.number().nullable().optional(),\n tax_amount: z.number().nullable().optional(),\n channel_id: z.string().uuid().nullable().optional(),\n user_id: z.string().uuid().nullable().optional(),\n user_group_id: z.string().uuid().nullable().optional(),\n customer_id: z.string().uuid().nullable().optional(),\n customer_group_id: z.string().uuid().nullable().optional(),\n metadata: z.record(z.string(), z.unknown()).nullable().optional(),\n starts_at: z.string().nullable().optional(),\n ends_at: z.string().nullable().optional(),\n created_at: z.string().nullable().optional(),\n updated_at: z.string().nullable().optional(),\n})\n\nexport const openApi = createCatalogCrudOpenApi({\n resourceName: 'Price',\n pluralName: 'Prices',\n querySchema: listSchema,\n listResponseSchema: createPagedListResponseSchema(priceListItemSchema),\n create: {\n schema: priceCreateSchema,\n description: 'Creates a new price entry for a product or variant.',\n },\n update: {\n schema: priceUpdateSchema,\n responseSchema: defaultOkResponseSchema,\n description: 'Updates an existing price by id.',\n },\n del: {\n schema: z.object({ id: z.string().uuid() }),\n responseSchema: defaultOkResponseSchema,\n description: 'Deletes a price by id.',\n },\n})\n"],
5
- "mappings": "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",
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 {\n buildCustomFieldFiltersFromQuery,\n extractAllCustomFieldEntries,\n} from \"@open-mercato/shared/lib/crud/custom-fields\";\nimport { resolveTranslations } from \"@open-mercato/shared/lib/i18n/server\";\nimport {\n CatalogProduct,\n CatalogProductPrice,\n CatalogProductUnitConversion,\n CatalogProductVariant,\n} from \"../../data/entities\";\nimport { priceCreateSchema, priceUpdateSchema } from \"../../data/validators\";\nimport { parseScopedCommandInput, resolveCrudRecordId } from \"../utils\";\nimport { E } from \"#generated/entities.ids.generated\";\nimport * as FP from \"#generated/entities/catalog_product_price\";\nimport {\n createCatalogCrudOpenApi,\n createPagedListResponseSchema,\n defaultOkResponseSchema,\n} from \"../openapi\";\nimport { toUnitLookupKey } from \"../../lib/unitCodes\";\nimport {\n findWithDecryption,\n findOneWithDecryption,\n} 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(100).default(50),\n productId: z.string().uuid().optional(),\n variantId: z.string().uuid().optional(),\n offerId: z.string().uuid().optional(),\n channelId: z.string().uuid().optional(),\n currencyCode: z.string().optional(),\n priceKindId: z.string().uuid().optional(),\n kind: z.string().optional(),\n userId: z.string().uuid().optional(),\n userGroupId: z.string().uuid().optional(),\n customerId: z.string().uuid().optional(),\n customerGroupId: z.string().uuid().optional(),\n quantity: z.coerce.number().min(1).max(100000).optional(),\n quantityUnit: z.string().trim().max(50).optional(),\n withDeleted: z.coerce.boolean().optional(),\n sortField: z.string().optional(),\n sortDir: z.enum([\"asc\", \"desc\"]).optional(),\n })\n .passthrough();\n\ntype PriceQuery = z.infer<typeof listSchema>;\n\nconst routeMetadata = {\n GET: { requireAuth: true, requireFeatures: [\"catalog.products.view\"] },\n POST: { requireAuth: true, requireFeatures: [\"catalog.pricing.manage\"] },\n PUT: { requireAuth: true, requireFeatures: [\"catalog.pricing.manage\"] },\n DELETE: { requireAuth: true, requireFeatures: [\"catalog.pricing.manage\"] },\n};\n\nexport const metadata = routeMetadata;\n\nasync function resolveNormalizedQuantityForFilter(params: {\n em: EntityManager;\n organizationId: string | null;\n tenantId: string | null;\n productId?: string;\n variantId?: string;\n quantity: number;\n quantityUnit?: string;\n}): Promise<number> {\n const quantity = params.quantity;\n const quantityUnitKey = toUnitLookupKey(params.quantityUnit);\n if ((!params.productId && !params.variantId) || !quantityUnitKey)\n return quantity;\n if (!params.organizationId || !params.tenantId) return quantity;\n let targetProductId = params.productId;\n if (!targetProductId && params.variantId) {\n const variant = await findOneWithDecryption(\n params.em,\n CatalogProductVariant,\n {\n id: params.variantId,\n organizationId: params.organizationId,\n tenantId: params.tenantId,\n deletedAt: null,\n },\n { fields: [\"id\", \"product\"] },\n );\n if (variant) {\n targetProductId =\n typeof variant.product === \"string\"\n ? variant.product\n : (variant.product?.id ?? null);\n }\n }\n if (!targetProductId) return quantity;\n const product = await findOneWithDecryption(\n params.em,\n CatalogProduct,\n {\n id: targetProductId,\n organizationId: params.organizationId,\n tenantId: params.tenantId,\n deletedAt: null,\n },\n { fields: [\"id\", \"defaultUnit\", \"uomRoundingScale\"] },\n );\n if (!product) return quantity;\n const baseUnitKey = toUnitLookupKey(product.defaultUnit);\n if (!baseUnitKey || baseUnitKey === quantityUnitKey) return quantity;\n const conversions = await findWithDecryption(\n params.em,\n CatalogProductUnitConversion,\n {\n product: product.id,\n organizationId: params.organizationId,\n tenantId: params.tenantId,\n isActive: true,\n deletedAt: null,\n },\n { fields: [\"id\", \"unitCode\", \"toBaseFactor\"] },\n );\n const conversion = conversions.find(\n (entry) => toUnitLookupKey(entry.unitCode) === quantityUnitKey,\n );\n if (!conversion) return quantity;\n const factor = Number(conversion.toBaseFactor);\n if (!Number.isFinite(factor) || factor <= 0) return quantity;\n const rawNormalized = quantity * factor;\n const scale = Number(product.uomRoundingScale ?? 4);\n const pow = Math.pow(10, scale);\n const normalized = Math.round(rawNormalized * pow) / pow;\n return Number.isFinite(normalized) && normalized > 0 ? normalized : quantity;\n}\n\nexport async function buildPriceFilters(\n query: PriceQuery,\n): Promise<Record<string, unknown>> {\n const filters: Record<string, unknown> = {};\n if (query.productId) {\n filters.product_id = { $eq: query.productId };\n }\n if (query.variantId) {\n filters.variant_id = { $eq: query.variantId };\n }\n if (query.offerId) {\n filters.offer_id = { $eq: query.offerId };\n }\n if (query.channelId) {\n filters.channel_id = { $eq: query.channelId };\n }\n if (query.currencyCode) {\n filters.currency_code = { $eq: query.currencyCode.trim().toUpperCase() };\n }\n if (query.priceKindId) {\n filters.price_kind_id = { $eq: query.priceKindId };\n }\n if (query.kind) {\n filters.kind = { $eq: query.kind };\n }\n if (query.userId) filters.user_id = { $eq: query.userId };\n if (query.userGroupId) filters.user_group_id = { $eq: query.userGroupId };\n if (query.customerId) filters.customer_id = { $eq: query.customerId };\n if (query.customerGroupId)\n filters.customer_group_id = { $eq: query.customerGroupId };\n return filters;\n}\n\nconst crud = makeCrudRoute({\n metadata: routeMetadata,\n orm: {\n entity: CatalogProductPrice,\n idField: \"id\",\n orgField: \"organizationId\",\n tenantField: \"tenantId\",\n softDeleteField: null,\n },\n indexer: {\n entityType: E.catalog.catalog_product_price,\n },\n list: {\n schema: listSchema,\n entityId: E.catalog.catalog_product_price,\n fields: [\n FP.id,\n \"product_id\",\n \"variant_id\",\n \"offer_id\",\n FP.currency_code,\n \"price_kind_id\",\n FP.kind,\n FP.min_quantity,\n FP.max_quantity,\n FP.unit_price_net,\n FP.unit_price_gross,\n FP.tax_rate,\n FP.tax_amount,\n FP.channel_id,\n FP.user_id,\n FP.user_group_id,\n FP.customer_id,\n FP.customer_group_id,\n FP.metadata,\n FP.starts_at,\n FP.ends_at,\n FP.created_at,\n FP.updated_at,\n ],\n sortFieldMap: {\n currencyCode: FP.currency_code,\n priceKindId: \"price_kind_id\",\n kind: FP.kind,\n minQuantity: FP.min_quantity,\n createdAt: FP.created_at,\n updatedAt: FP.updated_at,\n },\n buildFilters: async (query, ctx) => {\n const filters = await buildPriceFilters(query);\n const tenantId = ctx.auth?.tenantId ?? null;\n const organizationId =\n ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null;\n const em = ctx.container.resolve(\"em\") as EntityManager;\n try {\n const cfFilters = await buildCustomFieldFiltersFromQuery({\n entityIds: [E.catalog.catalog_product_price],\n query,\n em,\n tenantId,\n });\n Object.assign(filters, cfFilters);\n } catch (err) {\n // Custom field filter parsing may fail for non-existent or misconfigured fields.\n if (process.env.NODE_ENV === 'development') console.warn('[catalog:prices] custom field filter error', err);\n }\n if (\n typeof query.quantity === \"number\" &&\n Number.isFinite(query.quantity) &&\n query.quantity > 0\n ) {\n const normalizedQuantity = await resolveNormalizedQuantityForFilter({\n em,\n organizationId,\n tenantId,\n productId: query.productId,\n variantId: query.variantId,\n quantity: query.quantity,\n quantityUnit: query.quantityUnit,\n });\n filters.min_quantity = { $lte: normalizedQuantity };\n filters.$or = [\n { max_quantity: null },\n { max_quantity: { $gte: normalizedQuantity } },\n ];\n }\n return filters;\n },\n 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 return { ...normalized, ...cfEntries };\n },\n },\n actions: {\n create: {\n commandId: \"catalog.prices.create\",\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations();\n return parseScopedCommandInput(\n priceCreateSchema,\n raw ?? {},\n ctx,\n translate,\n );\n },\n response: ({ result }) => ({ id: result?.priceId ?? result?.id ?? null }),\n status: 201,\n },\n update: {\n commandId: \"catalog.prices.update\",\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations();\n return parseScopedCommandInput(\n priceUpdateSchema,\n raw ?? {},\n ctx,\n translate,\n );\n },\n response: () => ({ ok: true }),\n },\n delete: {\n commandId: \"catalog.prices.delete\",\n schema: rawBodySchema,\n mapInput: async ({ parsed, ctx }) => {\n const { translate } = await resolveTranslations();\n const id = resolveCrudRecordId(parsed, ctx, translate);\n if (!id)\n throw new CrudHttpError(400, {\n error: translate(\n \"catalog.errors.id_required\",\n \"Price id is required.\",\n ),\n });\n return { id };\n },\n response: () => ({ ok: true }),\n },\n },\n});\n\nexport const GET = crud.GET;\nexport const POST = crud.POST;\nexport const PUT = crud.PUT;\nexport const DELETE = crud.DELETE;\n\nconst priceListItemSchema = z.object({\n id: z.string().uuid(),\n product_id: z.string().uuid().nullable().optional(),\n variant_id: z.string().uuid().nullable().optional(),\n offer_id: z.string().uuid().nullable().optional(),\n currency_code: z.string().nullable().optional(),\n price_kind_id: z.string().uuid().nullable().optional(),\n kind: z.string().nullable().optional(),\n min_quantity: z.number().nullable().optional(),\n max_quantity: z.number().nullable().optional(),\n unit_price_net: z.number().nullable().optional(),\n unit_price_gross: z.number().nullable().optional(),\n tax_rate: z.number().nullable().optional(),\n tax_amount: z.number().nullable().optional(),\n channel_id: z.string().uuid().nullable().optional(),\n user_id: z.string().uuid().nullable().optional(),\n user_group_id: z.string().uuid().nullable().optional(),\n customer_id: z.string().uuid().nullable().optional(),\n customer_group_id: z.string().uuid().nullable().optional(),\n metadata: z.record(z.string(), z.unknown()).nullable().optional(),\n starts_at: z.string().nullable().optional(),\n ends_at: z.string().nullable().optional(),\n created_at: z.string().nullable().optional(),\n updated_at: z.string().nullable().optional(),\n});\n\nexport const openApi = createCatalogCrudOpenApi({\n resourceName: \"Price\",\n pluralName: \"Prices\",\n querySchema: listSchema,\n listResponseSchema: createPagedListResponseSchema(priceListItemSchema),\n create: {\n schema: priceCreateSchema,\n description: \"Creates a new price entry for a product or variant.\",\n },\n update: {\n schema: priceUpdateSchema,\n responseSchema: defaultOkResponseSchema,\n description: \"Updates an existing price by id.\",\n },\n del: {\n schema: z.object({ id: z.string().uuid() }),\n responseSchema: defaultOkResponseSchema,\n description: \"Deletes a price by id.\",\n },\n});\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,194 @@
1
+ import { z } from "zod";
2
+ import { makeCrudRoute } from "@open-mercato/shared/lib/crud/factory";
3
+ import { CrudHttpError } from "@open-mercato/shared/lib/crud/errors";
4
+ import { resolveTranslations } from "@open-mercato/shared/lib/i18n/server";
5
+ import { CatalogProductUnitConversion } from "../../data/entities.js";
6
+ import {
7
+ productUnitConversionCreateSchema,
8
+ productUnitConversionUpdateSchema,
9
+ productUnitConversionDeleteSchema
10
+ } from "../../data/validators.js";
11
+ import { parseScopedCommandInput } from "../utils.js";
12
+ import {
13
+ createCatalogCrudOpenApi,
14
+ createPagedListResponseSchema,
15
+ defaultCreateResponseSchema,
16
+ defaultOkResponseSchema
17
+ } from "../openapi.js";
18
+ import { canonicalizeUnitCode } from "../../lib/unitCodes.js";
19
+ import { E } from "../../../../generated/entities.ids.generated.js";
20
+ const rawBodySchema = z.object({}).passthrough();
21
+ const listSchema = z.object({
22
+ page: z.coerce.number().min(1).default(1),
23
+ pageSize: z.coerce.number().min(1).max(100).default(50),
24
+ id: z.string().uuid().optional(),
25
+ productId: z.string().uuid().optional(),
26
+ unitCode: z.string().trim().max(50).optional(),
27
+ isActive: z.coerce.boolean().optional(),
28
+ sortField: z.string().optional(),
29
+ sortDir: z.enum(["asc", "desc"]).optional()
30
+ }).passthrough();
31
+ const routeMetadata = {
32
+ GET: { requireAuth: true, requireFeatures: ["catalog.products.view"] },
33
+ POST: { requireAuth: true, requireFeatures: ["catalog.products.manage"] },
34
+ PUT: { requireAuth: true, requireFeatures: ["catalog.products.manage"] },
35
+ DELETE: { requireAuth: true, requireFeatures: ["catalog.products.manage"] }
36
+ };
37
+ const metadata = routeMetadata;
38
+ const crud = makeCrudRoute({
39
+ metadata: routeMetadata,
40
+ orm: {
41
+ entity: CatalogProductUnitConversion,
42
+ idField: "id",
43
+ orgField: "organizationId",
44
+ tenantField: "tenantId",
45
+ softDeleteField: "deletedAt"
46
+ },
47
+ indexer: {
48
+ entityType: E.catalog.catalog_product_unit_conversion
49
+ },
50
+ list: {
51
+ schema: listSchema,
52
+ entityId: E.catalog.catalog_product_unit_conversion,
53
+ fields: [
54
+ "id",
55
+ "product_id",
56
+ "unit_code",
57
+ "to_base_factor",
58
+ "sort_order",
59
+ "is_active",
60
+ "metadata",
61
+ "created_at",
62
+ "updated_at"
63
+ ],
64
+ sortFieldMap: {
65
+ createdAt: "created_at",
66
+ updatedAt: "updated_at",
67
+ sortOrder: "sort_order",
68
+ unitCode: "unit_code"
69
+ },
70
+ buildFilters: async (query) => {
71
+ const filters = {};
72
+ if (query.id) filters.id = { $eq: query.id };
73
+ if (query.productId) filters.product_id = { $eq: query.productId };
74
+ const unitCode = canonicalizeUnitCode(query.unitCode);
75
+ if (unitCode) {
76
+ filters.unit_code = { $eq: unitCode };
77
+ }
78
+ if (typeof query.isActive === "boolean") {
79
+ filters.is_active = query.isActive;
80
+ }
81
+ return filters;
82
+ },
83
+ transformItem: (item) => {
84
+ if (!item) return item;
85
+ const unitCode = canonicalizeUnitCode(
86
+ item["unit_code"] ?? item["unitCode"]
87
+ );
88
+ return {
89
+ ...item,
90
+ unit_code: unitCode,
91
+ unitCode
92
+ };
93
+ }
94
+ },
95
+ actions: {
96
+ create: {
97
+ commandId: "catalog.product-unit-conversions.create",
98
+ schema: rawBodySchema,
99
+ mapInput: async ({ raw, ctx }) => {
100
+ const { translate } = await resolveTranslations();
101
+ return parseScopedCommandInput(
102
+ productUnitConversionCreateSchema,
103
+ raw ?? {},
104
+ ctx,
105
+ translate
106
+ );
107
+ },
108
+ response: ({ result }) => ({ id: result?.conversionId ?? null }),
109
+ status: 201
110
+ },
111
+ update: {
112
+ commandId: "catalog.product-unit-conversions.update",
113
+ schema: rawBodySchema,
114
+ mapInput: async ({ raw, ctx }) => {
115
+ const { translate } = await resolveTranslations();
116
+ return parseScopedCommandInput(
117
+ productUnitConversionUpdateSchema,
118
+ raw ?? {},
119
+ ctx,
120
+ translate
121
+ );
122
+ },
123
+ response: () => ({ ok: true })
124
+ },
125
+ delete: {
126
+ commandId: "catalog.product-unit-conversions.delete",
127
+ schema: rawBodySchema,
128
+ mapInput: async ({ raw, ctx }) => {
129
+ const { translate } = await resolveTranslations();
130
+ const parsed = parseScopedCommandInput(
131
+ productUnitConversionDeleteSchema,
132
+ raw ?? {},
133
+ ctx,
134
+ translate
135
+ );
136
+ if (!parsed.id) {
137
+ throw new CrudHttpError(400, {
138
+ error: translate(
139
+ "catalog.errors.id_required",
140
+ "Record identifier is required."
141
+ )
142
+ });
143
+ }
144
+ return parsed;
145
+ },
146
+ response: () => ({ ok: true })
147
+ }
148
+ }
149
+ });
150
+ const GET = crud.GET;
151
+ const POST = crud.POST;
152
+ const PUT = crud.PUT;
153
+ const DELETE = crud.DELETE;
154
+ const conversionListItemSchema = z.object({
155
+ id: z.string().uuid(),
156
+ product_id: z.string().uuid(),
157
+ unit_code: z.string(),
158
+ to_base_factor: z.number(),
159
+ sort_order: z.number().nullable().optional(),
160
+ is_active: z.boolean().nullable().optional(),
161
+ metadata: z.record(z.string(), z.unknown()).nullable().optional(),
162
+ created_at: z.string().nullable().optional(),
163
+ updated_at: z.string().nullable().optional()
164
+ });
165
+ const openApi = createCatalogCrudOpenApi({
166
+ resourceName: "Product unit conversion",
167
+ pluralName: "Product unit conversions",
168
+ querySchema: listSchema,
169
+ listResponseSchema: createPagedListResponseSchema(conversionListItemSchema),
170
+ create: {
171
+ schema: productUnitConversionCreateSchema,
172
+ responseSchema: defaultCreateResponseSchema,
173
+ description: "Creates a product unit conversion."
174
+ },
175
+ update: {
176
+ schema: productUnitConversionUpdateSchema,
177
+ responseSchema: defaultOkResponseSchema,
178
+ description: "Updates an existing product unit conversion by id."
179
+ },
180
+ del: {
181
+ schema: productUnitConversionDeleteSchema,
182
+ responseSchema: defaultOkResponseSchema,
183
+ description: "Deletes a product unit conversion by id."
184
+ }
185
+ });
186
+ export {
187
+ DELETE,
188
+ GET,
189
+ POST,
190
+ PUT,
191
+ metadata,
192
+ openApi
193
+ };
194
+ //# sourceMappingURL=route.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/catalog/api/product-unit-conversions/route.ts"],
4
+ "sourcesContent": ["import { z } from \"zod\";\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 { CatalogProductUnitConversion } from \"../../data/entities\";\nimport {\n productUnitConversionCreateSchema,\n productUnitConversionUpdateSchema,\n productUnitConversionDeleteSchema,\n} from \"../../data/validators\";\nimport { parseScopedCommandInput } from \"../utils\";\nimport {\n createCatalogCrudOpenApi,\n createPagedListResponseSchema,\n defaultCreateResponseSchema,\n defaultOkResponseSchema,\n} from \"../openapi\";\nimport { canonicalizeUnitCode } from \"../../lib/unitCodes\";\nimport { E } from \"#generated/entities.ids.generated\";\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(100).default(50),\n id: z.string().uuid().optional(),\n productId: z.string().uuid().optional(),\n unitCode: z.string().trim().max(50).optional(),\n isActive: z.coerce.boolean().optional(),\n sortField: z.string().optional(),\n sortDir: z.enum([\"asc\", \"desc\"]).optional(),\n })\n .passthrough();\n\nconst routeMetadata = {\n GET: { requireAuth: true, requireFeatures: [\"catalog.products.view\"] },\n POST: { requireAuth: true, requireFeatures: [\"catalog.products.manage\"] },\n PUT: { requireAuth: true, requireFeatures: [\"catalog.products.manage\"] },\n DELETE: { requireAuth: true, requireFeatures: [\"catalog.products.manage\"] },\n};\n\nexport const metadata = routeMetadata;\n\nconst crud = makeCrudRoute({\n metadata: routeMetadata,\n orm: {\n entity: CatalogProductUnitConversion,\n idField: \"id\",\n orgField: \"organizationId\",\n tenantField: \"tenantId\",\n softDeleteField: \"deletedAt\",\n },\n indexer: {\n entityType: E.catalog.catalog_product_unit_conversion,\n },\n list: {\n schema: listSchema,\n entityId: E.catalog.catalog_product_unit_conversion,\n fields: [\n \"id\",\n \"product_id\",\n \"unit_code\",\n \"to_base_factor\",\n \"sort_order\",\n \"is_active\",\n \"metadata\",\n \"created_at\",\n \"updated_at\",\n ],\n sortFieldMap: {\n createdAt: \"created_at\",\n updatedAt: \"updated_at\",\n sortOrder: \"sort_order\",\n unitCode: \"unit_code\",\n },\n buildFilters: async (query) => {\n const filters: Record<string, unknown> = {};\n if (query.id) filters.id = { $eq: query.id };\n if (query.productId) filters.product_id = { $eq: query.productId };\n const unitCode = canonicalizeUnitCode(query.unitCode);\n if (unitCode) {\n filters.unit_code = { $eq: unitCode };\n }\n if (typeof query.isActive === \"boolean\") {\n filters.is_active = query.isActive;\n }\n return filters;\n },\n transformItem: (item: Record<string, unknown> | null | undefined) => {\n if (!item) return item;\n const unitCode = canonicalizeUnitCode(\n item[\"unit_code\"] ?? item[\"unitCode\"],\n );\n return {\n ...item,\n unit_code: unitCode,\n unitCode,\n };\n },\n },\n actions: {\n create: {\n commandId: \"catalog.product-unit-conversions.create\",\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations();\n return parseScopedCommandInput(\n productUnitConversionCreateSchema,\n raw ?? {},\n ctx,\n translate,\n );\n },\n response: ({ result }) => ({ id: result?.conversionId ?? null }),\n status: 201,\n },\n update: {\n commandId: \"catalog.product-unit-conversions.update\",\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations();\n return parseScopedCommandInput(\n productUnitConversionUpdateSchema,\n raw ?? {},\n ctx,\n translate,\n );\n },\n response: () => ({ ok: true }),\n },\n delete: {\n commandId: \"catalog.product-unit-conversions.delete\",\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations();\n const parsed = parseScopedCommandInput(\n productUnitConversionDeleteSchema,\n raw ?? {},\n ctx,\n translate,\n );\n if (!parsed.id) {\n throw new CrudHttpError(400, {\n error: translate(\n \"catalog.errors.id_required\",\n \"Record identifier is required.\",\n ),\n });\n }\n return parsed;\n },\n response: () => ({ ok: true }),\n },\n },\n});\n\nexport const GET = crud.GET;\nexport const POST = crud.POST;\nexport const PUT = crud.PUT;\nexport const DELETE = crud.DELETE;\n\nconst conversionListItemSchema = z.object({\n id: z.string().uuid(),\n product_id: z.string().uuid(),\n unit_code: z.string(),\n to_base_factor: z.number(),\n sort_order: z.number().nullable().optional(),\n is_active: z.boolean().nullable().optional(),\n metadata: z.record(z.string(), z.unknown()).nullable().optional(),\n created_at: z.string().nullable().optional(),\n updated_at: z.string().nullable().optional(),\n});\n\nexport const openApi = createCatalogCrudOpenApi({\n resourceName: \"Product unit conversion\",\n pluralName: \"Product unit conversions\",\n querySchema: listSchema,\n listResponseSchema: createPagedListResponseSchema(conversionListItemSchema),\n create: {\n schema: productUnitConversionCreateSchema,\n responseSchema: defaultCreateResponseSchema,\n description: \"Creates a product unit conversion.\",\n },\n update: {\n schema: productUnitConversionUpdateSchema,\n responseSchema: defaultOkResponseSchema,\n description: \"Updates an existing product unit conversion by id.\",\n },\n del: {\n schema: productUnitConversionDeleteSchema,\n responseSchema: defaultOkResponseSchema,\n description: \"Deletes a product unit conversion by id.\",\n },\n});\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }