@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.
- package/.turbo/turbo-build.log +1 -1
- package/dist/modules/feature_toggles/defaults.json +0 -8
- package/dist/modules/sales/lib/salesChannelsToggleSeed.js +33 -0
- package/dist/modules/sales/lib/salesChannelsToggleSeed.js.map +7 -0
- package/dist/modules/sales/setup.js +2 -0
- package/dist/modules/sales/setup.js.map +2 -2
- package/package.json +7 -7
- package/src/modules/feature_toggles/defaults.json +0 -8
- package/src/modules/sales/lib/salesChannelsToggleSeed.ts +42 -0
- package/src/modules/sales/setup.ts +2 -0
package/.turbo/turbo-build.log
CHANGED
|
@@ -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": "AAEA,SAAS,eAAe,uBAAuB,oBAAoB;AACnE,SAAS,6BAA6B,mCAAmC;AACzE,SAAS,6BAA6B,gCAAgC;AACtE,SAAS,+BAA+B;AACxC,SAAS,8BAA8B,mCAAmC;AAC1E,SAAS,yBAAyB;AAIlC,MAAM,oBAAoB;AAAA,EACxB,EAAE,MAAM,UAAU,MAAM,WAAW,MAAM,KAAK;AAAA,EAC9C,EAAE,MAAM,SAAS,MAAM,UAAU,MAAM,IAAI;AAC7C;AAEA,eAAe,kBAAkB,IAAmB,OAAiC;AACnF,QAAM,GAAG,cAAc,OAAO,QAAQ;AACpC,UAAM,WAAW,MAAM,IAAI,KAAK,cAAc;AAAA,MAC5C,UAAU,MAAM;AAAA,MAChB,gBAAgB,MAAM;AAAA,MACtB,WAAW;AAAA,IACb,CAAC;AACD,UAAM,gBAAgB,IAAI,IAAI,SAAS,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC;AAC/D,UAAM,aAAa,SAAS,KAAK,CAAC,SAAS,KAAK,SAAS;AACzD,UAAM,MAAM,oBAAI,KAAK;AACrB,QAAI,UAAU,CAAC;AAEf,eAAW,QAAQ,mBAAmB;AACpC,UAAI,cAAc,IAAI,KAAK,IAAI,EAAG;AAClC,UAAI;AAAA,QACF,IAAI,OAAO,cAAc;AAAA,UACvB,UAAU,MAAM;AAAA,UAChB,gBAAgB,MAAM;AAAA,UACtB,MAAM,KAAK;AAAA,UACX,MAAM,KAAK;AAAA,UACX,MAAM,KAAK;AAAA,UACX,UAAU;AAAA,UACV,YAAY;AAAA,UACZ,WAAW;AAAA,UACX,WAAW;AAAA,UACX,WAAW;AAAA,QACb,CAAC;AAAA,MACH;AACA,gBAAU;AAAA,IACZ;AAAA,EACF,CAAC;AACH;AAEO,MAAM,QAA2B;AAAA,EACtC,qBAAqB;AAAA,IACnB,OAAO,CAAC,WAAW,6BAA6B;AAAA,IAChD,UAAU;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,gBAAgB,EAAE,IAAI,UAAU,eAAe,GAAG;AACtD,UAAM,SAAS,MAAM,GAAG,QAAQ,eAAe,EAAE,UAAU,eAAe,CAAC;AAC3E,QAAI,CAAC,QAAQ;AACX,SAAG;AAAA,QACD,GAAG,OAAO,eAAe;AAAA,UACvB;AAAA,UACA;AAAA,UACA,mBAAmB;AAAA,UACnB,mBAAmB;AAAA,UACnB,WAAW,oBAAI,KAAK;AAAA,UACpB,WAAW,oBAAI,KAAK;AAAA,QACtB,CAAC;AAAA,MACH;AAAA,IACF;AAEA,eAAW,QAAQ,CAAC,SAAS,SAAS,UAAU,WAAW,aAAa,GAAY;AAClF,YAAM,MAAM,MAAM,GAAG,QAAQ,uBAAuB;AAAA,QAClD;AAAA,QACA;AAAA,QACA,cAAc;AAAA,MAChB,CAAC;AACD,UAAI,CAAC,KAAK;AACR,WAAG;AAAA,UACD,GAAG,OAAO,uBAAuB;AAAA,YAC/B;AAAA,YACA;AAAA,YACA,cAAc;AAAA,YACd,cAAc;AAAA,YACd,WAAW,oBAAI,KAAK;AAAA,YACpB,WAAW,oBAAI,KAAK;AAAA,UACtB,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAEA,UAAM,GAAG,MAAM;AAAA,EACjB;AAAA,EAEA,MAAM,aAAa,EAAE,IAAI,UAAU,eAAe,GAAG;AACnD,UAAM,QAAQ,EAAE,UAAU,eAAe;AACzC,UAAM,kBAAkB,IAAI,KAAK;AACjC,UAAM,4BAA4B,IAAI,KAAK;AAC3C,UAAM,yBAAyB,IAAI,KAAK;AACxC,UAAM,6BAA6B,IAAI,KAAK;AAC5C,UAAM,4BAA4B,IAAI,KAAK;AAC3C,UAAM,wBAAwB,EAAE;AAAA,EAClC;AAAA,EAEA,MAAM,aAAa,EAAE,IAAI,WAAW,UAAU,eAAe,GAAG;AAC9D,UAAM,QAAQ,EAAE,UAAU,eAAe;AACzC,UAAM,kBAAkB,IAAI,WAAW,KAAK;AAAA,EAC9C;AACF;AAEA,IAAO,gBAAQ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-mercato/core",
|
|
3
|
-
"version": "0.6.8-develop.
|
|
3
|
+
"version": "0.6.8-develop.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.
|
|
256
|
-
"@open-mercato/shared": "0.6.8-develop.
|
|
257
|
-
"@open-mercato/ui": "0.6.8-develop.
|
|
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.
|
|
263
|
-
"@open-mercato/shared": "0.6.8-develop.
|
|
264
|
-
"@open-mercato/ui": "0.6.8-develop.
|
|
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 }) {
|