@open-mercato/core 0.6.8-develop.7077.1.94f1126c13 → 0.6.8-develop.7078.1.ca2d1510b5

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.
@@ -1,4 +1,4 @@
1
- [build:core] found 4341 entry points
1
+ [build:core] found 4342 entry points
2
2
  [build:core] built successfully
3
3
  [build:core:generated] found 218 entry points
4
4
  [build:core:generated] built successfully
@@ -16,14 +16,6 @@
16
16
  "type": "string",
17
17
  "defaultValue": "Free shipping on orders over $50"
18
18
  },
19
- {
20
- "identifier": "sales_channels_enabled",
21
- "name": "Sales Channels",
22
- "description": "Show sales channel pickers, filters, and management UI. Disable for tenants that do not use sales channels.",
23
- "category": "sales",
24
- "type": "boolean",
25
- "defaultValue": true
26
- },
27
19
  {
28
20
  "identifier": "order_review_threshold",
29
21
  "name": "Order Review Threshold",
@@ -0,0 +1,33 @@
1
+ import { FeatureToggle } from "@open-mercato/core/modules/feature_toggles/data/entities";
2
+ import { findOneWithDecryption } from "@open-mercato/shared/lib/encryption/find";
3
+ import { SALES_CHANNELS_TOGGLE_ID } from "./salesChannelsToggleId.js";
4
+ const SALES_CHANNELS_TOGGLE_DEFINITION = {
5
+ identifier: SALES_CHANNELS_TOGGLE_ID,
6
+ name: "Sales Channels",
7
+ description: "Show sales channel pickers, filters, and management UI. Disable for tenants that do not use sales channels.",
8
+ category: "sales",
9
+ type: "boolean",
10
+ defaultValue: true
11
+ };
12
+ async function seedSalesChannelsToggle(em) {
13
+ const existing = await findOneWithDecryption(em, FeatureToggle, {
14
+ identifier: SALES_CHANNELS_TOGGLE_DEFINITION.identifier
15
+ });
16
+ if (existing) return;
17
+ em.persist(
18
+ em.create(FeatureToggle, {
19
+ identifier: SALES_CHANNELS_TOGGLE_DEFINITION.identifier,
20
+ name: SALES_CHANNELS_TOGGLE_DEFINITION.name,
21
+ description: SALES_CHANNELS_TOGGLE_DEFINITION.description,
22
+ category: SALES_CHANNELS_TOGGLE_DEFINITION.category,
23
+ type: SALES_CHANNELS_TOGGLE_DEFINITION.type,
24
+ defaultValue: SALES_CHANNELS_TOGGLE_DEFINITION.defaultValue
25
+ })
26
+ );
27
+ await em.flush();
28
+ }
29
+ export {
30
+ SALES_CHANNELS_TOGGLE_DEFINITION,
31
+ seedSalesChannelsToggle
32
+ };
33
+ //# sourceMappingURL=salesChannelsToggleSeed.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/sales/lib/salesChannelsToggleSeed.ts"],
4
+ "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { FeatureToggle } from '@open-mercato/core/modules/feature_toggles/data/entities'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { SALES_CHANNELS_TOGGLE_ID } from './salesChannelsToggleId'\n\nexport const SALES_CHANNELS_TOGGLE_DEFINITION = {\n identifier: SALES_CHANNELS_TOGGLE_ID,\n name: 'Sales Channels',\n description: 'Show sales channel pickers, filters, and management UI. Disable for tenants that do not use sales channels.',\n category: 'sales',\n type: 'boolean' as const,\n defaultValue: true,\n} as const\n\n// The sales module owns this toggle definition, so tenant setup registers it the\n// same way portal, customers and wms register theirs. Shipping it only in the\n// core defaults file left it unregistered on every database initialized before\n// the toggle existed, and `useSalesChannelsEnabled` then 404s on every mount.\n//\n// The lookup deliberately does not filter on `deletedAt`. Deletion is soft\n// (`feature_toggles.global.delete`) while `feature_toggles_identifier_unique`\n// covers every row, so filtering would make this insert a duplicate and fail the\n// whole seed run on any installation where the toggle was deleted. Matching the\n// create command's own uniqueness check also leaves an operator's deletion alone\n// instead of resurrecting the definition on every tenant seed.\nexport async function seedSalesChannelsToggle(em: EntityManager): Promise<void> {\n const existing = await findOneWithDecryption(em, FeatureToggle, {\n identifier: SALES_CHANNELS_TOGGLE_DEFINITION.identifier,\n })\n if (existing) return\n em.persist(\n em.create(FeatureToggle, {\n identifier: SALES_CHANNELS_TOGGLE_DEFINITION.identifier,\n name: SALES_CHANNELS_TOGGLE_DEFINITION.name,\n description: SALES_CHANNELS_TOGGLE_DEFINITION.description,\n category: SALES_CHANNELS_TOGGLE_DEFINITION.category,\n type: SALES_CHANNELS_TOGGLE_DEFINITION.type,\n defaultValue: SALES_CHANNELS_TOGGLE_DEFINITION.defaultValue,\n }),\n )\n await em.flush()\n}\n"],
5
+ "mappings": "AACA,SAAS,qBAAqB;AAC9B,SAAS,6BAA6B;AACtC,SAAS,gCAAgC;AAElC,MAAM,mCAAmC;AAAA,EAC9C,YAAY;AAAA,EACZ,MAAM;AAAA,EACN,aAAa;AAAA,EACb,UAAU;AAAA,EACV,MAAM;AAAA,EACN,cAAc;AAChB;AAaA,eAAsB,wBAAwB,IAAkC;AAC9E,QAAM,WAAW,MAAM,sBAAsB,IAAI,eAAe;AAAA,IAC9D,YAAY,iCAAiC;AAAA,EAC/C,CAAC;AACD,MAAI,SAAU;AACd,KAAG;AAAA,IACD,GAAG,OAAO,eAAe;AAAA,MACvB,YAAY,iCAAiC;AAAA,MAC7C,MAAM,iCAAiC;AAAA,MACvC,aAAa,iCAAiC;AAAA,MAC9C,UAAU,iCAAiC;AAAA,MAC3C,MAAM,iCAAiC;AAAA,MACvC,cAAc,iCAAiC;AAAA,IACjD,CAAC;AAAA,EACH;AACA,QAAM,GAAG,MAAM;AACjB;",
6
+ "names": []
7
+ }
@@ -1,6 +1,7 @@
1
1
  import { SalesSettings, SalesDocumentSequence, SalesTaxRate } from "./data/entities.js";
