@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,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/catalog/seed/examples.ts"],
4
- "sourcesContent": ["import { randomUUID } from 'node:crypto'\nimport path from 'node:path'\nimport { promises as fs } from 'node:fs'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport type { AwilixContainer } from 'awilix'\nimport { SalesChannel } from '@open-mercato/core/modules/sales/data/entities'\nimport {\n CatalogOffer,\n CatalogPriceKind,\n CatalogProduct,\n CatalogProductCategory,\n CatalogProductCategoryAssignment,\n CatalogProductPrice,\n CatalogProductVariant,\n} from '../data/entities'\nimport { DefaultDataEngine } from '@open-mercato/shared/lib/data/engine'\nimport { ensureCustomFieldDefinitions, type FieldSetInput } from '@open-mercato/core/modules/entities/lib/field-definitions'\nimport { CustomFieldEntityConfig } from '@open-mercato/core/modules/entities/data/entities'\nimport { rebuildCategoryHierarchyForOrganization } from '../lib/categoryHierarchy'\nimport { defineFields, cf } from '@open-mercato/shared/modules/dsl'\nimport { E } from '#generated/entities.ids.generated'\nimport { SalesTaxRate } from '@open-mercato/core/modules/sales/data/entities'\nimport { Attachment, AttachmentPartition } from '@open-mercato/core/modules/attachments/data/entities'\nimport { ensureDefaultPartitions, resolveDefaultPartitionCode } from '@open-mercato/core/modules/attachments/lib/partitions'\nimport { storePartitionFile } from '@open-mercato/core/modules/attachments/lib/storage'\nimport { mergeAttachmentMetadata } from '@open-mercato/core/modules/attachments/lib/metadata'\nimport { buildAttachmentFileUrl, buildAttachmentImageUrl, slugifyAttachmentFileName } from '@open-mercato/core/modules/attachments/lib/imageUrls'\n\ntype SeedScope = { tenantId: string; organizationId: string }\n\nconst EXAMPLES_MEDIA_ROOT = path.join(process.cwd(), 'public', 'examples')\n\nfunction detectMimeType(fileName: string): string {\n const ext = fileName.toLowerCase().split('.').pop() || ''\n if (ext === 'png') return 'image/png'\n if (ext === 'jpg' || ext === 'jpeg') return 'image/jpeg'\n if (ext === 'webp') return 'image/webp'\n return 'application/octet-stream'\n}\n\nasync function ensureAttachmentPartition(\n em: EntityManager,\n code: string\n): Promise<AttachmentPartition> {\n let partition = await em.findOne(AttachmentPartition, { code })\n if (!partition) {\n await ensureDefaultPartitions(em)\n partition = await em.findOne(AttachmentPartition, { code })\n }\n if (!partition) {\n throw new Error(`Attachment partition \"${code}\" is not configured.`)\n }\n return partition\n}\n\nasync function attachMediaFromExamples(\n em: EntityManager,\n scope: SeedScope,\n entityId: string,\n recordId: string,\n mediaSeeds?: MediaSeed[]\n): Promise<Array<{ id: string; imageUrl: string }>> {\n if (!mediaSeeds?.length) return []\n const partitionCode = resolveDefaultPartitionCode(entityId)\n const partition = await ensureAttachmentPartition(em, partitionCode)\n const results: Array<{ id: string; imageUrl: string }> = []\n for (const media of mediaSeeds) {\n const sourcePath = path.join(EXAMPLES_MEDIA_ROOT, media.file)\n let buffer: Buffer\n try {\n buffer = await fs.readFile(sourcePath)\n } catch (error) {\n console.warn(`[catalog.seed] Example media missing: ${sourcePath}`)\n continue\n }\n const stored = await storePartitionFile({\n partitionCode: partition.code,\n orgId: scope.organizationId,\n tenantId: scope.tenantId,\n fileName: media.file,\n buffer,\n })\n const attachmentId = randomUUID()\n const slug = slugifyAttachmentFileName(media.file, 'media')\n const metadata = mergeAttachmentMetadata(null, {\n assignments: [{ type: entityId, id: recordId }],\n })\n const attachment = em.create(Attachment, {\n id: attachmentId,\n entityId,\n recordId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n partitionCode: partition.code,\n fileName: media.file,\n mimeType: detectMimeType(media.file),\n fileSize: buffer.length,\n storageDriver: partition.storageDriver || 'local',\n storagePath: stored.storagePath,\n storageMetadata: metadata,\n url: buildAttachmentFileUrl(attachmentId),\n })\n em.persist(attachment)\n results.push({\n id: attachmentId,\n imageUrl: buildAttachmentImageUrl(attachmentId, { slug }),\n })\n }\n return results\n}\n\nconst PRODUCT_FIELDSETS = [\n {\n code: 'fashion_mens_footwear',\n label: 'Fashion \u00B7 Men \u00B7 Footwear',\n icon: 'carbon:sneaker',\n description: 'Material, construction, and care metadata for men\u2019s performance footwear.',\n groups: [\n { code: 'identity', title: 'Identity' },\n { code: 'materials', title: 'Materials & Build' },\n { code: 'care', title: 'Care instructions' },\n ],\n },\n {\n code: 'fashion_womens_dresses',\n label: 'Fashion \u00B7 Women \u00B7 Dresses & Jumpsuits',\n icon: 'solar:dress-linear',\n description: 'Silhouette, fabric, and care metadata for womenswear.',\n groups: [\n { code: 'identity', title: 'Identity' },\n { code: 'materials', title: 'Materials' },\n { code: 'fit', title: 'Fit & Length' },\n { code: 'care', title: 'Care instructions' },\n ],\n },\n {\n code: 'service_schedule',\n label: 'Services \u00B7 Scheduling',\n icon: 'solar:calendar-linear',\n description: 'Scheduling, preparation, and delivery metadata for service offerings.',\n groups: [\n { code: 'identity', title: 'Identity' },\n { code: 'timing', title: 'Timing rules' },\n { code: 'resources', title: 'Resources & Delivery' },\n ],\n },\n] as const\n\nconst VARIANT_FIELDSETS = [\n {\n code: 'fashion_mens_footwear',\n label: 'Fashion \u00B7 Men \u00B7 Footwear',\n icon: 'carbon:sneaker',\n description: 'Variant-level sizing metadata for men\u2019s footwear.',\n groups: [\n { code: 'fit', title: 'Fit' },\n { code: 'finish', title: 'Finish' },\n ],\n },\n {\n code: 'fashion_womens_dresses',\n label: 'Fashion \u00B7 Women \u00B7 Dresses & Jumpsuits',\n icon: 'solar:dress-linear',\n description: 'Variant-level sizing metadata for womenswear.',\n groups: [\n { code: 'fit', title: 'Fit' },\n { code: 'finish', title: 'Finish' },\n ],\n },\n {\n code: 'service_schedule',\n label: 'Services \u00B7 Scheduling',\n icon: 'solar:calendar-linear',\n description: 'Provider, duration, and environment metadata for service slots.',\n groups: [\n { code: 'provider', title: 'Provider' },\n { code: 'environment', title: 'Environment' },\n ],\n },\n] as const\n\nconst CUSTOM_FIELD_SETS: FieldSetInput[] = [\n defineFields(E.catalog.catalog_product, [\n cf.text('style_code', {\n label: 'Style code',\n description: 'Reference code shared with merchandising teams.',\n filterable: true,\n fieldset: 'fashion_mens_footwear',\n group: { code: 'identity' },\n }),\n cf.select('upper_material', ['engineered_knit', 'full_grain_leather', 'recycled_mesh'], {\n label: 'Upper material',\n fieldset: 'fashion_mens_footwear',\n group: { code: 'materials' },\n filterable: true,\n }),\n cf.select('cushioning_profile', ['responsive', 'plush', 'stability'], {\n label: 'Cushioning profile',\n fieldset: 'fashion_mens_footwear',\n group: { code: 'materials' },\n }),\n cf.multiline('care_notes', {\n label: 'Care notes',\n editor: 'markdown',\n fieldset: 'fashion_mens_footwear',\n group: { code: 'care' },\n }),\n ]),\n defineFields(E.catalog.catalog_product, [\n cf.select('silhouette', ['wrap', 'column', 'fit_and_flare', 'jumpsuit'], {\n label: 'Silhouette',\n fieldset: 'fashion_womens_dresses',\n group: { code: 'identity' },\n filterable: true,\n }),\n cf.select('fabric_mix', ['silk_blend', 'recycled_poly', 'linen', 'cupro'], {\n label: 'Fabric mix',\n fieldset: 'fashion_womens_dresses',\n group: { code: 'materials' },\n }),\n cf.select('occasion_ready', ['daytime', 'evening', 'resort'], {\n label: 'Occasion',\n fieldset: 'fashion_womens_dresses',\n group: { code: 'fit' },\n }),\n cf.multiline('finishing_details', {\n label: 'Finishing details',\n editor: 'markdown',\n fieldset: 'fashion_womens_dresses',\n group: { code: 'care' },\n }),\n ]),\n defineFields(E.catalog.catalog_product_variant, [\n cf.integer('shoe_size', {\n label: 'US size',\n fieldset: 'fashion_mens_footwear',\n group: { code: 'fit' },\n filterable: true,\n }),\n cf.select('shoe_width', ['B', 'D', 'EE'], {\n label: 'Width',\n fieldset: 'fashion_mens_footwear',\n group: { code: 'fit' },\n }),\n cf.text('colorway', {\n label: 'Colorway',\n fieldset: 'fashion_mens_footwear',\n group: { code: 'finish' },\n }),\n ]),\n defineFields(E.catalog.catalog_product_variant, [\n cf.integer('numeric_size', {\n label: 'Numeric size',\n fieldset: 'fashion_womens_dresses',\n group: { code: 'fit' },\n }),\n cf.select('length_profile', ['mini', 'midi', 'maxi'], {\n label: 'Length',\n fieldset: 'fashion_womens_dresses',\n group: { code: 'fit' },\n }),\n cf.text('color_story', {\n label: 'Color story',\n fieldset: 'fashion_womens_dresses',\n group: { code: 'finish' },\n }),\n ]),\n defineFields(E.catalog.catalog_product, [\n cf.integer('service_duration_minutes', {\n label: 'Duration (minutes)',\n description: 'Length of a single service slot.',\n fieldset: 'service_schedule',\n group: { code: 'timing' },\n filterable: true,\n required: true,\n }),\n cf.integer('service_buffer_minutes', {\n label: 'Buffer between appointments',\n description: 'Minimum downtime between consecutive service slots (minutes).',\n fieldset: 'service_schedule',\n group: { code: 'timing' },\n }),\n cf.text('service_location', {\n label: 'Location / Room',\n description: 'Where the service is delivered.',\n fieldset: 'service_schedule',\n group: { code: 'identity' },\n }),\n cf.select('service_resources', ['stylist', 'therapist', 'treatment_room', 'wash_station', 'steam_room'], {\n label: 'Required resources',\n description: 'Staff or rooms required to perform the service.',\n fieldset: 'service_schedule',\n group: { code: 'resources' },\n multi: true,\n }),\n cf.boolean('service_remote_available', {\n label: 'Remote session available',\n description: 'Indicates whether the service can be performed remotely or virtually.',\n fieldset: 'service_schedule',\n group: { code: 'resources' },\n defaultValue: false,\n }),\n ]),\n defineFields(E.catalog.catalog_product_variant, [\n cf.select('provider_level', ['junior', 'senior', 'master'], {\n label: 'Provider level',\n description: 'Seniority of the assigned specialist.',\n fieldset: 'service_schedule',\n group: { code: 'provider' },\n filterable: true,\n }),\n cf.text('staff_member', {\n label: 'Staff member',\n description: 'Optional name of the staff member who usually delivers this variant.',\n fieldset: 'service_schedule',\n group: { code: 'provider' },\n }),\n cf.select('environment_type', ['studio', 'suite', 'on_site'], {\n label: 'Environment',\n description: 'Where the session is hosted.',\n fieldset: 'service_schedule',\n group: { code: 'environment' },\n }),\n ]),\n]\n\ntype CategorySeed = {\n slug: string\n name: string\n description?: string\n children?: CategorySeed[]\n}\n\nconst CATEGORY_TREE: CategorySeed[] = [\n {\n slug: 'fashion',\n name: 'Fashion',\n description: 'Seasonal assortments and vertical-specific collections.',\n children: [\n {\n slug: 'fashion-men',\n name: 'Men',\n children: [\n {\n slug: 'fashion-men-footwear',\n name: 'Footwear',\n description: 'Premium sneakers, boots, and sandals.',\n },\n ],\n },\n {\n slug: 'fashion-women',\n name: 'Women',\n children: [\n {\n slug: 'fashion-women-dresses-jumpsuits',\n name: 'Dresses & Jumpsuits',\n description: 'Occasion-ready dresses and tailored jumpsuits.',\n },\n ],\n },\n ],\n },\n {\n slug: 'services',\n name: 'Services',\n description: 'Bookable in-person and virtual experiences.',\n children: [\n {\n slug: 'services-hairdresser',\n name: 'Hairdresser',\n description: 'Salon services ranging from quick trims to signature looks.',\n },\n {\n slug: 'services-massage',\n name: 'Massage',\n description: 'Wellness treatments and bodywork sessions.',\n },\n ],\n },\n]\n\ntype MediaSeed = {\n file: string\n title?: string\n}\n\ntype VariantSeed = {\n name: string\n sku: string\n isDefault?: boolean\n optionValues?: Record<string, string>\n prices: {\n regular: number\n sale?: number\n }\n customFields?: Record<string, string | number | boolean | null>\n media?: MediaSeed[]\n}\n\ntype ProductSeed = {\n title: string\n handle: string\n sku?: string\n description: string\n categorySlug: string\n customFieldsetCode: string\n variantFieldsetCode: string\n unit: string\n metadata?: Record<string, unknown>\n customFields?: Record<string, string | number | boolean | null>\n media?: MediaSeed[]\n variants: VariantSeed[]\n}\n\nconst PRODUCT_SEEDS: ProductSeed[] = [\n {\n title: 'Atlas Runner Sneaker',\n handle: 'atlas-runner-sneaker',\n sku: 'ATLAS-RUNNER',\n description:\n 'Lightweight road sneaker engineered with a breathable knit upper, recycled TPU overlays, and a decoupled heel for smooth transitions.',\n categorySlug: 'fashion-men-footwear',\n customFieldsetCode: 'fashion_mens_footwear',\n variantFieldsetCode: 'fashion_mens_footwear',\n unit: 'pair',\n metadata: { division: 'RunLab', season: 'SS25' },\n customFields: {\n style_code: 'AR-2025',\n upper_material: 'engineered_knit',\n cushioning_profile: 'responsive',\n care_notes: 'Spot clean after each run and air dry. Avoid machine drying.',\n },\n media: [\n { file: 'atlas-runner-midnight-1.png' },\n ],\n variants: [\n {\n name: 'Midnight Navy \u00B7 US 8',\n sku: 'ATLAS-RUN-NAVY-8',\n isDefault: true,\n optionValues: { color: 'Midnight Navy', size: 'US 8' },\n prices: { regular: 168, sale: 148 },\n customFields: { shoe_size: 8, shoe_width: 'D', colorway: 'Midnight Navy' },\n media: [\n { file: 'atlas-runner-midnight-1.png' },\n { file: 'atlas-runner-midnight-2.png' },\n ],\n },\n {\n name: 'Glacier Grey \u00B7 US 10',\n sku: 'ATLAS-RUN-GLACIER-10',\n optionValues: { color: 'Glacier Grey', size: 'US 10' },\n prices: { regular: 168, sale: 138 },\n customFields: { shoe_size: 10, shoe_width: 'EE', colorway: 'Glacier Grey' },\n media: [\n { file: 'atlas-runner-glacier-1.png' },\n { file: 'atlas-runner-glacier-2.png' },\n ],\n },\n ],\n },\n {\n title: 'Aurora Wrap Dress',\n handle: 'aurora-wrap-dress',\n sku: 'AURORA-WRAP',\n description:\n 'Bias-cut wrap dress with blouson sleeves, matte silk blend, and hidden interior snaps so the placket stays put at events.',\n categorySlug: 'fashion-women-dresses-jumpsuits',\n customFieldsetCode: 'fashion_womens_dresses',\n variantFieldsetCode: 'fashion_womens_dresses',\n unit: 'unit',\n metadata: { capsule: 'Evening Atelier', season: 'Resort 25' },\n customFields: {\n silhouette: 'wrap',\n fabric_mix: 'silk_blend',\n occasion_ready: 'evening',\n finishing_details: 'Hand-finished hem with subtle tonal beading along the wrap edge.',\n },\n media: [\n { file: 'aurora-wrap-rosewood.png' },\n ],\n variants: [\n {\n name: 'Rosewood \u00B7 Medium',\n sku: 'AURORA-ROSE-M',\n isDefault: true,\n optionValues: { color: 'Rosewood', size: 'Medium' },\n prices: { regular: 248, sale: 212 },\n customFields: { numeric_size: 6, length_profile: 'midi', color_story: 'Rosewood' },\n media: [\n { file: 'aurora-wrap-rosewood.png' },\n ],\n },\n {\n name: 'Celestial \u00B7 Large',\n sku: 'AURORA-CELESTIAL-L',\n optionValues: { color: 'Celestial', size: 'Large' },\n prices: { regular: 248, sale: 198 },\n customFields: { numeric_size: 8, length_profile: 'maxi', color_story: 'Celestial blue' },\n media: [\n { file: 'aurora-wrap-celestial.png' },\n ],\n },\n ],\n },\n {\n title: 'Signature Haircut & Finish',\n handle: 'signature-haircut-service',\n sku: 'SERV-HAIR-60',\n description:\n 'Tailored haircut with relaxing wash, scalp massage, and styling finish. Designed for repeat visits in the demo portal.',\n categorySlug: 'services-hairdresser',\n customFieldsetCode: 'service_schedule',\n variantFieldsetCode: 'service_schedule',\n unit: 'hour',\n metadata: { channel: 'salon', serviceType: 'hairdresser' },\n customFields: {\n service_duration_minutes: 60,\n service_buffer_minutes: 15,\n service_location: 'Salon Studio 3',\n service_resources: 'stylist,wash_station',\n service_remote_available: false,\n },\n media: [{ file: 'hairdresser-service.png' }],\n variants: [\n {\n name: 'Senior Stylist \u00B7 60 min',\n sku: 'SERV-HAIR-60-SENIOR',\n isDefault: true,\n optionValues: { stylist: 'Senior', duration: '60' },\n prices: { regular: 95, sale: 85 },\n customFields: {\n provider_level: 'senior',\n staff_member: 'Amelia Hart',\n environment_type: 'studio',\n },\n media: [{ file: 'hairdresser-service.png' }],\n },\n ],\n },\n {\n title: 'Restorative Massage Session',\n handle: 'restorative-massage-service',\n sku: 'SERV-MASSAGE-90',\n description:\n 'Full-body massage with aromatherapy oils and guided breathing. Includes complimentary refreshments and studio amenities.',\n categorySlug: 'services-massage',\n customFieldsetCode: 'service_schedule',\n variantFieldsetCode: 'service_schedule',\n unit: 'hour',\n metadata: { channel: 'wellness', serviceType: 'massage' },\n customFields: {\n service_duration_minutes: 90,\n service_buffer_minutes: 20,\n service_location: 'Wellness Suite B',\n service_resources: 'therapist,treatment_room,steam_room',\n service_remote_available: false,\n },\n media: [{ file: 'massage-service.png' }],\n variants: [\n {\n name: 'Master Therapist \u00B7 90 min',\n sku: 'SERV-MASSAGE-90-MASTER',\n isDefault: true,\n optionValues: { therapist: 'Master', duration: '90' },\n prices: { regular: 140, sale: 120 },\n customFields: {\n provider_level: 'master',\n staff_member: 'Noah Li',\n environment_type: 'suite',\n },\n media: [{ file: 'massage-service.png' }],\n },\n ],\n },\n]\n\nconst CHANNEL_DEFINITION = {\n code: 'fashion-online',\n name: 'Mercato Fashion Online',\n description: 'Direct-to-consumer storefront showcasing premium demos.',\n websiteUrl: 'https://demo.open-mercato.com',\n contactEmail: 'store@open-mercato.com',\n}\n\nfunction formatMoney(value: number): string {\n return value.toFixed(2)\n}\n\nasync function resolveDefaultTaxRate(\n em: EntityManager,\n scope: SeedScope\n): Promise<SalesTaxRate | null> {\n const [rate] = await em.find(\n SalesTaxRate,\n {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n },\n {\n limit: 1,\n orderBy: {\n isDefault: 'DESC',\n priority: 'ASC',\n rate: 'DESC',\n createdAt: 'ASC',\n },\n }\n )\n return rate ?? null\n}\n\nasync function ensureFieldsetConfig(\n em: EntityManager,\n scope: SeedScope,\n entityId: string,\n fieldsets: typeof PRODUCT_FIELDSETS | typeof VARIANT_FIELDSETS\n): Promise<void> {\n const now = new Date()\n let config = await em.findOne(CustomFieldEntityConfig, {\n entityId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n })\n if (!config) {\n config = em.create(CustomFieldEntityConfig, {\n id: randomUUID(),\n entityId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n isActive: true,\n createdAt: now,\n updatedAt: now,\n })\n }\n config.configJson = {\n fieldsets,\n singleFieldsetPerRecord: true,\n }\n config.isActive = true\n config.updatedAt = now\n em.persist(config)\n}\n\nasync function ensureFieldsetsAndDefinitions(em: EntityManager, scope: SeedScope): Promise<void> {\n await ensureFieldsetConfig(em, scope, E.catalog.catalog_product, PRODUCT_FIELDSETS)\n await ensureFieldsetConfig(em, scope, E.catalog.catalog_product_variant, VARIANT_FIELDSETS)\n await ensureCustomFieldDefinitions(em, CUSTOM_FIELD_SETS, {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n })\n await em.flush()\n}\n\nasync function ensureCategories(\n em: EntityManager,\n scope: SeedScope\n): Promise<Map<string, CatalogProductCategory>> {\n const map = new Map<string, CatalogProductCategory>()\n const now = new Date()\n\n const upsert = async (seed: CategorySeed, parent: CatalogProductCategory | null) => {\n let record = await em.findOne(CatalogProductCategory, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n slug: seed.slug,\n })\n if (!record) {\n record = em.create(CatalogProductCategory, {\n id: randomUUID(),\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n name: seed.name,\n slug: seed.slug,\n description: seed.description ?? null,\n parentId: parent ? parent.id : null,\n rootId: parent ? parent.rootId ?? parent.id : null,\n treePath: null,\n depth: parent ? (parent.depth ?? 0) + 1 : 0,\n ancestorIds: [],\n childIds: [],\n descendantIds: [],\n metadata: null,\n isActive: true,\n createdAt: now,\n updatedAt: now,\n })\n em.persist(record)\n } else {\n record.name = seed.name\n record.description = seed.description ?? null\n record.parentId = parent ? parent.id : null\n record.isActive = true\n record.updatedAt = now\n }\n map.set(seed.slug, record)\n if (Array.isArray(seed.children)) {\n for (const child of seed.children) {\n await upsert(child, record)\n }\n }\n }\n\n for (const seed of CATEGORY_TREE) {\n await upsert(seed, null)\n }\n\n await em.flush()\n await rebuildCategoryHierarchyForOrganization(em, scope.organizationId, scope.tenantId)\n\n return map\n}\n\nasync function ensureChannel(em: EntityManager, scope: SeedScope): Promise<SalesChannel> {\n const now = new Date()\n let channel = await em.findOne(SalesChannel, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n code: CHANNEL_DEFINITION.code,\n deletedAt: null,\n })\n if (!channel) {\n channel = em.create(SalesChannel, {\n id: randomUUID(),\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n code: CHANNEL_DEFINITION.code,\n name: CHANNEL_DEFINITION.name,\n description: CHANNEL_DEFINITION.description,\n websiteUrl: CHANNEL_DEFINITION.websiteUrl,\n contactEmail: CHANNEL_DEFINITION.contactEmail,\n status: 'active',\n isActive: true,\n metadata: { locale: 'en-US' },\n createdAt: now,\n updatedAt: now,\n })\n em.persist(channel)\n await em.flush()\n }\n return channel\n}\n\nasync function loadPriceKinds(\n em: EntityManager,\n scope: SeedScope\n): Promise<Map<string, CatalogPriceKind>> {\n const kinds = await em.find(CatalogPriceKind, {\n tenantId: scope.tenantId,\n code: { $in: ['regular', 'sale'] },\n deletedAt: null,\n })\n const map = new Map<string, CatalogPriceKind>()\n for (const kind of kinds) {\n map.set(kind.code.toLowerCase(), kind)\n }\n return map\n}\n\nexport async function seedCatalogExamples(\n em: EntityManager,\n container: AwilixContainer,\n scope: SeedScope\n): Promise<boolean> {\n await ensureFieldsetsAndDefinitions(em, scope)\n await ensureDefaultPartitions(em)\n\n const handles = PRODUCT_SEEDS.map((seed) => seed.handle)\n const existingProducts = await em.find(CatalogProduct, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n handle: { $in: handles as any },\n })\n const existingByHandle = new Map(existingProducts.map((product) => [product.handle?.toLowerCase(), product]))\n\n const categoryMap = await ensureCategories(em, scope)\n const channel = await ensureChannel(em, scope)\n const priceKinds = await loadPriceKinds(em, scope)\n const regularKind = priceKinds.get('regular')\n const saleKind = priceKinds.get('sale')\n const defaultTaxRate = await resolveDefaultTaxRate(em, scope)\n const defaultTaxRateId = defaultTaxRate?.id ?? null\n const defaultTaxRateValue = defaultTaxRate?.rate ?? null\n if (!regularKind || !saleKind) {\n throw new Error('Missing catalog price kinds; run `mercato catalog seed-price-kinds` first.')\n }\n\n const dataEngine = new DefaultDataEngine(em, container)\n const customFieldAssignments: Array<() => Promise<void>> = []\n let createdAny = false\n\n for (const productSeed of PRODUCT_SEEDS) {\n const existing = existingByHandle.get(productSeed.handle.toLowerCase())\n if (existing) {\n continue\n }\n createdAny = true\n const product = em.create(CatalogProduct, {\n id: randomUUID(),\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n title: productSeed.title,\n description: productSeed.description,\n sku: productSeed.sku ?? null,\n handle: productSeed.handle,\n productType: 'configurable',\n primaryCurrencyCode: 'USD',\n defaultUnit: productSeed.unit,\n customFieldsetCode: productSeed.customFieldsetCode,\n metadata: productSeed.metadata ?? null,\n taxRateId: defaultTaxRateId,\n taxRate: defaultTaxRateValue,\n isConfigurable: true,\n isActive: true,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(product)\n\n const category = categoryMap.get(productSeed.categorySlug)\n if (category) {\n const assignment = em.create(CatalogProductCategoryAssignment, {\n id: randomUUID(),\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n product,\n category,\n position: 0,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(assignment)\n }\n\n const offer = em.create(CatalogOffer, {\n id: randomUUID(),\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n product,\n channelId: channel.id,\n title: `${productSeed.title} \u00B7 Online`,\n description: 'Offer curated for the demo storefront channel.',\n metadata: { channelCode: CHANNEL_DEFINITION.code },\n isActive: true,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(offer)\n\n if (productSeed.customFields && Object.keys(productSeed.customFields).length) {\n const payload = { ...productSeed.customFields }\n customFieldAssignments.push(() =>\n dataEngine.setCustomFields({\n entityId: E.catalog.catalog_product,\n recordId: product.id,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n values: payload,\n })\n )\n }\n\n const productMedia = await attachMediaFromExamples(\n em,\n scope,\n E.catalog.catalog_product,\n product.id,\n productSeed.media\n )\n if (productMedia.length) {\n const hero = productMedia[0]\n product.defaultMediaId = hero.id\n product.defaultMediaUrl = hero.imageUrl\n offer.defaultMediaId = hero.id\n offer.defaultMediaUrl = hero.imageUrl\n }\n\n for (const variantSeed of productSeed.variants) {\n const variant = em.create(CatalogProductVariant, {\n id: randomUUID(),\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n product,\n name: variantSeed.name,\n sku: variantSeed.sku,\n isDefault: variantSeed.isDefault ?? false,\n optionValues: variantSeed.optionValues ?? null,\n customFieldsetCode: productSeed.variantFieldsetCode,\n metadata: null,\n taxRateId: defaultTaxRateId,\n taxRate: defaultTaxRateValue,\n isActive: true,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(variant)\n\n const variantMedia = await attachMediaFromExamples(\n em,\n scope,\n E.catalog.catalog_product_variant,\n variant.id,\n variantSeed.media\n )\n const variantCover = variantMedia[0] ?? productMedia[0]\n\n const regularPrice = em.create(CatalogProductPrice, {\n id: randomUUID(),\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n product,\n variant,\n offer,\n priceKind: regularKind,\n currencyCode: 'USD',\n kind: regularKind.code,\n minQuantity: 1,\n taxRate: defaultTaxRateValue,\n unitPriceGross: formatMoney(variantSeed.prices.regular),\n unitPriceNet: formatMoney(variantSeed.prices.regular),\n channelId: channel.id,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(regularPrice)\n\n if (variantSeed.prices.sale !== undefined) {\n const salePrice = em.create(CatalogProductPrice, {\n id: randomUUID(),\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n product,\n variant,\n offer,\n priceKind: saleKind,\n currencyCode: 'USD',\n kind: saleKind.code,\n minQuantity: 1,\n taxRate: defaultTaxRateValue,\n unitPriceGross: formatMoney(variantSeed.prices.sale),\n unitPriceNet: formatMoney(variantSeed.prices.sale),\n channelId: channel.id,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(salePrice)\n }\n\n if (variantSeed.customFields && Object.keys(variantSeed.customFields).length) {\n const payload = { ...variantSeed.customFields }\n customFieldAssignments.push(() =>\n dataEngine.setCustomFields({\n entityId: E.catalog.catalog_product_variant,\n recordId: variant.id,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n values: payload,\n })\n )\n }\n }\n }\n\n if (!createdAny) {\n return false\n }\n\n await em.flush()\n\n for (const assign of customFieldAssignments) {\n try {\n await assign()\n } catch (err) {\n console.warn('[catalog.seed] Failed to set example custom field values', err)\n }\n }\n\n return true\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { randomUUID } from \"node:crypto\";\nimport path from \"node:path\";\nimport { promises as fs } from \"node:fs\";\nimport type { EntityManager } from \"@mikro-orm/postgresql\";\nimport type { AwilixContainer } from \"awilix\";\nimport { SalesChannel } from \"@open-mercato/core/modules/sales/data/entities\";\nimport {\n CatalogOffer,\n CatalogPriceKind,\n CatalogProduct,\n CatalogProductCategory,\n CatalogProductCategoryAssignment,\n CatalogProductPrice,\n CatalogProductVariant,\n} from \"../data/entities\";\nimport { DefaultDataEngine } from \"@open-mercato/shared/lib/data/engine\";\nimport {\n ensureCustomFieldDefinitions,\n type FieldSetInput,\n} from \"@open-mercato/core/modules/entities/lib/field-definitions\";\nimport { CustomFieldEntityConfig } from \"@open-mercato/core/modules/entities/data/entities\";\nimport { rebuildCategoryHierarchyForOrganization } from \"../lib/categoryHierarchy\";\nimport { defineFields, cf } from \"@open-mercato/shared/modules/dsl\";\nimport { E } from \"#generated/entities.ids.generated\";\nimport { SalesTaxRate } from \"@open-mercato/core/modules/sales/data/entities\";\nimport {\n Attachment,\n AttachmentPartition,\n} from \"@open-mercato/core/modules/attachments/data/entities\";\nimport {\n ensureDefaultPartitions,\n resolveDefaultPartitionCode,\n} from \"@open-mercato/core/modules/attachments/lib/partitions\";\nimport { storePartitionFile } from \"@open-mercato/core/modules/attachments/lib/storage\";\nimport { mergeAttachmentMetadata } from \"@open-mercato/core/modules/attachments/lib/metadata\";\nimport {\n buildAttachmentFileUrl,\n buildAttachmentImageUrl,\n slugifyAttachmentFileName,\n} from \"@open-mercato/core/modules/attachments/lib/imageUrls\";\nimport { canonicalizeUnitCode } from \"../lib/unitCodes\";\n\ntype SeedScope = { tenantId: string; organizationId: string };\n\nconst EXAMPLES_MEDIA_ROOT = path.join(process.cwd(), \"public\", \"examples\");\n\nfunction detectMimeType(fileName: string): string {\n const ext = fileName.toLowerCase().split(\".\").pop() || \"\";\n if (ext === \"png\") return \"image/png\";\n if (ext === \"jpg\" || ext === \"jpeg\") return \"image/jpeg\";\n if (ext === \"webp\") return \"image/webp\";\n return \"application/octet-stream\";\n}\n\nasync function ensureAttachmentPartition(\n em: EntityManager,\n code: string,\n): Promise<AttachmentPartition> {\n let partition = await em.findOne(AttachmentPartition, { code });\n if (!partition) {\n await ensureDefaultPartitions(em);\n partition = await em.findOne(AttachmentPartition, { code });\n }\n if (!partition) {\n throw new Error(`Attachment partition \"${code}\" is not configured.`);\n }\n return partition;\n}\n\nasync function attachMediaFromExamples(\n em: EntityManager,\n scope: SeedScope,\n entityId: string,\n recordId: string,\n mediaSeeds?: MediaSeed[],\n): Promise<Array<{ id: string; imageUrl: string }>> {\n if (!mediaSeeds?.length) return [];\n const partitionCode = resolveDefaultPartitionCode(entityId);\n const partition = await ensureAttachmentPartition(em, partitionCode);\n const results: Array<{ id: string; imageUrl: string }> = [];\n for (const media of mediaSeeds) {\n const sourcePath = path.join(EXAMPLES_MEDIA_ROOT, media.file);\n let buffer: Buffer;\n try {\n buffer = await fs.readFile(sourcePath);\n } catch (error) {\n console.warn(`[catalog.seed] Example media missing: ${sourcePath}`);\n continue;\n }\n const stored = await storePartitionFile({\n partitionCode: partition.code,\n orgId: scope.organizationId,\n tenantId: scope.tenantId,\n fileName: media.file,\n buffer,\n });\n const attachmentId = randomUUID();\n const slug = slugifyAttachmentFileName(media.file, \"media\");\n const metadata = mergeAttachmentMetadata(null, {\n assignments: [{ type: entityId, id: recordId }],\n });\n const attachment = em.create(Attachment, {\n id: attachmentId,\n entityId,\n recordId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n partitionCode: partition.code,\n fileName: media.file,\n mimeType: detectMimeType(media.file),\n fileSize: buffer.length,\n storageDriver: partition.storageDriver || \"local\",\n storagePath: stored.storagePath,\n storageMetadata: metadata,\n url: buildAttachmentFileUrl(attachmentId),\n });\n em.persist(attachment);\n results.push({\n id: attachmentId,\n imageUrl: buildAttachmentImageUrl(attachmentId, { slug }),\n });\n }\n return results;\n}\n\nconst PRODUCT_FIELDSETS = [\n {\n code: \"fashion_mens_footwear\",\n label: \"Fashion \u00B7 Men \u00B7 Footwear\",\n icon: \"carbon:sneaker\",\n description:\n \"Material, construction, and care metadata for men\u2019s performance footwear.\",\n groups: [\n { code: \"identity\", title: \"Identity\" },\n { code: \"materials\", title: \"Materials & Build\" },\n { code: \"care\", title: \"Care instructions\" },\n ],\n },\n {\n code: \"fashion_womens_dresses\",\n label: \"Fashion \u00B7 Women \u00B7 Dresses & Jumpsuits\",\n icon: \"solar:dress-linear\",\n description: \"Silhouette, fabric, and care metadata for womenswear.\",\n groups: [\n { code: \"identity\", title: \"Identity\" },\n { code: \"materials\", title: \"Materials\" },\n { code: \"fit\", title: \"Fit & Length\" },\n { code: \"care\", title: \"Care instructions\" },\n ],\n },\n {\n code: \"service_schedule\",\n label: \"Services \u00B7 Scheduling\",\n icon: \"solar:calendar-linear\",\n description:\n \"Scheduling, preparation, and delivery metadata for service offerings.\",\n groups: [\n { code: \"identity\", title: \"Identity\" },\n { code: \"timing\", title: \"Timing rules\" },\n { code: \"resources\", title: \"Resources & Delivery\" },\n ],\n },\n] as const;\n\nconst VARIANT_FIELDSETS = [\n {\n code: \"fashion_mens_footwear\",\n label: \"Fashion \u00B7 Men \u00B7 Footwear\",\n icon: \"carbon:sneaker\",\n description: \"Variant-level sizing metadata for men\u2019s footwear.\",\n groups: [\n { code: \"fit\", title: \"Fit\" },\n { code: \"finish\", title: \"Finish\" },\n ],\n },\n {\n code: \"fashion_womens_dresses\",\n label: \"Fashion \u00B7 Women \u00B7 Dresses & Jumpsuits\",\n icon: \"solar:dress-linear\",\n description: \"Variant-level sizing metadata for womenswear.\",\n groups: [\n { code: \"fit\", title: \"Fit\" },\n { code: \"finish\", title: \"Finish\" },\n ],\n },\n {\n code: \"service_schedule\",\n label: \"Services \u00B7 Scheduling\",\n icon: \"solar:calendar-linear\",\n description:\n \"Provider, duration, and environment metadata for service slots.\",\n groups: [\n { code: \"provider\", title: \"Provider\" },\n { code: \"environment\", title: \"Environment\" },\n ],\n },\n] as const;\n\nconst CUSTOM_FIELD_SETS: FieldSetInput[] = [\n defineFields(E.catalog.catalog_product, [\n cf.text(\"style_code\", {\n label: \"Style code\",\n description: \"Reference code shared with merchandising teams.\",\n filterable: true,\n fieldset: \"fashion_mens_footwear\",\n group: { code: \"identity\" },\n }),\n cf.select(\n \"upper_material\",\n [\"engineered_knit\", \"full_grain_leather\", \"recycled_mesh\"],\n {\n label: \"Upper material\",\n fieldset: \"fashion_mens_footwear\",\n group: { code: \"materials\" },\n filterable: true,\n },\n ),\n cf.select(\"cushioning_profile\", [\"responsive\", \"plush\", \"stability\"], {\n label: \"Cushioning profile\",\n fieldset: \"fashion_mens_footwear\",\n group: { code: \"materials\" },\n }),\n cf.multiline(\"care_notes\", {\n label: \"Care notes\",\n editor: \"markdown\",\n fieldset: \"fashion_mens_footwear\",\n group: { code: \"care\" },\n }),\n ]),\n defineFields(E.catalog.catalog_product, [\n cf.select(\"silhouette\", [\"wrap\", \"column\", \"fit_and_flare\", \"jumpsuit\"], {\n label: \"Silhouette\",\n fieldset: \"fashion_womens_dresses\",\n group: { code: \"identity\" },\n filterable: true,\n }),\n cf.select(\"fabric_mix\", [\"silk_blend\", \"recycled_poly\", \"linen\", \"cupro\"], {\n label: \"Fabric mix\",\n fieldset: \"fashion_womens_dresses\",\n group: { code: \"materials\" },\n }),\n cf.select(\"occasion_ready\", [\"daytime\", \"evening\", \"resort\"], {\n label: \"Occasion\",\n fieldset: \"fashion_womens_dresses\",\n group: { code: \"fit\" },\n }),\n cf.multiline(\"finishing_details\", {\n label: \"Finishing details\",\n editor: \"markdown\",\n fieldset: \"fashion_womens_dresses\",\n group: { code: \"care\" },\n }),\n ]),\n defineFields(E.catalog.catalog_product_variant, [\n cf.integer(\"shoe_size\", {\n label: \"US size\",\n fieldset: \"fashion_mens_footwear\",\n group: { code: \"fit\" },\n filterable: true,\n }),\n cf.select(\"shoe_width\", [\"B\", \"D\", \"EE\"], {\n label: \"Width\",\n fieldset: \"fashion_mens_footwear\",\n group: { code: \"fit\" },\n }),\n cf.text(\"colorway\", {\n label: \"Colorway\",\n fieldset: \"fashion_mens_footwear\",\n group: { code: \"finish\" },\n }),\n ]),\n defineFields(E.catalog.catalog_product_variant, [\n cf.integer(\"numeric_size\", {\n label: \"Numeric size\",\n fieldset: \"fashion_womens_dresses\",\n group: { code: \"fit\" },\n }),\n cf.select(\"length_profile\", [\"mini\", \"midi\", \"maxi\"], {\n label: \"Length\",\n fieldset: \"fashion_womens_dresses\",\n group: { code: \"fit\" },\n }),\n cf.text(\"color_story\", {\n label: \"Color story\",\n fieldset: \"fashion_womens_dresses\",\n group: { code: \"finish\" },\n }),\n ]),\n defineFields(E.catalog.catalog_product, [\n cf.integer(\"service_duration_minutes\", {\n label: \"Duration (minutes)\",\n description: \"Length of a single service slot.\",\n fieldset: \"service_schedule\",\n group: { code: \"timing\" },\n filterable: true,\n required: true,\n }),\n cf.integer(\"service_buffer_minutes\", {\n label: \"Buffer between appointments\",\n description:\n \"Minimum downtime between consecutive service slots (minutes).\",\n fieldset: \"service_schedule\",\n group: { code: \"timing\" },\n }),\n cf.text(\"service_location\", {\n label: \"Location / Room\",\n description: \"Where the service is delivered.\",\n fieldset: \"service_schedule\",\n group: { code: \"identity\" },\n }),\n cf.select(\n \"service_resources\",\n [\"stylist\", \"therapist\", \"treatment_room\", \"wash_station\", \"steam_room\"],\n {\n label: \"Required resources\",\n description: \"Staff or rooms required to perform the service.\",\n fieldset: \"service_schedule\",\n group: { code: \"resources\" },\n multi: true,\n },\n ),\n cf.boolean(\"service_remote_available\", {\n label: \"Remote session available\",\n description:\n \"Indicates whether the service can be performed remotely or virtually.\",\n fieldset: \"service_schedule\",\n group: { code: \"resources\" },\n defaultValue: false,\n }),\n ]),\n defineFields(E.catalog.catalog_product_variant, [\n cf.select(\"provider_level\", [\"junior\", \"senior\", \"master\"], {\n label: \"Provider level\",\n description: \"Seniority of the assigned specialist.\",\n fieldset: \"service_schedule\",\n group: { code: \"provider\" },\n filterable: true,\n }),\n cf.text(\"staff_member\", {\n label: \"Staff member\",\n description:\n \"Optional name of the staff member who usually delivers this variant.\",\n fieldset: \"service_schedule\",\n group: { code: \"provider\" },\n }),\n cf.select(\"environment_type\", [\"studio\", \"suite\", \"on_site\"], {\n label: \"Environment\",\n description: \"Where the session is hosted.\",\n fieldset: \"service_schedule\",\n group: { code: \"environment\" },\n }),\n ]),\n];\n\ntype CategorySeed = {\n slug: string;\n name: string;\n description?: string;\n children?: CategorySeed[];\n};\n\nconst CATEGORY_TREE: CategorySeed[] = [\n {\n slug: \"fashion\",\n name: \"Fashion\",\n description: \"Seasonal assortments and vertical-specific collections.\",\n children: [\n {\n slug: \"fashion-men\",\n name: \"Men\",\n children: [\n {\n slug: \"fashion-men-footwear\",\n name: \"Footwear\",\n description: \"Premium sneakers, boots, and sandals.\",\n },\n ],\n },\n {\n slug: \"fashion-women\",\n name: \"Women\",\n children: [\n {\n slug: \"fashion-women-dresses-jumpsuits\",\n name: \"Dresses & Jumpsuits\",\n description: \"Occasion-ready dresses and tailored jumpsuits.\",\n },\n ],\n },\n ],\n },\n {\n slug: \"services\",\n name: \"Services\",\n description: \"Bookable in-person and virtual experiences.\",\n children: [\n {\n slug: \"services-hairdresser\",\n name: \"Hairdresser\",\n description:\n \"Salon services ranging from quick trims to signature looks.\",\n },\n {\n slug: \"services-massage\",\n name: \"Massage\",\n description: \"Wellness treatments and bodywork sessions.\",\n },\n ],\n },\n];\n\ntype MediaSeed = {\n file: string;\n title?: string;\n};\n\ntype VariantSeed = {\n name: string;\n sku: string;\n isDefault?: boolean;\n optionValues?: Record<string, string>;\n prices: {\n regular: number;\n sale?: number;\n };\n customFields?: Record<string, string | number | boolean | null>;\n media?: MediaSeed[];\n};\n\ntype ProductSeed = {\n title: string;\n handle: string;\n sku?: string;\n description: string;\n categorySlug: string;\n customFieldsetCode: string;\n variantFieldsetCode: string;\n unit: string;\n metadata?: Record<string, unknown>;\n customFields?: Record<string, string | number | boolean | null>;\n media?: MediaSeed[];\n variants: VariantSeed[];\n};\n\nconst PRODUCT_SEEDS: ProductSeed[] = [\n {\n title: \"Atlas Runner Sneaker\",\n handle: \"atlas-runner-sneaker\",\n sku: \"ATLAS-RUNNER\",\n description:\n \"Lightweight road sneaker engineered with a breathable knit upper, recycled TPU overlays, and a decoupled heel for smooth transitions.\",\n categorySlug: \"fashion-men-footwear\",\n customFieldsetCode: \"fashion_mens_footwear\",\n variantFieldsetCode: \"fashion_mens_footwear\",\n unit: \"pair\",\n metadata: { division: \"RunLab\", season: \"SS25\" },\n customFields: {\n style_code: \"AR-2025\",\n upper_material: \"engineered_knit\",\n cushioning_profile: \"responsive\",\n care_notes:\n \"Spot clean after each run and air dry. Avoid machine drying.\",\n },\n media: [{ file: \"atlas-runner-midnight-1.png\" }],\n variants: [\n {\n name: \"Midnight Navy \u00B7 US 8\",\n sku: \"ATLAS-RUN-NAVY-8\",\n isDefault: true,\n optionValues: { color: \"Midnight Navy\", size: \"US 8\" },\n prices: { regular: 168, sale: 148 },\n customFields: {\n shoe_size: 8,\n shoe_width: \"D\",\n colorway: \"Midnight Navy\",\n },\n media: [\n { file: \"atlas-runner-midnight-1.png\" },\n { file: \"atlas-runner-midnight-2.png\" },\n ],\n },\n {\n name: \"Glacier Grey \u00B7 US 10\",\n sku: \"ATLAS-RUN-GLACIER-10\",\n optionValues: { color: \"Glacier Grey\", size: \"US 10\" },\n prices: { regular: 168, sale: 138 },\n customFields: {\n shoe_size: 10,\n shoe_width: \"EE\",\n colorway: \"Glacier Grey\",\n },\n media: [\n { file: \"atlas-runner-glacier-1.png\" },\n { file: \"atlas-runner-glacier-2.png\" },\n ],\n },\n ],\n },\n {\n title: \"Aurora Wrap Dress\",\n handle: \"aurora-wrap-dress\",\n sku: \"AURORA-WRAP\",\n description:\n \"Bias-cut wrap dress with blouson sleeves, matte silk blend, and hidden interior snaps so the placket stays put at events.\",\n categorySlug: \"fashion-women-dresses-jumpsuits\",\n customFieldsetCode: \"fashion_womens_dresses\",\n variantFieldsetCode: \"fashion_womens_dresses\",\n unit: \"unit\",\n metadata: { capsule: \"Evening Atelier\", season: \"Resort 25\" },\n customFields: {\n silhouette: \"wrap\",\n fabric_mix: \"silk_blend\",\n occasion_ready: \"evening\",\n finishing_details:\n \"Hand-finished hem with subtle tonal beading along the wrap edge.\",\n },\n media: [{ file: \"aurora-wrap-rosewood.png\" }],\n variants: [\n {\n name: \"Rosewood \u00B7 Medium\",\n sku: \"AURORA-ROSE-M\",\n isDefault: true,\n optionValues: { color: \"Rosewood\", size: \"Medium\" },\n prices: { regular: 248, sale: 212 },\n customFields: {\n numeric_size: 6,\n length_profile: \"midi\",\n color_story: \"Rosewood\",\n },\n media: [{ file: \"aurora-wrap-rosewood.png\" }],\n },\n {\n name: \"Celestial \u00B7 Large\",\n sku: \"AURORA-CELESTIAL-L\",\n optionValues: { color: \"Celestial\", size: \"Large\" },\n prices: { regular: 248, sale: 198 },\n customFields: {\n numeric_size: 8,\n length_profile: \"maxi\",\n color_story: \"Celestial blue\",\n },\n media: [{ file: \"aurora-wrap-celestial.png\" }],\n },\n ],\n },\n {\n title: \"Signature Haircut & Finish\",\n handle: \"signature-haircut-service\",\n sku: \"SERV-HAIR-60\",\n description:\n \"Tailored haircut with relaxing wash, scalp massage, and styling finish. Designed for repeat visits in the demo portal.\",\n categorySlug: \"services-hairdresser\",\n customFieldsetCode: \"service_schedule\",\n variantFieldsetCode: \"service_schedule\",\n unit: \"hour\",\n metadata: { channel: \"salon\", serviceType: \"hairdresser\" },\n customFields: {\n service_duration_minutes: 60,\n service_buffer_minutes: 15,\n service_location: \"Salon Studio 3\",\n service_resources: \"stylist,wash_station\",\n service_remote_available: false,\n },\n media: [{ file: \"hairdresser-service.png\" }],\n variants: [\n {\n name: \"Senior Stylist \u00B7 60 min\",\n sku: \"SERV-HAIR-60-SENIOR\",\n isDefault: true,\n optionValues: { stylist: \"Senior\", duration: \"60\" },\n prices: { regular: 95, sale: 85 },\n customFields: {\n provider_level: \"senior\",\n staff_member: \"Amelia Hart\",\n environment_type: \"studio\",\n },\n media: [{ file: \"hairdresser-service.png\" }],\n },\n ],\n },\n {\n title: \"Restorative Massage Session\",\n handle: \"restorative-massage-service\",\n sku: \"SERV-MASSAGE-90\",\n description:\n \"Full-body massage with aromatherapy oils and guided breathing. Includes complimentary refreshments and studio amenities.\",\n categorySlug: \"services-massage\",\n customFieldsetCode: \"service_schedule\",\n variantFieldsetCode: \"service_schedule\",\n unit: \"hour\",\n metadata: { channel: \"wellness\", serviceType: \"massage\" },\n customFields: {\n service_duration_minutes: 90,\n service_buffer_minutes: 20,\n service_location: \"Wellness Suite B\",\n service_resources: \"therapist,treatment_room,steam_room\",\n service_remote_available: false,\n },\n media: [{ file: \"massage-service.png\" }],\n variants: [\n {\n name: \"Master Therapist \u00B7 90 min\",\n sku: \"SERV-MASSAGE-90-MASTER\",\n isDefault: true,\n optionValues: { therapist: \"Master\", duration: \"90\" },\n prices: { regular: 140, sale: 120 },\n customFields: {\n provider_level: \"master\",\n staff_member: \"Noah Li\",\n environment_type: \"suite\",\n },\n media: [{ file: \"massage-service.png\" }],\n },\n ],\n },\n];\n\nconst CHANNEL_DEFINITION = {\n code: \"fashion-online\",\n name: \"Mercato Fashion Online\",\n description: \"Direct-to-consumer storefront showcasing premium demos.\",\n websiteUrl: \"https://demo.open-mercato.com\",\n contactEmail: \"store@open-mercato.com\",\n};\n\nfunction formatMoney(value: number): string {\n return value.toFixed(2);\n}\n\nasync function resolveDefaultTaxRate(\n em: EntityManager,\n scope: SeedScope,\n): Promise<SalesTaxRate | null> {\n const [rate] = await em.find(\n SalesTaxRate,\n {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n },\n {\n limit: 1,\n orderBy: {\n isDefault: \"DESC\",\n priority: \"ASC\",\n rate: \"DESC\",\n createdAt: \"ASC\",\n },\n },\n );\n return rate ?? null;\n}\n\nasync function ensureFieldsetConfig(\n em: EntityManager,\n scope: SeedScope,\n entityId: string,\n fieldsets: typeof PRODUCT_FIELDSETS | typeof VARIANT_FIELDSETS,\n): Promise<void> {\n const now = new Date();\n let config = await em.findOne(CustomFieldEntityConfig, {\n entityId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n });\n if (!config) {\n config = em.create(CustomFieldEntityConfig, {\n id: randomUUID(),\n entityId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n isActive: true,\n createdAt: now,\n updatedAt: now,\n });\n }\n config.configJson = {\n fieldsets,\n singleFieldsetPerRecord: true,\n };\n config.isActive = true;\n config.updatedAt = now;\n em.persist(config);\n}\n\nasync function ensureFieldsetsAndDefinitions(\n em: EntityManager,\n scope: SeedScope,\n): Promise<void> {\n await ensureFieldsetConfig(\n em,\n scope,\n E.catalog.catalog_product,\n PRODUCT_FIELDSETS,\n );\n await ensureFieldsetConfig(\n em,\n scope,\n E.catalog.catalog_product_variant,\n VARIANT_FIELDSETS,\n );\n await ensureCustomFieldDefinitions(em, CUSTOM_FIELD_SETS, {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n });\n await em.flush();\n}\n\nasync function ensureCategories(\n em: EntityManager,\n scope: SeedScope,\n): Promise<Map<string, CatalogProductCategory>> {\n const map = new Map<string, CatalogProductCategory>();\n const now = new Date();\n\n const upsert = async (\n seed: CategorySeed,\n parent: CatalogProductCategory | null,\n ) => {\n let record = await em.findOne(CatalogProductCategory, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n slug: seed.slug,\n });\n if (!record) {\n record = em.create(CatalogProductCategory, {\n id: randomUUID(),\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n name: seed.name,\n slug: seed.slug,\n description: seed.description ?? null,\n parentId: parent ? parent.id : null,\n rootId: parent ? (parent.rootId ?? parent.id) : null,\n treePath: null,\n depth: parent ? (parent.depth ?? 0) + 1 : 0,\n ancestorIds: [],\n childIds: [],\n descendantIds: [],\n metadata: null,\n isActive: true,\n createdAt: now,\n updatedAt: now,\n });\n em.persist(record);\n } else {\n record.name = seed.name;\n record.description = seed.description ?? null;\n record.parentId = parent ? parent.id : null;\n record.isActive = true;\n record.updatedAt = now;\n }\n map.set(seed.slug, record);\n if (Array.isArray(seed.children)) {\n for (const child of seed.children) {\n await upsert(child, record);\n }\n }\n };\n\n for (const seed of CATEGORY_TREE) {\n await upsert(seed, null);\n }\n\n await em.flush();\n await rebuildCategoryHierarchyForOrganization(\n em,\n scope.organizationId,\n scope.tenantId,\n );\n\n return map;\n}\n\nasync function ensureChannel(\n em: EntityManager,\n scope: SeedScope,\n): Promise<SalesChannel> {\n const now = new Date();\n let channel = await em.findOne(SalesChannel, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n code: CHANNEL_DEFINITION.code,\n deletedAt: null,\n });\n if (!channel) {\n channel = em.create(SalesChannel, {\n id: randomUUID(),\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n code: CHANNEL_DEFINITION.code,\n name: CHANNEL_DEFINITION.name,\n description: CHANNEL_DEFINITION.description,\n websiteUrl: CHANNEL_DEFINITION.websiteUrl,\n contactEmail: CHANNEL_DEFINITION.contactEmail,\n status: \"active\",\n isActive: true,\n metadata: { locale: \"en-US\" },\n createdAt: now,\n updatedAt: now,\n });\n em.persist(channel);\n await em.flush();\n }\n return channel;\n}\n\nasync function loadPriceKinds(\n em: EntityManager,\n scope: SeedScope,\n): Promise<Map<string, CatalogPriceKind>> {\n const kinds = await em.find(CatalogPriceKind, {\n tenantId: scope.tenantId,\n code: { $in: [\"regular\", \"sale\"] },\n deletedAt: null,\n });\n const map = new Map<string, CatalogPriceKind>();\n for (const kind of kinds) {\n map.set(kind.code.toLowerCase(), kind);\n }\n return map;\n}\n\nexport async function seedCatalogExamples(\n em: EntityManager,\n container: AwilixContainer,\n scope: SeedScope,\n): Promise<boolean> {\n await ensureFieldsetsAndDefinitions(em, scope);\n await ensureDefaultPartitions(em);\n\n const handles = PRODUCT_SEEDS.map((seed) => seed.handle);\n const existingProducts = await em.find(CatalogProduct, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n handle: { $in: [...handles] },\n });\n const existingByHandle = new Map(\n existingProducts.map((product) => [product.handle?.toLowerCase(), product]),\n );\n\n const categoryMap = await ensureCategories(em, scope);\n const channel = await ensureChannel(em, scope);\n const priceKinds = await loadPriceKinds(em, scope);\n const regularKind = priceKinds.get(\"regular\");\n const saleKind = priceKinds.get(\"sale\");\n const defaultTaxRate = await resolveDefaultTaxRate(em, scope);\n const defaultTaxRateId = defaultTaxRate?.id ?? null;\n const defaultTaxRateValue = defaultTaxRate?.rate ?? null;\n if (!regularKind || !saleKind) {\n throw new Error(\n \"Missing catalog price kinds; run `mercato catalog seed-price-kinds` first.\",\n );\n }\n\n const dataEngine = new DefaultDataEngine(em, container);\n const customFieldAssignments: Array<() => Promise<void>> = [];\n let createdAny = false;\n\n for (const productSeed of PRODUCT_SEEDS) {\n const existing = existingByHandle.get(productSeed.handle.toLowerCase());\n if (existing) {\n continue;\n }\n createdAny = true;\n const product = em.create(CatalogProduct, {\n id: randomUUID(),\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n title: productSeed.title,\n description: productSeed.description,\n sku: productSeed.sku ?? null,\n handle: productSeed.handle,\n productType: \"configurable\",\n primaryCurrencyCode: \"USD\",\n defaultUnit: canonicalizeUnitCode(productSeed.unit) ?? productSeed.unit,\n customFieldsetCode: productSeed.customFieldsetCode,\n metadata: productSeed.metadata ?? null,\n taxRateId: defaultTaxRateId,\n taxRate: defaultTaxRateValue,\n isConfigurable: true,\n isActive: true,\n createdAt: new Date(),\n updatedAt: new Date(),\n });\n em.persist(product);\n\n const category = categoryMap.get(productSeed.categorySlug);\n if (category) {\n const assignment = em.create(CatalogProductCategoryAssignment, {\n id: randomUUID(),\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n product,\n category,\n position: 0,\n createdAt: new Date(),\n updatedAt: new Date(),\n });\n em.persist(assignment);\n }\n\n const offer = em.create(CatalogOffer, {\n id: randomUUID(),\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n product,\n channelId: channel.id,\n title: `${productSeed.title} \u00B7 Online`,\n description: \"Offer curated for the demo storefront channel.\",\n metadata: { channelCode: CHANNEL_DEFINITION.code },\n isActive: true,\n createdAt: new Date(),\n updatedAt: new Date(),\n });\n em.persist(offer);\n\n if (\n productSeed.customFields &&\n Object.keys(productSeed.customFields).length\n ) {\n const payload = { ...productSeed.customFields };\n customFieldAssignments.push(() =>\n dataEngine.setCustomFields({\n entityId: E.catalog.catalog_product,\n recordId: product.id,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n values: payload,\n }),\n );\n }\n\n const productMedia = await attachMediaFromExamples(\n em,\n scope,\n E.catalog.catalog_product,\n product.id,\n productSeed.media,\n );\n if (productMedia.length) {\n const hero = productMedia[0];\n product.defaultMediaId = hero.id;\n product.defaultMediaUrl = hero.imageUrl;\n offer.defaultMediaId = hero.id;\n offer.defaultMediaUrl = hero.imageUrl;\n }\n\n for (const variantSeed of productSeed.variants) {\n const variant = em.create(CatalogProductVariant, {\n id: randomUUID(),\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n product,\n name: variantSeed.name,\n sku: variantSeed.sku,\n isDefault: variantSeed.isDefault ?? false,\n optionValues: variantSeed.optionValues ?? null,\n customFieldsetCode: productSeed.variantFieldsetCode,\n metadata: null,\n taxRateId: defaultTaxRateId,\n taxRate: defaultTaxRateValue,\n isActive: true,\n createdAt: new Date(),\n updatedAt: new Date(),\n });\n em.persist(variant);\n\n const variantMedia = await attachMediaFromExamples(\n em,\n scope,\n E.catalog.catalog_product_variant,\n variant.id,\n variantSeed.media,\n );\n const regularPrice = em.create(CatalogProductPrice, {\n id: randomUUID(),\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n product,\n variant,\n offer,\n priceKind: regularKind,\n currencyCode: \"USD\",\n kind: regularKind.code,\n minQuantity: 1,\n taxRate: defaultTaxRateValue,\n unitPriceGross: formatMoney(variantSeed.prices.regular),\n unitPriceNet: formatMoney(variantSeed.prices.regular),\n channelId: channel.id,\n createdAt: new Date(),\n updatedAt: new Date(),\n });\n em.persist(regularPrice);\n\n if (variantSeed.prices.sale !== undefined) {\n const salePrice = em.create(CatalogProductPrice, {\n id: randomUUID(),\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n product,\n variant,\n offer,\n priceKind: saleKind,\n currencyCode: \"USD\",\n kind: saleKind.code,\n minQuantity: 1,\n taxRate: defaultTaxRateValue,\n unitPriceGross: formatMoney(variantSeed.prices.sale),\n unitPriceNet: formatMoney(variantSeed.prices.sale),\n channelId: channel.id,\n createdAt: new Date(),\n updatedAt: new Date(),\n });\n em.persist(salePrice);\n }\n\n if (\n variantSeed.customFields &&\n Object.keys(variantSeed.customFields).length\n ) {\n const payload = { ...variantSeed.customFields };\n customFieldAssignments.push(() =>\n dataEngine.setCustomFields({\n entityId: E.catalog.catalog_product_variant,\n recordId: variant.id,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n values: payload,\n }),\n );\n }\n }\n }\n\n if (!createdAny) {\n return false;\n }\n\n await em.flush();\n\n for (const assign of customFieldAssignments) {\n try {\n await assign();\n } catch (err) {\n console.warn(\n \"[catalog.seed] Failed to set example custom field values\",\n err,\n );\n }\n }\n\n return true;\n}\n"],
5
+ "mappings": "AAAA,SAAS,kBAAkB;AAC3B,OAAO,UAAU;AACjB,SAAS,YAAY,UAAU;AAG/B,SAAS,oBAAoB;AAC7B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,yBAAyB;AAClC;AAAA,EACE;AAAA,OAEK;AACP,SAAS,+BAA+B;AACxC,SAAS,+CAA+C;AACxD,SAAS,cAAc,UAAU;AACjC,SAAS,SAAS;AAClB,SAAS,oBAAoB;AAC7B;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP,SAAS,0BAA0B;AACnC,SAAS,+BAA+B;AACxC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,4BAA4B;AAIrC,MAAM,sBAAsB,KAAK,KAAK,QAAQ,IAAI,GAAG,UAAU,UAAU;AAEzE,SAAS,eAAe,UAA0B;AAChD,QAAM,MAAM,SAAS,YAAY,EAAE,MAAM,GAAG,EAAE,IAAI,KAAK;AACvD,MAAI,QAAQ,MAAO,QAAO;AAC1B,MAAI,QAAQ,SAAS,QAAQ,OAAQ,QAAO;AAC5C,MAAI,QAAQ,OAAQ,QAAO;AAC3B,SAAO;AACT;AAEA,eAAe,0BACb,IACA,MAC8B;AAC9B,MAAI,YAAY,MAAM,GAAG,QAAQ,qBAAqB,EAAE,KAAK,CAAC;AAC9D,MAAI,CAAC,WAAW;AACd,UAAM,wBAAwB,EAAE;AAChC,gBAAY,MAAM,GAAG,QAAQ,qBAAqB,EAAE,KAAK,CAAC;AAAA,EAC5D;AACA,MAAI,CAAC,WAAW;AACd,UAAM,IAAI,MAAM,yBAAyB,IAAI,sBAAsB;AAAA,EACrE;AACA,SAAO;AACT;AAEA,eAAe,wBACb,IACA,OACA,UACA,UACA,YACkD;AAClD,MAAI,CAAC,YAAY,OAAQ,QAAO,CAAC;AACjC,QAAM,gBAAgB,4BAA4B,QAAQ;AAC1D,QAAM,YAAY,MAAM,0BAA0B,IAAI,aAAa;AACnE,QAAM,UAAmD,CAAC;AAC1D,aAAW,SAAS,YAAY;AAC9B,UAAM,aAAa,KAAK,KAAK,qBAAqB,MAAM,IAAI;AAC5D,QAAI;AACJ,QAAI;AACF,eAAS,MAAM,GAAG,SAAS,UAAU;AAAA,IACvC,SAAS,OAAO;AACd,cAAQ,KAAK,yCAAyC,UAAU,EAAE;AAClE;AAAA,IACF;AACA,UAAM,SAAS,MAAM,mBAAmB;AAAA,MACtC,eAAe,UAAU;AAAA,MACzB,OAAO,MAAM;AAAA,MACb,UAAU,MAAM;AAAA,MAChB,UAAU,MAAM;AAAA,MAChB;AAAA,IACF,CAAC;AACD,UAAM,eAAe,WAAW;AAChC,UAAM,OAAO,0BAA0B,MAAM,MAAM,OAAO;AAC1D,UAAM,WAAW,wBAAwB,MAAM;AAAA,MAC7C,aAAa,CAAC,EAAE,MAAM,UAAU,IAAI,SAAS,CAAC;AAAA,IAChD,CAAC;AACD,UAAM,aAAa,GAAG,OAAO,YAAY;AAAA,MACvC,IAAI;AAAA,MACJ;AAAA,MACA;AAAA,MACA,gBAAgB,MAAM;AAAA,MACtB,UAAU,MAAM;AAAA,MAChB,eAAe,UAAU;AAAA,MACzB,UAAU,MAAM;AAAA,MAChB,UAAU,eAAe,MAAM,IAAI;AAAA,MACnC,UAAU,OAAO;AAAA,MACjB,eAAe,UAAU,iBAAiB;AAAA,MAC1C,aAAa,OAAO;AAAA,MACpB,iBAAiB;AAAA,MACjB,KAAK,uBAAuB,YAAY;AAAA,IAC1C,CAAC;AACD,OAAG,QAAQ,UAAU;AACrB,YAAQ,KAAK;AAAA,MACX,IAAI;AAAA,MACJ,UAAU,wBAAwB,cAAc,EAAE,KAAK,CAAC;AAAA,IAC1D,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAEA,MAAM,oBAAoB;AAAA,EACxB;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,MAAM;AAAA,IACN,aACE;AAAA,IACF,QAAQ;AAAA,MACN,EAAE,MAAM,YAAY,OAAO,WAAW;AAAA,MACtC,EAAE,MAAM,aAAa,OAAO,oBAAoB;AAAA,MAChD,EAAE,MAAM,QAAQ,OAAO,oBAAoB;AAAA,IAC7C;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,MAAM;AAAA,IACN,aAAa;AAAA,IACb,QAAQ;AAAA,MACN,EAAE,MAAM,YAAY,OAAO,WAAW;AAAA,MACtC,EAAE,MAAM,aAAa,OAAO,YAAY;AAAA,MACxC,EAAE,MAAM,OAAO,OAAO,eAAe;AAAA,MACrC,EAAE,MAAM,QAAQ,OAAO,oBAAoB;AAAA,IAC7C;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,MAAM;AAAA,IACN,aACE;AAAA,IACF,QAAQ;AAAA,MACN,EAAE,MAAM,YAAY,OAAO,WAAW;AAAA,MACtC,EAAE,MAAM,UAAU,OAAO,eAAe;AAAA,MACxC,EAAE,MAAM,aAAa,OAAO,uBAAuB;AAAA,IACrD;AAAA,EACF;AACF;AAEA,MAAM,oBAAoB;AAAA,EACxB;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,MAAM;AAAA,IACN,aAAa;AAAA,IACb,QAAQ;AAAA,MACN,EAAE,MAAM,OAAO,OAAO,MAAM;AAAA,MAC5B,EAAE,MAAM,UAAU,OAAO,SAAS;AAAA,IACpC;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,MAAM;AAAA,IACN,aAAa;AAAA,IACb,QAAQ;AAAA,MACN,EAAE,MAAM,OAAO,OAAO,MAAM;AAAA,MAC5B,EAAE,MAAM,UAAU,OAAO,SAAS;AAAA,IACpC;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,MAAM;AAAA,IACN,aACE;AAAA,IACF,QAAQ;AAAA,MACN,EAAE,MAAM,YAAY,OAAO,WAAW;AAAA,MACtC,EAAE,MAAM,eAAe,OAAO,cAAc;AAAA,IAC9C;AAAA,EACF;AACF;AAEA,MAAM,oBAAqC;AAAA,EACzC,aAAa,EAAE,QAAQ,iBAAiB;AAAA,IACtC,GAAG,KAAK,cAAc;AAAA,MACpB,OAAO;AAAA,MACP,aAAa;AAAA,MACb,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,OAAO,EAAE,MAAM,WAAW;AAAA,IAC5B,CAAC;AAAA,IACD,GAAG;AAAA,MACD;AAAA,MACA,CAAC,mBAAmB,sBAAsB,eAAe;AAAA,MACzD;AAAA,QACE,OAAO;AAAA,QACP,UAAU;AAAA,QACV,OAAO,EAAE,MAAM,YAAY;AAAA,QAC3B,YAAY;AAAA,MACd;AAAA,IACF;AAAA,IACA,GAAG,OAAO,sBAAsB,CAAC,cAAc,SAAS,WAAW,GAAG;AAAA,MACpE,OAAO;AAAA,MACP,UAAU;AAAA,MACV,OAAO,EAAE,MAAM,YAAY;AAAA,IAC7B,CAAC;AAAA,IACD,GAAG,UAAU,cAAc;AAAA,MACzB,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,OAAO,EAAE,MAAM,OAAO;AAAA,IACxB,CAAC;AAAA,EACH,CAAC;AAAA,EACD,aAAa,EAAE,QAAQ,iBAAiB;AAAA,IACtC,GAAG,OAAO,cAAc,CAAC,QAAQ,UAAU,iBAAiB,UAAU,GAAG;AAAA,MACvE,OAAO;AAAA,MACP,UAAU;AAAA,MACV,OAAO,EAAE,MAAM,WAAW;AAAA,MAC1B,YAAY;AAAA,IACd,CAAC;AAAA,IACD,GAAG,OAAO,cAAc,CAAC,cAAc,iBAAiB,SAAS,OAAO,GAAG;AAAA,MACzE,OAAO;AAAA,MACP,UAAU;AAAA,MACV,OAAO,EAAE,MAAM,YAAY;AAAA,IAC7B,CAAC;AAAA,IACD,GAAG,OAAO,kBAAkB,CAAC,WAAW,WAAW,QAAQ,GAAG;AAAA,MAC5D,OAAO;AAAA,MACP,UAAU;AAAA,MACV,OAAO,EAAE,MAAM,MAAM;AAAA,IACvB,CAAC;AAAA,IACD,GAAG,UAAU,qBAAqB;AAAA,MAChC,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,OAAO,EAAE,MAAM,OAAO;AAAA,IACxB,CAAC;AAAA,EACH,CAAC;AAAA,EACD,aAAa,EAAE,QAAQ,yBAAyB;AAAA,IAC9C,GAAG,QAAQ,aAAa;AAAA,MACtB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,OAAO,EAAE,MAAM,MAAM;AAAA,MACrB,YAAY;AAAA,IACd,CAAC;AAAA,IACD,GAAG,OAAO,cAAc,CAAC,KAAK,KAAK,IAAI,GAAG;AAAA,MACxC,OAAO;AAAA,MACP,UAAU;AAAA,MACV,OAAO,EAAE,MAAM,MAAM;AAAA,IACvB,CAAC;AAAA,IACD,GAAG,KAAK,YAAY;AAAA,MAClB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,OAAO,EAAE,MAAM,SAAS;AAAA,IAC1B,CAAC;AAAA,EACH,CAAC;AAAA,EACD,aAAa,EAAE,QAAQ,yBAAyB;AAAA,IAC9C,GAAG,QAAQ,gBAAgB;AAAA,MACzB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,OAAO,EAAE,MAAM,MAAM;AAAA,IACvB,CAAC;AAAA,IACD,GAAG,OAAO,kBAAkB,CAAC,QAAQ,QAAQ,MAAM,GAAG;AAAA,MACpD,OAAO;AAAA,MACP,UAAU;AAAA,MACV,OAAO,EAAE,MAAM,MAAM;AAAA,IACvB,CAAC;AAAA,IACD,GAAG,KAAK,eAAe;AAAA,MACrB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,OAAO,EAAE,MAAM,SAAS;AAAA,IAC1B,CAAC;AAAA,EACH,CAAC;AAAA,EACD,aAAa,EAAE,QAAQ,iBAAiB;AAAA,IACtC,GAAG,QAAQ,4BAA4B;AAAA,MACrC,OAAO;AAAA,MACP,aAAa;AAAA,MACb,UAAU;AAAA,MACV,OAAO,EAAE,MAAM,SAAS;AAAA,MACxB,YAAY;AAAA,MACZ,UAAU;AAAA,IACZ,CAAC;AAAA,IACD,GAAG,QAAQ,0BAA0B;AAAA,MACnC,OAAO;AAAA,MACP,aACE;AAAA,MACF,UAAU;AAAA,MACV,OAAO,EAAE,MAAM,SAAS;AAAA,IAC1B,CAAC;AAAA,IACD,GAAG,KAAK,oBAAoB;AAAA,MAC1B,OAAO;AAAA,MACP,aAAa;AAAA,MACb,UAAU;AAAA,MACV,OAAO,EAAE,MAAM,WAAW;AAAA,IAC5B,CAAC;AAAA,IACD,GAAG;AAAA,MACD;AAAA,MACA,CAAC,WAAW,aAAa,kBAAkB,gBAAgB,YAAY;AAAA,MACvE;AAAA,QACE,OAAO;AAAA,QACP,aAAa;AAAA,QACb,UAAU;AAAA,QACV,OAAO,EAAE,MAAM,YAAY;AAAA,QAC3B,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,GAAG,QAAQ,4BAA4B;AAAA,MACrC,OAAO;AAAA,MACP,aACE;AAAA,MACF,UAAU;AAAA,MACV,OAAO,EAAE,MAAM,YAAY;AAAA,MAC3B,cAAc;AAAA,IAChB,CAAC;AAAA,EACH,CAAC;AAAA,EACD,aAAa,EAAE,QAAQ,yBAAyB;AAAA,IAC9C,GAAG,OAAO,kBAAkB,CAAC,UAAU,UAAU,QAAQ,GAAG;AAAA,MAC1D,OAAO;AAAA,MACP,aAAa;AAAA,MACb,UAAU;AAAA,MACV,OAAO,EAAE,MAAM,WAAW;AAAA,MAC1B,YAAY;AAAA,IACd,CAAC;AAAA,IACD,GAAG,KAAK,gBAAgB;AAAA,MACtB,OAAO;AAAA,MACP,aACE;AAAA,MACF,UAAU;AAAA,MACV,OAAO,EAAE,MAAM,WAAW;AAAA,IAC5B,CAAC;AAAA,IACD,GAAG,OAAO,oBAAoB,CAAC,UAAU,SAAS,SAAS,GAAG;AAAA,MAC5D,OAAO;AAAA,MACP,aAAa;AAAA,MACb,UAAU;AAAA,MACV,OAAO,EAAE,MAAM,cAAc;AAAA,IAC/B,CAAC;AAAA,EACH,CAAC;AACH;AASA,MAAM,gBAAgC;AAAA,EACpC;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,MACR;AAAA,QACE,MAAM;AAAA,QACN,MAAM;AAAA,QACN,UAAU;AAAA,UACR;AAAA,YACE,MAAM;AAAA,YACN,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,QACF;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,MAAM;AAAA,QACN,UAAU;AAAA,UACR;AAAA,YACE,MAAM;AAAA,YACN,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,MACR;AAAA,QACE,MAAM;AAAA,QACN,MAAM;AAAA,QACN,aACE;AAAA,MACJ;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,MAAM;AAAA,QACN,aAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF;AACF;AAmCA,MAAM,gBAA+B;AAAA,EACnC;AAAA,IACE,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,KAAK;AAAA,IACL,aACE;AAAA,IACF,cAAc;AAAA,IACd,oBAAoB;AAAA,IACpB,qBAAqB;AAAA,IACrB,MAAM;AAAA,IACN,UAAU,EAAE,UAAU,UAAU,QAAQ,OAAO;AAAA,IAC/C,cAAc;AAAA,MACZ,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,oBAAoB;AAAA,MACpB,YACE;AAAA,IACJ;AAAA,IACA,OAAO,CAAC,EAAE,MAAM,8BAA8B,CAAC;AAAA,IAC/C,UAAU;AAAA,MACR;AAAA,QACE,MAAM;AAAA,QACN,KAAK;AAAA,QACL,WAAW;AAAA,QACX,cAAc,EAAE,OAAO,iBAAiB,MAAM,OAAO;AAAA,QACrD,QAAQ,EAAE,SAAS,KAAK,MAAM,IAAI;AAAA,QAClC,cAAc;AAAA,UACZ,WAAW;AAAA,UACX,YAAY;AAAA,UACZ,UAAU;AAAA,QACZ;AAAA,QACA,OAAO;AAAA,UACL,EAAE,MAAM,8BAA8B;AAAA,UACtC,EAAE,MAAM,8BAA8B;AAAA,QACxC;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,KAAK;AAAA,QACL,cAAc,EAAE,OAAO,gBAAgB,MAAM,QAAQ;AAAA,QACrD,QAAQ,EAAE,SAAS,KAAK,MAAM,IAAI;AAAA,QAClC,cAAc;AAAA,UACZ,WAAW;AAAA,UACX,YAAY;AAAA,UACZ,UAAU;AAAA,QACZ;AAAA,QACA,OAAO;AAAA,UACL,EAAE,MAAM,6BAA6B;AAAA,UACrC,EAAE,MAAM,6BAA6B;AAAA,QACvC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,KAAK;AAAA,IACL,aACE;AAAA,IACF,cAAc;AAAA,IACd,oBAAoB;AAAA,IACpB,qBAAqB;AAAA,IACrB,MAAM;AAAA,IACN,UAAU,EAAE,SAAS,mBAAmB,QAAQ,YAAY;AAAA,IAC5D,cAAc;AAAA,MACZ,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,mBACE;AAAA,IACJ;AAAA,IACA,OAAO,CAAC,EAAE,MAAM,2BAA2B,CAAC;AAAA,IAC5C,UAAU;AAAA,MACR;AAAA,QACE,MAAM;AAAA,QACN,KAAK;AAAA,QACL,WAAW;AAAA,QACX,cAAc,EAAE,OAAO,YAAY,MAAM,SAAS;AAAA,QAClD,QAAQ,EAAE,SAAS,KAAK,MAAM,IAAI;AAAA,QAClC,cAAc;AAAA,UACZ,cAAc;AAAA,UACd,gBAAgB;AAAA,UAChB,aAAa;AAAA,QACf;AAAA,QACA,OAAO,CAAC,EAAE,MAAM,2BAA2B,CAAC;AAAA,MAC9C;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,KAAK;AAAA,QACL,cAAc,EAAE,OAAO,aAAa,MAAM,QAAQ;AAAA,QAClD,QAAQ,EAAE,SAAS,KAAK,MAAM,IAAI;AAAA,QAClC,cAAc;AAAA,UACZ,cAAc;AAAA,UACd,gBAAgB;AAAA,UAChB,aAAa;AAAA,QACf;AAAA,QACA,OAAO,CAAC,EAAE,MAAM,4BAA4B,CAAC;AAAA,MAC/C;AAAA,IACF;AAAA,EACF;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,KAAK;AAAA,IACL,aACE;AAAA,IACF,cAAc;AAAA,IACd,oBAAoB;AAAA,IACpB,qBAAqB;AAAA,IACrB,MAAM;AAAA,IACN,UAAU,EAAE,SAAS,SAAS,aAAa,cAAc;AAAA,IACzD,cAAc;AAAA,MACZ,0BAA0B;AAAA,MAC1B,wBAAwB;AAAA,MACxB,kBAAkB;AAAA,MAClB,mBAAmB;AAAA,MACnB,0BAA0B;AAAA,IAC5B;AAAA,IACA,OAAO,CAAC,EAAE,MAAM,0BAA0B,CAAC;AAAA,IAC3C,UAAU;AAAA,MACR;AAAA,QACE,MAAM;AAAA,QACN,KAAK;AAAA,QACL,WAAW;AAAA,QACX,cAAc,EAAE,SAAS,UAAU,UAAU,KAAK;AAAA,QAClD,QAAQ,EAAE,SAAS,IAAI,MAAM,GAAG;AAAA,QAChC,cAAc;AAAA,UACZ,gBAAgB;AAAA,UAChB,cAAc;AAAA,UACd,kBAAkB;AAAA,QACpB;AAAA,QACA,OAAO,CAAC,EAAE,MAAM,0BAA0B,CAAC;AAAA,MAC7C;AAAA,IACF;AAAA,EACF;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,KAAK;AAAA,IACL,aACE;AAAA,IACF,cAAc;AAAA,IACd,oBAAoB;AAAA,IACpB,qBAAqB;AAAA,IACrB,MAAM;AAAA,IACN,UAAU,EAAE,SAAS,YAAY,aAAa,UAAU;AAAA,IACxD,cAAc;AAAA,MACZ,0BAA0B;AAAA,MAC1B,wBAAwB;AAAA,MACxB,kBAAkB;AAAA,MAClB,mBAAmB;AAAA,MACnB,0BAA0B;AAAA,IAC5B;AAAA,IACA,OAAO,CAAC,EAAE,MAAM,sBAAsB,CAAC;AAAA,IACvC,UAAU;AAAA,MACR;AAAA,QACE,MAAM;AAAA,QACN,KAAK;AAAA,QACL,WAAW;AAAA,QACX,cAAc,EAAE,WAAW,UAAU,UAAU,KAAK;AAAA,QACpD,QAAQ,EAAE,SAAS,KAAK,MAAM,IAAI;AAAA,QAClC,cAAc;AAAA,UACZ,gBAAgB;AAAA,UAChB,cAAc;AAAA,UACd,kBAAkB;AAAA,QACpB;AAAA,QACA,OAAO,CAAC,EAAE,MAAM,sBAAsB,CAAC;AAAA,MACzC;AAAA,IACF;AAAA,EACF;AACF;AAEA,MAAM,qBAAqB;AAAA,EACzB,MAAM;AAAA,EACN,MAAM;AAAA,EACN,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,cAAc;AAChB;AAEA,SAAS,YAAY,OAAuB;AAC1C,SAAO,MAAM,QAAQ,CAAC;AACxB;AAEA,eAAe,sBACb,IACA,OAC8B;AAC9B,QAAM,CAAC,IAAI,IAAI,MAAM,GAAG;AAAA,IACtB;AAAA,IACA;AAAA,MACE,UAAU,MAAM;AAAA,MAChB,gBAAgB,MAAM;AAAA,MACtB,WAAW;AAAA,IACb;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,SAAS;AAAA,QACP,WAAW;AAAA,QACX,UAAU;AAAA,QACV,MAAM;AAAA,QACN,WAAW;AAAA,MACb;AAAA,IACF;AAAA,EACF;AACA,SAAO,QAAQ;AACjB;AAEA,eAAe,qBACb,IACA,OACA,UACA,WACe;AACf,QAAM,MAAM,oBAAI,KAAK;AACrB,MAAI,SAAS,MAAM,GAAG,QAAQ,yBAAyB;AAAA,IACrD;AAAA,IACA,gBAAgB,MAAM;AAAA,IACtB,UAAU,MAAM;AAAA,EAClB,CAAC;AACD,MAAI,CAAC,QAAQ;AACX,aAAS,GAAG,OAAO,yBAAyB;AAAA,MAC1C,IAAI,WAAW;AAAA,MACf;AAAA,MACA,gBAAgB,MAAM;AAAA,MACtB,UAAU,MAAM;AAAA,MAChB,UAAU;AAAA,MACV,WAAW;AAAA,MACX,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AACA,SAAO,aAAa;AAAA,IAClB;AAAA,IACA,yBAAyB;AAAA,EAC3B;AACA,SAAO,WAAW;AAClB,SAAO,YAAY;AACnB,KAAG,QAAQ,MAAM;AACnB;AAEA,eAAe,8BACb,IACA,OACe;AACf,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,EAAE,QAAQ;AAAA,IACV;AAAA,EACF;AACA,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,EAAE,QAAQ;AAAA,IACV;AAAA,EACF;AACA,QAAM,6BAA6B,IAAI,mBAAmB;AAAA,IACxD,gBAAgB,MAAM;AAAA,IACtB,UAAU,MAAM;AAAA,EAClB,CAAC;AACD,QAAM,GAAG,MAAM;AACjB;AAEA,eAAe,iBACb,IACA,OAC8C;AAC9C,QAAM,MAAM,oBAAI,IAAoC;AACpD,QAAM,MAAM,oBAAI,KAAK;AAErB,QAAM,SAAS,OACb,MACA,WACG;AACH,QAAI,SAAS,MAAM,GAAG,QAAQ,wBAAwB;AAAA,MACpD,UAAU,MAAM;AAAA,MAChB,gBAAgB,MAAM;AAAA,MACtB,MAAM,KAAK;AAAA,IACb,CAAC;AACD,QAAI,CAAC,QAAQ;AACX,eAAS,GAAG,OAAO,wBAAwB;AAAA,QACzC,IAAI,WAAW;AAAA,QACf,gBAAgB,MAAM;AAAA,QACtB,UAAU,MAAM;AAAA,QAChB,MAAM,KAAK;AAAA,QACX,MAAM,KAAK;AAAA,QACX,aAAa,KAAK,eAAe;AAAA,QACjC,UAAU,SAAS,OAAO,KAAK;AAAA,QAC/B,QAAQ,SAAU,OAAO,UAAU,OAAO,KAAM;AAAA,QAChD,UAAU;AAAA,QACV,OAAO,UAAU,OAAO,SAAS,KAAK,IAAI;AAAA,QAC1C,aAAa,CAAC;AAAA,QACd,UAAU,CAAC;AAAA,QACX,eAAe,CAAC;AAAA,QAChB,UAAU;AAAA,QACV,UAAU;AAAA,QACV,WAAW;AAAA,QACX,WAAW;AAAA,MACb,CAAC;AACD,SAAG,QAAQ,MAAM;AAAA,IACnB,OAAO;AACL,aAAO,OAAO,KAAK;AACnB,aAAO,cAAc,KAAK,eAAe;AACzC,aAAO,WAAW,SAAS,OAAO,KAAK;AACvC,aAAO,WAAW;AAClB,aAAO,YAAY;AAAA,IACrB;AACA,QAAI,IAAI,KAAK,MAAM,MAAM;AACzB,QAAI,MAAM,QAAQ,KAAK,QAAQ,GAAG;AAChC,iBAAW,SAAS,KAAK,UAAU;AACjC,cAAM,OAAO,OAAO,MAAM;AAAA,MAC5B;AAAA,IACF;AAAA,EACF;AAEA,aAAW,QAAQ,eAAe;AAChC,UAAM,OAAO,MAAM,IAAI;AAAA,EACzB;AAEA,QAAM,GAAG,MAAM;AACf,QAAM;AAAA,IACJ;AAAA,IACA,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAEA,SAAO;AACT;AAEA,eAAe,cACb,IACA,OACuB;AACvB,QAAM,MAAM,oBAAI,KAAK;AACrB,MAAI,UAAU,MAAM,GAAG,QAAQ,cAAc;AAAA,IAC3C,UAAU,MAAM;AAAA,IAChB,gBAAgB,MAAM;AAAA,IACtB,MAAM,mBAAmB;AAAA,IACzB,WAAW;AAAA,EACb,CAAC;AACD,MAAI,CAAC,SAAS;AACZ,cAAU,GAAG,OAAO,cAAc;AAAA,MAChC,IAAI,WAAW;AAAA,MACf,gBAAgB,MAAM;AAAA,MACtB,UAAU,MAAM;AAAA,MAChB,MAAM,mBAAmB;AAAA,MACzB,MAAM,mBAAmB;AAAA,MACzB,aAAa,mBAAmB;AAAA,MAChC,YAAY,mBAAmB;AAAA,MAC/B,cAAc,mBAAmB;AAAA,MACjC,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,UAAU,EAAE,QAAQ,QAAQ;AAAA,MAC5B,WAAW;AAAA,MACX,WAAW;AAAA,IACb,CAAC;AACD,OAAG,QAAQ,OAAO;AAClB,UAAM,GAAG,MAAM;AAAA,EACjB;AACA,SAAO;AACT;AAEA,eAAe,eACb,IACA,OACwC;AACxC,QAAM,QAAQ,MAAM,GAAG,KAAK,kBAAkB;AAAA,IAC5C,UAAU,MAAM;AAAA,IAChB,MAAM,EAAE,KAAK,CAAC,WAAW,MAAM,EAAE;AAAA,IACjC,WAAW;AAAA,EACb,CAAC;AACD,QAAM,MAAM,oBAAI,IAA8B;AAC9C,aAAW,QAAQ,OAAO;AACxB,QAAI,IAAI,KAAK,KAAK,YAAY,GAAG,IAAI;AAAA,EACvC;AACA,SAAO;AACT;AAEA,eAAsB,oBACpB,IACA,WACA,OACkB;AAClB,QAAM,8BAA8B,IAAI,KAAK;AAC7C,QAAM,wBAAwB,EAAE;AAEhC,QAAM,UAAU,cAAc,IAAI,CAAC,SAAS,KAAK,MAAM;AACvD,QAAM,mBAAmB,MAAM,GAAG,KAAK,gBAAgB;AAAA,IACrD,UAAU,MAAM;AAAA,IAChB,gBAAgB,MAAM;AAAA,IACtB,QAAQ,EAAE,KAAK,CAAC,GAAG,OAAO,EAAE;AAAA,EAC9B,CAAC;AACD,QAAM,mBAAmB,IAAI;AAAA,IAC3B,iBAAiB,IAAI,CAAC,YAAY,CAAC,QAAQ,QAAQ,YAAY,GAAG,OAAO,CAAC;AAAA,EAC5E;AAEA,QAAM,cAAc,MAAM,iBAAiB,IAAI,KAAK;AACpD,QAAM,UAAU,MAAM,cAAc,IAAI,KAAK;AAC7C,QAAM,aAAa,MAAM,eAAe,IAAI,KAAK;AACjD,QAAM,cAAc,WAAW,IAAI,SAAS;AAC5C,QAAM,WAAW,WAAW,IAAI,MAAM;AACtC,QAAM,iBAAiB,MAAM,sBAAsB,IAAI,KAAK;AAC5D,QAAM,mBAAmB,gBAAgB,MAAM;AAC/C,QAAM,sBAAsB,gBAAgB,QAAQ;AACpD,MAAI,CAAC,eAAe,CAAC,UAAU;AAC7B,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAAa,IAAI,kBAAkB,IAAI,SAAS;AACtD,QAAM,yBAAqD,CAAC;AAC5D,MAAI,aAAa;AAEjB,aAAW,eAAe,eAAe;AACvC,UAAM,WAAW,iBAAiB,IAAI,YAAY,OAAO,YAAY,CAAC;AACtE,QAAI,UAAU;AACZ;AAAA,IACF;AACA,iBAAa;AACb,UAAM,UAAU,GAAG,OAAO,gBAAgB;AAAA,MACxC,IAAI,WAAW;AAAA,MACf,gBAAgB,MAAM;AAAA,MACtB,UAAU,MAAM;AAAA,MAChB,OAAO,YAAY;AAAA,MACnB,aAAa,YAAY;AAAA,MACzB,KAAK,YAAY,OAAO;AAAA,MACxB,QAAQ,YAAY;AAAA,MACpB,aAAa;AAAA,MACb,qBAAqB;AAAA,MACrB,aAAa,qBAAqB,YAAY,IAAI,KAAK,YAAY;AAAA,MACnE,oBAAoB,YAAY;AAAA,MAChC,UAAU,YAAY,YAAY;AAAA,MAClC,WAAW;AAAA,MACX,SAAS;AAAA,MACT,gBAAgB;AAAA,MAChB,UAAU;AAAA,MACV,WAAW,oBAAI,KAAK;AAAA,MACpB,WAAW,oBAAI,KAAK;AAAA,IACtB,CAAC;AACD,OAAG,QAAQ,OAAO;AAElB,UAAM,WAAW,YAAY,IAAI,YAAY,YAAY;AACzD,QAAI,UAAU;AACZ,YAAM,aAAa,GAAG,OAAO,kCAAkC;AAAA,QAC7D,IAAI,WAAW;AAAA,QACf,gBAAgB,MAAM;AAAA,QACtB,UAAU,MAAM;AAAA,QAChB;AAAA,QACA;AAAA,QACA,UAAU;AAAA,QACV,WAAW,oBAAI,KAAK;AAAA,QACpB,WAAW,oBAAI,KAAK;AAAA,MACtB,CAAC;AACD,SAAG,QAAQ,UAAU;AAAA,IACvB;AAEA,UAAM,QAAQ,GAAG,OAAO,cAAc;AAAA,MACpC,IAAI,WAAW;AAAA,MACf,gBAAgB,MAAM;AAAA,MACtB,UAAU,MAAM;AAAA,MAChB;AAAA,MACA,WAAW,QAAQ;AAAA,MACnB,OAAO,GAAG,YAAY,KAAK;AAAA,MAC3B,aAAa;AAAA,MACb,UAAU,EAAE,aAAa,mBAAmB,KAAK;AAAA,MACjD,UAAU;AAAA,MACV,WAAW,oBAAI,KAAK;AAAA,MACpB,WAAW,oBAAI,KAAK;AAAA,IACtB,CAAC;AACD,OAAG,QAAQ,KAAK;AAEhB,QACE,YAAY,gBACZ,OAAO,KAAK,YAAY,YAAY,EAAE,QACtC;AACA,YAAM,UAAU,EAAE,GAAG,YAAY,aAAa;AAC9C,6BAAuB;AAAA,QAAK,MAC1B,WAAW,gBAAgB;AAAA,UACzB,UAAU,EAAE,QAAQ;AAAA,UACpB,UAAU,QAAQ;AAAA,UAClB,gBAAgB,MAAM;AAAA,UACtB,UAAU,MAAM;AAAA,UAChB,QAAQ;AAAA,QACV,CAAC;AAAA,MACH;AAAA,IACF;AAEA,UAAM,eAAe,MAAM;AAAA,MACzB;AAAA,MACA;AAAA,MACA,EAAE,QAAQ;AAAA,MACV,QAAQ;AAAA,MACR,YAAY;AAAA,IACd;AACA,QAAI,aAAa,QAAQ;AACvB,YAAM,OAAO,aAAa,CAAC;AAC3B,cAAQ,iBAAiB,KAAK;AAC9B,cAAQ,kBAAkB,KAAK;AAC/B,YAAM,iBAAiB,KAAK;AAC5B,YAAM,kBAAkB,KAAK;AAAA,IAC/B;AAEA,eAAW,eAAe,YAAY,UAAU;AAC9C,YAAM,UAAU,GAAG,OAAO,uBAAuB;AAAA,QAC/C,IAAI,WAAW;AAAA,QACf,gBAAgB,MAAM;AAAA,QACtB,UAAU,MAAM;AAAA,QAChB;AAAA,QACA,MAAM,YAAY;AAAA,QAClB,KAAK,YAAY;AAAA,QACjB,WAAW,YAAY,aAAa;AAAA,QACpC,cAAc,YAAY,gBAAgB;AAAA,QAC1C,oBAAoB,YAAY;AAAA,QAChC,UAAU;AAAA,QACV,WAAW;AAAA,QACX,SAAS;AAAA,QACT,UAAU;AAAA,QACV,WAAW,oBAAI,KAAK;AAAA,QACpB,WAAW,oBAAI,KAAK;AAAA,MACtB,CAAC;AACD,SAAG,QAAQ,OAAO;AAElB,YAAM,eAAe,MAAM;AAAA,QACzB;AAAA,QACA;AAAA,QACA,EAAE,QAAQ;AAAA,QACV,QAAQ;AAAA,QACR,YAAY;AAAA,MACd;AACA,YAAM,eAAe,GAAG,OAAO,qBAAqB;AAAA,QAClD,IAAI,WAAW;AAAA,QACf,gBAAgB,MAAM;AAAA,QACtB,UAAU,MAAM;AAAA,QAChB;AAAA,QACA;AAAA,QACA;AAAA,QACA,WAAW;AAAA,QACX,cAAc;AAAA,QACd,MAAM,YAAY;AAAA,QAClB,aAAa;AAAA,QACb,SAAS;AAAA,QACT,gBAAgB,YAAY,YAAY,OAAO,OAAO;AAAA,QACtD,cAAc,YAAY,YAAY,OAAO,OAAO;AAAA,QACpD,WAAW,QAAQ;AAAA,QACnB,WAAW,oBAAI,KAAK;AAAA,QACpB,WAAW,oBAAI,KAAK;AAAA,MACtB,CAAC;AACD,SAAG,QAAQ,YAAY;AAEvB,UAAI,YAAY,OAAO,SAAS,QAAW;AACzC,cAAM,YAAY,GAAG,OAAO,qBAAqB;AAAA,UAC/C,IAAI,WAAW;AAAA,UACf,gBAAgB,MAAM;AAAA,UACtB,UAAU,MAAM;AAAA,UAChB;AAAA,UACA;AAAA,UACA;AAAA,UACA,WAAW;AAAA,UACX,cAAc;AAAA,UACd,MAAM,SAAS;AAAA,UACf,aAAa;AAAA,UACb,SAAS;AAAA,UACT,gBAAgB,YAAY,YAAY,OAAO,IAAI;AAAA,UACnD,cAAc,YAAY,YAAY,OAAO,IAAI;AAAA,UACjD,WAAW,QAAQ;AAAA,UACnB,WAAW,oBAAI,KAAK;AAAA,UACpB,WAAW,oBAAI,KAAK;AAAA,QACtB,CAAC;AACD,WAAG,QAAQ,SAAS;AAAA,MACtB;AAEA,UACE,YAAY,gBACZ,OAAO,KAAK,YAAY,YAAY,EAAE,QACtC;AACA,cAAM,UAAU,EAAE,GAAG,YAAY,aAAa;AAC9C,+BAAuB;AAAA,UAAK,MAC1B,WAAW,gBAAgB;AAAA,YACzB,UAAU,EAAE,QAAQ;AAAA,YACpB,UAAU,QAAQ;AAAA,YAClB,gBAAgB,MAAM;AAAA,YACtB,UAAU,MAAM;AAAA,YAChB,QAAQ;AAAA,UACV,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAAC,YAAY;AACf,WAAO;AAAA,EACT;AAEA,QAAM,GAAG,MAAM;AAEf,aAAW,UAAU,wBAAwB;AAC3C,QAAI;AACF,YAAM,OAAO;AAAA,IACf,SAAS,KAAK;AACZ,cAAQ;AAAA,QACN;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;",
6
6
  "names": []
