@endora-commerce/mod-price-lists 0.100.0
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/LICENSE +21 -0
- package/README.md +59 -0
- package/dist/admin/components/ApplicationRuleBuilder.d.ts +24 -0
- package/dist/admin/components/ApplicationRuleBuilder.d.ts.map +1 -0
- package/dist/admin/components/ApplicationRuleBuilder.js +249 -0
- package/dist/admin/components/ApplicationRuleBuilder.js.map +1 -0
- package/dist/admin/components/BracketGrid.d.ts +29 -0
- package/dist/admin/components/BracketGrid.d.ts.map +1 -0
- package/dist/admin/components/BracketGrid.js +252 -0
- package/dist/admin/components/BracketGrid.js.map +1 -0
- package/dist/admin/components/DisplayModeOverrideRow.d.ts +46 -0
- package/dist/admin/components/DisplayModeOverrideRow.d.ts.map +1 -0
- package/dist/admin/components/DisplayModeOverrideRow.js +109 -0
- package/dist/admin/components/DisplayModeOverrideRow.js.map +1 -0
- package/dist/admin/components/LinkedPriceListsPanel.d.ts +55 -0
- package/dist/admin/components/LinkedPriceListsPanel.d.ts.map +1 -0
- package/dist/admin/components/LinkedPriceListsPanel.js +131 -0
- package/dist/admin/components/LinkedPriceListsPanel.js.map +1 -0
- package/dist/admin/index.d.ts +34 -0
- package/dist/admin/index.d.ts.map +1 -0
- package/dist/admin/index.js +119 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/admin/pages/DisplayModeOverridesPage.d.ts +25 -0
- package/dist/admin/pages/DisplayModeOverridesPage.d.ts.map +1 -0
- package/dist/admin/pages/DisplayModeOverridesPage.js +266 -0
- package/dist/admin/pages/DisplayModeOverridesPage.js.map +1 -0
- package/dist/admin/pages/PriceListDetailPage.d.ts +23 -0
- package/dist/admin/pages/PriceListDetailPage.d.ts.map +1 -0
- package/dist/admin/pages/PriceListDetailPage.js +421 -0
- package/dist/admin/pages/PriceListDetailPage.js.map +1 -0
- package/dist/admin/pages/PriceListsPage.d.ts +17 -0
- package/dist/admin/pages/PriceListsPage.d.ts.map +1 -0
- package/dist/admin/pages/PriceListsPage.js +198 -0
- package/dist/admin/pages/PriceListsPage.js.map +1 -0
- package/dist/admin/zones/CategoryDisplayMode.d.ts +27 -0
- package/dist/admin/zones/CategoryDisplayMode.d.ts.map +1 -0
- package/dist/admin/zones/CategoryDisplayMode.js +11 -0
- package/dist/admin/zones/CategoryDisplayMode.js.map +1 -0
- package/dist/admin/zones/OrganizationDisplayMode.d.ts +36 -0
- package/dist/admin/zones/OrganizationDisplayMode.d.ts.map +1 -0
- package/dist/admin/zones/OrganizationDisplayMode.js +12 -0
- package/dist/admin/zones/OrganizationDisplayMode.js.map +1 -0
- package/dist/admin/zones/ProductLinkedPriceLists.d.ts +16 -0
- package/dist/admin/zones/ProductLinkedPriceLists.d.ts.map +1 -0
- package/dist/admin/zones/ProductLinkedPriceLists.js +7 -0
- package/dist/admin/zones/ProductLinkedPriceLists.js.map +1 -0
- package/dist/backend/entities/price-display-mode-override.entity.d.ts +23 -0
- package/dist/backend/entities/price-display-mode-override.entity.d.ts.map +1 -0
- package/dist/backend/entities/price-display-mode-override.entity.js +58 -0
- package/dist/backend/entities/price-display-mode-override.entity.js.map +1 -0
- package/dist/backend/entities/price-list-price-bracket.entity.d.ts +26 -0
- package/dist/backend/entities/price-list-price-bracket.entity.d.ts.map +1 -0
- package/dist/backend/entities/price-list-price-bracket.entity.js +73 -0
- package/dist/backend/entities/price-list-price-bracket.entity.js.map +1 -0
- package/dist/backend/entities/price-list-product.entity.d.ts +15 -0
- package/dist/backend/entities/price-list-product.entity.d.ts.map +1 -0
- package/dist/backend/entities/price-list-product.entity.js +43 -0
- package/dist/backend/entities/price-list-product.entity.js.map +1 -0
- package/dist/backend/entities/price-list.entity.d.ts +34 -0
- package/dist/backend/entities/price-list.entity.d.ts.map +1 -0
- package/dist/backend/entities/price-list.entity.js +115 -0
- package/dist/backend/entities/price-list.entity.js.map +1 -0
- package/dist/backend/index.d.ts +125 -0
- package/dist/backend/index.d.ts.map +1 -0
- package/dist/backend/index.js +179 -0
- package/dist/backend/index.js.map +1 -0
- package/dist/backend/plugin.d.ts +68 -0
- package/dist/backend/plugin.d.ts.map +1 -0
- package/dist/backend/plugin.js +88 -0
- package/dist/backend/plugin.js.map +1 -0
- package/dist/backend/routes.d.ts +40 -0
- package/dist/backend/routes.d.ts.map +1 -0
- package/dist/backend/routes.js +447 -0
- package/dist/backend/routes.js.map +1 -0
- package/dist/backend/routes.storefront.d.ts +47 -0
- package/dist/backend/routes.storefront.d.ts.map +1 -0
- package/dist/backend/routes.storefront.js +131 -0
- package/dist/backend/routes.storefront.js.map +1 -0
- package/dist/backend/services/application-rule-evaluator.d.ts +25 -0
- package/dist/backend/services/application-rule-evaluator.d.ts.map +1 -0
- package/dist/backend/services/application-rule-evaluator.js +2 -0
- package/dist/backend/services/application-rule-evaluator.js.map +1 -0
- package/dist/backend/services/audit-references.d.ts +11 -0
- package/dist/backend/services/audit-references.d.ts.map +1 -0
- package/dist/backend/services/audit-references.js +23 -0
- package/dist/backend/services/audit-references.js.map +1 -0
- package/dist/backend/services/default-price-list-migration.d.ts +70 -0
- package/dist/backend/services/default-price-list-migration.d.ts.map +1 -0
- package/dist/backend/services/default-price-list-migration.js +177 -0
- package/dist/backend/services/default-price-list-migration.js.map +1 -0
- package/dist/backend/services/display-mode-resolver.d.ts +78 -0
- package/dist/backend/services/display-mode-resolver.d.ts.map +1 -0
- package/dist/backend/services/display-mode-resolver.js +71 -0
- package/dist/backend/services/display-mode-resolver.js.map +1 -0
- package/dist/backend/services/listing-price-chain.d.ts +26 -0
- package/dist/backend/services/listing-price-chain.d.ts.map +1 -0
- package/dist/backend/services/listing-price-chain.js +55 -0
- package/dist/backend/services/listing-price-chain.js.map +1 -0
- package/dist/backend/services/price-bracket-resolver.d.ts +24 -0
- package/dist/backend/services/price-bracket-resolver.d.ts.map +1 -0
- package/dist/backend/services/price-bracket-resolver.js +16 -0
- package/dist/backend/services/price-bracket-resolver.js.map +1 -0
- package/dist/backend/services/price-list-candidate-vector.d.ts +116 -0
- package/dist/backend/services/price-list-candidate-vector.d.ts.map +1 -0
- package/dist/backend/services/price-list-candidate-vector.js +133 -0
- package/dist/backend/services/price-list-candidate-vector.js.map +1 -0
- package/dist/backend/services/price-list-currency-reference.d.ts +12 -0
- package/dist/backend/services/price-list-currency-reference.d.ts.map +1 -0
- package/dist/backend/services/price-list-currency-reference.js +24 -0
- package/dist/backend/services/price-list-currency-reference.js.map +1 -0
- package/dist/backend/services/price-list-read-port.d.ts +29 -0
- package/dist/backend/services/price-list-read-port.d.ts.map +1 -0
- package/dist/backend/services/price-list-read-port.js +64 -0
- package/dist/backend/services/price-list-read-port.js.map +1 -0
- package/dist/backend/services/price-list-resolver.d.ts +26 -0
- package/dist/backend/services/price-list-resolver.d.ts.map +1 -0
- package/dist/backend/services/price-list-resolver.js +37 -0
- package/dist/backend/services/price-list-resolver.js.map +1 -0
- package/dist/backend/services/price-list-service.d.ts +431 -0
- package/dist/backend/services/price-list-service.d.ts.map +1 -0
- package/dist/backend/services/price-list-service.js +1238 -0
- package/dist/backend/services/price-list-service.js.map +1 -0
- package/dist/backend/services/price-list-status-worker.d.ts +28 -0
- package/dist/backend/services/price-list-status-worker.d.ts.map +1 -0
- package/dist/backend/services/price-list-status-worker.js +38 -0
- package/dist/backend/services/price-list-status-worker.js.map +1 -0
- package/dist/backend/services/pricing-cache.d.ts +53 -0
- package/dist/backend/services/pricing-cache.d.ts.map +1 -0
- package/dist/backend/services/pricing-cache.js +88 -0
- package/dist/backend/services/pricing-cache.js.map +1 -0
- package/dist/backend/services/pricing-service.d.ts +304 -0
- package/dist/backend/services/pricing-service.d.ts.map +1 -0
- package/dist/backend/services/pricing-service.interface.d.ts +151 -0
- package/dist/backend/services/pricing-service.interface.d.ts.map +1 -0
- package/dist/backend/services/pricing-service.interface.js +10 -0
- package/dist/backend/services/pricing-service.interface.js.map +1 -0
- package/dist/backend/services/pricing-service.js +803 -0
- package/dist/backend/services/pricing-service.js.map +1 -0
- package/dist/backend/services/unit-price-ordering.d.ts +121 -0
- package/dist/backend/services/unit-price-ordering.d.ts.map +1 -0
- package/dist/backend/services/unit-price-ordering.js +164 -0
- package/dist/backend/services/unit-price-ordering.js.map +1 -0
- package/dist/manifest.d.ts +218 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +228 -0
- package/dist/manifest.js.map +1 -0
- package/dist/migrations/20260426T075235_price_lists_pricing_init.d.ts +24 -0
- package/dist/migrations/20260426T075235_price_lists_pricing_init.d.ts.map +1 -0
- package/dist/migrations/20260426T075235_price_lists_pricing_init.js +89 -0
- package/dist/migrations/20260426T075235_price_lists_pricing_init.js.map +1 -0
- package/dist/migrations/20260504T125655_price_lists_engine.d.ts +6 -0
- package/dist/migrations/20260504T125655_price_lists_engine.d.ts.map +1 -0
- package/dist/migrations/20260504T125655_price_lists_engine.js +319 -0
- package/dist/migrations/20260504T125655_price_lists_engine.js.map +1 -0
- package/dist/migrations/20260817T055457_price_lists_single_system_price_list.d.ts +15 -0
- package/dist/migrations/20260817T055457_price_lists_single_system_price_list.d.ts.map +1 -0
- package/dist/migrations/20260817T055457_price_lists_single_system_price_list.js +58 -0
- package/dist/migrations/20260817T055457_price_lists_single_system_price_list.js.map +1 -0
- package/dist/migrations/20260821T135907_price_lists_unit_price_amount_index.d.ts +40 -0
- package/dist/migrations/20260821T135907_price_lists_unit_price_amount_index.d.ts.map +1 -0
- package/dist/migrations/20260821T135907_price_lists_unit_price_amount_index.js +46 -0
- package/dist/migrations/20260821T135907_price_lists_unit_price_amount_index.js.map +1 -0
- package/dist/migrations/index.d.ts +30 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +35 -0
- package/dist/migrations/index.js.map +1 -0
- package/docs/price_lists.md +278 -0
- package/i18n/en.json +14 -0
- package/i18n/pl.json +14 -0
- package/package.json +99 -0
- package/tailwind.css +14 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
export function resolveDisplayMode(customer, overrides, settings) {
|
|
2
|
+
if (overrides.productOverride !== null) {
|
|
3
|
+
return { mode: overrides.productOverride, resolvedFrom: 'product' };
|
|
4
|
+
}
|
|
5
|
+
if (overrides.categoryOverride !== null) {
|
|
6
|
+
return { mode: overrides.categoryOverride, resolvedFrom: 'category' };
|
|
7
|
+
}
|
|
8
|
+
if (customer === 'signed_in' && overrides.organizationOverride !== null) {
|
|
9
|
+
return { mode: overrides.organizationOverride, resolvedFrom: 'organization' };
|
|
10
|
+
}
|
|
11
|
+
if (customer === 'guest') {
|
|
12
|
+
return {
|
|
13
|
+
mode: settings.unauthenticatedDisplayMode,
|
|
14
|
+
resolvedFrom: 'settings.unauthenticated',
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
return { mode: settings.defaultDisplayMode, resolvedFrom: 'settings.default' };
|
|
18
|
+
}
|
|
19
|
+
/** Most specific first: deepest, then `(sort_order asc, id asc)` as tie-break. */
|
|
20
|
+
export function pickCategoryOverride(candidates) {
|
|
21
|
+
let best = null;
|
|
22
|
+
for (const candidate of candidates) {
|
|
23
|
+
if (best === null) {
|
|
24
|
+
best = candidate;
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
if (candidate.depth !== best.depth) {
|
|
28
|
+
if (candidate.depth > best.depth)
|
|
29
|
+
best = candidate;
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
if (candidate.sortOrder !== best.sortOrder) {
|
|
33
|
+
if (candidate.sortOrder < best.sortOrder)
|
|
34
|
+
best = candidate;
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
if (candidate.categoryId.localeCompare(best.categoryId) < 0)
|
|
38
|
+
best = candidate;
|
|
39
|
+
}
|
|
40
|
+
return best;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* The chain's decision with the settings tier left **unread**.
|
|
44
|
+
*
|
|
45
|
+
* The eager `resolveDisplayMode` above wants both settings values in hand,
|
|
46
|
+
* which is one query per product on a listing page and two more on a cart line
|
|
47
|
+
* that an override already answered. This form names the settings step instead
|
|
48
|
+
* of taking its value, so the per-product path reads the pair only when it is
|
|
49
|
+
* reached and the batched path reads it once for the whole page.
|
|
50
|
+
*
|
|
51
|
+
* `organizationOverride` is the caller's answer to "is this a signed-in
|
|
52
|
+
* customer with an organization" — a guest passes `null`, exactly as the
|
|
53
|
+
* eager resolver's `customer === 'signed_in'` guard requires.
|
|
54
|
+
*/
|
|
55
|
+
export function decideDisplayMode(inputs) {
|
|
56
|
+
if (inputs.productOverride !== null) {
|
|
57
|
+
return { source: 'product', mode: inputs.productOverride };
|
|
58
|
+
}
|
|
59
|
+
const category = pickCategoryOverride(inputs.categoryCandidates);
|
|
60
|
+
if (category !== null)
|
|
61
|
+
return { source: 'category', mode: category.mode };
|
|
62
|
+
if (inputs.organizationOverride !== null) {
|
|
63
|
+
return { source: 'organization', mode: inputs.organizationOverride };
|
|
64
|
+
}
|
|
65
|
+
return { source: 'settings' };
|
|
66
|
+
}
|
|
67
|
+
/** Which `pricing.*` settings key answers for this customer kind. */
|
|
68
|
+
export function settingsDisplayModeKey(customer) {
|
|
69
|
+
return customer === 'guest' ? 'unauthenticated_display_mode' : 'default_display_mode';
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=display-mode-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"display-mode-resolver.js","sourceRoot":"","sources":["../../../src/backend/services/display-mode-resolver.ts"],"names":[],"mappings":"AA4CA,MAAM,UAAU,kBAAkB,CAChC,QAAsB,EACtB,SAAoC,EACpC,QAA0B;IAE1B,IAAI,SAAS,CAAC,eAAe,KAAK,IAAI,EAAE,CAAC;QACvC,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,eAAe,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC;IACtE,CAAC;IACD,IAAI,SAAS,CAAC,gBAAgB,KAAK,IAAI,EAAE,CAAC;QACxC,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,gBAAgB,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC;IACxE,CAAC;IACD,IAAI,QAAQ,KAAK,WAAW,IAAI,SAAS,CAAC,oBAAoB,KAAK,IAAI,EAAE,CAAC;QACxE,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,oBAAoB,EAAE,YAAY,EAAE,cAAc,EAAE,CAAC;IAChF,CAAC;IACD,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACzB,OAAO;YACL,IAAI,EAAE,QAAQ,CAAC,0BAA0B;YACzC,YAAY,EAAE,0BAA0B;SACzC,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,QAAQ,CAAC,kBAAkB,EAAE,YAAY,EAAE,kBAAkB,EAAE,CAAC;AACjF,CAAC;AAkBD,kFAAkF;AAClF,MAAM,UAAU,oBAAoB,CAClC,UAAmD;IAEnD,IAAI,IAAI,GAAwC,IAAI,CAAC;IACrD,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAClB,IAAI,GAAG,SAAS,CAAC;YACjB,SAAS;QACX,CAAC;QACD,IAAI,SAAS,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC;YACnC,IAAI,SAAS,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK;gBAAE,IAAI,GAAG,SAAS,CAAC;YACnD,SAAS;QACX,CAAC;QACD,IAAI,SAAS,CAAC,SAAS,KAAK,IAAI,CAAC,SAAS,EAAE,CAAC;YAC3C,IAAI,SAAS,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS;gBAAE,IAAI,GAAG,SAAS,CAAC;YAC3D,SAAS;QACX,CAAC;QACD,IAAI,SAAS,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,IAAI,GAAG,SAAS,CAAC;IAChF,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAMD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAIjC;IACC,IAAI,MAAM,CAAC,eAAe,KAAK,IAAI,EAAE,CAAC;QACpC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,eAAe,EAAE,CAAC;IAC7D,CAAC;IACD,MAAM,QAAQ,GAAG,oBAAoB,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;IACjE,IAAI,QAAQ,KAAK,IAAI;QAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC1E,IAAI,MAAM,CAAC,oBAAoB,KAAK,IAAI,EAAE,CAAC;QACzC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,CAAC,oBAAoB,EAAE,CAAC;IACvE,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;AAChC,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,sBAAsB,CACpC,QAAsB;IAEtB,OAAO,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,8BAA8B,CAAC,CAAC,CAAC,sBAAsB,CAAC;AACxF,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ListingPrice } from '@endora-commerce/contracts';
|
|
2
|
+
import type { PricingLineResult } from './pricing-service.interface.js';
|
|
3
|
+
/**
|
|
4
|
+
* The catalogue-listing pricing chain (issue #132), as a pure function.
|
|
5
|
+
*
|
|
6
|
+
* The product ruling: **applicable price list → the price assigned directly to
|
|
7
|
+
* the Product → nothing.** There is always one default price list — a system
|
|
8
|
+
* list `PriceListService` refuses to delete, refuses to move out of `active`
|
|
9
|
+
* and pins to a `kind: 'all'` rule — so the first step is the path a listing
|
|
10
|
+
* normally takes and the other two are a genuine margin.
|
|
11
|
+
*
|
|
12
|
+
* The chain lives here, in the module that owns pricing, rather than in the
|
|
13
|
+
* four listing paths that need it. That is the same rule the composition
|
|
14
|
+
* checklist states for a degrade: it belongs inside the owner's implementation
|
|
15
|
+
* and is expressed in the return type, so no consumer can invent a step of its
|
|
16
|
+
* own — which is precisely how four read paths came to render a figure no
|
|
17
|
+
* price list supported.
|
|
18
|
+
*
|
|
19
|
+
* `null` for `line` is the engine's own "nothing applies" answer, which is
|
|
20
|
+
* distinct from "the module is absent": the port gate throws before this
|
|
21
|
+
* function is ever reached.
|
|
22
|
+
*/
|
|
23
|
+
export declare function listingPriceFrom(line: PricingLineResult | null, product: {
|
|
24
|
+
attributeValues: Record<string, unknown>;
|
|
25
|
+
}, currencyCode: string): ListingPrice;
|
|
26
|
+
//# sourceMappingURL=listing-price-chain.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listing-price-chain.d.ts","sourceRoot":"","sources":["../../../src/backend/services/listing-price-chain.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAExE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,iBAAiB,GAAG,IAAI,EAC9B,OAAO,EAAE;IAAE,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,EACrD,YAAY,EAAE,MAAM,GACnB,YAAY,CAad"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The catalogue-listing pricing chain (issue #132), as a pure function.
|
|
3
|
+
*
|
|
4
|
+
* The product ruling: **applicable price list → the price assigned directly to
|
|
5
|
+
* the Product → nothing.** There is always one default price list — a system
|
|
6
|
+
* list `PriceListService` refuses to delete, refuses to move out of `active`
|
|
7
|
+
* and pins to a `kind: 'all'` rule — so the first step is the path a listing
|
|
8
|
+
* normally takes and the other two are a genuine margin.
|
|
9
|
+
*
|
|
10
|
+
* The chain lives here, in the module that owns pricing, rather than in the
|
|
11
|
+
* four listing paths that need it. That is the same rule the composition
|
|
12
|
+
* checklist states for a degrade: it belongs inside the owner's implementation
|
|
13
|
+
* and is expressed in the return type, so no consumer can invent a step of its
|
|
14
|
+
* own — which is precisely how four read paths came to render a figure no
|
|
15
|
+
* price list supported.
|
|
16
|
+
*
|
|
17
|
+
* `null` for `line` is the engine's own "nothing applies" answer, which is
|
|
18
|
+
* distinct from "the module is absent": the port gate throws before this
|
|
19
|
+
* function is ever reached.
|
|
20
|
+
*/
|
|
21
|
+
export function listingPriceFrom(line, product, currencyCode) {
|
|
22
|
+
if (line) {
|
|
23
|
+
return {
|
|
24
|
+
source: 'price_list',
|
|
25
|
+
amount: line.amount,
|
|
26
|
+
currency: line.currency.toUpperCase(),
|
|
27
|
+
priceListId: line.priceListId,
|
|
28
|
+
isSale: line.isSale,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
const own = productOwnAmount(product);
|
|
32
|
+
if (own === null)
|
|
33
|
+
return { source: 'none' };
|
|
34
|
+
return { source: 'product', amount: own, currency: currencyCode.toUpperCase() };
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The price assigned directly to the Product — the legacy `defaultPrice` (and
|
|
38
|
+
* older `price`) attribute, read in exactly one place now that the chain is the
|
|
39
|
+
* owner's.
|
|
40
|
+
*
|
|
41
|
+
* Returns a decimal string so the `price_list` and `product` arms of the union
|
|
42
|
+
* carry the same kind of amount, and `null` when there is no number to carry.
|
|
43
|
+
* Zero is a number: it comes back as `'0.00'` and reaches the listing as zero,
|
|
44
|
+
* never as an absence.
|
|
45
|
+
*/
|
|
46
|
+
function productOwnAmount(product) {
|
|
47
|
+
const raw = product.attributeValues['defaultPrice'] ?? product.attributeValues['price'];
|
|
48
|
+
if (typeof raw !== 'number' && typeof raw !== 'string')
|
|
49
|
+
return null;
|
|
50
|
+
const value = Number(raw);
|
|
51
|
+
if (!Number.isFinite(value) || value < 0)
|
|
52
|
+
return null;
|
|
53
|
+
return value.toFixed(2);
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=listing-price-chain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listing-price-chain.js","sourceRoot":"","sources":["../../../src/backend/services/listing-price-chain.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,gBAAgB,CAC9B,IAA8B,EAC9B,OAAqD,EACrD,YAAoB;IAEpB,IAAI,IAAI,EAAE,CAAC;QACT,OAAO;YACL,MAAM,EAAE,YAAY;YACpB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE;YACrC,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC;IACJ,CAAC;IACD,MAAM,GAAG,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACtC,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAC5C,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,YAAY,CAAC,WAAW,EAAE,EAAE,CAAC;AAClF,CAAC;AAED;;;;;;;;;GASG;AACH,SAAS,gBAAgB,CAAC,OAAqD;IAC7E,MAAM,GAAG,GAAG,OAAO,CAAC,eAAe,CAAC,cAAc,CAAC,IAAI,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;IACxF,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACpE,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IAC1B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACtD,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure bracket resolver (feature 011 / FR-014, FR-016, FR-031).
|
|
3
|
+
*
|
|
4
|
+
* Given a list of brackets across currencies, returns the bracket whose
|
|
5
|
+
* `(currency, minQuantity, maxQuantity)` window covers the requested
|
|
6
|
+
* `(currency, qty)`. Returns null when the requested currency is missing
|
|
7
|
+
* from the bracket set OR the requested quantity falls outside every
|
|
8
|
+
* bracket on that currency (the bracket-gap fall-through case from
|
|
9
|
+
* research §R5 — the resolver advances to the next-priority list).
|
|
10
|
+
*
|
|
11
|
+
* Brackets are expected to be non-overlapping within the same currency
|
|
12
|
+
* (overlap-freedom is enforced at the service layer when brackets are
|
|
13
|
+
* written; this resolver assumes valid input).
|
|
14
|
+
*/
|
|
15
|
+
export interface PriceBracketRow {
|
|
16
|
+
priceListId: string;
|
|
17
|
+
productId: string;
|
|
18
|
+
currencyCode: string;
|
|
19
|
+
minQuantity: number;
|
|
20
|
+
maxQuantity: number | null;
|
|
21
|
+
amount: string;
|
|
22
|
+
}
|
|
23
|
+
export declare function resolvePriceBracket(brackets: readonly PriceBracketRow[], currencyCode: string, quantity: number): PriceBracketRow | null;
|
|
24
|
+
//# sourceMappingURL=price-bracket-resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"price-bracket-resolver.d.ts","sourceRoot":"","sources":["../../../src/backend/services/price-bracket-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,SAAS,eAAe,EAAE,EACpC,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,GACf,eAAe,GAAG,IAAI,CAUxB"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export function resolvePriceBracket(brackets, currencyCode, quantity) {
|
|
2
|
+
if (quantity < 1)
|
|
3
|
+
return null;
|
|
4
|
+
const inCurrency = brackets.filter((b) => b.currencyCode === currencyCode);
|
|
5
|
+
if (inCurrency.length === 0)
|
|
6
|
+
return null;
|
|
7
|
+
for (const b of inCurrency) {
|
|
8
|
+
if (b.minQuantity > quantity)
|
|
9
|
+
continue;
|
|
10
|
+
if (b.maxQuantity != null && b.maxQuantity < quantity)
|
|
11
|
+
continue;
|
|
12
|
+
return b;
|
|
13
|
+
}
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=price-bracket-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"price-bracket-resolver.js","sourceRoot":"","sources":["../../../src/backend/services/price-bracket-resolver.ts"],"names":[],"mappings":"AAuBA,MAAM,UAAU,mBAAmB,CACjC,QAAoC,EACpC,YAAoB,EACpB,QAAgB;IAEhB,IAAI,QAAQ,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAC9B,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,KAAK,YAAY,CAAC,CAAC;IAC3E,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACzC,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,IAAI,CAAC,CAAC,WAAW,GAAG,QAAQ;YAAE,SAAS;QACvC,IAAI,CAAC,CAAC,WAAW,IAAI,IAAI,IAAI,CAAC,CAAC,WAAW,GAAG,QAAQ;YAAE,SAAS;QAChE,OAAO,CAAC,CAAC;IACX,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { type ApplicationRule } from '@endora-commerce/contracts';
|
|
2
|
+
/**
|
|
3
|
+
* The viewer's ordered price-list candidates (feature 086, research §R1), as a
|
|
4
|
+
* **pure** function of the active lists and the viewer's rule dimensions.
|
|
5
|
+
*
|
|
6
|
+
* ## The structural fact this rests on
|
|
7
|
+
*
|
|
8
|
+
* `evaluateApplicationRule` has five criterion types — `salesChannel`,
|
|
9
|
+
* `organization`, `customerGroup`, `currency`, `category` — and four of them
|
|
10
|
+
* read only the viewer. **`category` is the only one that reads the product.**
|
|
11
|
+
* So for a fixed viewer the set of lists that match, and the priority each
|
|
12
|
+
* matches at, is the same for every product *except* where a rule names a
|
|
13
|
+
* category; and `pickPriorityChain`'s walk is a total order over candidates, so
|
|
14
|
+
* FR-031's fall-through ("drop the list with no usable bracket and re-pick") is
|
|
15
|
+
* exactly "take the first candidate in that order that has a bracket" —
|
|
16
|
+
* removing elements from a totally ordered set does not reorder what remains.
|
|
17
|
+
*
|
|
18
|
+
* That is what turns the resolution into a merge of ordered streams instead of
|
|
19
|
+
* a per-product loop, and it is why this file exists at all.
|
|
20
|
+
*
|
|
21
|
+
* ## The order is produced by the walk, not by a copy of it
|
|
22
|
+
*
|
|
23
|
+
* The vector is built by calling {@link pickPriorityChain} repeatedly and
|
|
24
|
+
* removing the winner — which *is* the fall-through walk, run to exhaustion.
|
|
25
|
+
* Writing the priority chain out as a sort key would be a second implementation
|
|
26
|
+
* of the resolver's ranking, free to drift from it; this cannot drift, because
|
|
27
|
+
* it is the same function.
|
|
28
|
+
*
|
|
29
|
+
* ## The sale partition leads the base partition, wholesale
|
|
30
|
+
*
|
|
31
|
+
* `lineFromEngine` charges the sale price whenever the sale partition resolves
|
|
32
|
+
* *any* bracket, and only otherwise the base one. So "first candidate that
|
|
33
|
+
* prices the product wins" reproduces it exactly when every sale candidate is
|
|
34
|
+
* ordered above every base candidate — not by interleaving the two partitions
|
|
35
|
+
* by priority.
|
|
36
|
+
*
|
|
37
|
+
* ## Category criteria become membership predicates, not evaluations
|
|
38
|
+
*
|
|
39
|
+
* A rule that names a category matches some products and not others, so one
|
|
40
|
+
* price list can appear in the vector **more than once**: once per subset of
|
|
41
|
+
* its category criteria that could be true, each entry carrying the memberships
|
|
42
|
+
* that subset requires. Two properties make that safe and make the entries
|
|
43
|
+
* cheap:
|
|
44
|
+
*
|
|
45
|
+
* - the rule AST is **monotone** (`all`, `criterion`, `AND`, `OR` — there is no
|
|
46
|
+
* negation), so making one more criterion true can only move `explicitOn`
|
|
47
|
+
* up the priority chain, never down. An entry therefore never over-ranks the
|
|
48
|
+
* products it covers: its rank is a floor, and the entry that carries the
|
|
49
|
+
* exact rank is enumerated too and sorts ahead of it;
|
|
50
|
+
* - which means an entry needs no *negative* membership predicate. It says
|
|
51
|
+
* which categories a product must be in, never which it must be out of, and
|
|
52
|
+
* a product that also satisfies a criterion the entry left out is answered by
|
|
53
|
+
* the better-ranked entry that includes it. Both entries name the same price
|
|
54
|
+
* list and therefore the same amount, so a tie between them changes nothing.
|
|
55
|
+
*
|
|
56
|
+
* The synthetic category set each subset is evaluated against still has to
|
|
57
|
+
* exclude the criteria outside the subset, or the evaluation would come back
|
|
58
|
+
* with a rank the subset has not earned. A subset whose criteria cannot all be
|
|
59
|
+
* true once the others are excluded is unreachable and is skipped — the entry
|
|
60
|
+
* that covers those products is the larger subset.
|
|
61
|
+
*/
|
|
62
|
+
/** A price list, as the vector reads it. */
|
|
63
|
+
export interface CandidateListInput {
|
|
64
|
+
id: string;
|
|
65
|
+
type: 'base' | 'sale';
|
|
66
|
+
applicationRule: ApplicationRule;
|
|
67
|
+
modifiedAt: Date;
|
|
68
|
+
name: string;
|
|
69
|
+
isSystem: boolean;
|
|
70
|
+
}
|
|
71
|
+
/** The viewer's rule dimensions — everything except the product. */
|
|
72
|
+
export interface CandidateViewerContext {
|
|
73
|
+
organizationId: string | null;
|
|
74
|
+
organizationChain: readonly string[];
|
|
75
|
+
customerGroupId: string | null;
|
|
76
|
+
salesChannelId: string;
|
|
77
|
+
currencyCode: string;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* One stream of the merge: a price list, and the category memberships a product
|
|
81
|
+
* must satisfy for this list to apply to it at this rank.
|
|
82
|
+
*/
|
|
83
|
+
export interface OrderedCandidate {
|
|
84
|
+
priceListId: string;
|
|
85
|
+
/** The partition the candidate came from — the row's `isSale`. */
|
|
86
|
+
isSale: boolean;
|
|
87
|
+
/**
|
|
88
|
+
* Each group is one `category` criterion's value list. A product qualifies
|
|
89
|
+
* when it belongs to **at least one** category in **every** group. An empty
|
|
90
|
+
* array means the candidate applies to every product this viewer sees.
|
|
91
|
+
*/
|
|
92
|
+
requireAnyOf: readonly (readonly string[])[];
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* The most `category` criteria one rule may carry before this module refuses to
|
|
96
|
+
* express the ordering.
|
|
97
|
+
*
|
|
98
|
+
* The enumeration is `2^k` per rule, so it needs a ceiling; 8 is far above
|
|
99
|
+
* anything an operator writes (the reference catalogue's rules carry zero) and
|
|
100
|
+
* still bounded at 256 evaluations of a pure function. Above it the answer is a
|
|
101
|
+
* refusal rather than an approximation: an ordering that quietly ranked a list
|
|
102
|
+
* wrongly is precisely the failure this feature exists to avoid, and an
|
|
103
|
+
* unorderable page is visible while a mis-ordered one is not.
|
|
104
|
+
*/
|
|
105
|
+
export declare const MAX_CATEGORY_CRITERIA_PER_RULE = 8;
|
|
106
|
+
/** Thrown when a rule carries more `category` criteria than the vector enumerates. */
|
|
107
|
+
export declare class UnorderableRuleError extends Error {
|
|
108
|
+
readonly priceListId: string;
|
|
109
|
+
constructor(priceListId: string);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* The viewer's candidates, best first: every sale candidate in priority order,
|
|
113
|
+
* then every base candidate in priority order.
|
|
114
|
+
*/
|
|
115
|
+
export declare function buildCandidateVector(lists: readonly CandidateListInput[], viewer: CandidateViewerContext): OrderedCandidate[];
|
|
116
|
+
//# sourceMappingURL=price-list-candidate-vector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"price-list-candidate-vector.d.ts","sourceRoot":"","sources":["../../../src/backend/services/price-list-candidate-vector.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,eAAe,EAErB,MAAM,4BAA4B,CAAC;AAGpC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2DG;AAEH,4CAA4C;AAC5C,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,eAAe,EAAE,eAAe,CAAC;IACjC,UAAU,EAAE,IAAI,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,oEAAoE;AACpE,MAAM,WAAW,sBAAsB;IACrC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,kEAAkE;IAClE,MAAM,EAAE,OAAO,CAAC;IAChB;;;;OAIG;IACH,YAAY,EAAE,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC;CAC9C;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,8BAA8B,IAAI,CAAC;AAEhD,sFAAsF;AACtF,qBAAa,oBAAqB,SAAQ,KAAK;IACjC,QAAQ,CAAC,WAAW,EAAE,MAAM;gBAAnB,WAAW,EAAE,MAAM;CAOzC;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,SAAS,kBAAkB,EAAE,EACpC,MAAM,EAAE,sBAAsB,GAC7B,gBAAgB,EAAE,CASpB"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { evaluateApplicationRule, } from '@endora-commerce/contracts';
|
|
2
|
+
import { pickPriorityChain } from './price-list-resolver.js';
|
|
3
|
+
/**
|
|
4
|
+
* The most `category` criteria one rule may carry before this module refuses to
|
|
5
|
+
* express the ordering.
|
|
6
|
+
*
|
|
7
|
+
* The enumeration is `2^k` per rule, so it needs a ceiling; 8 is far above
|
|
8
|
+
* anything an operator writes (the reference catalogue's rules carry zero) and
|
|
9
|
+
* still bounded at 256 evaluations of a pure function. Above it the answer is a
|
|
10
|
+
* refusal rather than an approximation: an ordering that quietly ranked a list
|
|
11
|
+
* wrongly is precisely the failure this feature exists to avoid, and an
|
|
12
|
+
* unorderable page is visible while a mis-ordered one is not.
|
|
13
|
+
*/
|
|
14
|
+
export const MAX_CATEGORY_CRITERIA_PER_RULE = 8;
|
|
15
|
+
/** Thrown when a rule carries more `category` criteria than the vector enumerates. */
|
|
16
|
+
export class UnorderableRuleError extends Error {
|
|
17
|
+
priceListId;
|
|
18
|
+
constructor(priceListId) {
|
|
19
|
+
super(`Price list ${priceListId} carries more than ${MAX_CATEGORY_CRITERIA_PER_RULE} category ` +
|
|
20
|
+
'criteria, so its applicability cannot be expressed as an ordered stream.');
|
|
21
|
+
this.priceListId = priceListId;
|
|
22
|
+
this.name = 'UnorderableRuleError';
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The viewer's candidates, best first: every sale candidate in priority order,
|
|
27
|
+
* then every base candidate in priority order.
|
|
28
|
+
*/
|
|
29
|
+
export function buildCandidateVector(lists, viewer) {
|
|
30
|
+
const sale = [];
|
|
31
|
+
const base = [];
|
|
32
|
+
for (const list of lists) {
|
|
33
|
+
for (const entry of entriesFor(list, viewer)) {
|
|
34
|
+
(list.type === 'sale' ? sale : base).push(entry);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return [...walk(sale), ...walk(base)];
|
|
38
|
+
}
|
|
39
|
+
/** `pickPriorityChain` run to exhaustion — the fall-through walk itself. */
|
|
40
|
+
function walk(candidates) {
|
|
41
|
+
const remaining = [...candidates];
|
|
42
|
+
const out = [];
|
|
43
|
+
while (remaining.length > 0) {
|
|
44
|
+
const picked = pickPriorityChain(remaining);
|
|
45
|
+
if (!picked)
|
|
46
|
+
break;
|
|
47
|
+
out.push(picked.list);
|
|
48
|
+
remaining.splice(remaining.indexOf(picked), 1);
|
|
49
|
+
}
|
|
50
|
+
return out;
|
|
51
|
+
}
|
|
52
|
+
function entriesFor(list, viewer) {
|
|
53
|
+
const groups = categoryCriterionGroups(list.applicationRule);
|
|
54
|
+
if (groups.length > MAX_CATEGORY_CRITERIA_PER_RULE)
|
|
55
|
+
throw new UnorderableRuleError(list.id);
|
|
56
|
+
const out = [];
|
|
57
|
+
const seen = new Set();
|
|
58
|
+
for (let mask = 0; mask < 1 << groups.length; mask += 1) {
|
|
59
|
+
const included = [];
|
|
60
|
+
const excluded = new Set();
|
|
61
|
+
for (let i = 0; i < groups.length; i += 1) {
|
|
62
|
+
if ((mask >> i) & 1)
|
|
63
|
+
included.push(groups[i]);
|
|
64
|
+
else
|
|
65
|
+
for (const value of groups[i])
|
|
66
|
+
excluded.add(value);
|
|
67
|
+
}
|
|
68
|
+
// The categories a product covered by this subset may be assumed to carry:
|
|
69
|
+
// everything the included criteria name, minus everything the excluded ones
|
|
70
|
+
// do, so the evaluation below awards this subset's rank and no better one.
|
|
71
|
+
const synthetic = new Set();
|
|
72
|
+
for (const group of included) {
|
|
73
|
+
for (const value of group)
|
|
74
|
+
if (!excluded.has(value))
|
|
75
|
+
synthetic.add(value);
|
|
76
|
+
}
|
|
77
|
+
// A criterion left with no representative cannot be true while the excluded
|
|
78
|
+
// ones are false: the subset describes no product, and the products it was
|
|
79
|
+
// meant to cover belong to a larger subset that is enumerated too.
|
|
80
|
+
if (included.some((group) => !group.some((value) => synthetic.has(value))))
|
|
81
|
+
continue;
|
|
82
|
+
const ctx = {
|
|
83
|
+
organizationId: viewer.organizationId,
|
|
84
|
+
organizationChain: viewer.organizationChain,
|
|
85
|
+
customerGroupId: viewer.customerGroupId,
|
|
86
|
+
salesChannelId: viewer.salesChannelId,
|
|
87
|
+
currencyCode: viewer.currencyCode,
|
|
88
|
+
productCategoryIds: synthetic,
|
|
89
|
+
};
|
|
90
|
+
const evaluation = evaluateApplicationRule(list.applicationRule, ctx);
|
|
91
|
+
if (!evaluation.matched)
|
|
92
|
+
continue;
|
|
93
|
+
const requireAnyOf = included.map((group) => [...group].sort());
|
|
94
|
+
const signature = `${[...evaluation.explicitOn].sort().join('+')}|${evaluation.organizationRank ?? ''}|${requireAnyOf.map((g) => g.join(',')).join(';')}`;
|
|
95
|
+
if (seen.has(signature))
|
|
96
|
+
continue;
|
|
97
|
+
seen.add(signature);
|
|
98
|
+
out.push({
|
|
99
|
+
list: { priceListId: list.id, isSale: list.type === 'sale', requireAnyOf },
|
|
100
|
+
evaluation,
|
|
101
|
+
modifiedAt: list.modifiedAt,
|
|
102
|
+
name: list.name,
|
|
103
|
+
isSystem: list.isSystem,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
return out;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* The distinct `category` criteria in a rule, as value groups.
|
|
110
|
+
*
|
|
111
|
+
* De-duplicated by value set: two criteria naming the same categories are the
|
|
112
|
+
* same predicate, and collapsing them keeps the enumeration below its ceiling
|
|
113
|
+
* in the shape an operator most plausibly writes one (the same category named
|
|
114
|
+
* in both halves of an `OR`).
|
|
115
|
+
*/
|
|
116
|
+
function categoryCriterionGroups(rule) {
|
|
117
|
+
const byKey = new Map();
|
|
118
|
+
const visit = (node) => {
|
|
119
|
+
if (node.kind === 'criterion') {
|
|
120
|
+
if (node.type !== 'category' || node.values.length === 0)
|
|
121
|
+
return;
|
|
122
|
+
const values = [...new Set(node.values)].sort();
|
|
123
|
+
byKey.set(values.join(','), values);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
if (node.kind === 'group')
|
|
127
|
+
for (const child of node.children)
|
|
128
|
+
visit(child);
|
|
129
|
+
};
|
|
130
|
+
visit(rule);
|
|
131
|
+
return [...byKey.values()];
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=price-list-candidate-vector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"price-list-candidate-vector.js","sourceRoot":"","sources":["../../../src/backend/services/price-list-candidate-vector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { DictionaryReferenceRegistryPort } from '@endora-commerce/contracts';
|
|
2
|
+
import type { EntityManager } from '@mikro-orm/postgresql';
|
|
3
|
+
/**
|
|
4
|
+
* Who in `price_lists` still points at a currency (feature 077, D-87).
|
|
5
|
+
*
|
|
6
|
+
* `currencies` used to ask this with `select count(*) from "price_lists"` of
|
|
7
|
+
* its own — this module's table, named in a string no import-level boundary
|
|
8
|
+
* check can see. A price list denominated in a currency the platform no
|
|
9
|
+
* longer has is not a price list, so the reference blocks the delete.
|
|
10
|
+
*/
|
|
11
|
+
export declare function registerPriceListCurrencyReferences(registry: DictionaryReferenceRegistryPort, emFactory: () => EntityManager): void;
|
|
12
|
+
//# sourceMappingURL=price-list-currency-reference.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"price-list-currency-reference.d.ts","sourceRoot":"","sources":["../../../src/backend/services/price-list-currency-reference.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,4BAA4B,CAAC;AAClF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D;;;;;;;GAOG;AACH,wBAAgB,mCAAmC,CACjD,QAAQ,EAAE,+BAA+B,EACzC,SAAS,EAAE,MAAM,aAAa,GAC7B,IAAI,CAoBN"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Who in `price_lists` still points at a currency (feature 077, D-87).
|
|
3
|
+
*
|
|
4
|
+
* `currencies` used to ask this with `select count(*) from "price_lists"` of
|
|
5
|
+
* its own — this module's table, named in a string no import-level boundary
|
|
6
|
+
* check can see. A price list denominated in a currency the platform no
|
|
7
|
+
* longer has is not a price list, so the reference blocks the delete.
|
|
8
|
+
*/
|
|
9
|
+
export function registerPriceListCurrencyReferences(registry, emFactory) {
|
|
10
|
+
registry.register({
|
|
11
|
+
ownerModuleId: 'price_lists',
|
|
12
|
+
consumer: 'price_lists',
|
|
13
|
+
tableName: 'price_lists',
|
|
14
|
+
columnName: 'currency',
|
|
15
|
+
blocking: true,
|
|
16
|
+
countReferences: async (code) => {
|
|
17
|
+
const rows = (await emFactory().execute(`select count(*)::int as n from "price_lists" where "currency" = ?`, [code]));
|
|
18
|
+
return rows[0]?.n ?? 0;
|
|
19
|
+
},
|
|
20
|
+
usedCodes: async () => (await emFactory().execute(`select "currency" as code, count(*)::int as count
|
|
21
|
+
from "price_lists" where "currency" is not null group by "currency"`)),
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=price-list-currency-reference.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"price-list-currency-reference.js","sourceRoot":"","sources":["../../../src/backend/services/price-list-currency-reference.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,MAAM,UAAU,mCAAmC,CACjD,QAAyC,EACzC,SAA8B;IAE9B,QAAQ,CAAC,QAAQ,CAAC;QAChB,aAAa,EAAE,aAAa;QAC5B,QAAQ,EAAE,aAAa;QACvB,SAAS,EAAE,aAAa;QACxB,UAAU,EAAE,UAAU;QACtB,QAAQ,EAAE,IAAI;QACd,eAAe,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YAC9B,MAAM,IAAI,GAAG,CAAC,MAAM,SAAS,EAAE,CAAC,OAAO,CACrC,mEAAmE,EACnE,CAAC,IAAI,CAAC,CACP,CAAyB,CAAC;YAC3B,OAAO,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;QACzB,CAAC;QACD,SAAS,EAAE,KAAK,IAAI,EAAE,CACpB,CAAC,MAAM,SAAS,EAAE,CAAC,OAAO,CACxB;+EACuE,CACxE,CAA2C;KAC/C,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { EntityManager } from '@mikro-orm/postgresql';
|
|
2
|
+
import type { PriceListReadPort, PriceListRecord } from '@endora-commerce/contracts';
|
|
3
|
+
import { PriceList } from '../entities/price-list.entity.js';
|
|
4
|
+
/**
|
|
5
|
+
* The row-level read model `price_lists` publishes (feature 075, Phase P).
|
|
6
|
+
*
|
|
7
|
+
* `organizations` resolves which lists apply to an organisation and
|
|
8
|
+
* `product_feeds` reads the list a feed prices from; both reached the entity
|
|
9
|
+
* class before this port existed.
|
|
10
|
+
*
|
|
11
|
+
* The customer-group half left with the entity in feature 076 (D-79) — see
|
|
12
|
+
* `customer_accounts/services/customer-group-read-port.ts`.
|
|
13
|
+
*
|
|
14
|
+
* `listActive` exists on the price-list side because "active" is a status the
|
|
15
|
+
* owning module defines and the schedule can move — a caller filtering on
|
|
16
|
+
* `status === 'active'` itself is a caller that will not notice the day
|
|
17
|
+
* `scheduled` starts counting.
|
|
18
|
+
*/
|
|
19
|
+
export declare class PriceListReadService implements PriceListReadPort {
|
|
20
|
+
private readonly emFactory;
|
|
21
|
+
constructor(emFactory: () => EntityManager);
|
|
22
|
+
findById(id: string): Promise<PriceListRecord | null>;
|
|
23
|
+
findByIds(ids: readonly string[]): Promise<PriceListRecord[]>;
|
|
24
|
+
findByCode(code: string): Promise<PriceListRecord | null>;
|
|
25
|
+
listAll(): Promise<PriceListRecord[]>;
|
|
26
|
+
listActive(): Promise<PriceListRecord[]>;
|
|
27
|
+
}
|
|
28
|
+
export declare function toPriceListRecord(list: PriceList): PriceListRecord;
|
|
29
|
+
//# sourceMappingURL=price-list-read-port.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"price-list-read-port.d.ts","sourceRoot":"","sources":["../../../src/backend/services/price-list-read-port.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AACrF,OAAO,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAE7D;;;;;;;;;;;;;;GAcG;AACH,qBAAa,oBAAqB,YAAW,iBAAiB;IAChD,OAAO,CAAC,QAAQ,CAAC,SAAS;gBAAT,SAAS,EAAE,MAAM,aAAa;IAErD,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAKrD,SAAS,CAAC,GAAG,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IAM7D,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAKzD,OAAO,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;IASrC,UAAU,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;CAQ/C;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,GAAG,eAAe,CAkBlE"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { PriceList } from '../entities/price-list.entity.js';
|
|
2
|
+
/**
|
|
3
|
+
* The row-level read model `price_lists` publishes (feature 075, Phase P).
|
|
4
|
+
*
|
|
5
|
+
* `organizations` resolves which lists apply to an organisation and
|
|
6
|
+
* `product_feeds` reads the list a feed prices from; both reached the entity
|
|
7
|
+
* class before this port existed.
|
|
8
|
+
*
|
|
9
|
+
* The customer-group half left with the entity in feature 076 (D-79) — see
|
|
10
|
+
* `customer_accounts/services/customer-group-read-port.ts`.
|
|
11
|
+
*
|
|
12
|
+
* `listActive` exists on the price-list side because "active" is a status the
|
|
13
|
+
* owning module defines and the schedule can move — a caller filtering on
|
|
14
|
+
* `status === 'active'` itself is a caller that will not notice the day
|
|
15
|
+
* `scheduled` starts counting.
|
|
16
|
+
*/
|
|
17
|
+
export class PriceListReadService {
|
|
18
|
+
emFactory;
|
|
19
|
+
constructor(emFactory) {
|
|
20
|
+
this.emFactory = emFactory;
|
|
21
|
+
}
|
|
22
|
+
async findById(id) {
|
|
23
|
+
const list = await this.emFactory().findOne(PriceList, { id });
|
|
24
|
+
return list ? toPriceListRecord(list) : null;
|
|
25
|
+
}
|
|
26
|
+
async findByIds(ids) {
|
|
27
|
+
if (ids.length === 0)
|
|
28
|
+
return [];
|
|
29
|
+
const lists = await this.emFactory().find(PriceList, { id: { $in: [...ids] } });
|
|
30
|
+
return lists.map(toPriceListRecord);
|
|
31
|
+
}
|
|
32
|
+
async findByCode(code) {
|
|
33
|
+
const list = await this.emFactory().findOne(PriceList, { code });
|
|
34
|
+
return list ? toPriceListRecord(list) : null;
|
|
35
|
+
}
|
|
36
|
+
async listAll() {
|
|
37
|
+
const lists = await this.emFactory().find(PriceList, {}, { orderBy: { priority: 'desc', code: 'asc' } });
|
|
38
|
+
return lists.map(toPriceListRecord);
|
|
39
|
+
}
|
|
40
|
+
async listActive() {
|
|
41
|
+
const lists = await this.emFactory().find(PriceList, { status: 'active' }, { orderBy: { priority: 'desc', code: 'asc' } });
|
|
42
|
+
return lists.map(toPriceListRecord);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export function toPriceListRecord(list) {
|
|
46
|
+
return {
|
|
47
|
+
id: list.id,
|
|
48
|
+
code: list.code,
|
|
49
|
+
name: list.name,
|
|
50
|
+
currency: list.currency,
|
|
51
|
+
isDefault: list.isDefault,
|
|
52
|
+
priority: list.priority,
|
|
53
|
+
type: list.type,
|
|
54
|
+
status: list.status,
|
|
55
|
+
startsAt: list.startsAt ?? null,
|
|
56
|
+
endsAt: list.endsAt ?? null,
|
|
57
|
+
applicationRule: list.applicationRule,
|
|
58
|
+
isSystem: list.isSystem,
|
|
59
|
+
modifiedAt: list.modifiedAt,
|
|
60
|
+
createdAt: list.createdAt,
|
|
61
|
+
updatedAt: list.updatedAt,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=price-list-read-port.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"price-list-read-port.js","sourceRoot":"","sources":["../../../src/backend/services/price-list-read-port.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAE7D;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAO,oBAAoB;IACF;IAA7B,YAA6B,SAA8B;QAA9B,cAAS,GAAT,SAAS,CAAqB;IAAG,CAAC;IAE/D,KAAK,CAAC,QAAQ,CAAC,EAAU;QACvB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;QAC/D,OAAO,IAAI,CAAC,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/C,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,GAAsB;QACpC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAChC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,GAAG,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;QAChF,OAAO,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACtC,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,IAAY;QAC3B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QACjE,OAAO,IAAI,CAAC,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/C,CAAC;IAED,KAAK,CAAC,OAAO;QACX,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC,IAAI,CACvC,SAAS,EACT,EAAE,EACF,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,CAC/C,CAAC;QACF,OAAO,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACtC,CAAC;IAED,KAAK,CAAC,UAAU;QACd,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC,IAAI,CACvC,SAAS,EACT,EAAE,MAAM,EAAE,QAAQ,EAAE,EACpB,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,CAC/C,CAAC;QACF,OAAO,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACtC,CAAC;CACF;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAe;IAC/C,OAAO;QACL,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,IAAI;QAC/B,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,IAAI;QAC3B,eAAe,EAAE,IAAI,CAAC,eAAe;QACrC,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,SAAS,EAAE,IAAI,CAAC,SAAS;KAC1B,CAAC;AACJ,CAAC"}
|