@dainamite/cpq 0.4.0 → 0.6.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/CHANGELOG.md +70 -0
- package/MIGRATION.md +101 -0
- package/dist/modules/cpq/acl.js +1 -0
- package/dist/modules/cpq/acl.js.map +2 -2
- package/dist/modules/cpq/api/_helpers/adjustmentCommandRoute.js +45 -0
- package/dist/modules/cpq/api/_helpers/adjustmentCommandRoute.js.map +7 -0
- package/dist/modules/cpq/api/_helpers/handleArcError.js +2 -2
- package/dist/modules/cpq/api/_helpers/handleArcError.js.map +2 -2
- package/dist/modules/cpq/api/_helpers/quoteMutationGuard.js +23 -0
- package/dist/modules/cpq/api/_helpers/quoteMutationGuard.js.map +7 -0
- package/dist/modules/cpq/api/_helpers/quoteRouteOpenApi.js +19 -0
- package/dist/modules/cpq/api/_helpers/quoteRouteOpenApi.js.map +7 -0
- package/dist/modules/cpq/api/orders/[orderId]/activate/route.js +2 -2
- package/dist/modules/cpq/api/orders/[orderId]/activate/route.js.map +2 -2
- package/dist/modules/cpq/api/orders/[orderId]/route.js +19 -3
- package/dist/modules/cpq/api/orders/[orderId]/route.js.map +2 -2
- package/dist/modules/cpq/api/orders/[orderId]/status/route.js +2 -2
- package/dist/modules/cpq/api/orders/[orderId]/status/route.js.map +2 -2
- package/dist/modules/cpq/api/orders/route.js +49 -4
- package/dist/modules/cpq/api/orders/route.js.map +2 -2
- package/dist/modules/cpq/api/quotes/[quoteId]/clone/route.js +2 -2
- package/dist/modules/cpq/api/quotes/[quoteId]/clone/route.js.map +2 -2
- package/dist/modules/cpq/api/quotes/[quoteId]/items/[lineId]/restore/route.js +54 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/items/[lineId]/restore/route.js.map +7 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/items/[lineId]/route.js +45 -5
- package/dist/modules/cpq/api/quotes/[quoteId]/items/[lineId]/route.js.map +2 -2
- package/dist/modules/cpq/api/quotes/[quoteId]/items/route.js +27 -2
- package/dist/modules/cpq/api/quotes/[quoteId]/items/route.js.map +2 -2
- package/dist/modules/cpq/api/quotes/[quoteId]/price-adjustments/[adjustmentId]/route.js +47 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/price-adjustments/[adjustmentId]/route.js.map +7 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/price-adjustments/preview/route.js +30 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/price-adjustments/preview/route.js.map +7 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/price-adjustments/route.js +47 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/price-adjustments/route.js.map +7 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/recalculate/route.js +34 -4
- package/dist/modules/cpq/api/quotes/[quoteId]/recalculate/route.js.map +2 -2
- package/dist/modules/cpq/api/quotes/[quoteId]/route.js +2 -2
- package/dist/modules/cpq/api/quotes/[quoteId]/route.js.map +2 -2
- package/dist/modules/cpq/api/quotes/[quoteId]/status/route.js +33 -2
- package/dist/modules/cpq/api/quotes/[quoteId]/status/route.js.map +2 -2
- package/dist/modules/cpq/api/quotes/price/route.js +43 -3
- package/dist/modules/cpq/api/quotes/price/route.js.map +2 -2
- package/dist/modules/cpq/api/quotes/route.js +2 -2
- package/dist/modules/cpq/api/quotes/route.js.map +2 -2
- package/dist/modules/cpq/backend/cpq/inventory/AssetsTable.js.map +1 -1
- package/dist/modules/cpq/backend/cpq/inventory/SubscriptionsTable.js.map +1 -1
- package/dist/modules/cpq/backend/cpq/inventory/page.meta.js +1 -1
- package/dist/modules/cpq/backend/cpq/inventory/page.meta.js.map +1 -1
- package/dist/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.js +22 -8
- package/dist/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.js.map +2 -2
- package/dist/modules/cpq/backend/cpq/offerings/page.js.map +1 -1
- package/dist/modules/cpq/backend/cpq/orders/[id]/page.js +89 -232
- package/dist/modules/cpq/backend/cpq/orders/[id]/page.js.map +2 -2
- package/dist/modules/cpq/backend/cpq/orders/page.js.map +1 -1
- package/dist/modules/cpq/backend/cpq/orders/page.meta.js +1 -1
- package/dist/modules/cpq/backend/cpq/orders/page.meta.js.map +1 -1
- package/dist/modules/cpq/backend/cpq/price-rules/page.js.map +1 -1
- package/dist/modules/cpq/backend/cpq/pricing/page.js.map +1 -1
- package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/PriceAdjustmentDialog.js +205 -0
- package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/PriceAdjustmentDialog.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/PriceAdjustmentsPanel.js +79 -0
- package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/PriceAdjustmentsPanel.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/arcLineRemoval.js +53 -0
- package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/arcLineRemoval.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/priceAdjustmentContext.js +107 -0
- package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/priceAdjustmentContext.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/usePriceAdjustments.js +130 -0
- package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/usePriceAdjustments.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/quotes/[id]/page.js +144 -221
- package/dist/modules/cpq/backend/cpq/quotes/[id]/page.js.map +3 -3
- package/dist/modules/cpq/backend/cpq/quotes/page.js.map +1 -1
- package/dist/modules/cpq/backend/cpq/quotes/page.meta.js +1 -1
- package/dist/modules/cpq/backend/cpq/quotes/page.meta.js.map +1 -1
- package/dist/modules/cpq/backend/cpq/specifications/page.js.map +1 -1
- package/dist/modules/cpq/backend/cpq/wizards/page.js.map +1 -1
- package/dist/modules/cpq/ce.js +8 -0
- package/dist/modules/cpq/ce.js.map +2 -2
- package/dist/modules/cpq/cli.js +34 -1
- package/dist/modules/cpq/cli.js.map +2 -2
- package/dist/modules/cpq/commands/price-adjustments.js +107 -0
- package/dist/modules/cpq/commands/price-adjustments.js.map +7 -0
- package/dist/modules/cpq/components/ArcLineDiff.js +53 -0
- package/dist/modules/cpq/components/ArcLineDiff.js.map +7 -0
- package/dist/modules/cpq/components/ChargeBreakdownTable.js +154 -0
- package/dist/modules/cpq/components/ChargeBreakdownTable.js.map +7 -0
- package/dist/modules/cpq/components/CpqListView.js.map +2 -2
- package/dist/modules/cpq/components/PriceWaterfall.js +66 -0
- package/dist/modules/cpq/components/PriceWaterfall.js.map +7 -0
- package/dist/modules/cpq/components/PricingSummaryCard.js +117 -0
- package/dist/modules/cpq/components/PricingSummaryCard.js.map +7 -0
- package/dist/modules/cpq/components/useGrantedFeatures.js +27 -0
- package/dist/modules/cpq/components/useGrantedFeatures.js.map +7 -0
- package/dist/modules/cpq/data/entities.js +97 -0
- package/dist/modules/cpq/data/entities.js.map +2 -2
- package/dist/modules/cpq/data/price-adjustments.js +70 -0
- package/dist/modules/cpq/data/price-adjustments.js.map +7 -0
- package/dist/modules/cpq/data/validators.js +4 -0
- package/dist/modules/cpq/data/validators.js.map +2 -2
- package/dist/modules/cpq/di.js +6 -0
- package/dist/modules/cpq/di.js.map +2 -2
- package/dist/modules/cpq/events.js +47 -0
- package/dist/modules/cpq/events.js.map +2 -2
- package/dist/modules/cpq/index.js +1 -1
- package/dist/modules/cpq/index.js.map +2 -2
- package/dist/modules/cpq/lib/auditActor.js +10 -0
- package/dist/modules/cpq/lib/auditActor.js.map +7 -0
- package/dist/modules/cpq/lib/formatMoney.js +7 -0
- package/dist/modules/cpq/lib/formatMoney.js.map +7 -0
- package/dist/modules/cpq/lib/priceAdjustmentDefaults.js +60 -0
- package/dist/modules/cpq/lib/priceAdjustmentDefaults.js.map +7 -0
- package/dist/modules/cpq/lib/priceAdjustmentView.js +169 -0
- package/dist/modules/cpq/lib/priceAdjustmentView.js.map +7 -0
- package/dist/modules/cpq/lib/quotePermissions.js +13 -0
- package/dist/modules/cpq/lib/quotePermissions.js.map +7 -0
- package/dist/modules/cpq/lib/quoteSummaryView.js +28 -0
- package/dist/modules/cpq/lib/quoteSummaryView.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20261110213052.js +22 -0
- package/dist/modules/cpq/migrations/Migration20261110213052.js.map +7 -0
- package/dist/modules/cpq/services/arcLineRemoval.js +53 -0
- package/dist/modules/cpq/services/arcLineRemoval.js.map +7 -0
- package/dist/modules/cpq/services/arcPriceFreeze.js +79 -0
- package/dist/modules/cpq/services/arcPriceFreeze.js.map +7 -0
- package/dist/modules/cpq/services/cpqOrderService.js +34 -30
- package/dist/modules/cpq/services/cpqOrderService.js.map +2 -2
- package/dist/modules/cpq/services/cpqPricingService.js +7 -0
- package/dist/modules/cpq/services/cpqPricingService.js.map +2 -2
- package/dist/modules/cpq/services/cpqQuotingService.js +339 -111
- package/dist/modules/cpq/services/cpqQuotingService.js.map +2 -2
- package/dist/modules/cpq/services/orderPricingSummary.js +26 -0
- package/dist/modules/cpq/services/orderPricingSummary.js.map +7 -0
- package/dist/modules/cpq/services/priceAdjustments/adjustmentService.js +264 -0
- package/dist/modules/cpq/services/priceAdjustments/adjustmentService.js.map +7 -0
- package/dist/modules/cpq/services/priceAdjustments/chargeWaterfall.js +25 -0
- package/dist/modules/cpq/services/priceAdjustments/chargeWaterfall.js.map +7 -0
- package/dist/modules/cpq/services/priceAdjustments/loadQuoteAdjustments.js +38 -0
- package/dist/modules/cpq/services/priceAdjustments/loadQuoteAdjustments.js.map +7 -0
- package/dist/modules/cpq/services/priceAdjustments/pricingSnapshot.js +104 -0
- package/dist/modules/cpq/services/priceAdjustments/pricingSnapshot.js.map +7 -0
- package/dist/modules/cpq/services/priceAdjustments/quoteAdjustmentLifecycle.js +102 -0
- package/dist/modules/cpq/services/priceAdjustments/quoteAdjustmentLifecycle.js.map +7 -0
- package/dist/modules/cpq/services/priceAdjustments/quotePricingEvents.js +52 -0
- package/dist/modules/cpq/services/priceAdjustments/quotePricingEvents.js.map +7 -0
- package/dist/modules/cpq/services/priceAdjustments/quotePricingWrite.js +37 -0
- package/dist/modules/cpq/services/priceAdjustments/quotePricingWrite.js.map +7 -0
- package/dist/modules/cpq/services/priceAdjustments/resolveManualAdjustments.js +107 -0
- package/dist/modules/cpq/services/priceAdjustments/resolveManualAdjustments.js.map +7 -0
- package/dist/modules/cpq/services/priceAdjustments/storedAdjustmentFailure.js +30 -0
- package/dist/modules/cpq/services/priceAdjustments/storedAdjustmentFailure.js.map +7 -0
- package/dist/modules/cpq/services/types.js.map +2 -2
- package/dist/modules/cpq/setup.js +6 -0
- package/dist/modules/cpq/setup.js.map +2 -2
- package/package.json +9 -9
- package/src/modules/cpq/__integration__/TC-CPQ-002.spec.ts +8 -5
- package/src/modules/cpq/__integration__/TC-CPQ-ARC-012.spec.ts +134 -0
- package/src/modules/cpq/acl.ts +1 -0
- package/src/modules/cpq/api/__tests__/adjustmentRoutes.test.ts +79 -0
- package/src/modules/cpq/api/__tests__/quoteWriteGuards.test.ts +100 -0
- package/src/modules/cpq/api/_helpers/__tests__/quoteMutationGuard.test.ts +48 -0
- package/src/modules/cpq/api/_helpers/adjustmentCommandRoute.ts +45 -0
- package/src/modules/cpq/api/_helpers/handleArcError.ts +12 -12
- package/src/modules/cpq/api/_helpers/quoteMutationGuard.ts +38 -0
- package/src/modules/cpq/api/_helpers/quoteRouteOpenApi.ts +19 -0
- package/src/modules/cpq/api/orders/[orderId]/activate/route.ts +2 -2
- package/src/modules/cpq/api/orders/[orderId]/route.ts +20 -2
- package/src/modules/cpq/api/orders/[orderId]/status/route.ts +2 -2
- package/src/modules/cpq/api/orders/route.ts +53 -3
- package/src/modules/cpq/api/quotes/[quoteId]/clone/route.ts +2 -2
- package/src/modules/cpq/api/quotes/[quoteId]/items/[lineId]/restore/route.ts +56 -0
- package/src/modules/cpq/api/quotes/[quoteId]/items/[lineId]/route.ts +51 -4
- package/src/modules/cpq/api/quotes/[quoteId]/items/route.ts +31 -1
- package/src/modules/cpq/api/quotes/[quoteId]/price-adjustments/[adjustmentId]/route.ts +39 -0
- package/src/modules/cpq/api/quotes/[quoteId]/price-adjustments/preview/route.ts +24 -0
- package/src/modules/cpq/api/quotes/[quoteId]/price-adjustments/route.ts +40 -0
- package/src/modules/cpq/api/quotes/[quoteId]/recalculate/__tests__/route.test.ts +95 -0
- package/src/modules/cpq/api/quotes/[quoteId]/recalculate/route.ts +42 -3
- package/src/modules/cpq/api/quotes/[quoteId]/route.ts +2 -2
- package/src/modules/cpq/api/quotes/[quoteId]/status/__tests__/route.test.ts +74 -0
- package/src/modules/cpq/api/quotes/[quoteId]/status/route.ts +37 -1
- package/src/modules/cpq/api/quotes/price/__tests__/route.test.ts +37 -0
- package/src/modules/cpq/api/quotes/price/route.ts +28 -2
- package/src/modules/cpq/api/quotes/route.ts +2 -2
- package/src/modules/cpq/backend/cpq/inventory/AssetsTable.tsx +1 -1
- package/src/modules/cpq/backend/cpq/inventory/SubscriptionsTable.tsx +1 -1
- package/src/modules/cpq/backend/cpq/inventory/page.meta.ts +1 -1
- package/src/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.tsx +32 -10
- package/src/modules/cpq/backend/cpq/offerings/page.tsx +1 -1
- package/src/modules/cpq/backend/cpq/orders/[id]/page.tsx +60 -269
- package/src/modules/cpq/backend/cpq/orders/page.meta.ts +1 -1
- package/src/modules/cpq/backend/cpq/orders/page.tsx +1 -1
- package/src/modules/cpq/backend/cpq/price-rules/page.tsx +1 -1
- package/src/modules/cpq/backend/cpq/pricing/page.tsx +1 -1
- package/src/modules/cpq/backend/cpq/quotes/[id]/_components/PriceAdjustmentDialog.tsx +260 -0
- package/src/modules/cpq/backend/cpq/quotes/[id]/_components/PriceAdjustmentsPanel.tsx +124 -0
- package/src/modules/cpq/backend/cpq/quotes/[id]/_components/__tests__/PriceAdjustmentsPanel.test.tsx +76 -0
- package/src/modules/cpq/backend/cpq/quotes/[id]/_components/arcLineRemoval.tsx +76 -0
- package/src/modules/cpq/backend/cpq/quotes/[id]/_components/priceAdjustmentContext.tsx +133 -0
- package/src/modules/cpq/backend/cpq/quotes/[id]/_components/usePriceAdjustments.tsx +165 -0
- package/src/modules/cpq/backend/cpq/quotes/[id]/page.tsx +178 -266
- package/src/modules/cpq/backend/cpq/quotes/page.meta.ts +1 -1
- package/src/modules/cpq/backend/cpq/quotes/page.tsx +1 -1
- package/src/modules/cpq/backend/cpq/specifications/page.tsx +1 -1
- package/src/modules/cpq/backend/cpq/wizards/page.tsx +1 -1
- package/src/modules/cpq/ce.ts +8 -0
- package/src/modules/cpq/cli.ts +48 -1
- package/src/modules/cpq/commands/__tests__/price-adjustments.test.ts +54 -0
- package/src/modules/cpq/commands/price-adjustments.ts +90 -0
- package/src/modules/cpq/components/ArcLineDiff.tsx +87 -0
- package/src/modules/cpq/components/ChargeBreakdownTable.tsx +201 -0
- package/src/modules/cpq/components/CpqListView.tsx +2 -1
- package/src/modules/cpq/components/PriceWaterfall.tsx +94 -0
- package/src/modules/cpq/components/PricingSummaryCard.tsx +128 -0
- package/src/modules/cpq/components/__tests__/PriceWaterfall.test.tsx +38 -0
- package/src/modules/cpq/components/useGrantedFeatures.ts +35 -0
- package/src/modules/cpq/data/__tests__/price-adjustment-migration.test.ts +11 -0
- package/src/modules/cpq/data/__tests__/price-adjustments.test.ts +26 -0
- package/src/modules/cpq/data/entities.ts +83 -0
- package/src/modules/cpq/data/price-adjustments.ts +67 -0
- package/src/modules/cpq/data/validators.ts +3 -0
- package/src/modules/cpq/di.ts +6 -0
- package/src/modules/cpq/events.ts +53 -2
- package/src/modules/cpq/index.ts +1 -1
- package/src/modules/cpq/lib/__tests__/auditActor.test.ts +12 -0
- package/src/modules/cpq/lib/__tests__/priceAdjustmentDefaults.test.ts +37 -0
- package/src/modules/cpq/lib/__tests__/priceAdjustmentView.test.ts +152 -0
- package/src/modules/cpq/lib/__tests__/quotePermissions.test.ts +30 -0
- package/src/modules/cpq/lib/__tests__/quoteSummaryView.test.ts +56 -0
- package/src/modules/cpq/lib/auditActor.ts +13 -0
- package/src/modules/cpq/lib/formatMoney.ts +4 -0
- package/src/modules/cpq/lib/priceAdjustmentDefaults.ts +36 -0
- package/src/modules/cpq/lib/priceAdjustmentView.ts +259 -0
- package/src/modules/cpq/lib/quotePermissions.ts +22 -0
- package/src/modules/cpq/lib/quoteSummaryView.ts +51 -0
- package/src/modules/cpq/migrations/.snapshot-open-mercato.json +3298 -2423
- package/src/modules/cpq/migrations/Migration20261110213052.ts +22 -0
- package/src/modules/cpq/services/__tests__/_helpers/mockEm.ts +9 -2
- package/src/modules/cpq/services/__tests__/adjustmentService.test.ts +183 -0
- package/src/modules/cpq/services/__tests__/arcLineRemoval.test.ts +109 -0
- package/src/modules/cpq/services/__tests__/arcPriceFreeze.test.ts +141 -0
- package/src/modules/cpq/services/__tests__/chargeWaterfall.test.ts +28 -0
- package/src/modules/cpq/services/__tests__/cpqOrderService.test.ts +35 -2
- package/src/modules/cpq/services/__tests__/cpqPricingService.test.ts +57 -0
- package/src/modules/cpq/services/__tests__/cpqQuotingService.arc.test.ts +237 -0
- package/src/modules/cpq/services/__tests__/cpqQuotingService.test.ts +58 -3
- package/src/modules/cpq/services/__tests__/errorBrands.test.ts +72 -0
- package/src/modules/cpq/services/__tests__/orderPricingSummary.test.ts +50 -0
- package/src/modules/cpq/services/__tests__/pricingSnapshot.test.ts +62 -0
- package/src/modules/cpq/services/__tests__/quoteAdjustmentLifecycle.test.ts +35 -0
- package/src/modules/cpq/services/__tests__/quoteAdjustmentPricing.test.ts +65 -0
- package/src/modules/cpq/services/__tests__/quoteCloneAdjustments.test.ts +45 -0
- package/src/modules/cpq/services/__tests__/quoteDetachTargetAdjustments.test.ts +54 -0
- package/src/modules/cpq/services/__tests__/quoteEventsService.test.ts +72 -0
- package/src/modules/cpq/services/__tests__/quotePricingEvents.test.ts +126 -0
- package/src/modules/cpq/services/__tests__/quotePricingIsolation.test.ts +52 -0
- package/src/modules/cpq/services/__tests__/quotePricingWrite.test.ts +74 -0
- package/src/modules/cpq/services/__tests__/resolveManualAdjustments.test.ts +90 -0
- package/src/modules/cpq/services/__tests__/storedAdjustmentFailure.test.ts +9 -0
- package/src/modules/cpq/services/arcLineRemoval.ts +87 -0
- package/src/modules/cpq/services/arcPriceFreeze.ts +165 -0
- package/src/modules/cpq/services/cpqOrderService.ts +32 -28
- package/src/modules/cpq/services/cpqPricingService.ts +8 -0
- package/src/modules/cpq/services/cpqQuotingService.ts +388 -125
- package/src/modules/cpq/services/orderPricingSummary.ts +47 -0
- package/src/modules/cpq/services/priceAdjustments/adjustmentService.ts +249 -0
- package/src/modules/cpq/services/priceAdjustments/chargeWaterfall.ts +28 -0
- package/src/modules/cpq/services/priceAdjustments/loadQuoteAdjustments.ts +25 -0
- package/src/modules/cpq/services/priceAdjustments/pricingSnapshot.ts +86 -0
- package/src/modules/cpq/services/priceAdjustments/quoteAdjustmentLifecycle.ts +68 -0
- package/src/modules/cpq/services/priceAdjustments/quotePricingEvents.ts +94 -0
- package/src/modules/cpq/services/priceAdjustments/quotePricingWrite.ts +51 -0
- package/src/modules/cpq/services/priceAdjustments/resolveManualAdjustments.ts +116 -0
- package/src/modules/cpq/services/priceAdjustments/storedAdjustmentFailure.ts +31 -0
- package/src/modules/cpq/services/types.ts +34 -1
- package/src/modules/cpq/setup.ts +7 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/cpq/services/cpqPricingService.ts"],
|
|
4
|
-
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { CpqProductCharge, CpqPricingTable, CpqPricingTableEntry, CpqPriceRule } from '../data/entities'\nimport type { ResolvedCharge, RuleAdjustment, TierBreakdown } from './types'\nimport { getBaseCurrencyCode } from './types'\nimport { normalizeChargePricing } from '../data/charge-pricing'\n\nexport type { ResolvedCharge, RuleAdjustment, TierBreakdown }\n\nexport interface QuotePricingSummary {\n lines: Array<{\n lineId: string\n productId: string\n charges: ResolvedCharge[]\n }>\n totals: {\n nrcTotal: number\n mrcTotal: number\n usageCharges: Array<{ chargeCode: string; unitPrice: number; note: string }>\n }\n currencyCode: string\n}\n\ninterface ApplicabilityCondition {\n attribute: string\n operator: 'eq' | 'neq'\n value: string\n}\n\nfunction evaluateApplicability(\n condition: Record<string, unknown> | null | undefined,\n configuration: Record<string, unknown>,\n): boolean {\n if (!condition) return true\n const cond = condition as unknown as ApplicabilityCondition\n if (!cond.attribute || !cond.operator) return true\n const configValue = String(configuration[cond.attribute] ?? '')\n const conditionValue = String(cond.value ?? '')\n if (cond.operator === 'eq') return configValue === conditionValue\n if (cond.operator === 'neq') return configValue !== conditionValue\n return true\n}\n\nfunction entryMatchesDimensions(\n entry: CpqPricingTableEntry,\n dimensions: Array<{ key: string }>,\n configuration: Record<string, unknown>,\n): boolean {\n return dimensions.every((dim) => {\n const configVal = String(configuration[dim.key] ?? '')\n const entryVal = String(entry.dimensionValues[dim.key] ?? '')\n return configVal.toLowerCase() === entryVal.toLowerCase()\n })\n}\n\nfunction matchEntry(\n entries: CpqPricingTableEntry[],\n dimensions: Array<{ key: string }>,\n configuration: Record<string, unknown>,\n): CpqPricingTableEntry | null {\n return entries.find((entry) => entryMatchesDimensions(entry, dimensions, configuration)) ?? null\n}\n\nexport class DefaultCpqPricingService {\n private em: EntityManager\n\n constructor(em: EntityManager) {\n this.em = em\n }\n\n /**\n * Resolve charges for an offering (v2) or product (v1 fallback).\n * When offeringId is provided, charges are loaded by offeringId.\n * When only productId is provided, falls back to loading by productId.\n */\n async resolveProductCharges(params: {\n offeringId?: string | null\n productId?: string | null\n configuration: Record<string, unknown>\n currencyCode?: string\n tenantId: string\n organizationId: string\n }): Promise<ResolvedCharge[]> {\n const { offeringId, productId, configuration, tenantId, organizationId, currencyCode } = params\n\n const chargeFilter: Record<string, unknown> = {\n tenantId,\n organizationId,\n isActive: true,\n deletedAt: null,\n }\n\n if (offeringId) {\n chargeFilter.offeringId = offeringId\n } else if (productId) {\n chargeFilter.productId = productId\n } else {\n return []\n }\n\n const charges = await this.em.find(CpqProductCharge, chargeFilter, {\n orderBy: { sortOrder: 'asc' },\n })\n\n const applicableCharges = charges.filter((charge) =>\n evaluateApplicability(charge.applicabilityCondition, configuration),\n )\n\n const results: ResolvedCharge[] = []\n for (const charge of applicableCharges) {\n const resolved = await this.calculateCharge({\n charge,\n configuration,\n tenantId,\n organizationId,\n currencyCode,\n })\n // R-CPRICE-8: quote-level currency overrides entry-level currency for consistency.\n // Entry filtering by currencyCode (line 274) ensures price values already match.\n if (currencyCode) {\n resolved.currencyCode = currencyCode\n }\n resolved.adjustments = []\n results.push(resolved)\n }\n\n const rules = await this.loadPriceRules({\n offeringId: offeringId ?? null,\n tenantId,\n organizationId,\n })\n\n if (rules.length > 0) {\n this.applyPriceRules(results, rules, configuration)\n }\n\n return results\n }\n\n private async loadPriceRules(params: {\n offeringId: string | null | undefined\n tenantId: string\n organizationId: string\n }): Promise<CpqPriceRule[]> {\n const { offeringId, tenantId, organizationId } = params\n\n const rules = await this.em.find(\n CpqPriceRule,\n {\n tenantId,\n organizationId,\n isActive: true,\n deletedAt: null,\n $or: [\n { productOfferingId: null },\n ...(offeringId ? [{ productOfferingId: offeringId }] : []),\n ],\n },\n { orderBy: { sortOrder: 'asc' } },\n )\n\n return rules\n }\n\n private applyPriceRules(\n charges: ResolvedCharge[],\n rules: CpqPriceRule[],\n configuration: Record<string, unknown>,\n ): void {\n for (const rule of rules) {\n if (!evaluateApplicability(rule.applicabilityCondition, configuration)) continue\n\n for (const charge of charges) {\n if (rule.chargeCodeFilter && rule.chargeCodeFilter !== charge.chargeCode) continue\n if (rule.chargeTypeFilter && rule.chargeTypeFilter !== charge.chargeType) continue\n\n const unitPriceBefore = charge.unitPrice\n const ruleValue = Number(rule.value)\n let unitPriceAfter: number\n let totalPriceOverride: number | undefined\n\n switch (rule.ruleType) {\n case 'discount_percent':\n unitPriceAfter = Math.max(0, unitPriceBefore * (1 - ruleValue / 100))\n break\n case 'discount_absolute': {\n const currentTotal = charge.totalPrice ?? unitPriceBefore\n totalPriceOverride = Math.max(0, currentTotal - ruleValue)\n const qty = charge.quantity && charge.quantity > 0 ? charge.quantity : 1\n unitPriceAfter = totalPriceOverride / qty\n break\n }\n case 'surcharge_percent':\n unitPriceAfter = unitPriceBefore * (1 + ruleValue / 100)\n break\n case 'surcharge_absolute': {\n const currentTotal = charge.totalPrice ?? unitPriceBefore\n totalPriceOverride = currentTotal + ruleValue\n const qty = charge.quantity && charge.quantity > 0 ? charge.quantity : 1\n unitPriceAfter = totalPriceOverride / qty\n break\n }\n case 'price_override':\n unitPriceAfter = ruleValue\n break\n default:\n continue\n }\n\n charge.unitPrice = unitPriceAfter\n\n if (charge.chargeType === 'usage') {\n // totalPrice stays null for usage charges\n } else if (totalPriceOverride !== undefined) {\n charge.totalPrice = totalPriceOverride\n } else if (charge.quantity !== null) {\n charge.totalPrice = unitPriceAfter * charge.quantity\n } else {\n charge.totalPrice = unitPriceAfter\n }\n\n const adjustment: RuleAdjustment = {\n ruleCode: rule.code,\n ruleName: rule.name,\n ruleType: rule.ruleType,\n value: ruleValue,\n unitPriceBefore,\n unitPriceAfter,\n delta: unitPriceAfter - unitPriceBefore,\n }\n\n if (!charge.adjustments) {\n charge.adjustments = [adjustment]\n } else {\n charge.adjustments.push(adjustment)\n }\n }\n }\n }\n\n async calculateCharge(params: {\n charge: CpqProductCharge\n configuration: Record<string, unknown>\n tenantId: string\n organizationId: string\n currencyCode?: string\n }): Promise<ResolvedCharge> {\n const { charge, configuration, tenantId, organizationId, currencyCode } = params\n\n // Resolve the two axes (chargeModel \u00D7 pricingSource), tolerating legacy\n // rows that still carry a combined pricingMethod (flat | per_unit | tiered).\n const { model, source } = normalizeChargePricing(charge)\n\n const fallbackCurrency = currencyCode ?? charge.currencyCode ?? await getBaseCurrencyCode(this.em, { tenantId, organizationId })\n const base: ResolvedCharge = {\n chargeCode: charge.code,\n chargeName: charge.name,\n chargeType: charge.chargeType as ResolvedCharge['chargeType'],\n pricingMethod: model,\n unitPrice: 0,\n quantity: 1,\n totalPrice: 0,\n currencyCode: fallbackCurrency,\n }\n\n // \u2500\u2500 Fixed price: unit price is the charge's own fixedPrice. Also the\n // fallback when a table-sourced charge has no table configured yet. \u2500\u2500\n if (source === 'fixed' || !charge.pricingTableId) {\n const unitPrice = Number(charge.fixedPrice ?? 0)\n if (model === 'per_unit') {\n const quantity = Number(configuration[charge.quantityAttributeCode ?? ''] ?? 0)\n return { ...base, unitPrice, quantity, totalPrice: unitPrice * quantity }\n }\n // flat (volume/tiered without a table degrade to a single flat price).\n return { ...base, unitPrice, quantity: 1, totalPrice: unitPrice }\n }\n\n // \u2500\u2500 Table lookup \u2500\u2500\n const table = await this.em.findOne(CpqPricingTable, {\n id: charge.pricingTableId,\n tenantId,\n organizationId,\n })\n if (!table) return base\n\n const entryFilters: Record<string, unknown> = {\n pricingTableId: table.id,\n tenantId,\n organizationId,\n isActive: true,\n deletedAt: null,\n }\n if (currencyCode) {\n entryFilters.currencyCode = currencyCode\n }\n\n const entries = await this.em.find(CpqPricingTableEntry, entryFilters)\n\n const priceKey = charge.priceColumnKey ?? ''\n\n if (model === 'flat') {\n return this.calculateFlat(base, charge, entries, table.dimensions, configuration, priceKey)\n }\n if (model === 'per_unit') {\n return this.calculatePerUnit(base, charge, entries, table.dimensions, configuration, priceKey)\n }\n if (model === 'volume') {\n return this.calculateVolume(base, charge, entries, table.dimensions, configuration, priceKey)\n }\n if (model === 'tiered') {\n return this.calculateTiered(base, charge, entries, table.dimensions, configuration, priceKey)\n }\n\n return base\n }\n\n private calculateFlat(\n base: ResolvedCharge,\n charge: CpqProductCharge,\n entries: CpqPricingTableEntry[],\n dimensions: Array<{ key: string }>,\n configuration: Record<string, unknown>,\n priceKey: string,\n ): ResolvedCharge {\n const entry = matchEntry(entries, dimensions, configuration)\n if (!entry) return base\n const unitPrice = entry.prices[priceKey] ?? 0\n\n if (charge.chargeType === 'usage') {\n return {\n ...base,\n unitPrice,\n quantity: null,\n totalPrice: null,\n currencyCode: entry.currencyCode,\n note: charge.description ?? 'Usage-based charge \u2014 billed on actual consumption.',\n }\n }\n\n return { ...base, unitPrice, quantity: 1, totalPrice: unitPrice, currencyCode: entry.currencyCode }\n }\n\n private calculatePerUnit(\n base: ResolvedCharge,\n charge: CpqProductCharge,\n entries: CpqPricingTableEntry[],\n dimensions: Array<{ key: string }>,\n configuration: Record<string, unknown>,\n priceKey: string,\n ): ResolvedCharge {\n const entry = matchEntry(entries, dimensions, configuration)\n if (!entry) return base\n const unitPrice = entry.prices[priceKey] ?? 0\n const entryCurrency = entry.currencyCode\n\n if (charge.chargeType === 'usage') {\n return {\n ...base,\n unitPrice,\n quantity: null,\n totalPrice: null,\n currencyCode: entryCurrency,\n note: charge.description ?? 'Usage-based charge \u2014 billed on actual consumption.',\n }\n }\n\n const quantity = Number(configuration[charge.quantityAttributeCode ?? ''] ?? 0)\n return { ...base, unitPrice, quantity, totalPrice: unitPrice * quantity, currencyCode: entryCurrency }\n }\n\n private calculateTiered(\n base: ResolvedCharge,\n charge: CpqProductCharge,\n entries: CpqPricingTableEntry[],\n dimensions: Array<{ key: string }>,\n configuration: Record<string, unknown>,\n priceKey: string,\n ): ResolvedCharge {\n const quantity = Number(configuration[charge.quantityAttributeCode ?? ''] ?? 0)\n if (quantity <= 0) return { ...base, quantity: 0, totalPrice: 0 }\n\n // tiered must filter to the dimension-matched slice first; flat/per_unit do this via matchEntry.\n const matched = entries.filter((entry) => entryMatchesDimensions(entry, dimensions, configuration))\n // No row matches the configured dimensions \u2192 unpriced; fall back to base\n // (quantity 1, total 0), consistent with flat/per_unit's null-match path.\n if (matched.length === 0) return base\n\n const sorted = [...matched].sort((a, b) => (a.tierNumber ?? 0) - (b.tierNumber ?? 0))\n\n let allocated = 0\n let total = 0\n const tiers: TierBreakdown['tiers'] = []\n let entryCurrency = base.currencyCode\n\n for (const entry of sorted) {\n if (allocated >= quantity) break\n const to = entry.rangeTo ? Number(entry.rangeTo) : Infinity\n const tierCeil = to === Infinity ? quantity : Math.min(to, quantity)\n const qty = tierCeil - allocated\n if (qty <= 0) continue\n const price = entry.prices[priceKey] ?? 0\n entryCurrency = entry.currencyCode\n tiers.push({\n tier: entry.tierNumber ?? 0,\n from: allocated + 1,\n to: allocated + qty,\n pricePerUnit: price,\n quantity: qty,\n subtotal: qty * price,\n })\n total += qty * price\n allocated += qty\n }\n\n return {\n ...base,\n unitPrice: quantity > 0 ? total / quantity : 0,\n quantity,\n totalPrice: total,\n breakdown: { tiers },\n currencyCode: entryCurrency,\n }\n }\n\n // Volume pricing: the WHOLE quantity is billed at the single rate of the tier\n // whose range contains the total quantity \u2014 unlike tiered, which bills each\n // slice at its own rate. Dimension-filtered first, like tiered.\n private calculateVolume(\n base: ResolvedCharge,\n charge: CpqProductCharge,\n entries: CpqPricingTableEntry[],\n dimensions: Array<{ key: string }>,\n configuration: Record<string, unknown>,\n priceKey: string,\n ): ResolvedCharge {\n const quantity = Number(configuration[charge.quantityAttributeCode ?? ''] ?? 0)\n if (quantity <= 0) return { ...base, quantity: 0, totalPrice: 0 }\n\n const matched = entries.filter((entry) => entryMatchesDimensions(entry, dimensions, configuration))\n if (matched.length === 0) return base\n\n // Ranges are [rangeFrom, rangeTo]; rangeTo null = \u221E. Fall back to the top\n // tier if the quantity overflows every defined range.\n const sorted = [...matched].sort((a, b) => (a.tierNumber ?? 0) - (b.tierNumber ?? 0))\n const entry =\n sorted.find((e) => {\n const from = e.rangeFrom != null ? Number(e.rangeFrom) : 0\n const to = e.rangeTo != null ? Number(e.rangeTo) : Infinity\n return quantity >= from && quantity <= to\n }) ?? sorted[sorted.length - 1]\n\n const unitPrice = entry.prices[priceKey] ?? 0\n return {\n ...base,\n unitPrice,\n quantity,\n totalPrice: unitPrice * quantity,\n currencyCode: entry.currencyCode,\n }\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { CpqProductCharge, CpqPricingTable, CpqPricingTableEntry, CpqPriceRule } from '../data/entities'\nimport type { ResolvedCharge, RuleAdjustment, TierBreakdown } from './types'\nimport { getBaseCurrencyCode } from './types'\nimport { normalizeChargePricing } from '../data/charge-pricing'\n\nexport type { ResolvedCharge, RuleAdjustment, TierBreakdown }\n\nexport interface QuotePricingSummary {\n lines: Array<{\n lineId: string\n productId: string\n charges: ResolvedCharge[]\n }>\n totals: {\n nrcTotal: number\n mrcTotal: number\n usageCharges: Array<{ chargeCode: string; unitPrice: number; note: string }>\n }\n currencyCode: string\n}\n\ninterface ApplicabilityCondition {\n attribute: string\n operator: 'eq' | 'neq'\n value: string\n}\n\nfunction evaluateApplicability(\n condition: Record<string, unknown> | null | undefined,\n configuration: Record<string, unknown>,\n): boolean {\n if (!condition) return true\n const cond = condition as unknown as ApplicabilityCondition\n if (!cond.attribute || !cond.operator) return true\n const configValue = String(configuration[cond.attribute] ?? '')\n const conditionValue = String(cond.value ?? '')\n if (cond.operator === 'eq') return configValue === conditionValue\n if (cond.operator === 'neq') return configValue !== conditionValue\n return true\n}\n\nfunction entryMatchesDimensions(\n entry: CpqPricingTableEntry,\n dimensions: Array<{ key: string }>,\n configuration: Record<string, unknown>,\n): boolean {\n return dimensions.every((dim) => {\n const configVal = String(configuration[dim.key] ?? '')\n const entryVal = String(entry.dimensionValues[dim.key] ?? '')\n return configVal.toLowerCase() === entryVal.toLowerCase()\n })\n}\n\nfunction matchEntry(\n entries: CpqPricingTableEntry[],\n dimensions: Array<{ key: string }>,\n configuration: Record<string, unknown>,\n): CpqPricingTableEntry | null {\n return entries.find((entry) => entryMatchesDimensions(entry, dimensions, configuration)) ?? null\n}\n\nexport class DefaultCpqPricingService {\n private em: EntityManager\n\n constructor(em: EntityManager) {\n this.em = em\n }\n\n /**\n * Resolve charges for an offering (v2) or product (v1 fallback).\n * When offeringId is provided, charges are loaded by offeringId.\n * When only productId is provided, falls back to loading by productId.\n */\n async resolveProductCharges(params: {\n offeringId?: string | null\n productId?: string | null\n configuration: Record<string, unknown>\n currencyCode?: string\n tenantId: string\n organizationId: string\n }): Promise<ResolvedCharge[]> {\n const { offeringId, productId, configuration, tenantId, organizationId, currencyCode } = params\n\n const chargeFilter: Record<string, unknown> = {\n tenantId,\n organizationId,\n isActive: true,\n deletedAt: null,\n }\n\n if (offeringId) {\n chargeFilter.offeringId = offeringId\n } else if (productId) {\n chargeFilter.productId = productId\n } else {\n return []\n }\n\n const charges = await this.em.find(CpqProductCharge, chargeFilter, {\n orderBy: { sortOrder: 'asc' },\n })\n\n const applicableCharges = charges.filter((charge) =>\n evaluateApplicability(charge.applicabilityCondition, configuration),\n )\n\n const results: ResolvedCharge[] = []\n for (const charge of applicableCharges) {\n const resolved = await this.calculateCharge({\n charge,\n configuration,\n tenantId,\n organizationId,\n currencyCode,\n })\n // R-CPRICE-8: quote-level currency overrides entry-level currency for consistency.\n // Entry filtering by currencyCode (line 274) ensures price values already match.\n if (currencyCode) {\n resolved.currencyCode = currencyCode\n }\n resolved.listUnitPrice = resolved.unitPrice\n resolved.listTotalPrice = resolved.totalPrice\n resolved.adjustments = []\n results.push(resolved)\n }\n\n const rules = await this.loadPriceRules({\n offeringId: offeringId ?? null,\n tenantId,\n organizationId,\n })\n\n if (rules.length > 0) {\n this.applyPriceRules(results, rules, configuration)\n }\n\n for (const resolved of results) {\n resolved.standardUnitPrice = resolved.unitPrice\n resolved.standardTotalPrice = resolved.totalPrice\n }\n\n return results\n }\n\n private async loadPriceRules(params: {\n offeringId: string | null | undefined\n tenantId: string\n organizationId: string\n }): Promise<CpqPriceRule[]> {\n const { offeringId, tenantId, organizationId } = params\n\n const rules = await this.em.find(\n CpqPriceRule,\n {\n tenantId,\n organizationId,\n isActive: true,\n deletedAt: null,\n $or: [\n { productOfferingId: null },\n ...(offeringId ? [{ productOfferingId: offeringId }] : []),\n ],\n },\n { orderBy: { sortOrder: 'asc' } },\n )\n\n return rules\n }\n\n private applyPriceRules(\n charges: ResolvedCharge[],\n rules: CpqPriceRule[],\n configuration: Record<string, unknown>,\n ): void {\n for (const rule of rules) {\n if (!evaluateApplicability(rule.applicabilityCondition, configuration)) continue\n\n for (const charge of charges) {\n if (rule.chargeCodeFilter && rule.chargeCodeFilter !== charge.chargeCode) continue\n if (rule.chargeTypeFilter && rule.chargeTypeFilter !== charge.chargeType) continue\n\n const unitPriceBefore = charge.unitPrice\n const ruleValue = Number(rule.value)\n let unitPriceAfter: number\n let totalPriceOverride: number | undefined\n\n switch (rule.ruleType) {\n case 'discount_percent':\n unitPriceAfter = Math.max(0, unitPriceBefore * (1 - ruleValue / 100))\n break\n case 'discount_absolute': {\n const currentTotal = charge.totalPrice ?? unitPriceBefore\n totalPriceOverride = Math.max(0, currentTotal - ruleValue)\n const qty = charge.quantity && charge.quantity > 0 ? charge.quantity : 1\n unitPriceAfter = totalPriceOverride / qty\n break\n }\n case 'surcharge_percent':\n unitPriceAfter = unitPriceBefore * (1 + ruleValue / 100)\n break\n case 'surcharge_absolute': {\n const currentTotal = charge.totalPrice ?? unitPriceBefore\n totalPriceOverride = currentTotal + ruleValue\n const qty = charge.quantity && charge.quantity > 0 ? charge.quantity : 1\n unitPriceAfter = totalPriceOverride / qty\n break\n }\n case 'price_override':\n unitPriceAfter = ruleValue\n break\n default:\n continue\n }\n\n charge.unitPrice = unitPriceAfter\n\n if (charge.chargeType === 'usage') {\n // totalPrice stays null for usage charges\n } else if (totalPriceOverride !== undefined) {\n charge.totalPrice = totalPriceOverride\n } else if (charge.quantity !== null) {\n charge.totalPrice = unitPriceAfter * charge.quantity\n } else {\n charge.totalPrice = unitPriceAfter\n }\n\n const adjustment: RuleAdjustment = {\n origin: 'rule',\n ruleCode: rule.code,\n ruleName: rule.name,\n ruleType: rule.ruleType,\n value: ruleValue,\n unitPriceBefore,\n unitPriceAfter,\n delta: unitPriceAfter - unitPriceBefore,\n }\n\n if (!charge.adjustments) {\n charge.adjustments = [adjustment]\n } else {\n charge.adjustments.push(adjustment)\n }\n }\n }\n }\n\n async calculateCharge(params: {\n charge: CpqProductCharge\n configuration: Record<string, unknown>\n tenantId: string\n organizationId: string\n currencyCode?: string\n }): Promise<ResolvedCharge> {\n const { charge, configuration, tenantId, organizationId, currencyCode } = params\n\n // Resolve the two axes (chargeModel \u00D7 pricingSource), tolerating legacy\n // rows that still carry a combined pricingMethod (flat | per_unit | tiered).\n const { model, source } = normalizeChargePricing(charge)\n\n const fallbackCurrency = currencyCode ?? charge.currencyCode ?? await getBaseCurrencyCode(this.em, { tenantId, organizationId })\n const base: ResolvedCharge = {\n chargeCode: charge.code,\n chargeName: charge.name,\n chargeType: charge.chargeType as ResolvedCharge['chargeType'],\n pricingMethod: model,\n unitPrice: 0,\n quantity: 1,\n totalPrice: 0,\n currencyCode: fallbackCurrency,\n }\n\n // \u2500\u2500 Fixed price: unit price is the charge's own fixedPrice. Also the\n // fallback when a table-sourced charge has no table configured yet. \u2500\u2500\n if (source === 'fixed' || !charge.pricingTableId) {\n const unitPrice = Number(charge.fixedPrice ?? 0)\n if (model === 'per_unit') {\n const quantity = Number(configuration[charge.quantityAttributeCode ?? ''] ?? 0)\n return { ...base, unitPrice, quantity, totalPrice: unitPrice * quantity }\n }\n // flat (volume/tiered without a table degrade to a single flat price).\n return { ...base, unitPrice, quantity: 1, totalPrice: unitPrice }\n }\n\n // \u2500\u2500 Table lookup \u2500\u2500\n const table = await this.em.findOne(CpqPricingTable, {\n id: charge.pricingTableId,\n tenantId,\n organizationId,\n })\n if (!table) return base\n\n const entryFilters: Record<string, unknown> = {\n pricingTableId: table.id,\n tenantId,\n organizationId,\n isActive: true,\n deletedAt: null,\n }\n if (currencyCode) {\n entryFilters.currencyCode = currencyCode\n }\n\n const entries = await this.em.find(CpqPricingTableEntry, entryFilters)\n\n const priceKey = charge.priceColumnKey ?? ''\n\n if (model === 'flat') {\n return this.calculateFlat(base, charge, entries, table.dimensions, configuration, priceKey)\n }\n if (model === 'per_unit') {\n return this.calculatePerUnit(base, charge, entries, table.dimensions, configuration, priceKey)\n }\n if (model === 'volume') {\n return this.calculateVolume(base, charge, entries, table.dimensions, configuration, priceKey)\n }\n if (model === 'tiered') {\n return this.calculateTiered(base, charge, entries, table.dimensions, configuration, priceKey)\n }\n\n return base\n }\n\n private calculateFlat(\n base: ResolvedCharge,\n charge: CpqProductCharge,\n entries: CpqPricingTableEntry[],\n dimensions: Array<{ key: string }>,\n configuration: Record<string, unknown>,\n priceKey: string,\n ): ResolvedCharge {\n const entry = matchEntry(entries, dimensions, configuration)\n if (!entry) return base\n const unitPrice = entry.prices[priceKey] ?? 0\n\n if (charge.chargeType === 'usage') {\n return {\n ...base,\n unitPrice,\n quantity: null,\n totalPrice: null,\n currencyCode: entry.currencyCode,\n note: charge.description ?? 'Usage-based charge \u2014 billed on actual consumption.',\n }\n }\n\n return { ...base, unitPrice, quantity: 1, totalPrice: unitPrice, currencyCode: entry.currencyCode }\n }\n\n private calculatePerUnit(\n base: ResolvedCharge,\n charge: CpqProductCharge,\n entries: CpqPricingTableEntry[],\n dimensions: Array<{ key: string }>,\n configuration: Record<string, unknown>,\n priceKey: string,\n ): ResolvedCharge {\n const entry = matchEntry(entries, dimensions, configuration)\n if (!entry) return base\n const unitPrice = entry.prices[priceKey] ?? 0\n const entryCurrency = entry.currencyCode\n\n if (charge.chargeType === 'usage') {\n return {\n ...base,\n unitPrice,\n quantity: null,\n totalPrice: null,\n currencyCode: entryCurrency,\n note: charge.description ?? 'Usage-based charge \u2014 billed on actual consumption.',\n }\n }\n\n const quantity = Number(configuration[charge.quantityAttributeCode ?? ''] ?? 0)\n return { ...base, unitPrice, quantity, totalPrice: unitPrice * quantity, currencyCode: entryCurrency }\n }\n\n private calculateTiered(\n base: ResolvedCharge,\n charge: CpqProductCharge,\n entries: CpqPricingTableEntry[],\n dimensions: Array<{ key: string }>,\n configuration: Record<string, unknown>,\n priceKey: string,\n ): ResolvedCharge {\n const quantity = Number(configuration[charge.quantityAttributeCode ?? ''] ?? 0)\n if (quantity <= 0) return { ...base, quantity: 0, totalPrice: 0 }\n\n // tiered must filter to the dimension-matched slice first; flat/per_unit do this via matchEntry.\n const matched = entries.filter((entry) => entryMatchesDimensions(entry, dimensions, configuration))\n // No row matches the configured dimensions \u2192 unpriced; fall back to base\n // (quantity 1, total 0), consistent with flat/per_unit's null-match path.\n if (matched.length === 0) return base\n\n const sorted = [...matched].sort((a, b) => (a.tierNumber ?? 0) - (b.tierNumber ?? 0))\n\n let allocated = 0\n let total = 0\n const tiers: TierBreakdown['tiers'] = []\n let entryCurrency = base.currencyCode\n\n for (const entry of sorted) {\n if (allocated >= quantity) break\n const to = entry.rangeTo ? Number(entry.rangeTo) : Infinity\n const tierCeil = to === Infinity ? quantity : Math.min(to, quantity)\n const qty = tierCeil - allocated\n if (qty <= 0) continue\n const price = entry.prices[priceKey] ?? 0\n entryCurrency = entry.currencyCode\n tiers.push({\n tier: entry.tierNumber ?? 0,\n from: allocated + 1,\n to: allocated + qty,\n pricePerUnit: price,\n quantity: qty,\n subtotal: qty * price,\n })\n total += qty * price\n allocated += qty\n }\n\n return {\n ...base,\n unitPrice: quantity > 0 ? total / quantity : 0,\n quantity,\n totalPrice: total,\n breakdown: { tiers },\n currencyCode: entryCurrency,\n }\n }\n\n // Volume pricing: the WHOLE quantity is billed at the single rate of the tier\n // whose range contains the total quantity \u2014 unlike tiered, which bills each\n // slice at its own rate. Dimension-filtered first, like tiered.\n private calculateVolume(\n base: ResolvedCharge,\n charge: CpqProductCharge,\n entries: CpqPricingTableEntry[],\n dimensions: Array<{ key: string }>,\n configuration: Record<string, unknown>,\n priceKey: string,\n ): ResolvedCharge {\n const quantity = Number(configuration[charge.quantityAttributeCode ?? ''] ?? 0)\n if (quantity <= 0) return { ...base, quantity: 0, totalPrice: 0 }\n\n const matched = entries.filter((entry) => entryMatchesDimensions(entry, dimensions, configuration))\n if (matched.length === 0) return base\n\n // Ranges are [rangeFrom, rangeTo]; rangeTo null = \u221E. Fall back to the top\n // tier if the quantity overflows every defined range.\n const sorted = [...matched].sort((a, b) => (a.tierNumber ?? 0) - (b.tierNumber ?? 0))\n const entry =\n sorted.find((e) => {\n const from = e.rangeFrom != null ? Number(e.rangeFrom) : 0\n const to = e.rangeTo != null ? Number(e.rangeTo) : Infinity\n return quantity >= from && quantity <= to\n }) ?? sorted[sorted.length - 1]\n\n const unitPrice = entry.prices[priceKey] ?? 0\n return {\n ...base,\n unitPrice,\n quantity,\n totalPrice: unitPrice * quantity,\n currencyCode: entry.currencyCode,\n }\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["entry"]
|
|
7
7
|
}
|