2
2
  import { DEFAULT_ORDER_NUMBER_FORMAT, DEFAULT_QUOTE_NUMBER_FORMAT } from "./lib/documentNumberTokens.js";
3
3
  import { seedSalesStatusDictionaries, seedSalesAdjustmentKinds } from "./lib/dictionaries.js";
4
+ import { seedSalesChannelsToggle } from "./lib/salesChannelsToggleSeed.js";
4
5
  import { ensureExampleShippingMethods, ensureExamplePaymentMethods } from "./seed/examples-data.js";
5
6
  import { seedSalesExamples } from "./seed/examples.js";
6
7
  const DEFAULT_TAX_RATES = [
@@ -104,6 +105,7 @@ const setup = {
104
105
  await seedSalesAdjustmentKinds(em, scope);
105
106
  await ensureExampleShippingMethods(em, scope);
106
107
  await ensureExamplePaymentMethods(em, scope);
108
+ await seedSalesChannelsToggle(em);
107
109
  },
108
110
  async seedExamples({ em, container, tenantId, organizationId }) {
109
111
  const scope = { tenantId, organizationId };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/modules/sales/setup.ts"],
4
- "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport type { ModuleSetupConfig } from '@open-mercato/shared/modules/setup'\nimport { SalesSettings, SalesDocumentSequence, SalesTaxRate } from './data/entities'\nimport { DEFAULT_ORDER_NUMBER_FORMAT, DEFAULT_QUOTE_NUMBER_FORMAT } from './lib/documentNumberTokens'\nimport { seedSalesStatusDictionaries, seedSalesAdjustmentKinds } from './lib/dictionaries'\nimport { ensureExampleShippingMethods, ensureExamplePaymentMethods } from './seed/examples-data'\nimport { seedSalesExamples } from './seed/examples'\n\ntype SeedScope = { tenantId: string; organizationId: string }\n\nconst DEFAULT_TAX_RATES = [\n { code: 'vat-23', name: '23% VAT', rate: '23' },\n { code: 'vat-0', name: '0% VAT', rate: '0' },\n] as const\n\nasync function seedSalesTaxRates(em: EntityManager, scope: SeedScope): Promise<void> {\n await em.transactional(async (tem) => {\n const existing = await tem.find(SalesTaxRate, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n })\n const existingCodes = new Set(existing.map((rate) => rate.code))\n const hasDefault = existing.some((rate) => rate.isDefault)\n const now = new Date()\n let isFirst = !hasDefault\n\n for (const seed of DEFAULT_TAX_RATES) {\n if (existingCodes.has(seed.code)) continue\n tem.persist(\n tem.create(SalesTaxRate, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n code: seed.code,\n name: seed.name,\n rate: seed.rate,\n priority: 0,\n isCompound: false,\n isDefault: isFirst,\n createdAt: now,\n updatedAt: now,\n })\n )\n isFirst = false\n }\n })\n}\n\nexport const setup: ModuleSetupConfig = {\n defaultRoleFeatures: {\n admin: ['sales.*', 'sales.documents.number.edit'],\n employee: [\n 'sales.channels.view',\n 'sales.channels.manage',\n 'sales.settings.view',\n 'sales.settings.manage',\n 'sales.orders.view',\n 'sales.orders.manage',\n 'sales.orders.approve',\n 'sales.widgets.new-orders',\n 'sales.widgets.new-quotes',\n 'sales.quotes.view',\n 'sales.quotes.manage',\n 'sales.shipments.manage',\n 'sales.payments.manage',\n 'sales.returns.view',\n 'sales.returns.create',\n 'sales.returns.manage',\n 'sales.invoices.manage',\n 'sales.credit_memos.manage',\n ],\n },\n\n async onTenantCreated({ em, tenantId, organizationId }) {\n const exists = await em.findOne(SalesSettings, { tenantId, organizationId })\n if (!exists) {\n em.persist(\n em.create(SalesSettings, {\n tenantId,\n organizationId,\n orderNumberFormat: DEFAULT_ORDER_NUMBER_FORMAT,\n quoteNumberFormat: DEFAULT_QUOTE_NUMBER_FORMAT,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n )\n }\n\n for (const kind of ['order', 'quote', 'return', 'invoice', 'credit_memo'] as const) {\n const seq = await em.findOne(SalesDocumentSequence, {\n tenantId,\n organizationId,\n documentKind: kind,\n })\n if (!seq) {\n em.persist(\n em.create(SalesDocumentSequence, {\n tenantId,\n organizationId,\n documentKind: kind,\n currentValue: 0,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n )\n }\n }\n\n await em.flush()\n },\n\n async seedDefaults({ em, tenantId, organizationId }) {\n const scope = { tenantId, organizationId }\n await seedSalesTaxRates(em, scope)\n await seedSalesStatusDictionaries(em, scope)\n await seedSalesAdjustmentKinds(em, scope)\n await ensureExampleShippingMethods(em, scope)\n await ensureExamplePaymentMethods(em, scope)\n },\n\n async seedExamples({ em, container, tenantId, organizationId }) {\n const scope = { tenantId, organizationId }\n await seedSalesExamples(em, container, scope)\n },\n}\n\nexport default setup\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport type { ModuleSetupConfig } from '@open-mercato/shared/modules/setup'\nimport { SalesSettings, SalesDocumentSequence, SalesTaxRate } from './data/entities'\nimport { DEFAULT_ORDER_NUMBER_FORMAT, DEFAULT_QUOTE_NUMBER_FORMAT } from './lib/documentNumberTokens'\nimport { seedSalesStatusDictionaries, seedSalesAdjustmentKinds } from './lib/dictionaries'\nimport { seedSalesChannelsToggle } from './lib/salesChannelsToggleSeed'\nimport { ensureExampleShippingMethods, ensureExamplePaymentMethods } from './seed/examples-data'\nimport { seedSalesExamples } from './seed/examples'\n\ntype SeedScope = { tenantId: string; organizationId: string }\n\nconst DEFAULT_TAX_RATES = [\n { code: 'vat-23', name: '23% VAT', rate: '23' },\n { code: 'vat-0', name: '0% VAT', rate: '0' },\n] as const\n\nasync function seedSalesTaxRates(em: EntityManager, scope: SeedScope): Promise<void> {\n await em.transactional(async (tem) => {\n const existing = await tem.find(SalesTaxRate, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n })\n const existingCodes = new Set(existing.map((rate) => rate.code))\n const hasDefault = existing.some((rate) => rate.isDefault)\n const now = new Date()\n let isFirst = !hasDefault\n\n for (const seed of DEFAULT_TAX_RATES) {\n if (existingCodes.has(seed.code)) continue\n tem.persist(\n tem.create(SalesTaxRate, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n code: seed.code,\n name: seed.name,\n rate: seed.rate,\n priority: 0,\n isCompound: false,\n isDefault: isFirst,\n createdAt: now,\n updatedAt: now,\n })\n )\n isFirst = false\n }\n })\n}\n\nexport const setup: ModuleSetupConfig = {\n defaultRoleFeatures: {\n admin: ['sales.*', 'sales.documents.number.edit'],\n employee: [\n 'sales.channels.view',\n 'sales.channels.manage',\n 'sales.settings.view',\n 'sales.settings.manage',\n 'sales.orders.view',\n 'sales.orders.manage',\n 'sales.orders.approve',\n 'sales.widgets.new-orders',\n 'sales.widgets.new-quotes',\n 'sales.quotes.view',\n 'sales.quotes.manage',\n 'sales.shipments.manage',\n 'sales.payments.manage',\n 'sales.returns.view',\n 'sales.returns.create',\n 'sales.returns.manage',\n 'sales.invoices.manage',\n 'sales.credit_memos.manage',\n ],\n },\n\n async onTenantCreated({ em, tenantId, organizationId }) {\n const exists = await em.findOne(SalesSettings, { tenantId, organizationId })\n if (!exists) {\n em.persist(\n em.create(SalesSettings, {\n tenantId,\n organizationId,\n orderNumberFormat: DEFAULT_ORDER_NUMBER_FORMAT,\n quoteNumberFormat: DEFAULT_QUOTE_NUMBER_FORMAT,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n )\n }\n\n for (const kind of ['order', 'quote', 'return', 'invoice', 'credit_memo'] as const) {\n const seq = await em.findOne(SalesDocumentSequence, {\n tenantId,\n organizationId,\n documentKind: kind,\n })\n if (!seq) {\n em.persist(\n em.create(SalesDocumentSequence, {\n tenantId,\n organizationId,\n documentKind: kind,\n currentValue: 0,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n )\n }\n }\n\n await em.flush()\n },\n\n async seedDefaults({ em, tenantId, organizationId }) {\n const scope = { tenantId, organizationId }\n await seedSalesTaxRates(em, scope)\n await seedSalesStatusDictionaries(em, scope)\n await seedSalesAdjustmentKinds(em, scope)\n await ensureExampleShippingMethods(em, scope)\n await ensureExamplePaymentMethods(em, scope)\n await seedSalesChannelsToggle(em)\n },\n\n async seedExamples({ em, container, tenantId, organizationId }) {\n const scope = { tenantId, organizationId }\n await seedSalesExamples(em, container, scope)\n },\n}\n\nexport default setup\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/core",
3
- "version": "0.6.8-develop.7077.1.94f1126c13",
3
+ "version": "0.6.8-develop.7078.1.ca2d1510b5",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -252,16 +252,16 @@
252
252
  "zod": "^4.4.3"
253
253
  },
254
254
  "peerDependencies": {
255
- "@open-mercato/ai-assistant": "0.6.8-develop.7077.1.94f1126c13",
256
- "@open-mercato/shared": "0.6.8-develop.7077.1.94f1126c13",
257
- "@open-mercato/ui": "0.6.8-develop.7077.1.94f1126c13",
255
+ "@open-mercato/ai-assistant": "0.6.8-develop.7078.1.ca2d1510b5",
256
+ "@open-mercato/shared": "0.6.8-develop.7078.1.ca2d1510b5",
257
+ "@open-mercato/ui": "0.6.8-develop.7078.1.ca2d1510b5",
258
258
  "react": "^19.0.0",
259
259
  "react-dom": "^19.0.0"
260
260
  },
261
261
  "devDependencies": {
262
- "@open-mercato/ai-assistant": "0.6.8-develop.7077.1.94f1126c13",
263
- "@open-mercato/shared": "0.6.8-develop.7077.1.94f1126c13",
264
- "@open-mercato/ui": "0.6.8-develop.7077.1.94f1126c13",
262
+ "@open-mercato/ai-assistant": "0.6.8-develop.7078.1.ca2d1510b5",
263
+ "@open-mercato/shared": "0.6.8-develop.7078.1.ca2d1510b5",
264
+ "@open-mercato/ui": "0.6.8-develop.7078.1.ca2d1510b5",
265
265
  "@testing-library/dom": "^10.4.1",
266
266
  "@testing-library/jest-dom": "^7.0.0",
267
267
  "@testing-library/react": "^16.3.1",
@@ -16,14 +16,6 @@
16
16
  "type": "string",
17
17
  "defaultValue": "Free shipping on orders over $50"
18
18
  },
19
- {
20
- "identifier": "sales_channels_enabled",
21
- "name": "Sales Channels",
22
- "description": "Show sales channel pickers, filters, and management UI. Disable for tenants that do not use sales channels.",
23
- "category": "sales",
24
- "type": "boolean",
25
- "defaultValue": true
26
- },
27
19
  {
28
20
  "identifier": "order_review_threshold",
29
21
  "name": "Order Review Threshold",
@@ -0,0 +1,42 @@
1
+ import type { EntityManager } from '@mikro-orm/postgresql'
2
+ import { FeatureToggle } from '@open-mercato/core/modules/feature_toggles/data/entities'
3
+ import { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'
4
+ import { SALES_CHANNELS_TOGGLE_ID } from './salesChannelsToggleId'
5
+
6
+ export const SALES_CHANNELS_TOGGLE_DEFINITION = {
7
+ identifier: SALES_CHANNELS_TOGGLE_ID,
8
+ name: 'Sales Channels',
9
+ description: 'Show sales channel pickers, filters, and management UI. Disable for tenants that do not use sales channels.',
10
+ category: 'sales',
11
+ type: 'boolean' as const,
12
+ defaultValue: true,
13
+ } as const
14
+
15
+ // The sales module owns this toggle definition, so tenant setup registers it the
16
+ // same way portal, customers and wms register theirs. Shipping it only in the
17
+ // core defaults file left it unregistered on every database initialized before
18
+ // the toggle existed, and `useSalesChannelsEnabled` then 404s on every mount.
19
+ //
20
+ // The lookup deliberately does not filter on `deletedAt`. Deletion is soft
21
+ // (`feature_toggles.global.delete`) while `feature_toggles_identifier_unique`
22
+ // covers every row, so filtering would make this insert a duplicate and fail the
23
+ // whole seed run on any installation where the toggle was deleted. Matching the
24
+ // create command's own uniqueness check also leaves an operator's deletion alone
25
+ // instead of resurrecting the definition on every tenant seed.
26
+ export async function seedSalesChannelsToggle(em: EntityManager): Promise<void> {
27
+ const existing = await findOneWithDecryption(em, FeatureToggle, {
28
+ identifier: SALES_CHANNELS_TOGGLE_DEFINITION.identifier,
29
+ })
30
+ if (existing) return
31
+ em.persist(
32
+ em.create(FeatureToggle, {
33
+ identifier: SALES_CHANNELS_TOGGLE_DEFINITION.identifier,
34
+ name: SALES_CHANNELS_TOGGLE_DEFINITION.name,
35
+ description: SALES_CHANNELS_TOGGLE_DEFINITION.description,
36
+ category: SALES_CHANNELS_TOGGLE_DEFINITION.category,
37
+ type: SALES_CHANNELS_TOGGLE_DEFINITION.type,
38
+ defaultValue: SALES_CHANNELS_TOGGLE_DEFINITION.defaultValue,
39
+ }),
40
+ )
41
+ await em.flush()
42
+ }
@@ -3,6 +3,7 @@ import type { ModuleSetupConfig } from '@open-mercato/shared/modules/setup'
3
3
  import { SalesSettings, SalesDocumentSequence, SalesTaxRate } from './data/entities'
4
4
  import { DEFAULT_ORDER_NUMBER_FORMAT, DEFAULT_QUOTE_NUMBER_FORMAT } from './lib/documentNumberTokens'
5
5
  import { seedSalesStatusDictionaries, seedSalesAdjustmentKinds } from './lib/dictionaries'
6
+ import { seedSalesChannelsToggle } from './lib/salesChannelsToggleSeed'
6
7
  import { ensureExampleShippingMethods, ensureExamplePaymentMethods } from './seed/examples-data'
7
8
  import { seedSalesExamples } from './seed/examples'
8
9
 
@@ -116,6 +117,7 @@ export const setup: ModuleSetupConfig = {
116
117
  await seedSalesAdjustmentKinds(em, scope)
117
118
  await ensureExampleShippingMethods(em, scope)
118
119
  await ensureExamplePaymentMethods(em, scope)
120
+ await seedSalesChannelsToggle(em)
119
121
  },
120
122
 
121
123
  async seedExamples({ em, container, tenantId, organizationId }) {