@dainamite/cpq 0.5.0 → 0.7.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 +64 -0
- package/MIGRATION.md +74 -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/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]/route.js +17 -1
- package/dist/modules/cpq/api/orders/[orderId]/route.js.map +2 -2
- package/dist/modules/cpq/api/orders/route.js +47 -2
- package/dist/modules/cpq/api/orders/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 +42 -2
- 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 +32 -2
- package/dist/modules/cpq/api/quotes/[quoteId]/recalculate/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/backend/cpq/inventory/AssetsTable.js +3 -9
- package/dist/modules/cpq/backend/cpq/inventory/AssetsTable.js.map +2 -2
- package/dist/modules/cpq/backend/cpq/inventory/SubscriptionsTable.js +21 -25
- package/dist/modules/cpq/backend/cpq/inventory/SubscriptionsTable.js.map +2 -2
- package/dist/modules/cpq/backend/cpq/inventory/assets/[id]/page.js +48 -47
- package/dist/modules/cpq/backend/cpq/inventory/assets/[id]/page.js.map +2 -2
- package/dist/modules/cpq/backend/cpq/inventory/assets/[id]/page.meta.js +1 -1
- package/dist/modules/cpq/backend/cpq/inventory/assets/[id]/page.meta.js.map +2 -2
- package/dist/modules/cpq/backend/cpq/inventory/page.meta.js +3 -3
- package/dist/modules/cpq/backend/cpq/inventory/page.meta.js.map +2 -2
- package/dist/modules/cpq/backend/cpq/inventory/shared.js +37 -2
- package/dist/modules/cpq/backend/cpq/inventory/shared.js.map +2 -2
- package/dist/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.js +174 -184
- package/dist/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.js.map +2 -2
- package/dist/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.meta.js +1 -1
- package/dist/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.meta.js.map +2 -2
- package/dist/modules/cpq/backend/cpq/offerings/[id]/page.js +168 -143
- package/dist/modules/cpq/backend/cpq/offerings/[id]/page.js.map +2 -2
- package/dist/modules/cpq/backend/cpq/offerings/page.js +36 -34
- package/dist/modules/cpq/backend/cpq/offerings/page.js.map +2 -2
- package/dist/modules/cpq/backend/cpq/orders/[id]/page.js +140 -280
- package/dist/modules/cpq/backend/cpq/orders/[id]/page.js.map +2 -2
- package/dist/modules/cpq/backend/cpq/orders/page.js +6 -6
- package/dist/modules/cpq/backend/cpq/orders/page.js.map +2 -2
- 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/PriceRuleForm.js +41 -36
- package/dist/modules/cpq/backend/cpq/price-rules/PriceRuleForm.js.map +2 -2
- package/dist/modules/cpq/backend/cpq/price-rules/[id]/page.js +76 -72
- package/dist/modules/cpq/backend/cpq/price-rules/[id]/page.js.map +2 -2
- package/dist/modules/cpq/backend/cpq/price-rules/[id]/page.meta.js +1 -1
- package/dist/modules/cpq/backend/cpq/price-rules/[id]/page.meta.js.map +2 -2
- package/dist/modules/cpq/backend/cpq/price-rules/page.js +18 -15
- package/dist/modules/cpq/backend/cpq/price-rules/page.js.map +2 -2
- package/dist/modules/cpq/backend/cpq/pricing/[id]/EntriesEditor.js +23 -21
- package/dist/modules/cpq/backend/cpq/pricing/[id]/EntriesEditor.js.map +2 -2
- package/dist/modules/cpq/backend/cpq/pricing/[id]/ImportPreview.js +22 -50
- package/dist/modules/cpq/backend/cpq/pricing/[id]/ImportPreview.js.map +2 -2
- package/dist/modules/cpq/backend/cpq/pricing/[id]/page.js +74 -52
- package/dist/modules/cpq/backend/cpq/pricing/[id]/page.js.map +2 -2
- package/dist/modules/cpq/backend/cpq/pricing/[id]/xlsxImport.js +20 -17
- package/dist/modules/cpq/backend/cpq/pricing/[id]/xlsxImport.js.map +2 -2
- package/dist/modules/cpq/backend/cpq/pricing/page.js +1 -1
- package/dist/modules/cpq/backend/cpq/pricing/page.js.map +2 -2
- package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/ArcQuoteConfigurator.js +115 -123
- package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/ArcQuoteConfigurator.js.map +2 -2
- package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/PriceAdjustmentDialog.js +208 -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 +269 -311
- package/dist/modules/cpq/backend/cpq/quotes/[id]/page.js.map +3 -3
- package/dist/modules/cpq/backend/cpq/quotes/page.js +23 -19
- package/dist/modules/cpq/backend/cpq/quotes/page.js.map +2 -2
- 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/[id]/DependsOnRulesEditor.js +19 -15
- package/dist/modules/cpq/backend/cpq/specifications/[id]/DependsOnRulesEditor.js.map +2 -2
- package/dist/modules/cpq/backend/cpq/specifications/[id]/page.js +171 -178
- package/dist/modules/cpq/backend/cpq/specifications/[id]/page.js.map +2 -2
- package/dist/modules/cpq/backend/cpq/specifications/page.js +2 -2
- package/dist/modules/cpq/backend/cpq/specifications/page.js.map +2 -2
- package/dist/modules/cpq/backend/cpq/wizards/[definitionCode]/detail/page.js +60 -50
- package/dist/modules/cpq/backend/cpq/wizards/[definitionCode]/detail/page.js.map +2 -2
- package/dist/modules/cpq/backend/cpq/wizards/[definitionCode]/page.js +22 -18
- package/dist/modules/cpq/backend/cpq/wizards/[definitionCode]/page.js.map +2 -2
- package/dist/modules/cpq/backend/cpq/wizards/page.js +1 -1
- package/dist/modules/cpq/backend/cpq/wizards/page.js.map +2 -2
- 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 +148 -0
- package/dist/modules/cpq/components/ChargeBreakdownTable.js.map +7 -0
- package/dist/modules/cpq/components/PriceWaterfall.js +68 -0
- package/dist/modules/cpq/components/PriceWaterfall.js.map +7 -0
- package/dist/modules/cpq/components/PricingSummaryCard.js +112 -0
- package/dist/modules/cpq/components/PricingSummaryCard.js.map +7 -0
- package/dist/modules/cpq/components/StatusPath.js +5 -3
- package/dist/modules/cpq/components/StatusPath.js.map +2 -2
- package/dist/modules/cpq/components/useCpqRowActions.js +10 -22
- package/dist/modules/cpq/components/useCpqRowActions.js.map +2 -2
- 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/i18n/de.json +1220 -0
- package/dist/modules/cpq/i18n/en.json +1220 -0
- package/dist/modules/cpq/i18n/es.json +1220 -0
- package/dist/modules/cpq/i18n/pl.json +1220 -0
- 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 +25 -28
- 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 +330 -109
- 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/dist/modules/cpq/widgets/injection/customer-inventory/widget.client.js +39 -31
- package/dist/modules/cpq/widgets/injection/customer-inventory/widget.client.js.map +2 -2
- package/dist/modules/cpq/widgets/injection/order-cpq-tab/widget.client.js +13 -5
- package/dist/modules/cpq/widgets/injection/order-cpq-tab/widget.client.js.map +2 -2
- package/dist/modules/cpq/widgets/injection/quote-configurator/widget.client.js +41 -21
- package/dist/modules/cpq/widgets/injection/quote-configurator/widget.client.js.map +2 -2
- package/dist/modules/cpq/widgets/injection-table.js +2 -2
- package/dist/modules/cpq/widgets/injection-table.js.map +2 -2
- package/dist/modules/cpq/workflows/WizardRunner.js +10 -8
- package/dist/modules/cpq/workflows/WizardRunner.js.map +2 -2
- package/dist/modules/cpq/workflows/WizardTrigger.js +15 -9
- package/dist/modules/cpq/workflows/WizardTrigger.js.map +2 -2
- package/dist/modules/cpq/workflows/steps/CustomerSelectStep.js +9 -7
- package/dist/modules/cpq/workflows/steps/CustomerSelectStep.js.map +2 -2
- package/dist/modules/cpq/workflows/steps/InventorySelectStep.js +9 -4
- package/dist/modules/cpq/workflows/steps/InventorySelectStep.js.map +2 -2
- package/dist/modules/cpq/workflows/steps/ItemListStep.js +16 -19
- package/dist/modules/cpq/workflows/steps/ItemListStep.js.map +2 -2
- package/dist/modules/cpq/workflows/steps/OfferingSelectStep.js +19 -32
- package/dist/modules/cpq/workflows/steps/OfferingSelectStep.js.map +2 -2
- package/dist/modules/cpq/workflows/steps/ProductConfigureStep.js +8 -6
- package/dist/modules/cpq/workflows/steps/ProductConfigureStep.js.map +2 -2
- package/dist/modules/cpq/workflows/steps/ReviewStep.js +32 -30
- package/dist/modules/cpq/workflows/steps/ReviewStep.js.map +2 -2
- package/dist/modules/cpq/workflows/steps/index.js +12 -0
- package/dist/modules/cpq/workflows/steps/index.js.map +2 -2
- package/package.json +1 -1
- package/src/modules/cpq/__integration__/TC-CPQ-ARC-012.spec.ts +134 -0
- package/src/modules/cpq/__tests__/i18n/dictionaries.test.ts +62 -0
- package/src/modules/cpq/__tests__/i18n/hardcodedStrings.test.ts +35 -0
- package/src/modules/cpq/__tests__/i18n/sourceScan.ts +109 -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/quoteMutationGuard.ts +38 -0
- package/src/modules/cpq/api/_helpers/quoteRouteOpenApi.ts +19 -0
- package/src/modules/cpq/api/orders/[orderId]/route.ts +18 -0
- package/src/modules/cpq/api/orders/route.ts +51 -1
- 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 +48 -1
- 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 +40 -1
- 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/backend/cpq/inventory/AssetsTable.tsx +3 -9
- package/src/modules/cpq/backend/cpq/inventory/SubscriptionsTable.tsx +22 -26
- package/src/modules/cpq/backend/cpq/inventory/assets/[id]/page.meta.ts +1 -1
- package/src/modules/cpq/backend/cpq/inventory/assets/[id]/page.tsx +43 -46
- package/src/modules/cpq/backend/cpq/inventory/page.meta.ts +3 -3
- package/src/modules/cpq/backend/cpq/inventory/shared.tsx +37 -1
- package/src/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.meta.ts +1 -1
- package/src/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.tsx +164 -120
- package/src/modules/cpq/backend/cpq/offerings/[id]/page.tsx +169 -130
- package/src/modules/cpq/backend/cpq/offerings/page.tsx +34 -24
- package/src/modules/cpq/backend/cpq/orders/[id]/page.tsx +122 -308
- package/src/modules/cpq/backend/cpq/orders/page.meta.ts +1 -1
- package/src/modules/cpq/backend/cpq/orders/page.tsx +6 -6
- package/src/modules/cpq/backend/cpq/price-rules/PriceRuleForm.tsx +48 -34
- package/src/modules/cpq/backend/cpq/price-rules/[id]/page.meta.ts +1 -1
- package/src/modules/cpq/backend/cpq/price-rules/[id]/page.tsx +76 -70
- package/src/modules/cpq/backend/cpq/price-rules/page.tsx +25 -16
- package/src/modules/cpq/backend/cpq/pricing/[id]/EntriesEditor.tsx +24 -18
- package/src/modules/cpq/backend/cpq/pricing/[id]/ImportPreview.tsx +29 -19
- package/src/modules/cpq/backend/cpq/pricing/[id]/page.tsx +95 -47
- package/src/modules/cpq/backend/cpq/pricing/[id]/xlsxImport.ts +23 -15
- package/src/modules/cpq/backend/cpq/pricing/page.tsx +1 -1
- package/src/modules/cpq/backend/cpq/quotes/[id]/_components/ArcQuoteConfigurator.tsx +111 -88
- 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 +304 -348
- package/src/modules/cpq/backend/cpq/quotes/page.meta.ts +1 -1
- package/src/modules/cpq/backend/cpq/quotes/page.tsx +29 -21
- package/src/modules/cpq/backend/cpq/specifications/[id]/DependsOnRulesEditor.tsx +19 -15
- package/src/modules/cpq/backend/cpq/specifications/[id]/page.tsx +171 -171
- package/src/modules/cpq/backend/cpq/specifications/page.tsx +2 -2
- package/src/modules/cpq/backend/cpq/wizards/[definitionCode]/detail/page.tsx +51 -41
- package/src/modules/cpq/backend/cpq/wizards/[definitionCode]/page.tsx +17 -13
- 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 +203 -0
- package/src/modules/cpq/components/PriceWaterfall.tsx +96 -0
- package/src/modules/cpq/components/PricingSummaryCard.tsx +128 -0
- package/src/modules/cpq/components/StatusPath.tsx +7 -4
- package/src/modules/cpq/components/__tests__/PriceWaterfall.test.tsx +38 -0
- package/src/modules/cpq/components/useCpqRowActions.tsx +17 -25
- 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/i18n/de.json +1220 -0
- package/src/modules/cpq/i18n/en.json +1220 -0
- package/src/modules/cpq/i18n/es.json +1220 -0
- package/src/modules/cpq/i18n/pl.json +1220 -0
- 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__/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 +22 -28
- package/src/modules/cpq/services/cpqPricingService.ts +8 -0
- package/src/modules/cpq/services/cpqQuotingService.ts +374 -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
- package/src/modules/cpq/widgets/injection/customer-inventory/widget.client.tsx +38 -31
- package/src/modules/cpq/widgets/injection/order-cpq-tab/widget.client.tsx +7 -5
- package/src/modules/cpq/widgets/injection/quote-configurator/widget.client.tsx +36 -21
- package/src/modules/cpq/widgets/injection-table.ts +8 -2
- package/src/modules/cpq/workflows/WizardRunner.tsx +8 -5
- package/src/modules/cpq/workflows/WizardTrigger.tsx +15 -9
- package/src/modules/cpq/workflows/steps/CustomerSelectStep.tsx +11 -7
- package/src/modules/cpq/workflows/steps/InventorySelectStep.tsx +9 -5
- package/src/modules/cpq/workflows/steps/ItemListStep.tsx +18 -12
- package/src/modules/cpq/workflows/steps/OfferingSelectStep.tsx +20 -16
- package/src/modules/cpq/workflows/steps/ProductConfigureStep.tsx +8 -6
- package/src/modules/cpq/workflows/steps/ReviewStep.tsx +33 -18
- package/src/modules/cpq/workflows/steps/index.ts +12 -0
- package/src/modules/cpq/workflows/types.ts +4 -0
|
@@ -2,23 +2,36 @@
|
|
|
2
2
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { useRouter, useParams } from "next/navigation";
|
|
5
|
+
import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
5
6
|
import { Alert } from "@open-mercato/ui/primitives/alert";
|
|
6
7
|
import { Button } from "@open-mercato/ui/primitives/button";
|
|
7
8
|
import { Tag } from "@open-mercato/ui/primitives/tag";
|
|
8
9
|
import { FormHeader } from "@open-mercato/ui/backend/forms";
|
|
9
10
|
import {
|
|
10
|
-
formatStatusLabel,
|
|
11
11
|
subscriptionStatusMap
|
|
12
12
|
} from "../../../../../components/statusMaps.js";
|
|
13
13
|
import { StatusPath } from "../../../../../components/StatusPath.js";
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
14
|
+
import { DepthBadge, PriceWaterfall } from "../../../../../components/PriceWaterfall.js";
|
|
15
|
+
import { parseStoredCharge } from "../../../../../lib/priceAdjustmentView.js";
|
|
16
|
+
import { buildInventoryStatusLabels, inventoryStatusLabel } from "../../shared.js";
|
|
17
|
+
function changeTypeLabel(t, changeType) {
|
|
18
|
+
switch (changeType) {
|
|
19
|
+
case "created":
|
|
20
|
+
return t("cpq.inventory.subscriptions.detail.changeType.created", "Created");
|
|
21
|
+
case "amend":
|
|
22
|
+
return t("cpq.inventory.subscriptions.detail.changeType.amend", "Amended");
|
|
23
|
+
case "renew":
|
|
24
|
+
return t("cpq.inventory.subscriptions.detail.changeType.renew", "Renewed");
|
|
25
|
+
case "cancel":
|
|
26
|
+
return t("cpq.inventory.subscriptions.detail.changeType.cancel", "Cancelled");
|
|
27
|
+
case "merge-result":
|
|
28
|
+
return t("cpq.inventory.subscriptions.detail.changeType.mergeResult", "Created from merging contracts");
|
|
29
|
+
case "merge-source":
|
|
30
|
+
return t("cpq.inventory.subscriptions.detail.changeType.mergeSource", "Merged into a new contract");
|
|
31
|
+
default:
|
|
32
|
+
return changeType;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
22
35
|
const CHANGE_TYPE_VARIANTS = {
|
|
23
36
|
created: "neutral",
|
|
24
37
|
amend: "info",
|
|
@@ -34,20 +47,16 @@ const ALLOWED_TRANSITIONS = {
|
|
|
34
47
|
terminated: [],
|
|
35
48
|
expired: []
|
|
36
49
|
};
|
|
37
|
-
const
|
|
38
|
-
pending: "Pending",
|
|
39
|
-
active: "Active",
|
|
40
|
-
suspended: "Suspended",
|
|
41
|
-
terminated: "Terminated",
|
|
42
|
-
expired: "Expired"
|
|
43
|
-
};
|
|
50
|
+
const SUBSCRIPTION_STATUSES = ["pending", "active", "suspended", "terminated", "expired"];
|
|
44
51
|
function fmt(amount, currency) {
|
|
45
52
|
return new Intl.NumberFormat("en-US", { style: "currency", currency }).format(Number(amount));
|
|
46
53
|
}
|
|
47
54
|
function StatusBadge({ status }) {
|
|
48
|
-
|
|
55
|
+
const t = useT();
|
|
56
|
+
return /* @__PURE__ */ jsx(Tag, { variant: subscriptionStatusMap[status] ?? "neutral", dot: true, children: inventoryStatusLabel(t, status) });
|
|
49
57
|
}
|
|
50
58
|
function SubscriptionDetailPage(props) {
|
|
59
|
+
const t = useT();
|
|
51
60
|
const router = useRouter();
|
|
52
61
|
const urlParams = useParams();
|
|
53
62
|
const subId = props.params?.id ?? urlParams?.id;
|
|
@@ -82,16 +91,16 @@ function SubscriptionDetailPage(props) {
|
|
|
82
91
|
const body = await res.json().catch(() => ({}));
|
|
83
92
|
if (body.existingQuoteId) {
|
|
84
93
|
const ok = window.confirm(
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
94
|
+
t("cpq.inventory.subscriptions.detail.arc.existingQuoteConfirm", "{error}\n\nOpen the existing quote now?", {
|
|
95
|
+
error: body.error ?? t("cpq.inventory.subscriptions.detail.arc.existingQuoteInProgress", "Subscription has another ARC quote in progress.")
|
|
96
|
+
})
|
|
88
97
|
);
|
|
89
98
|
if (ok) {
|
|
90
99
|
router.push(`/backend/cpq/quotes/${body.existingQuoteId}`);
|
|
91
100
|
}
|
|
92
101
|
return;
|
|
93
102
|
}
|
|
94
|
-
alert(
|
|
103
|
+
alert(t("cpq.inventory.subscriptions.detail.arc.startFailed", "Failed to start {type} quote: {error}", { type, error: body.error ?? res.statusText }));
|
|
95
104
|
return;
|
|
96
105
|
}
|
|
97
106
|
const data = await res.json();
|
|
@@ -100,7 +109,7 @@ Open the existing quote now?`
|
|
|
100
109
|
setArcInFlight(null);
|
|
101
110
|
}
|
|
102
111
|
},
|
|
103
|
-
[router, sub]
|
|
112
|
+
[router, sub, t]
|
|
104
113
|
);
|
|
105
114
|
const transitionStatus = async (targetStatus) => {
|
|
106
115
|
if (!sub) return;
|
|
@@ -113,7 +122,7 @@ Open the existing quote now?`
|
|
|
113
122
|
body: JSON.stringify({ id: sub.id, targetStatus })
|
|
114
123
|
});
|
|
115
124
|
const data = await res.json();
|
|
116
|
-
if (!res.ok) throw new Error(data?.error ?? "Status transition failed");
|
|
125
|
+
if (!res.ok) throw new Error(data?.error ?? t("cpq.inventory.subscriptions.detail.error.transitionFailed", "Status transition failed"));
|
|
117
126
|
const [freshSub, freshAssets] = await Promise.all([
|
|
118
127
|
fetch(`/api/cpq/inventory/subscriptions?id=${sub.id}`).then((r) => r.ok ? r.json() : null),
|
|
119
128
|
fetch(`/api/cpq/inventory/assets?subscriptionId=${sub.id}&pageSize=50`).then((r) => r.ok ? r.json() : null).then((r) => r?.items ?? [])
|
|
@@ -173,7 +182,7 @@ Open the existing quote now?`
|
|
|
173
182
|
async function load() {
|
|
174
183
|
try {
|
|
175
184
|
const res = await fetch(`/api/cpq/inventory/subscriptions?id=${subId}`);
|
|
176
|
-
if (!res.ok) throw new Error("Subscription not found");
|
|
185
|
+
if (!res.ok) throw new Error(t("cpq.inventory.subscriptions.detail.error.notFound", "Subscription not found"));
|
|
177
186
|
const data = await res.json();
|
|
178
187
|
if (!cancelled) {
|
|
179
188
|
setSub(data);
|
|
@@ -238,7 +247,7 @@ Open the existing quote now?`
|
|
|
238
247
|
return () => {
|
|
239
248
|
cancelled = true;
|
|
240
249
|
};
|
|
241
|
-
}, [subId]);
|
|
250
|
+
}, [subId, t]);
|
|
242
251
|
const toggleItem = (id) => {
|
|
243
252
|
setExpandedItems((prev) => {
|
|
244
253
|
const n = new Set(prev);
|
|
@@ -249,31 +258,36 @@ Open the existing quote now?`
|
|
|
249
258
|
if (loading) {
|
|
250
259
|
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 py-12 justify-center text-sm text-muted-foreground", children: [
|
|
251
260
|
/* @__PURE__ */ jsx(Spinner, {}),
|
|
252
|
-
"
|
|
261
|
+
" ",
|
|
262
|
+
t("cpq.inventory.subscriptions.detail.loading", "Loading\u2026")
|
|
253
263
|
] });
|
|
254
264
|
}
|
|
255
265
|
if (!sub) {
|
|
256
266
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
257
|
-
/* @__PURE__ */
|
|
267
|
+
/* @__PURE__ */ jsxs("button", { onClick: () => router.push("/backend/cpq/inventory"), className: "text-sm text-muted-foreground hover:text-foreground", children: [
|
|
268
|
+
"\u2190 ",
|
|
269
|
+
t("cpq.common.back", "Back")
|
|
270
|
+
] }),
|
|
258
271
|
error && /* @__PURE__ */ jsx(ErrorBanner, { message: error }),
|
|
259
|
-
/* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-card p-6 text-center text-sm text-muted-foreground", children: "Subscription not found." })
|
|
272
|
+
/* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-card p-6 text-center text-sm text-muted-foreground", children: t("cpq.inventory.subscriptions.detail.notFound", "Subscription not found.") })
|
|
260
273
|
] });
|
|
261
274
|
}
|
|
262
275
|
const currency = sub.currencyCode || "USD";
|
|
263
276
|
const flatItems = flattenItems(sub.items);
|
|
264
277
|
const canArc = sub.status === "active" || sub.status === "suspended";
|
|
265
278
|
const statusTransitions = ALLOWED_TRANSITIONS[sub.status] ?? [];
|
|
279
|
+
const statusLabels = buildInventoryStatusLabels(t, SUBSCRIPTION_STATUSES);
|
|
266
280
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
|
|
267
281
|
/* @__PURE__ */ jsx(
|
|
268
282
|
FormHeader,
|
|
269
283
|
{
|
|
270
284
|
mode: "detail",
|
|
271
285
|
backHref: "/backend/cpq/inventory",
|
|
272
|
-
backLabel: "Back to Customer Inventory",
|
|
273
|
-
entityTypeLabel: "Subscription",
|
|
286
|
+
backLabel: t("cpq.inventory.detail.backToInventory", "Back to Customer Inventory"),
|
|
287
|
+
entityTypeLabel: t("cpq.inventory.subscriptions.detail.entityType", "Subscription"),
|
|
274
288
|
title: sub.name,
|
|
275
289
|
statusBadge: /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2 pt-1", children: [
|
|
276
|
-
/* @__PURE__ */ jsx(Tag, { variant: subscriptionStatusMap[sub.status] ?? "neutral", dot: true, children:
|
|
290
|
+
/* @__PURE__ */ jsx(Tag, { variant: subscriptionStatusMap[sub.status] ?? "neutral", dot: true, children: inventoryStatusLabel(t, sub.status) }),
|
|
277
291
|
/* @__PURE__ */ jsx(Tag, { variant: "neutral", className: "capitalize", children: sub.billingCycle }),
|
|
278
292
|
transitioning && /* @__PURE__ */ jsx(Spinner, {})
|
|
279
293
|
] }),
|
|
@@ -285,7 +299,7 @@ Open the existing quote now?`
|
|
|
285
299
|
variant: "outline",
|
|
286
300
|
disabled: arcInFlight !== null,
|
|
287
301
|
onClick: () => startArcQuote("amend"),
|
|
288
|
-
children: "Amend"
|
|
302
|
+
children: t("cpq.inventory.subscriptions.detail.arc.amend", "Amend")
|
|
289
303
|
}
|
|
290
304
|
),
|
|
291
305
|
/* @__PURE__ */ jsx(
|
|
@@ -295,7 +309,7 @@ Open the existing quote now?`
|
|
|
295
309
|
variant: "outline",
|
|
296
310
|
disabled: arcInFlight !== null,
|
|
297
311
|
onClick: () => startArcQuote("renew"),
|
|
298
|
-
children: "Renew"
|
|
312
|
+
children: t("cpq.inventory.subscriptions.detail.arc.renew", "Renew")
|
|
299
313
|
}
|
|
300
314
|
),
|
|
301
315
|
/* @__PURE__ */ jsx(
|
|
@@ -305,7 +319,7 @@ Open the existing quote now?`
|
|
|
305
319
|
variant: "destructive-outline",
|
|
306
320
|
disabled: arcInFlight !== null,
|
|
307
321
|
onClick: () => startArcQuote("cancel"),
|
|
308
|
-
children: "Cancel"
|
|
322
|
+
children: t("cpq.inventory.subscriptions.detail.arc.cancel", "Cancel")
|
|
309
323
|
}
|
|
310
324
|
)
|
|
311
325
|
] }) : null
|
|
@@ -318,52 +332,52 @@ Open the existing quote now?`
|
|
|
318
332
|
path: ["pending", "active"],
|
|
319
333
|
terminals: ["suspended", "terminated", "expired"],
|
|
320
334
|
statusMap: subscriptionStatusMap,
|
|
321
|
-
labels:
|
|
335
|
+
labels: statusLabels,
|
|
322
336
|
onTransition: transitionStatus,
|
|
323
337
|
allowedTransitions: statusTransitions,
|
|
324
338
|
disabled: transitioning,
|
|
325
|
-
ariaLabel: "Subscription status path"
|
|
339
|
+
ariaLabel: t("cpq.inventory.subscriptions.detail.statusPath", "Subscription status path")
|
|
326
340
|
}
|
|
327
341
|
) }),
|
|
328
342
|
error && /* @__PURE__ */ jsx(ErrorBanner, { message: error }),
|
|
329
343
|
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
330
344
|
/* @__PURE__ */ jsxs("div", { className: "rounded-lg border bg-card p-4 space-y-3", children: [
|
|
331
|
-
/* @__PURE__ */ jsx("h3", { className: "text-sm font-medium", children: "Subscription Details" }),
|
|
345
|
+
/* @__PURE__ */ jsx("h3", { className: "text-sm font-medium", children: t("cpq.inventory.subscriptions.detail.sections.details", "Subscription Details") }),
|
|
332
346
|
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-4 gap-y-2", children: [
|
|
333
|
-
/* @__PURE__ */ jsx(Field, { label: "Code", value: sub.code, mono: true }),
|
|
334
|
-
/* @__PURE__ */ jsx(Field, { label: "Status", value: sub.status }),
|
|
335
|
-
/* @__PURE__ */ jsx(Field, { label: "Billing Cycle", value: sub.billingCycle }),
|
|
336
|
-
/* @__PURE__ */ jsx(Field, { label: "Currency", value: currency }),
|
|
337
|
-
/* @__PURE__ */ jsx(Field, { label: "Auto-Renew", value: sub.autoRenew ? "Yes" : "No" }),
|
|
338
|
-
sub.termMonths != null && /* @__PURE__ */ jsx(Field, { label: "Term", value:
|
|
339
|
-
sub.startDate && /* @__PURE__ */ jsx(Field, { label: "Start Date", value: new Date(sub.startDate).toLocaleDateString() }),
|
|
340
|
-
sub.currentTermEnd && /* @__PURE__ */ jsx(Field, { label: "Term End", value: new Date(sub.currentTermEnd).toLocaleDateString() }),
|
|
341
|
-
sub.activatedAt && /* @__PURE__ */ jsx(Field, { label: "Activated", value: new Date(sub.activatedAt).toLocaleString() }),
|
|
342
|
-
sub.suspendedAt && /* @__PURE__ */ jsx(Field, { label: "Suspended", value: new Date(sub.suspendedAt).toLocaleString() }),
|
|
343
|
-
sub.terminatedAt && /* @__PURE__ */ jsx(Field, { label: "Terminated", value: new Date(sub.terminatedAt).toLocaleString() })
|
|
347
|
+
/* @__PURE__ */ jsx(Field, { label: t("cpq.inventory.subscriptions.detail.fields.code", "Code"), value: sub.code, mono: true }),
|
|
348
|
+
/* @__PURE__ */ jsx(Field, { label: t("cpq.inventory.subscriptions.detail.fields.status", "Status"), value: sub.status }),
|
|
349
|
+
/* @__PURE__ */ jsx(Field, { label: t("cpq.inventory.subscriptions.detail.fields.billingCycle", "Billing Cycle"), value: sub.billingCycle }),
|
|
350
|
+
/* @__PURE__ */ jsx(Field, { label: t("cpq.inventory.subscriptions.detail.fields.currency", "Currency"), value: currency }),
|
|
351
|
+
/* @__PURE__ */ jsx(Field, { label: t("cpq.inventory.subscriptions.detail.fields.autoRenew", "Auto-Renew"), value: sub.autoRenew ? t("cpq.common.yes", "Yes") : t("cpq.common.no", "No") }),
|
|
352
|
+
sub.termMonths != null && /* @__PURE__ */ jsx(Field, { label: t("cpq.inventory.subscriptions.detail.fields.term", "Term"), value: t("cpq.inventory.subscriptions.detail.fields.termMonths", "{count} months", { count: sub.termMonths }) }),
|
|
353
|
+
sub.startDate && /* @__PURE__ */ jsx(Field, { label: t("cpq.inventory.subscriptions.detail.fields.startDate", "Start Date"), value: new Date(sub.startDate).toLocaleDateString() }),
|
|
354
|
+
sub.currentTermEnd && /* @__PURE__ */ jsx(Field, { label: t("cpq.inventory.subscriptions.detail.fields.termEnd", "Term End"), value: new Date(sub.currentTermEnd).toLocaleDateString() }),
|
|
355
|
+
sub.activatedAt && /* @__PURE__ */ jsx(Field, { label: t("cpq.inventory.subscriptions.detail.fields.activated", "Activated"), value: new Date(sub.activatedAt).toLocaleString() }),
|
|
356
|
+
sub.suspendedAt && /* @__PURE__ */ jsx(Field, { label: t("cpq.inventory.subscriptions.detail.fields.suspended", "Suspended"), value: new Date(sub.suspendedAt).toLocaleString() }),
|
|
357
|
+
sub.terminatedAt && /* @__PURE__ */ jsx(Field, { label: t("cpq.inventory.subscriptions.detail.fields.terminated", "Terminated"), value: new Date(sub.terminatedAt).toLocaleString() })
|
|
344
358
|
] }),
|
|
345
359
|
sub.description && /* @__PURE__ */ jsxs("div", { className: "pt-1", children: [
|
|
346
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Description" }),
|
|
360
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: t("cpq.inventory.subscriptions.detail.fields.description", "Description") }),
|
|
347
361
|
/* @__PURE__ */ jsx("p", { className: "text-sm", children: sub.description })
|
|
348
362
|
] })
|
|
349
363
|
] }),
|
|
350
364
|
/* @__PURE__ */ jsxs("div", { className: "rounded-lg border bg-card p-4 space-y-3", children: [
|
|
351
|
-
/* @__PURE__ */ jsx("h3", { className: "text-sm font-medium", children: "Pricing & References" }),
|
|
365
|
+
/* @__PURE__ */ jsx("h3", { className: "text-sm font-medium", children: t("cpq.inventory.subscriptions.detail.sections.pricing", "Pricing & References") }),
|
|
352
366
|
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
|
|
353
367
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
354
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Monthly Recurring (MRC)" }),
|
|
368
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: t("cpq.inventory.subscriptions.detail.fields.mrc", "Monthly Recurring (MRC)") }),
|
|
355
369
|
/* @__PURE__ */ jsx("p", { className: "text-lg font-semibold font-mono", children: fmt(sub.mrcAmount, currency) })
|
|
356
370
|
] }),
|
|
357
371
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
358
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Non-Recurring (NRC)" }),
|
|
372
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: t("cpq.inventory.subscriptions.detail.fields.nrc", "Non-Recurring (NRC)") }),
|
|
359
373
|
/* @__PURE__ */ jsx("p", { className: "text-lg font-semibold font-mono", children: fmt(sub.nrcAmount, currency) })
|
|
360
374
|
] })
|
|
361
375
|
] }),
|
|
362
376
|
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-4 gap-y-2 pt-1", children: [
|
|
363
|
-
/* @__PURE__ */ jsx(Field, { label: "Customer", value: customerName ?? sub.customerId.slice(0, 12) + "\u2026" }),
|
|
364
|
-
/* @__PURE__ */ jsx(Field, { label: "Created", value: new Date(sub.createdAt).toLocaleString() }),
|
|
377
|
+
/* @__PURE__ */ jsx(Field, { label: t("cpq.inventory.subscriptions.detail.fields.customer", "Customer"), value: customerName ?? sub.customerId.slice(0, 12) + "\u2026" }),
|
|
378
|
+
/* @__PURE__ */ jsx(Field, { label: t("cpq.inventory.subscriptions.detail.fields.created", "Created"), value: new Date(sub.createdAt).toLocaleString() }),
|
|
365
379
|
sub.sourceQuoteId && /* @__PURE__ */ jsxs("div", { children: [
|
|
366
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Source Quote" }),
|
|
380
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: t("cpq.inventory.subscriptions.detail.fields.sourceQuote", "Source Quote") }),
|
|
367
381
|
/* @__PURE__ */ jsx(
|
|
368
382
|
"button",
|
|
369
383
|
{
|
|
@@ -374,7 +388,7 @@ Open the existing quote now?`
|
|
|
374
388
|
)
|
|
375
389
|
] }),
|
|
376
390
|
sub.sourceOrderId && /* @__PURE__ */ jsxs("div", { children: [
|
|
377
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Source Order" }),
|
|
391
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: t("cpq.inventory.subscriptions.detail.fields.sourceOrder", "Source Order") }),
|
|
378
392
|
/* @__PURE__ */ jsx(
|
|
379
393
|
"button",
|
|
380
394
|
{
|
|
@@ -388,7 +402,7 @@ Open the existing quote now?`
|
|
|
388
402
|
] })
|
|
389
403
|
] }),
|
|
390
404
|
sub.metadata && Object.keys(sub.metadata).length > 0 && /* @__PURE__ */ jsxs("div", { className: "rounded-lg border bg-card p-4", children: [
|
|
391
|
-
/* @__PURE__ */ jsx("h3", { className: "text-sm font-medium mb-2", children: "Metadata" }),
|
|
405
|
+
/* @__PURE__ */ jsx("h3", { className: "text-sm font-medium mb-2", children: t("cpq.inventory.subscriptions.detail.sections.metadata", "Metadata") }),
|
|
392
406
|
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 sm:grid-cols-3 gap-x-4 gap-y-1", children: Object.entries(sub.metadata).map(([key, value]) => /* @__PURE__ */ jsxs("div", { className: "text-xs", children: [
|
|
393
407
|
/* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
|
|
394
408
|
key,
|
|
@@ -398,12 +412,8 @@ Open the existing quote now?`
|
|
|
398
412
|
] }, key)) })
|
|
399
413
|
] }),
|
|
400
414
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
401
|
-
/* @__PURE__ */
|
|
402
|
-
|
|
403
|
-
flatItems.length,
|
|
404
|
-
")"
|
|
405
|
-
] }),
|
|
406
|
-
flatItems.length === 0 ? /* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-card py-8 text-center text-sm text-muted-foreground", children: "No items." }) : /* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-card divide-y", children: flatItems.map((item) => {
|
|
415
|
+
/* @__PURE__ */ jsx("h3", { className: "text-sm font-medium mb-2 px-1", children: t("cpq.inventory.subscriptions.detail.items.title", "Subscription Items ({count})", { count: flatItems.length }) }),
|
|
416
|
+
flatItems.length === 0 ? /* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-card py-8 text-center text-sm text-muted-foreground", children: t("cpq.inventory.subscriptions.detail.items.empty", "No items.") }) : /* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-card divide-y", children: flatItems.map((item) => {
|
|
407
417
|
const isExpanded = expandedItems.has(item.id);
|
|
408
418
|
const indent = item._depth ?? 0;
|
|
409
419
|
return /* @__PURE__ */ jsxs("div", { children: [
|
|
@@ -425,11 +435,17 @@ Open the existing quote now?`
|
|
|
425
435
|
] }) }),
|
|
426
436
|
/* @__PURE__ */ jsxs("div", { className: "shrink-0 text-right text-xs space-y-0.5", children: [
|
|
427
437
|
Number(item.mrcAmount) > 0 && /* @__PURE__ */ jsxs("div", { children: [
|
|
428
|
-
/* @__PURE__ */
|
|
438
|
+
/* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
|
|
439
|
+
t("cpq.inventory.subscriptions.detail.items.mrc", "MRC"),
|
|
440
|
+
" "
|
|
441
|
+
] }),
|
|
429
442
|
/* @__PURE__ */ jsx("span", { className: "font-mono font-medium", children: fmt(item.mrcAmount, item.currencyCode || currency) })
|
|
430
443
|
] }),
|
|
431
444
|
Number(item.nrcAmount) > 0 && /* @__PURE__ */ jsxs("div", { children: [
|
|
432
|
-
/* @__PURE__ */
|
|
445
|
+
/* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
|
|
446
|
+
t("cpq.inventory.subscriptions.detail.items.nrc", "NRC"),
|
|
447
|
+
" "
|
|
448
|
+
] }),
|
|
433
449
|
/* @__PURE__ */ jsx("span", { className: "font-mono font-medium", children: fmt(item.nrcAmount, item.currencyCode || currency) })
|
|
434
450
|
] })
|
|
435
451
|
] })
|
|
@@ -441,7 +457,7 @@ Open the existing quote now?`
|
|
|
441
457
|
item.offeringId && /* @__PURE__ */ jsx(
|
|
442
458
|
RefField,
|
|
443
459
|
{
|
|
444
|
-
label: "Offering",
|
|
460
|
+
label: t("cpq.inventory.subscriptions.detail.fields.offering", "Offering"),
|
|
445
461
|
name: offeringNames[item.offeringId],
|
|
446
462
|
fallback: item.offeringId,
|
|
447
463
|
onClick: () => router.push(`/backend/cpq/offerings/${item.offeringId}`)
|
|
@@ -450,7 +466,7 @@ Open the existing quote now?`
|
|
|
450
466
|
item.specId && /* @__PURE__ */ jsx(
|
|
451
467
|
RefField,
|
|
452
468
|
{
|
|
453
|
-
label: "Specification",
|
|
469
|
+
label: t("cpq.inventory.subscriptions.detail.fields.specification", "Specification"),
|
|
454
470
|
name: specNames[item.specId],
|
|
455
471
|
fallback: item.specId,
|
|
456
472
|
onClick: () => router.push(`/backend/cpq/specifications/${item.specId}`)
|
|
@@ -459,18 +475,18 @@ Open the existing quote now?`
|
|
|
459
475
|
item.productId && /* @__PURE__ */ jsx(
|
|
460
476
|
RefField,
|
|
461
477
|
{
|
|
462
|
-
label: "Product",
|
|
478
|
+
label: t("cpq.inventory.subscriptions.detail.fields.product", "Product"),
|
|
463
479
|
name: productNames[item.productId],
|
|
464
480
|
fallback: item.productId,
|
|
465
481
|
onClick: () => router.push(`/backend/catalog/products/${item.productId}`)
|
|
466
482
|
}
|
|
467
483
|
),
|
|
468
|
-
/* @__PURE__ */ jsx(Field, { label: "Currency", value: item.currencyCode || currency }),
|
|
469
|
-
/* @__PURE__ */ jsx(Field, { label: "Quantity", value: String(item.quantity) }),
|
|
470
|
-
item.capacityTotal && /* @__PURE__ */ jsx(Field, { label: "Capacity", value: `${item.capacityUsed ?? "0"} / ${item.capacityTotal} ${item.capacityUnit ?? ""}` })
|
|
484
|
+
/* @__PURE__ */ jsx(Field, { label: t("cpq.inventory.subscriptions.detail.fields.currency", "Currency"), value: item.currencyCode || currency }),
|
|
485
|
+
/* @__PURE__ */ jsx(Field, { label: t("cpq.inventory.subscriptions.detail.fields.quantity", "Quantity"), value: String(item.quantity) }),
|
|
486
|
+
item.capacityTotal && /* @__PURE__ */ jsx(Field, { label: t("cpq.inventory.subscriptions.detail.fields.capacity", "Capacity"), value: `${item.capacityUsed ?? "0"} / ${item.capacityTotal} ${item.capacityUnit ?? ""}` })
|
|
471
487
|
] }),
|
|
472
488
|
item.configuration && Object.keys(item.configuration).length > 0 && /* @__PURE__ */ jsxs("div", { children: [
|
|
473
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs font-medium text-muted-foreground mb-1", children: "Configuration" }),
|
|
489
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs font-medium text-muted-foreground mb-1", children: t("cpq.inventory.subscriptions.detail.items.configuration", "Configuration") }),
|
|
474
490
|
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 sm:grid-cols-3 gap-x-4 gap-y-1", children: Object.entries(item.configuration).map(([key, value]) => /* @__PURE__ */ jsxs("div", { className: "text-xs", children: [
|
|
475
491
|
/* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
|
|
476
492
|
key,
|
|
@@ -480,26 +496,38 @@ Open the existing quote now?`
|
|
|
480
496
|
] }, key)) })
|
|
481
497
|
] }),
|
|
482
498
|
item.charges && item.charges.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
|
|
483
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs font-medium text-muted-foreground mb-1", children: "Charges" }),
|
|
499
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs font-medium text-muted-foreground mb-1", children: t("cpq.inventory.subscriptions.detail.items.charges", "Charges") }),
|
|
484
500
|
/* @__PURE__ */ jsxs("table", { className: "w-full text-xs", children: [
|
|
485
501
|
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { className: "text-muted-foreground", children: [
|
|
486
|
-
/* @__PURE__ */ jsx("th", { className: "text-left py-1 font-medium", children: "Charge" }),
|
|
487
|
-
/* @__PURE__ */ jsx("th", { className: "text-left py-1 font-medium", children: "Type" }),
|
|
488
|
-
/* @__PURE__ */ jsx("th", { className: "text-right py-1 font-medium", children: "
|
|
489
|
-
/* @__PURE__ */ jsx("th", { className: "text-right py-1 font-medium", children: "
|
|
490
|
-
/* @__PURE__ */ jsx("th", { className: "text-right py-1 font-medium", children: "
|
|
502
|
+
/* @__PURE__ */ jsx("th", { className: "text-left py-1 font-medium", children: t("cpq.inventory.subscriptions.detail.charges.charge", "Charge") }),
|
|
503
|
+
/* @__PURE__ */ jsx("th", { className: "text-left py-1 font-medium", children: t("cpq.inventory.subscriptions.detail.charges.type", "Type") }),
|
|
504
|
+
/* @__PURE__ */ jsx("th", { className: "text-right py-1 font-medium", children: t("cpq.inventory.subscriptions.detail.charges.list", "List") }),
|
|
505
|
+
/* @__PURE__ */ jsx("th", { className: "text-right py-1 font-medium", children: t("cpq.inventory.subscriptions.detail.charges.offer", "Offer") }),
|
|
506
|
+
/* @__PURE__ */ jsx("th", { className: "text-right py-1 font-medium", children: t("cpq.inventory.subscriptions.detail.charges.qty", "Qty") }),
|
|
507
|
+
/* @__PURE__ */ jsx("th", { className: "text-right py-1 font-medium", children: t("cpq.inventory.subscriptions.detail.charges.total", "Total") })
|
|
491
508
|
] }) }),
|
|
492
|
-
/* @__PURE__ */ jsx("tbody", { children: item.charges.map((
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
/* @__PURE__ */
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
509
|
+
/* @__PURE__ */ jsx("tbody", { children: item.charges.map((raw, i) => {
|
|
510
|
+
const c = parseStoredCharge(raw);
|
|
511
|
+
if (!c) return null;
|
|
512
|
+
return /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
|
513
|
+
/* @__PURE__ */ jsxs("tr", { className: "border-t border-dashed border-border/50", children: [
|
|
514
|
+
/* @__PURE__ */ jsx("td", { className: "py-1", children: c.chargeName }),
|
|
515
|
+
/* @__PURE__ */ jsx("td", { className: "py-1 uppercase", children: c.chargeType }),
|
|
516
|
+
/* @__PURE__ */ jsx("td", { className: "py-1 text-right font-mono text-muted-foreground", children: fmt(c.listUnitPrice ?? c.unitPrice, currency) }),
|
|
517
|
+
/* @__PURE__ */ jsx("td", { className: "py-1 text-right font-mono", children: /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1", children: [
|
|
518
|
+
/* @__PURE__ */ jsx(DepthBadge, { before: c.listUnitPrice ?? c.unitPrice, after: c.unitPrice }),
|
|
519
|
+
fmt(c.unitPrice, currency)
|
|
520
|
+
] }) }),
|
|
521
|
+
/* @__PURE__ */ jsx("td", { className: "py-1 text-right font-mono", children: c.quantity ?? "\u2014" }),
|
|
522
|
+
/* @__PURE__ */ jsx("td", { className: "py-1 text-right font-mono", children: c.totalPrice != null ? fmt(c.totalPrice, currency) : "\u2014" })
|
|
523
|
+
] }),
|
|
524
|
+
(c.adjustments?.length ?? 0) > 0 && /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { colSpan: 6, className: "pb-2 pl-4", children: /* @__PURE__ */ jsx(PriceWaterfall, { charge: c, currency }) }) })
|
|
525
|
+
] }, i);
|
|
526
|
+
}) })
|
|
499
527
|
] })
|
|
500
528
|
] }),
|
|
501
529
|
item.metadata && Object.keys(item.metadata).length > 0 && /* @__PURE__ */ jsxs("div", { children: [
|
|
502
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs font-medium text-muted-foreground mb-1", children: "Metadata" }),
|
|
530
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs font-medium text-muted-foreground mb-1", children: t("cpq.inventory.subscriptions.detail.items.metadata", "Metadata") }),
|
|
503
531
|
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 sm:grid-cols-3 gap-x-4 gap-y-1", children: Object.entries(item.metadata).map(([key, value]) => /* @__PURE__ */ jsxs("div", { className: "text-xs", children: [
|
|
504
532
|
/* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
|
|
505
533
|
key,
|
|
@@ -509,107 +537,68 @@ Open the existing quote now?`
|
|
|
509
537
|
] }, key)) })
|
|
510
538
|
] }),
|
|
511
539
|
/* @__PURE__ */ jsxs("div", { className: "flex gap-4 text-xs text-muted-foreground", children: [
|
|
512
|
-
/* @__PURE__ */
|
|
513
|
-
|
|
514
|
-
new Date(item.createdAt).toLocaleString()
|
|
515
|
-
] }),
|
|
516
|
-
/* @__PURE__ */ jsxs("span", { children: [
|
|
517
|
-
"Updated: ",
|
|
518
|
-
new Date(item.updatedAt).toLocaleString()
|
|
519
|
-
] })
|
|
540
|
+
/* @__PURE__ */ jsx("span", { children: t("cpq.inventory.subscriptions.detail.items.createdAt", "Created: {date}", { date: new Date(item.createdAt).toLocaleString() }) }),
|
|
541
|
+
/* @__PURE__ */ jsx("span", { children: t("cpq.inventory.subscriptions.detail.items.updatedAt", "Updated: {date}", { date: new Date(item.updatedAt).toLocaleString() }) })
|
|
520
542
|
] })
|
|
521
543
|
] })
|
|
522
544
|
] }, item.id);
|
|
523
545
|
}) })
|
|
524
546
|
] }),
|
|
525
547
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
526
|
-
/* @__PURE__ */
|
|
527
|
-
|
|
528
|
-
changeLog.length,
|
|
529
|
-
")"
|
|
530
|
-
] }),
|
|
531
|
-
changeLogLoading ? /* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-card py-6 text-center text-sm text-muted-foreground", children: "Loading\u2026" }) : changeLog.length === 0 ? /* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-card py-6 text-center text-sm text-muted-foreground", children: "No ARC changes yet." }) : /* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-card divide-y", children: changeLog.map((row) => /* @__PURE__ */ jsxs("div", { className: "px-4 py-3 space-y-1", children: [
|
|
548
|
+
/* @__PURE__ */ jsx("h3", { className: "text-sm font-medium mb-2 px-1", children: t("cpq.inventory.subscriptions.detail.changeLog.title", "Change History ({count})", { count: changeLog.length }) }),
|
|
549
|
+
changeLogLoading ? /* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-card py-6 text-center text-sm text-muted-foreground", children: t("cpq.inventory.subscriptions.detail.loading", "Loading\u2026") }) : changeLog.length === 0 ? /* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-card py-6 text-center text-sm text-muted-foreground", children: t("cpq.inventory.subscriptions.detail.changeLog.empty", "No ARC changes yet.") }) : /* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-card divide-y", children: changeLog.map((row) => /* @__PURE__ */ jsxs("div", { className: "px-4 py-3 space-y-1", children: [
|
|
532
550
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
533
|
-
/* @__PURE__ */ jsx(Tag, { variant: CHANGE_TYPE_VARIANTS[row.changeType] ?? "neutral", children:
|
|
551
|
+
/* @__PURE__ */ jsx(Tag, { variant: CHANGE_TYPE_VARIANTS[row.changeType] ?? "neutral", children: changeTypeLabel(t, row.changeType) }),
|
|
534
552
|
/* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: new Date(row.effectiveAt).toLocaleString() }),
|
|
535
|
-
row.sourceQuoteId && /* @__PURE__ */
|
|
553
|
+
row.sourceQuoteId && /* @__PURE__ */ jsx(
|
|
536
554
|
"button",
|
|
537
555
|
{
|
|
538
556
|
onClick: () => router.push(`/backend/cpq/quotes/${row.sourceQuoteId}`),
|
|
539
557
|
className: "text-xs text-primary hover:underline",
|
|
540
|
-
children: [
|
|
541
|
-
"Quote ",
|
|
542
|
-
logQuoteNumbers[row.sourceQuoteId] ?? `${row.sourceQuoteId.slice(0, 8)}\u2026`
|
|
543
|
-
]
|
|
558
|
+
children: t("cpq.inventory.subscriptions.detail.changeLog.quote", "Quote {number}", { number: logQuoteNumbers[row.sourceQuoteId] ?? `${row.sourceQuoteId.slice(0, 8)}\u2026` })
|
|
544
559
|
}
|
|
545
560
|
),
|
|
546
|
-
row.sourceOrderId && /* @__PURE__ */
|
|
561
|
+
row.sourceOrderId && /* @__PURE__ */ jsx(
|
|
547
562
|
"button",
|
|
548
563
|
{
|
|
549
564
|
onClick: () => router.push(`/backend/cpq/orders/${row.sourceOrderId}`),
|
|
550
565
|
className: "text-xs text-primary hover:underline",
|
|
551
|
-
children: [
|
|
552
|
-
"Order ",
|
|
553
|
-
logOrderNumbers[row.sourceOrderId] ?? `${row.sourceOrderId.slice(0, 8)}\u2026`
|
|
554
|
-
]
|
|
566
|
+
children: t("cpq.inventory.subscriptions.detail.changeLog.order", "Order {number}", { number: logOrderNumbers[row.sourceOrderId] ?? `${row.sourceOrderId.slice(0, 8)}\u2026` })
|
|
555
567
|
}
|
|
556
568
|
)
|
|
557
569
|
] }),
|
|
558
570
|
/* @__PURE__ */ jsx(ChangeLogLineDetails, { row, currency }),
|
|
559
|
-
row.termChange && /* @__PURE__ */
|
|
560
|
-
|
|
561
|
-
String(row.termChange.
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
row.reasonCode && /* @__PURE__ */ jsxs("div", { className: "text-xs text-muted-foreground", children: [
|
|
566
|
-
"Reason: ",
|
|
567
|
-
row.reasonCode,
|
|
568
|
-
row.reasonText ? ` \u2014 ${row.reasonText}` : ""
|
|
569
|
-
] }),
|
|
570
|
-
row.etfAmount && /* @__PURE__ */ jsxs("div", { className: "text-xs text-muted-foreground", children: [
|
|
571
|
-
"ETF: ",
|
|
572
|
-
row.etfAmount,
|
|
573
|
-
" ",
|
|
574
|
-
row.etfCurrency ?? ""
|
|
575
|
-
] }),
|
|
571
|
+
row.termChange && /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground", children: t("cpq.inventory.subscriptions.detail.changeLog.term", "Term: {from} \u2192 {to}", {
|
|
572
|
+
from: String(row.termChange.oldTermEnd ?? "\u2014"),
|
|
573
|
+
to: String(row.termChange.newTermEnd ?? "\u2014")
|
|
574
|
+
}) }),
|
|
575
|
+
row.reasonCode && /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground", children: row.reasonText ? t("cpq.inventory.subscriptions.detail.changeLog.reasonWithText", "Reason: {code} \u2014 {text}", { code: row.reasonCode, text: row.reasonText }) : t("cpq.inventory.subscriptions.detail.changeLog.reason", "Reason: {code}", { code: row.reasonCode }) }),
|
|
576
|
+
row.etfAmount && /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground", children: t("cpq.inventory.subscriptions.detail.changeLog.etf", "ETF: {amount} {currency}", { amount: row.etfAmount, currency: row.etfCurrency ?? "" }) }),
|
|
576
577
|
row.mergedIntoSubscriptionId && /* @__PURE__ */ jsxs("div", { className: "text-xs text-muted-foreground", children: [
|
|
577
|
-
"Merged into",
|
|
578
|
+
t("cpq.inventory.subscriptions.detail.changeLog.mergedInto", "Merged into"),
|
|
578
579
|
" ",
|
|
579
|
-
/* @__PURE__ */
|
|
580
|
+
/* @__PURE__ */ jsx(
|
|
580
581
|
"button",
|
|
581
582
|
{
|
|
582
583
|
onClick: () => router.push(`/backend/cpq/inventory/subscriptions/${row.mergedIntoSubscriptionId}`),
|
|
583
584
|
className: "text-primary hover:underline",
|
|
584
|
-
children:
|
|
585
|
-
"subscription ",
|
|
586
|
-
row.mergedIntoSubscriptionId.slice(0, 8),
|
|
587
|
-
"\u2026"
|
|
588
|
-
]
|
|
585
|
+
children: t("cpq.inventory.subscriptions.detail.changeLog.mergedIntoSubscription", "subscription {id}\u2026", { id: row.mergedIntoSubscriptionId.slice(0, 8) })
|
|
589
586
|
}
|
|
590
587
|
)
|
|
591
588
|
] }),
|
|
592
|
-
row.mergedFromSubscriptionIds && row.mergedFromSubscriptionIds.length > 0 && /* @__PURE__ */
|
|
593
|
-
"Merged from ",
|
|
594
|
-
row.mergedFromSubscriptionIds.length,
|
|
595
|
-
" subscriptions"
|
|
596
|
-
] })
|
|
589
|
+
row.mergedFromSubscriptionIds && row.mergedFromSubscriptionIds.length > 0 && /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground", children: t("cpq.inventory.subscriptions.detail.changeLog.mergedFrom", "Merged from {count} subscriptions", { count: row.mergedFromSubscriptionIds.length }) })
|
|
597
590
|
] }, row.id)) })
|
|
598
591
|
] }),
|
|
599
592
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
600
|
-
/* @__PURE__ */
|
|
601
|
-
|
|
602
|
-
assets.length,
|
|
603
|
-
")"
|
|
604
|
-
] }),
|
|
605
|
-
assets.length === 0 ? /* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-card py-8 text-center text-sm text-muted-foreground", children: "No assets linked to this subscription." }) : /* @__PURE__ */ jsx("div", { className: "rounded-lg border", children: /* @__PURE__ */ jsxs("table", { className: "w-full text-sm", children: [
|
|
593
|
+
/* @__PURE__ */ jsx("h3", { className: "text-sm font-medium mb-2 px-1", children: t("cpq.inventory.subscriptions.detail.assets.title", "Linked Assets ({count})", { count: assets.length }) }),
|
|
594
|
+
assets.length === 0 ? /* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-card py-8 text-center text-sm text-muted-foreground", children: t("cpq.inventory.subscriptions.detail.assets.empty", "No assets linked to this subscription.") }) : /* @__PURE__ */ jsx("div", { className: "rounded-lg border", children: /* @__PURE__ */ jsxs("table", { className: "w-full text-sm", children: [
|
|
606
595
|
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { className: "border-b bg-muted/50", children: [
|
|
607
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left font-medium", children: "Code" }),
|
|
608
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left font-medium", children: "Name" }),
|
|
609
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left font-medium", children: "Type" }),
|
|
610
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left font-medium", children: "Status" }),
|
|
611
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-right font-medium", children: "Price" }),
|
|
612
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-right font-medium", children: "Qty" })
|
|
596
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left font-medium", children: t("cpq.inventory.subscriptions.detail.assets.table.code", "Code") }),
|
|
597
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left font-medium", children: t("cpq.inventory.subscriptions.detail.assets.table.name", "Name") }),
|
|
598
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left font-medium", children: t("cpq.inventory.subscriptions.detail.assets.table.type", "Type") }),
|
|
599
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left font-medium", children: t("cpq.inventory.subscriptions.detail.assets.table.status", "Status") }),
|
|
600
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-right font-medium", children: t("cpq.inventory.subscriptions.detail.assets.table.price", "Price") }),
|
|
601
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-right font-medium", children: t("cpq.inventory.subscriptions.detail.assets.table.qty", "Qty") })
|
|
613
602
|
] }) }),
|
|
614
603
|
/* @__PURE__ */ jsx("tbody", { children: assets.map((a) => /* @__PURE__ */ jsxs("tr", { onClick: () => router.push(`/backend/cpq/inventory/assets/${a.id}`), className: "border-b cursor-pointer hover:bg-muted/30 transition-colors", children: [
|
|
615
604
|
/* @__PURE__ */ jsx("td", { className: "px-4 py-3 text-muted-foreground", children: a.code }),
|
|
@@ -669,6 +658,8 @@ function ErrorBanner({ message }) {
|
|
|
669
658
|
return /* @__PURE__ */ jsx(Alert, { variant: "destructive", children: message });
|
|
670
659
|
}
|
|
671
660
|
function ChangeLogLineDetails({ row, currency }) {
|
|
661
|
+
const t = useT();
|
|
662
|
+
const itemFallback = t("cpq.inventory.subscriptions.detail.changeLog.item", "Item");
|
|
672
663
|
const beforeItems = new Map(
|
|
673
664
|
(row.beforeSnapshot?.items ?? []).map((it) => [it.id, it])
|
|
674
665
|
);
|
|
@@ -690,7 +681,7 @@ function ChangeLogLineDetails({ row, currency }) {
|
|
|
690
681
|
derived.push({
|
|
691
682
|
key: `${itemId}-${i}`,
|
|
692
683
|
action: lc.action,
|
|
693
|
-
name: item?.name ?? (lc.action === "add" ? "New item" :
|
|
684
|
+
name: item?.name ?? (lc.action === "add" ? t("cpq.inventory.subscriptions.detail.changeLog.newItem", "New item") : itemFallback),
|
|
694
685
|
beforeMrc,
|
|
695
686
|
afterMrc: lc.action === "add" && afterMrc == null && lc.mrcAmount != null ? Number(lc.mrcAmount) : afterMrc,
|
|
696
687
|
delta: explicitDelta ?? computedDelta
|
|
@@ -702,7 +693,7 @@ function ChangeLogLineDetails({ row, currency }) {
|
|
|
702
693
|
derived.push({
|
|
703
694
|
key: it.id,
|
|
704
695
|
action: "cancel",
|
|
705
|
-
name: it.name ??
|
|
696
|
+
name: it.name ?? itemFallback,
|
|
706
697
|
beforeMrc: mrc,
|
|
707
698
|
afterMrc: 0,
|
|
708
699
|
delta: -mrc
|
|
@@ -714,7 +705,7 @@ function ChangeLogLineDetails({ row, currency }) {
|
|
|
714
705
|
derived.push({
|
|
715
706
|
key: it.id,
|
|
716
707
|
action: "add",
|
|
717
|
-
name: it.name ??
|
|
708
|
+
name: it.name ?? itemFallback,
|
|
718
709
|
beforeMrc: null,
|
|
719
710
|
afterMrc: mrc,
|
|
720
711
|
delta: null
|
|
@@ -726,7 +717,7 @@ function ChangeLogLineDetails({ row, currency }) {
|
|
|
726
717
|
derived.push({
|
|
727
718
|
key: it.id,
|
|
728
719
|
action: "cancel",
|
|
729
|
-
name: it.name ??
|
|
720
|
+
name: it.name ?? itemFallback,
|
|
730
721
|
beforeMrc: mrc,
|
|
731
722
|
afterMrc: 0,
|
|
732
723
|
delta: -mrc
|
|
@@ -735,57 +726,56 @@ function ChangeLogLineDetails({ row, currency }) {
|
|
|
735
726
|
}
|
|
736
727
|
if (derived.length === 0) {
|
|
737
728
|
if (row.changeType === "amend" || row.changeType === "renew") {
|
|
738
|
-
return /* @__PURE__ */ jsx("div", { className: "mt-1.5 text-xs text-muted-foreground italic", children: "No item-level changes recorded." });
|
|
729
|
+
return /* @__PURE__ */ jsx("div", { className: "mt-1.5 text-xs text-muted-foreground italic", children: t("cpq.inventory.subscriptions.detail.changeLog.noItemChanges", "No item-level changes recorded.") });
|
|
739
730
|
}
|
|
740
731
|
return null;
|
|
741
732
|
}
|
|
742
733
|
return /* @__PURE__ */ jsx("div", { className: "mt-1.5 rounded border bg-muted/20 px-3 py-2 space-y-1", children: derived.map((d) => /* @__PURE__ */ jsx(ChangeLogLineRow, { change: d, currency }, d.key)) });
|
|
743
734
|
}
|
|
744
735
|
const ACTION_GLYPH = {
|
|
745
|
-
add: { sign: "+", color: "text-status-success-text"
|
|
746
|
-
modify: { sign: "~", color: "text-status-info-text"
|
|
747
|
-
cancel: { sign: "\u2212", color: "text-destructive"
|
|
736
|
+
add: { sign: "+", color: "text-status-success-text" },
|
|
737
|
+
modify: { sign: "~", color: "text-status-info-text" },
|
|
738
|
+
cancel: { sign: "\u2212", color: "text-destructive" }
|
|
748
739
|
};
|
|
740
|
+
function actionGlyphLabel(t, action) {
|
|
741
|
+
switch (action) {
|
|
742
|
+
case "add":
|
|
743
|
+
return t("cpq.inventory.subscriptions.detail.changeLog.action.add", "added");
|
|
744
|
+
case "modify":
|
|
745
|
+
return t("cpq.inventory.subscriptions.detail.changeLog.action.modify", "modified");
|
|
746
|
+
case "cancel":
|
|
747
|
+
return t("cpq.inventory.subscriptions.detail.changeLog.action.cancel", "removed");
|
|
748
|
+
}
|
|
749
|
+
}
|
|
749
750
|
function ChangeLogLineRow({
|
|
750
751
|
change,
|
|
751
752
|
currency
|
|
752
753
|
}) {
|
|
754
|
+
const t = useT();
|
|
753
755
|
const glyph = ACTION_GLYPH[change.action];
|
|
754
756
|
const showPriceChange = change.action === "modify" && change.beforeMrc != null && change.afterMrc != null && change.beforeMrc !== change.afterMrc;
|
|
755
757
|
const showSinglePrice = !showPriceChange && (change.action === "add" && change.afterMrc != null && change.afterMrc > 0 || change.action === "cancel" && change.beforeMrc != null && change.beforeMrc > 0);
|
|
756
758
|
const showDelta = change.delta != null && change.delta !== 0;
|
|
757
759
|
const isNoopModify = change.action === "modify" && !showPriceChange && !showDelta;
|
|
758
760
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-x-2 gap-y-0.5 text-xs", children: [
|
|
759
|
-
/* @__PURE__ */ jsx("span", { className: `font-bold w-3 text-center ${glyph.color}`, title:
|
|
761
|
+
/* @__PURE__ */ jsx("span", { className: `font-bold w-3 text-center ${glyph.color}`, title: actionGlyphLabel(t, change.action), children: glyph.sign }),
|
|
760
762
|
/* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: change.name }),
|
|
761
|
-
showPriceChange && /* @__PURE__ */
|
|
762
|
-
fmt(change.beforeMrc, currency),
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
fmt(change.afterMrc, currency),
|
|
769
|
-
"/mo"
|
|
770
|
-
] }),
|
|
771
|
-
showSinglePrice && change.action === "cancel" && /* @__PURE__ */ jsxs("span", { className: "font-mono text-muted-foreground", children: [
|
|
772
|
-
"was ",
|
|
773
|
-
fmt(change.beforeMrc, currency),
|
|
774
|
-
"/mo"
|
|
775
|
-
] }),
|
|
776
|
-
showDelta && /* @__PURE__ */ jsxs(
|
|
763
|
+
showPriceChange && /* @__PURE__ */ jsx("span", { className: "font-mono text-muted-foreground", children: t("cpq.inventory.subscriptions.detail.changeLog.priceChangePerMonth", "{before} \u2192 {after}/mo", {
|
|
764
|
+
before: fmt(change.beforeMrc, currency),
|
|
765
|
+
after: fmt(change.afterMrc, currency)
|
|
766
|
+
}) }),
|
|
767
|
+
showSinglePrice && change.action === "add" && /* @__PURE__ */ jsx("span", { className: "font-mono text-muted-foreground", children: t("cpq.inventory.subscriptions.detail.changeLog.pricePerMonth", "{price}/mo", { price: fmt(change.afterMrc, currency) }) }),
|
|
768
|
+
showSinglePrice && change.action === "cancel" && /* @__PURE__ */ jsx("span", { className: "font-mono text-muted-foreground", children: t("cpq.inventory.subscriptions.detail.changeLog.wasPricePerMonth", "was {price}/mo", { price: fmt(change.beforeMrc, currency) }) }),
|
|
769
|
+
showDelta && /* @__PURE__ */ jsx(
|
|
777
770
|
"span",
|
|
778
771
|
{
|
|
779
772
|
className: `font-mono font-medium ${change.delta > 0 ? "text-status-success-text" : "text-destructive"}`,
|
|
780
|
-
children:
|
|
781
|
-
"(
|
|
782
|
-
|
|
783
|
-
fmt(change.delta, currency),
|
|
784
|
-
"/mo)"
|
|
785
|
-
]
|
|
773
|
+
children: t("cpq.inventory.subscriptions.detail.changeLog.deltaPerMonth", "({delta}/mo)", {
|
|
774
|
+
delta: `${change.delta > 0 ? "+" : ""}${fmt(change.delta, currency)}`
|
|
775
|
+
})
|
|
786
776
|
}
|
|
787
777
|
),
|
|
788
|
-
isNoopModify && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground italic", children: "no price change" })
|
|
778
|
+
isNoopModify && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground italic", children: t("cpq.inventory.subscriptions.detail.changeLog.noPriceChange", "no price change") })
|
|
789
779
|
] });
|
|
790
780
|
}
|
|
791
781
|
export {
|