7
7
  }
@@ -306,6 +306,9 @@ async function seedAnalyticsData(em, scope, options = {}) {
306
306
  kind: "product",
307
307
  name: lineData.product.title,
308
308
  quantity: toAmount(lineData.quantity),
309
+ normalizedQuantity: toAmount(lineData.quantity),
310
+ normalizedUnit: null,
311
+ uomSnapshot: null,
309
312
  currencyCode: "USD",
310
313
  unitPriceNet: toAmount(lineData.unitPriceNet),
311
314
  unitPriceGross: toAmount(lineData.unitPriceGross),
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/dashboards/seed/analytics.ts"],
4
- "sourcesContent": ["import { randomUUID } from 'crypto'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport {\n SalesOrder,\n SalesOrderLine,\n} from '@open-mercato/core/modules/sales/data/entities'\nimport {\n CustomerEntity,\n CustomerCompanyProfile,\n CustomerDeal,\n} from '@open-mercato/core/modules/customers/data/entities'\nimport {\n CatalogProduct,\n CatalogProductVariant,\n} from '@open-mercato/core/modules/catalog/data/entities'\n\nexport type AnalyticsSeedScope = {\n tenantId: string\n organizationId: string\n}\n\nexport type AnalyticsSeedOptions = {\n months?: number\n ordersPerMonth?: number\n customersCount?: number\n productsCount?: number\n dealsCount?: number\n}\n\nconst ORDER_STATUSES = ['draft', 'pending', 'confirmed', 'processing', 'shipped', 'delivered', 'cancelled'] as const\nconst FULFILLMENT_STATUSES = ['pending', 'in_fulfillment', 'partially_fulfilled', 'fulfilled'] as const\nconst PAYMENT_STATUSES = ['unpaid', 'partial', 'paid', 'refunded'] as const\nconst DEAL_PIPELINE_STAGES = ['lead', 'qualified', 'proposal', 'negotiation', 'closed_won', 'closed_lost'] as const\nconst COUNTRIES = ['US', 'GB', 'DE', 'FR', 'CA', 'AU', 'NL', 'ES', 'IT', 'PL'] as const\nconst REGIONS_BY_COUNTRY: Record<string, string[]> = {\n US: ['California', 'New York', 'Texas', 'Florida', 'Illinois', 'Washington', 'Massachusetts'],\n GB: ['England', 'Scotland', 'Wales'],\n DE: ['Bavaria', 'Berlin', 'Hamburg', 'Hessen'],\n FR: ['\u00CEle-de-France', 'Provence', 'Rh\u00F4ne-Alpes'],\n CA: ['Ontario', 'Quebec', 'British Columbia'],\n AU: ['New South Wales', 'Victoria', 'Queensland'],\n NL: ['North Holland', 'South Holland'],\n ES: ['Madrid', 'Catalonia', 'Andalusia'],\n IT: ['Lombardy', 'Lazio', 'Veneto'],\n PL: ['Mazovia', 'Lesser Poland', 'Silesia'],\n}\n\nconst COMPANY_NAMES = [\n 'Acme Corp', 'Global Industries', 'Tech Solutions', 'Prime Services',\n 'Northern Analytics', 'Blue Ocean Trading', 'Summit Enterprises', 'Horizon Dynamics',\n 'Vertex Systems', 'Atlas Logistics', 'Pinnacle Group', 'Quantum Labs',\n 'Stellar Innovations', 'Pacific Partners', 'Apex Manufacturing', 'Nexus Technologies',\n 'Eclipse Ventures', 'Titan Holdings', 'Vanguard Solutions', 'Momentum Corp',\n 'Crystal Clear Media', 'Silver Line Transport', 'Golden Gate Imports', 'Red Rock Mining',\n 'Green Valley Foods', 'Blue Sky Aviation', 'White Mountain Retail', 'Black Diamond Sports',\n]\n\nconst PRODUCT_NAMES = [\n 'Premium Widget', 'Standard Component', 'Professional Kit', 'Enterprise Module',\n 'Basic Starter Pack', 'Advanced System', 'Deluxe Bundle', 'Essential Tools',\n 'Pro Series Device', 'Ultra Performance Unit', 'Classic Edition', 'Limited Series',\n 'Industrial Grade Part', 'Consumer Package', 'Business Solution', 'Home Edition',\n]\n\nconst DEAL_TITLES = [\n 'Enterprise License Deal', 'Annual Subscription', 'Pilot Program', 'Strategic Partnership',\n 'Volume Purchase Agreement', 'Service Contract', 'Implementation Project', 'Expansion Deal',\n 'Renewal Opportunity', 'Upsell Initiative', 'Cross-sell Package', 'Custom Solution',\n]\n\nfunction randomInt(min: number, max: number): number {\n return Math.floor(Math.random() * (max - min + 1)) + min\n}\n\nfunction randomFloat(min: number, max: number, decimals = 2): number {\n const value = Math.random() * (max - min) + min\n return Number(value.toFixed(decimals))\n}\n\nfunction randomElement<T>(arr: readonly T[]): T {\n return arr[Math.floor(Math.random() * arr.length)]\n}\n\nfunction randomElements<T>(arr: readonly T[], count: number): T[] {\n const shuffled = [...arr].sort(() => Math.random() - 0.5)\n return shuffled.slice(0, Math.min(count, arr.length))\n}\n\nfunction toAmount(value: number): string {\n return value.toFixed(2)\n}\n\nfunction daysAgo(days: number): Date {\n const date = new Date()\n date.setDate(date.getDate() - days)\n return date\n}\n\nfunction randomDateInRange(startDaysAgo: number, endDaysAgo: number): Date {\n const daysOffset = randomInt(endDaysAgo, startDaysAgo)\n return daysAgo(daysOffset)\n}\n\nfunction generateOrderNumber(index: number): string {\n return `SO-ANALYTICS-${String(index).padStart(5, '0')}`\n}\n\nexport async function seedAnalyticsData(\n em: EntityManager,\n scope: AnalyticsSeedScope,\n options: AnalyticsSeedOptions = {}\n): Promise<{ orders: number; customers: number; products: number; deals: number }> {\n const {\n months = 6,\n ordersPerMonth = 50,\n customersCount = 25,\n productsCount = 15,\n dealsCount = 20,\n } = options\n\n const existingOrders = await em.count(SalesOrder, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n orderNumber: { $like: 'SO-ANALYTICS-%' },\n })\n\n if (existingOrders > 0) {\n return { orders: 0, customers: 0, products: 0, deals: 0 }\n }\n\n const customers: CustomerEntity[] = []\n const products: CatalogProduct[] = []\n const variants: CatalogProductVariant[] = []\n\n for (let i = 0; i < customersCount; i++) {\n const companyName = COMPANY_NAMES[i % COMPANY_NAMES.length]\n const customerCreatedAt = randomDateInRange(months * 30 + 60, 0)\n\n const customer = em.create(CustomerEntity, {\n id: randomUUID(),\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n kind: 'company',\n displayName: `${companyName} #${i + 1}`,\n primaryEmail: `contact${i + 1}@${companyName.toLowerCase().replace(/\\s+/g, '')}.example.com`,\n status: 'active',\n lifecycleStage: randomElement(['lead', 'customer', 'opportunity']),\n isActive: true,\n createdAt: customerCreatedAt,\n updatedAt: customerCreatedAt,\n })\n em.persist(customer)\n customers.push(customer)\n\n const companyProfile = em.create(CustomerCompanyProfile, {\n id: randomUUID(),\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n entity: customer,\n legalName: `${companyName} Inc.`,\n brandName: companyName,\n industry: randomElement(['Technology', 'Manufacturing', 'Retail', 'Services', 'Healthcare']),\n sizeBucket: randomElement(['small', 'medium', 'large', 'enterprise']),\n annualRevenue: toAmount(randomFloat(100000, 50000000)),\n createdAt: customerCreatedAt,\n updatedAt: customerCreatedAt,\n })\n em.persist(companyProfile)\n }\n\n for (let i = 0; i < productsCount; i++) {\n const productName = PRODUCT_NAMES[i % PRODUCT_NAMES.length]\n const productCreatedAt = daysAgo(months * 30 + randomInt(0, 30))\n\n const product = em.create(CatalogProduct, {\n id: randomUUID(),\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n title: `${productName} ${i + 1}`,\n handle: `analytics-product-${i + 1}`,\n sku: `SKU-ANALYTICS-${String(i + 1).padStart(3, '0')}`,\n productType: 'simple',\n isConfigurable: false,\n isActive: true,\n createdAt: productCreatedAt,\n updatedAt: productCreatedAt,\n })\n em.persist(product)\n products.push(product)\n\n const variant = em.create(CatalogProductVariant, {\n id: randomUUID(),\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n product,\n name: 'Default',\n sku: `${product.sku}-DEFAULT`,\n isDefault: true,\n isActive: true,\n createdAt: productCreatedAt,\n updatedAt: productCreatedAt,\n })\n em.persist(variant)\n variants.push(variant)\n }\n\n let orderIndex = 1\n const totalDays = months * 30\n const orders: SalesOrder[] = []\n\n for (let dayOffset = totalDays; dayOffset >= 0; dayOffset--) {\n const ordersToday = Math.round(ordersPerMonth / 30 * randomFloat(0.5, 1.5))\n\n for (let j = 0; j < ordersToday; j++) {\n const orderDate = daysAgo(dayOffset)\n const customer = randomElement(customers)\n const country = randomElement(COUNTRIES)\n const region = randomElement(REGIONS_BY_COUNTRY[country] || [''])\n\n const lineCount = randomInt(1, 5)\n const selectedProducts = randomElements(products, lineCount)\n\n let subtotalNet = 0\n let subtotalGross = 0\n let taxTotal = 0\n\n const orderLines: Array<{\n product: CatalogProduct\n variant: CatalogProductVariant\n quantity: number\n unitPriceNet: number\n unitPriceGross: number\n taxRate: number\n lineNetAmount: number\n lineGrossAmount: number\n lineTaxAmount: number\n }> = []\n\n for (let k = 0; k < selectedProducts.length; k++) {\n const product = selectedProducts[k]\n const variant = variants.find((v) => v.product.id === product.id) || variants[0]\n const quantity = randomInt(1, 10)\n const unitPriceNet = randomFloat(10, 500)\n const taxRate = randomElement([0, 5, 10, 20, 23])\n const unitPriceGross = unitPriceNet * (1 + taxRate / 100)\n const lineNetAmount = unitPriceNet * quantity\n const lineGrossAmount = unitPriceGross * quantity\n const lineTaxAmount = lineGrossAmount - lineNetAmount\n\n subtotalNet += lineNetAmount\n subtotalGross += lineGrossAmount\n taxTotal += lineTaxAmount\n\n orderLines.push({\n product,\n variant,\n quantity,\n unitPriceNet,\n unitPriceGross,\n taxRate,\n lineNetAmount,\n lineGrossAmount,\n lineTaxAmount,\n })\n }\n\n const order = em.create(SalesOrder, {\n id: randomUUID(),\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n orderNumber: generateOrderNumber(orderIndex++),\n status: randomElement(ORDER_STATUSES),\n fulfillmentStatus: randomElement(FULFILLMENT_STATUSES),\n paymentStatus: randomElement(PAYMENT_STATUSES),\n customerEntityId: customer.id,\n customerSnapshot: {\n customer: {\n id: customer.id,\n kind: customer.kind,\n displayName: customer.displayName,\n },\n },\n currencyCode: 'USD',\n placedAt: orderDate,\n shippingAddressSnapshot: {\n country,\n region,\n city: `City ${randomInt(1, 100)}`,\n postalCode: String(randomInt(10000, 99999)),\n },\n billingAddressSnapshot: {\n country,\n region,\n city: `City ${randomInt(1, 100)}`,\n postalCode: String(randomInt(10000, 99999)),\n },\n subtotalNetAmount: toAmount(subtotalNet),\n subtotalGrossAmount: toAmount(subtotalGross),\n discountTotalAmount: '0.00',\n taxTotalAmount: toAmount(taxTotal),\n shippingNetAmount: '0.00',\n shippingGrossAmount: '0.00',\n surchargeTotalAmount: '0.00',\n grandTotalNetAmount: toAmount(subtotalNet),\n grandTotalGrossAmount: toAmount(subtotalGross),\n paidTotalAmount: '0.00',\n refundedTotalAmount: '0.00',\n outstandingAmount: toAmount(subtotalGross),\n lineItemCount: orderLines.length,\n metadata: { seed: 'dashboards.analytics' },\n createdAt: orderDate,\n updatedAt: orderDate,\n })\n em.persist(order)\n orders.push(order)\n\n for (let k = 0; k < orderLines.length; k++) {\n const lineData = orderLines[k]\n const line = em.create(SalesOrderLine, {\n id: randomUUID(),\n order,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n lineNumber: k + 1,\n kind: 'product',\n name: lineData.product.title,\n quantity: toAmount(lineData.quantity),\n currencyCode: 'USD',\n unitPriceNet: toAmount(lineData.unitPriceNet),\n unitPriceGross: toAmount(lineData.unitPriceGross),\n discountAmount: '0.00',\n discountPercent: '0.00',\n taxRate: toAmount(lineData.taxRate),\n taxAmount: toAmount(lineData.lineTaxAmount),\n totalNetAmount: toAmount(lineData.lineNetAmount),\n totalGrossAmount: toAmount(lineData.lineGrossAmount),\n reservedQuantity: '0',\n fulfilledQuantity: '0',\n invoicedQuantity: '0',\n returnedQuantity: '0',\n productId: lineData.product.id,\n productVariantId: lineData.variant?.id ?? null,\n catalogSnapshot: {\n product: {\n id: lineData.product.id,\n title: lineData.product.title,\n sku: lineData.product.sku,\n },\n variant: lineData.variant\n ? {\n id: lineData.variant.id,\n name: lineData.variant.name,\n sku: lineData.variant.sku,\n }\n : null,\n },\n createdAt: orderDate,\n updatedAt: orderDate,\n })\n em.persist(line)\n }\n }\n }\n\n for (let i = 0; i < dealsCount; i++) {\n const customer = randomElement(customers)\n const dealCreatedAt = randomDateInRange(months * 30, 0)\n const pipelineStage = randomElement(DEAL_PIPELINE_STAGES)\n\n const probabilityByStage: Record<string, number> = {\n lead: 10,\n qualified: 25,\n proposal: 50,\n negotiation: 75,\n closed_won: 100,\n closed_lost: 0,\n }\n\n const deal = em.create(CustomerDeal, {\n id: randomUUID(),\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n title: `${randomElement(DEAL_TITLES)} - ${customer.displayName}`,\n status: pipelineStage === 'closed_won' || pipelineStage === 'closed_lost' ? 'closed' : 'open',\n pipelineStage,\n valueAmount: toAmount(randomFloat(5000, 500000)),\n valueCurrency: 'USD',\n probability: probabilityByStage[pipelineStage],\n expectedCloseAt: daysAgo(randomInt(-60, 90)),\n source: randomElement(['inbound', 'outbound', 'referral', 'partner']),\n createdAt: dealCreatedAt,\n updatedAt: dealCreatedAt,\n })\n em.persist(deal)\n }\n\n await em.flush()\n\n return {\n orders: orders.length,\n customers: customers.length,\n products: products.length,\n deals: dealsCount,\n }\n}\n"],
5
- "mappings": "AAAA,SAAS,kBAAkB;AAE3B;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAeP,MAAM,iBAAiB,CAAC,SAAS,WAAW,aAAa,cAAc,WAAW,aAAa,WAAW;AAC1G,MAAM,uBAAuB,CAAC,WAAW,kBAAkB,uBAAuB,WAAW;AAC7F,MAAM,mBAAmB,CAAC,UAAU,WAAW,QAAQ,UAAU;AACjE,MAAM,uBAAuB,CAAC,QAAQ,aAAa,YAAY,eAAe,cAAc,aAAa;AACzG,MAAM,YAAY,CAAC,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,IAAI;AAC7E,MAAM,qBAA+C;AAAA,EACnD,IAAI,CAAC,cAAc,YAAY,SAAS,WAAW,YAAY,cAAc,eAAe;AAAA,EAC5F,IAAI,CAAC,WAAW,YAAY,OAAO;AAAA,EACnC,IAAI,CAAC,WAAW,UAAU,WAAW,QAAQ;AAAA,EAC7C,IAAI,CAAC,oBAAiB,YAAY,gBAAa;AAAA,EAC/C,IAAI,CAAC,WAAW,UAAU,kBAAkB;AAAA,EAC5C,IAAI,CAAC,mBAAmB,YAAY,YAAY;AAAA,EAChD,IAAI,CAAC,iBAAiB,eAAe;AAAA,EACrC,IAAI,CAAC,UAAU,aAAa,WAAW;AAAA,EACvC,IAAI,CAAC,YAAY,SAAS,QAAQ;AAAA,EAClC,IAAI,CAAC,WAAW,iBAAiB,SAAS;AAC5C;AAEA,MAAM,gBAAgB;AAAA,EACpB;AAAA,EAAa;AAAA,EAAqB;AAAA,EAAkB;AAAA,EACpD;AAAA,EAAsB;AAAA,EAAsB;AAAA,EAAsB;AAAA,EAClE;AAAA,EAAkB;AAAA,EAAmB;AAAA,EAAkB;AAAA,EACvD;AAAA,EAAuB;AAAA,EAAoB;AAAA,EAAsB;AAAA,EACjE;AAAA,EAAoB;AAAA,EAAkB;AAAA,EAAsB;AAAA,EAC5D;AAAA,EAAuB;AAAA,EAAyB;AAAA,EAAuB;AAAA,EACvE;AAAA,EAAsB;AAAA,EAAqB;AAAA,EAAyB;AACtE;AAEA,MAAM,gBAAgB;AAAA,EACpB;AAAA,EAAkB;AAAA,EAAsB;AAAA,EAAoB;AAAA,EAC5D;AAAA,EAAsB;AAAA,EAAmB;AAAA,EAAiB;AAAA,EAC1D;AAAA,EAAqB;AAAA,EAA0B;AAAA,EAAmB;AAAA,EAClE;AAAA,EAAyB;AAAA,EAAoB;AAAA,EAAqB;AACpE;AAEA,MAAM,cAAc;AAAA,EAClB;AAAA,EAA2B;AAAA,EAAuB;AAAA,EAAiB;AAAA,EACnE;AAAA,EAA6B;AAAA,EAAoB;AAAA,EAA0B;AAAA,EAC3E;AAAA,EAAuB;AAAA,EAAqB;AAAA,EAAsB;AACpE;AAEA,SAAS,UAAU,KAAa,KAAqB;AACnD,SAAO,KAAK,MAAM,KAAK,OAAO,KAAK,MAAM,MAAM,EAAE,IAAI;AACvD;AAEA,SAAS,YAAY,KAAa,KAAa,WAAW,GAAW;AACnE,QAAM,QAAQ,KAAK,OAAO,KAAK,MAAM,OAAO;AAC5C,SAAO,OAAO,MAAM,QAAQ,QAAQ,CAAC;AACvC;AAEA,SAAS,cAAiB,KAAsB;AAC9C,SAAO,IAAI,KAAK,MAAM,KAAK,OAAO,IAAI,IAAI,MAAM,CAAC;AACnD;AAEA,SAAS,eAAkB,KAAmB,OAAoB;AAChE,QAAM,WAAW,CAAC,GAAG,GAAG,EAAE,KAAK,MAAM,KAAK,OAAO,IAAI,GAAG;AACxD,SAAO,SAAS,MAAM,GAAG,KAAK,IAAI,OAAO,IAAI,MAAM,CAAC;AACtD;AAEA,SAAS,SAAS,OAAuB;AACvC,SAAO,MAAM,QAAQ,CAAC;AACxB;AAEA,SAAS,QAAQ,MAAoB;AACnC,QAAM,OAAO,oBAAI,KAAK;AACtB,OAAK,QAAQ,KAAK,QAAQ,IAAI,IAAI;AAClC,SAAO;AACT;AAEA,SAAS,kBAAkB,cAAsB,YAA0B;AACzE,QAAM,aAAa,UAAU,YAAY,YAAY;AACrD,SAAO,QAAQ,UAAU;AAC3B;AAEA,SAAS,oBAAoB,OAAuB;AAClD,SAAO,gBAAgB,OAAO,KAAK,EAAE,SAAS,GAAG,GAAG,CAAC;AACvD;AAEA,eAAsB,kBACpB,IACA,OACA,UAAgC,CAAC,GACgD;AACjF,QAAM;AAAA,IACJ,SAAS;AAAA,IACT,iBAAiB;AAAA,IACjB,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,IAChB,aAAa;AAAA,EACf,IAAI;AAEJ,QAAM,iBAAiB,MAAM,GAAG,MAAM,YAAY;AAAA,IAChD,UAAU,MAAM;AAAA,IAChB,gBAAgB,MAAM;AAAA,IACtB,aAAa,EAAE,OAAO,iBAAiB;AAAA,EACzC,CAAC;AAED,MAAI,iBAAiB,GAAG;AACtB,WAAO,EAAE,QAAQ,GAAG,WAAW,GAAG,UAAU,GAAG,OAAO,EAAE;AAAA,EAC1D;AAEA,QAAM,YAA8B,CAAC;AACrC,QAAM,WAA6B,CAAC;AACpC,QAAM,WAAoC,CAAC;AAE3C,WAAS,IAAI,GAAG,IAAI,gBAAgB,KAAK;AACvC,UAAM,cAAc,cAAc,IAAI,cAAc,MAAM;AAC1D,UAAM,oBAAoB,kBAAkB,SAAS,KAAK,IAAI,CAAC;AAE/D,UAAM,WAAW,GAAG,OAAO,gBAAgB;AAAA,MACzC,IAAI,WAAW;AAAA,MACf,gBAAgB,MAAM;AAAA,MACtB,UAAU,MAAM;AAAA,MAChB,MAAM;AAAA,MACN,aAAa,GAAG,WAAW,KAAK,IAAI,CAAC;AAAA,MACrC,cAAc,UAAU,IAAI,CAAC,IAAI,YAAY,YAAY,EAAE,QAAQ,QAAQ,EAAE,CAAC;AAAA,MAC9E,QAAQ;AAAA,MACR,gBAAgB,cAAc,CAAC,QAAQ,YAAY,aAAa,CAAC;AAAA,MACjE,UAAU;AAAA,MACV,WAAW;AAAA,MACX,WAAW;AAAA,IACb,CAAC;AACD,OAAG,QAAQ,QAAQ;AACnB,cAAU,KAAK,QAAQ;AAEvB,UAAM,iBAAiB,GAAG,OAAO,wBAAwB;AAAA,MACvD,IAAI,WAAW;AAAA,MACf,gBAAgB,MAAM;AAAA,MACtB,UAAU,MAAM;AAAA,MAChB,QAAQ;AAAA,MACR,WAAW,GAAG,WAAW;AAAA,MACzB,WAAW;AAAA,MACX,UAAU,cAAc,CAAC,cAAc,iBAAiB,UAAU,YAAY,YAAY,CAAC;AAAA,MAC3F,YAAY,cAAc,CAAC,SAAS,UAAU,SAAS,YAAY,CAAC;AAAA,MACpE,eAAe,SAAS,YAAY,KAAQ,GAAQ,CAAC;AAAA,MACrD,WAAW;AAAA,MACX,WAAW;AAAA,IACb,CAAC;AACD,OAAG,QAAQ,cAAc;AAAA,EAC3B;AAEA,WAAS,IAAI,GAAG,IAAI,eAAe,KAAK;AACtC,UAAM,cAAc,cAAc,IAAI,cAAc,MAAM;AAC1D,UAAM,mBAAmB,QAAQ,SAAS,KAAK,UAAU,GAAG,EAAE,CAAC;AAE/D,UAAM,UAAU,GAAG,OAAO,gBAAgB;AAAA,MACxC,IAAI,WAAW;AAAA,MACf,gBAAgB,MAAM;AAAA,MACtB,UAAU,MAAM;AAAA,MAChB,OAAO,GAAG,WAAW,IAAI,IAAI,CAAC;AAAA,MAC9B,QAAQ,qBAAqB,IAAI,CAAC;AAAA,MAClC,KAAK,iBAAiB,OAAO,IAAI,CAAC,EAAE,SAAS,GAAG,GAAG,CAAC;AAAA,MACpD,aAAa;AAAA,MACb,gBAAgB;AAAA,MAChB,UAAU;AAAA,MACV,WAAW;AAAA,MACX,WAAW;AAAA,IACb,CAAC;AACD,OAAG,QAAQ,OAAO;AAClB,aAAS,KAAK,OAAO;AAErB,UAAM,UAAU,GAAG,OAAO,uBAAuB;AAAA,MAC/C,IAAI,WAAW;AAAA,MACf,gBAAgB,MAAM;AAAA,MACtB,UAAU,MAAM;AAAA,MAChB;AAAA,MACA,MAAM;AAAA,MACN,KAAK,GAAG,QAAQ,GAAG;AAAA,MACnB,WAAW;AAAA,MACX,UAAU;AAAA,MACV,WAAW;AAAA,MACX,WAAW;AAAA,IACb,CAAC;AACD,OAAG,QAAQ,OAAO;AAClB,aAAS,KAAK,OAAO;AAAA,EACvB;AAEA,MAAI,aAAa;AACjB,QAAM,YAAY,SAAS;AAC3B,QAAM,SAAuB,CAAC;AAE9B,WAAS,YAAY,WAAW,aAAa,GAAG,aAAa;AAC3D,UAAM,cAAc,KAAK,MAAM,iBAAiB,KAAK,YAAY,KAAK,GAAG,CAAC;AAE1E,aAAS,IAAI,GAAG,IAAI,aAAa,KAAK;AACpC,YAAM,YAAY,QAAQ,SAAS;AACnC,YAAM,WAAW,cAAc,SAAS;AACxC,YAAM,UAAU,cAAc,SAAS;AACvC,YAAM,SAAS,cAAc,mBAAmB,OAAO,KAAK,CAAC,EAAE,CAAC;AAEhE,YAAM,YAAY,UAAU,GAAG,CAAC;AAChC,YAAM,mBAAmB,eAAe,UAAU,SAAS;AAE3D,UAAI,cAAc;AAClB,UAAI,gBAAgB;AACpB,UAAI,WAAW;AAEf,YAAM,aAUD,CAAC;AAEN,eAAS,IAAI,GAAG,IAAI,iBAAiB,QAAQ,KAAK;AAChD,cAAM,UAAU,iBAAiB,CAAC;AAClC,cAAM,UAAU,SAAS,KAAK,CAAC,MAAM,EAAE,QAAQ,OAAO,QAAQ,EAAE,KAAK,SAAS,CAAC;AAC/E,cAAM,WAAW,UAAU,GAAG,EAAE;AAChC,cAAM,eAAe,YAAY,IAAI,GAAG;AACxC,cAAM,UAAU,cAAc,CAAC,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;AAChD,cAAM,iBAAiB,gBAAgB,IAAI,UAAU;AACrD,cAAM,gBAAgB,eAAe;AACrC,cAAM,kBAAkB,iBAAiB;AACzC,cAAM,gBAAgB,kBAAkB;AAExC,uBAAe;AACf,yBAAiB;AACjB,oBAAY;AAEZ,mBAAW,KAAK;AAAA,UACd;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH;AAEA,YAAM,QAAQ,GAAG,OAAO,YAAY;AAAA,QAClC,IAAI,WAAW;AAAA,QACf,gBAAgB,MAAM;AAAA,QACtB,UAAU,MAAM;AAAA,QAChB,aAAa,oBAAoB,YAAY;AAAA,QAC7C,QAAQ,cAAc,cAAc;AAAA,QACpC,mBAAmB,cAAc,oBAAoB;AAAA,QACrD,eAAe,cAAc,gBAAgB;AAAA,QAC7C,kBAAkB,SAAS;AAAA,QAC3B,kBAAkB;AAAA,UAChB,UAAU;AAAA,YACR,IAAI,SAAS;AAAA,YACb,MAAM,SAAS;AAAA,YACf,aAAa,SAAS;AAAA,UACxB;AAAA,QACF;AAAA,QACA,cAAc;AAAA,QACd,UAAU;AAAA,QACV,yBAAyB;AAAA,UACvB;AAAA,UACA;AAAA,UACA,MAAM,QAAQ,UAAU,GAAG,GAAG,CAAC;AAAA,UAC/B,YAAY,OAAO,UAAU,KAAO,KAAK,CAAC;AAAA,QAC5C;AAAA,QACA,wBAAwB;AAAA,UACtB;AAAA,UACA;AAAA,UACA,MAAM,QAAQ,UAAU,GAAG,GAAG,CAAC;AAAA,UAC/B,YAAY,OAAO,UAAU,KAAO,KAAK,CAAC;AAAA,QAC5C;AAAA,QACA,mBAAmB,SAAS,WAAW;AAAA,QACvC,qBAAqB,SAAS,aAAa;AAAA,QAC3C,qBAAqB;AAAA,QACrB,gBAAgB,SAAS,QAAQ;AAAA,QACjC,mBAAmB;AAAA,QACnB,qBAAqB;AAAA,QACrB,sBAAsB;AAAA,QACtB,qBAAqB,SAAS,WAAW;AAAA,QACzC,uBAAuB,SAAS,aAAa;AAAA,QAC7C,iBAAiB;AAAA,QACjB,qBAAqB;AAAA,QACrB,mBAAmB,SAAS,aAAa;AAAA,QACzC,eAAe,WAAW;AAAA,QAC1B,UAAU,EAAE,MAAM,uBAAuB;AAAA,QACzC,WAAW;AAAA,QACX,WAAW;AAAA,MACb,CAAC;AACD,SAAG,QAAQ,KAAK;AAChB,aAAO,KAAK,KAAK;AAEjB,eAAS,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK;AAC1C,cAAM,WAAW,WAAW,CAAC;AAC7B,cAAM,OAAO,GAAG,OAAO,gBAAgB;AAAA,UACrC,IAAI,WAAW;AAAA,UACf;AAAA,UACA,gBAAgB,MAAM;AAAA,UACtB,UAAU,MAAM;AAAA,UAChB,YAAY,IAAI;AAAA,UAChB,MAAM;AAAA,UACN,MAAM,SAAS,QAAQ;AAAA,UACvB,UAAU,SAAS,SAAS,QAAQ;AAAA,UACpC,cAAc;AAAA,UACd,cAAc,SAAS,SAAS,YAAY;AAAA,UAC5C,gBAAgB,SAAS,SAAS,cAAc;AAAA,UAChD,gBAAgB;AAAA,UAChB,iBAAiB;AAAA,UACjB,SAAS,SAAS,SAAS,OAAO;AAAA,UAClC,WAAW,SAAS,SAAS,aAAa;AAAA,UAC1C,gBAAgB,SAAS,SAAS,aAAa;AAAA,UAC/C,kBAAkB,SAAS,SAAS,eAAe;AAAA,UACnD,kBAAkB;AAAA,UAClB,mBAAmB;AAAA,UACnB,kBAAkB;AAAA,UAClB,kBAAkB;AAAA,UAClB,WAAW,SAAS,QAAQ;AAAA,UAC5B,kBAAkB,SAAS,SAAS,MAAM;AAAA,UAC1C,iBAAiB;AAAA,YACf,SAAS;AAAA,cACP,IAAI,SAAS,QAAQ;AAAA,cACrB,OAAO,SAAS,QAAQ;AAAA,cACxB,KAAK,SAAS,QAAQ;AAAA,YACxB;AAAA,YACA,SAAS,SAAS,UACd;AAAA,cACE,IAAI,SAAS,QAAQ;AAAA,cACrB,MAAM,SAAS,QAAQ;AAAA,cACvB,KAAK,SAAS,QAAQ;AAAA,YACxB,IACA;AAAA,UACN;AAAA,UACA,WAAW;AAAA,UACX,WAAW;AAAA,QACb,CAAC;AACD,WAAG,QAAQ,IAAI;AAAA,MACjB;AAAA,IACF;AAAA,EACF;AAEA,WAAS,IAAI,GAAG,IAAI,YAAY,KAAK;AACnC,UAAM,WAAW,cAAc,SAAS;AACxC,UAAM,gBAAgB,kBAAkB,SAAS,IAAI,CAAC;AACtD,UAAM,gBAAgB,cAAc,oBAAoB;AAExD,UAAM,qBAA6C;AAAA,MACjD,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,aAAa;AAAA,MACb,YAAY;AAAA,MACZ,aAAa;AAAA,IACf;AAEA,UAAM,OAAO,GAAG,OAAO,cAAc;AAAA,MACnC,IAAI,WAAW;AAAA,MACf,gBAAgB,MAAM;AAAA,MACtB,UAAU,MAAM;AAAA,MAChB,OAAO,GAAG,cAAc,WAAW,CAAC,MAAM,SAAS,WAAW;AAAA,MAC9D,QAAQ,kBAAkB,gBAAgB,kBAAkB,gBAAgB,WAAW;AAAA,MACvF;AAAA,MACA,aAAa,SAAS,YAAY,KAAM,GAAM,CAAC;AAAA,MAC/C,eAAe;AAAA,MACf,aAAa,mBAAmB,aAAa;AAAA,MAC7C,iBAAiB,QAAQ,UAAU,KAAK,EAAE,CAAC;AAAA,MAC3C,QAAQ,cAAc,CAAC,WAAW,YAAY,YAAY,SAAS,CAAC;AAAA,MACpE,WAAW;AAAA,MACX,WAAW;AAAA,IACb,CAAC;AACD,OAAG,QAAQ,IAAI;AAAA,EACjB;AAEA,QAAM,GAAG,MAAM;AAEf,SAAO;AAAA,IACL,QAAQ,OAAO;AAAA,IACf,WAAW,UAAU;AAAA,IACrB,UAAU,SAAS;AAAA,IACnB,OAAO;AAAA,EACT;AACF;",
4
+ "sourcesContent": ["import { randomUUID } from 'crypto'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport {\n SalesOrder,\n SalesOrderLine,\n} from '@open-mercato/core/modules/sales/data/entities'\nimport {\n CustomerEntity,\n CustomerCompanyProfile,\n CustomerDeal,\n} from '@open-mercato/core/modules/customers/data/entities'\nimport {\n CatalogProduct,\n CatalogProductVariant,\n} from '@open-mercato/core/modules/catalog/data/entities'\n\nexport type AnalyticsSeedScope = {\n tenantId: string\n organizationId: string\n}\n\nexport type AnalyticsSeedOptions = {\n months?: number\n ordersPerMonth?: number\n customersCount?: number\n productsCount?: number\n dealsCount?: number\n}\n\nconst ORDER_STATUSES = ['draft', 'pending', 'confirmed', 'processing', 'shipped', 'delivered', 'cancelled'] as const\nconst FULFILLMENT_STATUSES = ['pending', 'in_fulfillment', 'partially_fulfilled', 'fulfilled'] as const\nconst PAYMENT_STATUSES = ['unpaid', 'partial', 'paid', 'refunded'] as const\nconst DEAL_PIPELINE_STAGES = ['lead', 'qualified', 'proposal', 'negotiation', 'closed_won', 'closed_lost'] as const\nconst COUNTRIES = ['US', 'GB', 'DE', 'FR', 'CA', 'AU', 'NL', 'ES', 'IT', 'PL'] as const\nconst REGIONS_BY_COUNTRY: Record<string, string[]> = {\n US: ['California', 'New York', 'Texas', 'Florida', 'Illinois', 'Washington', 'Massachusetts'],\n GB: ['England', 'Scotland', 'Wales'],\n DE: ['Bavaria', 'Berlin', 'Hamburg', 'Hessen'],\n FR: ['\u00CEle-de-France', 'Provence', 'Rh\u00F4ne-Alpes'],\n CA: ['Ontario', 'Quebec', 'British Columbia'],\n AU: ['New South Wales', 'Victoria', 'Queensland'],\n NL: ['North Holland', 'South Holland'],\n ES: ['Madrid', 'Catalonia', 'Andalusia'],\n IT: ['Lombardy', 'Lazio', 'Veneto'],\n PL: ['Mazovia', 'Lesser Poland', 'Silesia'],\n}\n\nconst COMPANY_NAMES = [\n 'Acme Corp', 'Global Industries', 'Tech Solutions', 'Prime Services',\n 'Northern Analytics', 'Blue Ocean Trading', 'Summit Enterprises', 'Horizon Dynamics',\n 'Vertex Systems', 'Atlas Logistics', 'Pinnacle Group', 'Quantum Labs',\n 'Stellar Innovations', 'Pacific Partners', 'Apex Manufacturing', 'Nexus Technologies',\n 'Eclipse Ventures', 'Titan Holdings', 'Vanguard Solutions', 'Momentum Corp',\n 'Crystal Clear Media', 'Silver Line Transport', 'Golden Gate Imports', 'Red Rock Mining',\n 'Green Valley Foods', 'Blue Sky Aviation', 'White Mountain Retail', 'Black Diamond Sports',\n]\n\nconst PRODUCT_NAMES = [\n 'Premium Widget', 'Standard Component', 'Professional Kit', 'Enterprise Module',\n 'Basic Starter Pack', 'Advanced System', 'Deluxe Bundle', 'Essential Tools',\n 'Pro Series Device', 'Ultra Performance Unit', 'Classic Edition', 'Limited Series',\n 'Industrial Grade Part', 'Consumer Package', 'Business Solution', 'Home Edition',\n]\n\nconst DEAL_TITLES = [\n 'Enterprise License Deal', 'Annual Subscription', 'Pilot Program', 'Strategic Partnership',\n 'Volume Purchase Agreement', 'Service Contract', 'Implementation Project', 'Expansion Deal',\n 'Renewal Opportunity', 'Upsell Initiative', 'Cross-sell Package', 'Custom Solution',\n]\n\nfunction randomInt(min: number, max: number): number {\n return Math.floor(Math.random() * (max - min + 1)) + min\n}\n\nfunction randomFloat(min: number, max: number, decimals = 2): number {\n const value = Math.random() * (max - min) + min\n return Number(value.toFixed(decimals))\n}\n\nfunction randomElement<T>(arr: readonly T[]): T {\n return arr[Math.floor(Math.random() * arr.length)]\n}\n\nfunction randomElements<T>(arr: readonly T[], count: number): T[] {\n const shuffled = [...arr].sort(() => Math.random() - 0.5)\n return shuffled.slice(0, Math.min(count, arr.length))\n}\n\nfunction toAmount(value: number): string {\n return value.toFixed(2)\n}\n\nfunction daysAgo(days: number): Date {\n const date = new Date()\n date.setDate(date.getDate() - days)\n return date\n}\n\nfunction randomDateInRange(startDaysAgo: number, endDaysAgo: number): Date {\n const daysOffset = randomInt(endDaysAgo, startDaysAgo)\n return daysAgo(daysOffset)\n}\n\nfunction generateOrderNumber(index: number): string {\n return `SO-ANALYTICS-${String(index).padStart(5, '0')}`\n}\n\nexport async function seedAnalyticsData(\n em: EntityManager,\n scope: AnalyticsSeedScope,\n options: AnalyticsSeedOptions = {}\n): Promise<{ orders: number; customers: number; products: number; deals: number }> {\n const {\n months = 6,\n ordersPerMonth = 50,\n customersCount = 25,\n productsCount = 15,\n dealsCount = 20,\n } = options\n\n const existingOrders = await em.count(SalesOrder, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n orderNumber: { $like: 'SO-ANALYTICS-%' },\n })\n\n if (existingOrders > 0) {\n return { orders: 0, customers: 0, products: 0, deals: 0 }\n }\n\n const customers: CustomerEntity[] = []\n const products: CatalogProduct[] = []\n const variants: CatalogProductVariant[] = []\n\n for (let i = 0; i < customersCount; i++) {\n const companyName = COMPANY_NAMES[i % COMPANY_NAMES.length]\n const customerCreatedAt = randomDateInRange(months * 30 + 60, 0)\n\n const customer = em.create(CustomerEntity, {\n id: randomUUID(),\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n kind: 'company',\n displayName: `${companyName} #${i + 1}`,\n primaryEmail: `contact${i + 1}@${companyName.toLowerCase().replace(/\\s+/g, '')}.example.com`,\n status: 'active',\n lifecycleStage: randomElement(['lead', 'customer', 'opportunity']),\n isActive: true,\n createdAt: customerCreatedAt,\n updatedAt: customerCreatedAt,\n })\n em.persist(customer)\n customers.push(customer)\n\n const companyProfile = em.create(CustomerCompanyProfile, {\n id: randomUUID(),\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n entity: customer,\n legalName: `${companyName} Inc.`,\n brandName: companyName,\n industry: randomElement(['Technology', 'Manufacturing', 'Retail', 'Services', 'Healthcare']),\n sizeBucket: randomElement(['small', 'medium', 'large', 'enterprise']),\n annualRevenue: toAmount(randomFloat(100000, 50000000)),\n createdAt: customerCreatedAt,\n updatedAt: customerCreatedAt,\n })\n em.persist(companyProfile)\n }\n\n for (let i = 0; i < productsCount; i++) {\n const productName = PRODUCT_NAMES[i % PRODUCT_NAMES.length]\n const productCreatedAt = daysAgo(months * 30 + randomInt(0, 30))\n\n const product = em.create(CatalogProduct, {\n id: randomUUID(),\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n title: `${productName} ${i + 1}`,\n handle: `analytics-product-${i + 1}`,\n sku: `SKU-ANALYTICS-${String(i + 1).padStart(3, '0')}`,\n productType: 'simple',\n isConfigurable: false,\n isActive: true,\n createdAt: productCreatedAt,\n updatedAt: productCreatedAt,\n })\n em.persist(product)\n products.push(product)\n\n const variant = em.create(CatalogProductVariant, {\n id: randomUUID(),\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n product,\n name: 'Default',\n sku: `${product.sku}-DEFAULT`,\n isDefault: true,\n isActive: true,\n createdAt: productCreatedAt,\n updatedAt: productCreatedAt,\n })\n em.persist(variant)\n variants.push(variant)\n }\n\n let orderIndex = 1\n const totalDays = months * 30\n const orders: SalesOrder[] = []\n\n for (let dayOffset = totalDays; dayOffset >= 0; dayOffset--) {\n const ordersToday = Math.round(ordersPerMonth / 30 * randomFloat(0.5, 1.5))\n\n for (let j = 0; j < ordersToday; j++) {\n const orderDate = daysAgo(dayOffset)\n const customer = randomElement(customers)\n const country = randomElement(COUNTRIES)\n const region = randomElement(REGIONS_BY_COUNTRY[country] || [''])\n\n const lineCount = randomInt(1, 5)\n const selectedProducts = randomElements(products, lineCount)\n\n let subtotalNet = 0\n let subtotalGross = 0\n let taxTotal = 0\n\n const orderLines: Array<{\n product: CatalogProduct\n variant: CatalogProductVariant\n quantity: number\n unitPriceNet: number\n unitPriceGross: number\n taxRate: number\n lineNetAmount: number\n lineGrossAmount: number\n lineTaxAmount: number\n }> = []\n\n for (let k = 0; k < selectedProducts.length; k++) {\n const product = selectedProducts[k]\n const variant = variants.find((v) => v.product.id === product.id) || variants[0]\n const quantity = randomInt(1, 10)\n const unitPriceNet = randomFloat(10, 500)\n const taxRate = randomElement([0, 5, 10, 20, 23])\n const unitPriceGross = unitPriceNet * (1 + taxRate / 100)\n const lineNetAmount = unitPriceNet * quantity\n const lineGrossAmount = unitPriceGross * quantity\n const lineTaxAmount = lineGrossAmount - lineNetAmount\n\n subtotalNet += lineNetAmount\n subtotalGross += lineGrossAmount\n taxTotal += lineTaxAmount\n\n orderLines.push({\n product,\n variant,\n quantity,\n unitPriceNet,\n unitPriceGross,\n taxRate,\n lineNetAmount,\n lineGrossAmount,\n lineTaxAmount,\n })\n }\n\n const order = em.create(SalesOrder, {\n id: randomUUID(),\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n orderNumber: generateOrderNumber(orderIndex++),\n status: randomElement(ORDER_STATUSES),\n fulfillmentStatus: randomElement(FULFILLMENT_STATUSES),\n paymentStatus: randomElement(PAYMENT_STATUSES),\n customerEntityId: customer.id,\n customerSnapshot: {\n customer: {\n id: customer.id,\n kind: customer.kind,\n displayName: customer.displayName,\n },\n },\n currencyCode: 'USD',\n placedAt: orderDate,\n shippingAddressSnapshot: {\n country,\n region,\n city: `City ${randomInt(1, 100)}`,\n postalCode: String(randomInt(10000, 99999)),\n },\n billingAddressSnapshot: {\n country,\n region,\n city: `City ${randomInt(1, 100)}`,\n postalCode: String(randomInt(10000, 99999)),\n },\n subtotalNetAmount: toAmount(subtotalNet),\n subtotalGrossAmount: toAmount(subtotalGross),\n discountTotalAmount: '0.00',\n taxTotalAmount: toAmount(taxTotal),\n shippingNetAmount: '0.00',\n shippingGrossAmount: '0.00',\n surchargeTotalAmount: '0.00',\n grandTotalNetAmount: toAmount(subtotalNet),\n grandTotalGrossAmount: toAmount(subtotalGross),\n paidTotalAmount: '0.00',\n refundedTotalAmount: '0.00',\n outstandingAmount: toAmount(subtotalGross),\n lineItemCount: orderLines.length,\n metadata: { seed: 'dashboards.analytics' },\n createdAt: orderDate,\n updatedAt: orderDate,\n })\n em.persist(order)\n orders.push(order)\n\n for (let k = 0; k < orderLines.length; k++) {\n const lineData = orderLines[k]\n const line = em.create(SalesOrderLine, {\n id: randomUUID(),\n order,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n lineNumber: k + 1,\n kind: 'product',\n name: lineData.product.title,\n quantity: toAmount(lineData.quantity),\n normalizedQuantity: toAmount(lineData.quantity),\n normalizedUnit: null,\n uomSnapshot: null,\n currencyCode: 'USD',\n unitPriceNet: toAmount(lineData.unitPriceNet),\n unitPriceGross: toAmount(lineData.unitPriceGross),\n discountAmount: '0.00',\n discountPercent: '0.00',\n taxRate: toAmount(lineData.taxRate),\n taxAmount: toAmount(lineData.lineTaxAmount),\n totalNetAmount: toAmount(lineData.lineNetAmount),\n totalGrossAmount: toAmount(lineData.lineGrossAmount),\n reservedQuantity: '0',\n fulfilledQuantity: '0',\n invoicedQuantity: '0',\n returnedQuantity: '0',\n productId: lineData.product.id,\n productVariantId: lineData.variant?.id ?? null,\n catalogSnapshot: {\n product: {\n id: lineData.product.id,\n title: lineData.product.title,\n sku: lineData.product.sku,\n },\n variant: lineData.variant\n ? {\n id: lineData.variant.id,\n name: lineData.variant.name,\n sku: lineData.variant.sku,\n }\n : null,\n },\n createdAt: orderDate,\n updatedAt: orderDate,\n })\n em.persist(line)\n }\n }\n }\n\n for (let i = 0; i < dealsCount; i++) {\n const customer = randomElement(customers)\n const dealCreatedAt = randomDateInRange(months * 30, 0)\n const pipelineStage = randomElement(DEAL_PIPELINE_STAGES)\n\n const probabilityByStage: Record<string, number> = {\n lead: 10,\n qualified: 25,\n proposal: 50,\n negotiation: 75,\n closed_won: 100,\n closed_lost: 0,\n }\n\n const deal = em.create(CustomerDeal, {\n id: randomUUID(),\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n title: `${randomElement(DEAL_TITLES)} - ${customer.displayName}`,\n status: pipelineStage === 'closed_won' || pipelineStage === 'closed_lost' ? 'closed' : 'open',\n pipelineStage,\n valueAmount: toAmount(randomFloat(5000, 500000)),\n valueCurrency: 'USD',\n probability: probabilityByStage[pipelineStage],\n expectedCloseAt: daysAgo(randomInt(-60, 90)),\n source: randomElement(['inbound', 'outbound', 'referral', 'partner']),\n createdAt: dealCreatedAt,\n updatedAt: dealCreatedAt,\n })\n em.persist(deal)\n }\n\n await em.flush()\n\n return {\n orders: orders.length,\n customers: customers.length,\n products: products.length,\n deals: dealsCount,\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -2,18 +2,35 @@ import { z } from "zod";
2
2
  import { makeCrudRoute } from "@open-mercato/shared/lib/crud/factory";
3
3
  import { resolveTranslations } from "@open-mercato/shared/lib/i18n/server";
4
4
  import { CrudHttpError } from "@open-mercato/shared/lib/crud/errors";
5
- import { buildCustomFieldFiltersFromQuery, extractAllCustomFieldEntries } from "@open-mercato/shared/lib/crud/custom-fields";
5
+ import {
6
+ buildCustomFieldFiltersFromQuery,
7
+ extractAllCustomFieldEntries
8
+ } from "@open-mercato/shared/lib/crud/custom-fields";
6
9
  import { SalesOrderLine } from "../../data/entities.js";
7
10
  import { orderLineCreateSchema } from "../../data/validators.js";
8
- import { createPagedListResponseSchema, createSalesCrudOpenApi, defaultOkResponseSchema } from "../openapi.js";
11
+ import {
12
+ createPagedListResponseSchema,
13
+ createSalesCrudOpenApi,
14
+ defaultOkResponseSchema
15
+ } from "../openapi.js";
9
16
  import { withScopedPayload } from "../utils.js";
10
17
  import { E } from "../../../../generated/entities.ids.generated.js";
11
18
  import * as F from "../../../../generated/entities/sales_order_line/index.js";
19
+ import { canonicalizeUnitCode, REFERENCE_UNIT_CODES } from "@open-mercato/shared/lib/units/unitCodes";
12
20
  const rawBodySchema = z.object({}).passthrough();
13
- const resolveRawBody = (raw) => raw && typeof raw === "object" && "body" in raw ? raw.body : raw;
21
+ const resolveRawBody = (raw) => {
22
+ if (!raw || typeof raw !== "object") return {};
23
+ if ("body" in raw) {
24
+ const payload = raw;
25
+ if (payload.body && typeof payload.body === "object") {
26
+ return payload.body;
27
+ }
28
+ }
29
+ return raw;
30
+ };
14
31
  const listSchema = z.object({
15
32
  page: z.coerce.number().min(1).default(1),
16
- pageSize: z.coerce.number().min(1).max(200).default(50),
33
+ pageSize: z.coerce.number().min(1).max(100).default(50),
17
34
  id: z.string().uuid().optional(),
18
35
  orderId: z.string().uuid().optional(),
19
36
  sortField: z.string().optional(),
@@ -25,7 +42,9 @@ const routeMetadata = {
25
42
  PUT: { requireAuth: true, requireFeatures: ["sales.orders.manage"] },
26
43
  DELETE: { requireAuth: true, requireFeatures: ["sales.orders.manage"] }
27
44
  };
28
- const upsertSchema = orderLineCreateSchema.extend({ id: z.string().uuid().optional() });
45
+ const upsertSchema = orderLineCreateSchema.extend({
46
+ id: z.string().uuid().optional()
47
+ });
29
48
  const deleteSchema = z.object({
30
49
  id: z.string().uuid(),
31
50
  orderId: z.string().uuid()
@@ -62,6 +81,9 @@ const crud = makeCrudRoute({
62
81
  F.tenant_id,
63
82
  F.quantity,
64
83
  F.quantity_unit,
84
+ F.normalized_quantity,
85
+ F.normalized_unit,
86
+ F.uom_snapshot,
65
87
  F.currency_code,
66
88
  F.unit_price_net,
67
89
  F.unit_price_gross,
@@ -108,7 +130,18 @@ const crud = makeCrudRoute({
108
130
  for (const key of Object.keys(normalized)) {
109
131
  if (key.startsWith("cf:")) delete normalized[key];
110
132
  }
111
- return { ...normalized, ...cfEntries };
133
+ const quantityUnit = canonicalizeUnitCode(
134
+ normalized["quantity_unit"] ?? normalized["quantityUnit"]
135
+ );
136
+ const normalizedUnit = canonicalizeUnitCode(
137
+ normalized["normalized_unit"] ?? normalized["normalizedUnit"]
138
+ ) ?? quantityUnit;
139
+ return {
140
+ ...normalized,
141
+ quantity_unit: quantityUnit,
142
+ normalized_unit: normalizedUnit,
143
+ ...cfEntries
144
+ };
112
145
  }
113
146
  },
114
147
  actions: {
@@ -116,12 +149,16 @@ const crud = makeCrudRoute({
116
149
  commandId: "sales.orders.lines.upsert",
117
150
  schema: rawBodySchema,
118
151
  mapInput: async ({ raw, ctx }) => {
119
- console.log("CREATE order line raw input:", raw);
120
152
  const { translate } = await resolveTranslations();
121
- const payload = upsertSchema.parse(withScopedPayload(resolveRawBody(raw) ?? {}, ctx, translate));
153
+ const payload = upsertSchema.parse(
154
+ withScopedPayload(resolveRawBody(raw) ?? {}, ctx, translate)
155
+ );
122
156
  return { body: payload };
123
157
  },
124
- response: ({ result }) => ({ id: result?.lineId ?? null, orderId: result?.orderId ?? null }),
158
+ response: ({ result }) => ({
159
+ id: result?.lineId ?? null,
160
+ orderId: result?.orderId ?? null
161
+ }),
125
162
  status: 201
126
163
  },
127
164
  update: {
@@ -129,19 +166,31 @@ const crud = makeCrudRoute({
129
166
  schema: rawBodySchema,
130
167
  mapInput: async ({ raw, ctx }) => {
131
168
  const { translate } = await resolveTranslations();
132
- const payload = upsertSchema.parse(withScopedPayload(resolveRawBody(raw) ?? {}, ctx, translate));
169
+ const payload = upsertSchema.parse(
170
+ withScopedPayload(resolveRawBody(raw) ?? {}, ctx, translate)
171
+ );
133
172
  return { body: payload };
134
173
  },
135
- response: ({ result }) => ({ id: result?.lineId ?? null, orderId: result?.orderId ?? null })
174
+ response: ({ result }) => ({
175
+ id: result?.lineId ?? null,
176
+ orderId: result?.orderId ?? null
177
+ })
136
178
  },
137
179
  delete: {
138
180
  commandId: "sales.orders.lines.delete",
139
181
  schema: rawBodySchema,
140
182
  mapInput: async ({ raw, ctx }) => {
141
183
  const { translate } = await resolveTranslations();
142
- const payload = deleteSchema.parse(withScopedPayload(resolveRawBody(raw) ?? {}, ctx, translate));
184
+ const payload = deleteSchema.parse(
185
+ withScopedPayload(resolveRawBody(raw) ?? {}, ctx, translate)
186
+ );
143
187
  if (!payload.id || !payload.orderId) {
144
- throw new CrudHttpError(400, { error: translate("sales.documents.detail.error", "Document not found or inaccessible.") });
188
+ throw new CrudHttpError(400, {
189
+ error: translate(
190
+ "sales.documents.detail.error",
191
+ "Document not found or inaccessible."
192
+ )
193
+ });
145
194
  }
146
195
  return { body: payload };
147
196
  },
@@ -150,6 +199,31 @@ const crud = makeCrudRoute({
150
199
  }
151
200
  });
152
201
  const { GET, POST, PUT, DELETE } = crud;
202
+ const uomSnapshotOpenApiSchema = z.object({
203
+ version: z.literal(1),
204
+ productId: z.string().nullable(),
205
+ productVariantId: z.string().nullable(),
206
+ baseUnitCode: z.string().nullable(),
207
+ enteredUnitCode: z.string().nullable(),
208
+ enteredQuantity: z.string(),
209
+ toBaseFactor: z.string(),
210
+ normalizedQuantity: z.string(),
211
+ rounding: z.object({
212
+ mode: z.enum(["half_up", "down", "up"]),
213
+ scale: z.number().int()
214
+ }),
215
+ source: z.object({
216
+ conversionId: z.string().nullable(),
217
+ resolvedAt: z.string()
218
+ }),
219
+ unitPriceReference: z.object({
220
+ enabled: z.boolean(),
221
+ referenceUnitCode: z.enum(REFERENCE_UNIT_CODES).nullable(),
222
+ baseQuantity: z.string().nullable(),
223
+ grossPerReference: z.string().nullable().optional(),
224
+ netPerReference: z.string().nullable().optional()
225
+ }).optional()
226
+ }).nullable().optional();
153
227
  const orderLineSchema = z.object({
154
228
  id: z.string().uuid(),
155
229
  order_id: z.string().uuid(),
@@ -165,6 +239,9 @@ const orderLineSchema = z.object({
165
239
  comment: z.string().nullable().optional(),
166
240
  quantity: z.number(),
167
241
  quantity_unit: z.string().nullable().optional(),
242
+ normalized_quantity: z.number(),
243
+ normalized_unit: z.string().nullable().optional(),
244
+ uom_snapshot: uomSnapshotOpenApiSchema,
168
245
  currency_code: z.string(),
169
246
  unit_price_net: z.number(),
170
247
  unit_price_gross: z.number(),
@@ -188,12 +265,18 @@ const openApi = createSalesCrudOpenApi({
188
265
  listResponseSchema: createPagedListResponseSchema(orderLineSchema),
189
266
  create: {
190
267
  schema: upsertSchema,
191
- responseSchema: z.object({ id: z.string().uuid().nullable(), orderId: z.string().uuid().nullable() }),
268
+ responseSchema: z.object({
269
+ id: z.string().uuid().nullable(),
270
+ orderId: z.string().uuid().nullable()
271
+ }),
192
272
  description: "Creates an order line and recalculates totals."
193
273
  },
194
274
  update: {
195
275
  schema: upsertSchema,
196
- responseSchema: z.object({ id: z.string().uuid().nullable(), orderId: z.string().uuid().nullable() }),
276
+ responseSchema: z.object({
277
+ id: z.string().uuid().nullable(),
278
+ orderId: z.string().uuid().nullable()
279
+ }),
197
280
  description: "Updates an order line and recalculates totals."
198
281
  },
199
282
  del: {