@dainamite/cpq 0.2.2
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/LICENSE +21 -0
- package/MIGRATION.md +236 -0
- package/README.md +108 -0
- package/dist/modules/cpq/acl.js +30 -0
- package/dist/modules/cpq/acl.js.map +7 -0
- package/dist/modules/cpq/api/_helpers/handleArcError.js +37 -0
- package/dist/modules/cpq/api/_helpers/handleArcError.js.map +7 -0
- package/dist/modules/cpq/api/attribute-options/route.js +47 -0
- package/dist/modules/cpq/api/attribute-options/route.js.map +7 -0
- package/dist/modules/cpq/api/bundle-slots/route.js +101 -0
- package/dist/modules/cpq/api/bundle-slots/route.js.map +7 -0
- package/dist/modules/cpq/api/bundle-tree/route.js +28 -0
- package/dist/modules/cpq/api/bundle-tree/route.js.map +7 -0
- package/dist/modules/cpq/api/context.js +29 -0
- package/dist/modules/cpq/api/context.js.map +7 -0
- package/dist/modules/cpq/api/inventory/assets/route.js +113 -0
- package/dist/modules/cpq/api/inventory/assets/route.js.map +7 -0
- package/dist/modules/cpq/api/inventory/assets/status/route.js +35 -0
- package/dist/modules/cpq/api/inventory/assets/status/route.js.map +7 -0
- package/dist/modules/cpq/api/inventory/customer/[customerId]/parent-items/route.js +30 -0
- package/dist/modules/cpq/api/inventory/customer/[customerId]/parent-items/route.js.map +7 -0
- package/dist/modules/cpq/api/inventory/customer/[customerId]/route.js +31 -0
- package/dist/modules/cpq/api/inventory/customer/[customerId]/route.js.map +7 -0
- package/dist/modules/cpq/api/inventory/subscription-items/route.js +99 -0
- package/dist/modules/cpq/api/inventory/subscription-items/route.js.map +7 -0
- package/dist/modules/cpq/api/inventory/subscriptions/[subscriptionId]/change-log/route.js +57 -0
- package/dist/modules/cpq/api/inventory/subscriptions/[subscriptionId]/change-log/route.js.map +7 -0
- package/dist/modules/cpq/api/inventory/subscriptions/expiring/route.js +62 -0
- package/dist/modules/cpq/api/inventory/subscriptions/expiring/route.js.map +7 -0
- package/dist/modules/cpq/api/inventory/subscriptions/route.js +116 -0
- package/dist/modules/cpq/api/inventory/subscriptions/route.js.map +7 -0
- package/dist/modules/cpq/api/inventory/subscriptions/status/route.js +35 -0
- package/dist/modules/cpq/api/inventory/subscriptions/status/route.js.map +7 -0
- package/dist/modules/cpq/api/offering-components/route.js +91 -0
- package/dist/modules/cpq/api/offering-components/route.js.map +7 -0
- package/dist/modules/cpq/api/orders/[orderId]/activate/route.js +39 -0
- package/dist/modules/cpq/api/orders/[orderId]/activate/route.js.map +7 -0
- package/dist/modules/cpq/api/orders/[orderId]/route.js +28 -0
- package/dist/modules/cpq/api/orders/[orderId]/route.js.map +7 -0
- package/dist/modules/cpq/api/orders/[orderId]/status/route.js +38 -0
- package/dist/modules/cpq/api/orders/[orderId]/status/route.js.map +7 -0
- package/dist/modules/cpq/api/orders/route.js +71 -0
- package/dist/modules/cpq/api/orders/route.js.map +7 -0
- package/dist/modules/cpq/api/price-rules/route.js +180 -0
- package/dist/modules/cpq/api/price-rules/route.js.map +7 -0
- package/dist/modules/cpq/api/pricing-table-entries/route.js +142 -0
- package/dist/modules/cpq/api/pricing-table-entries/route.js.map +7 -0
- package/dist/modules/cpq/api/pricing-tables/route.js +179 -0
- package/dist/modules/cpq/api/pricing-tables/route.js.map +7 -0
- package/dist/modules/cpq/api/product-attributes/route.js +160 -0
- package/dist/modules/cpq/api/product-attributes/route.js.map +7 -0
- package/dist/modules/cpq/api/product-charges/route.js +166 -0
- package/dist/modules/cpq/api/product-charges/route.js.map +7 -0
- package/dist/modules/cpq/api/product-offerings/route.js +294 -0
- package/dist/modules/cpq/api/product-offerings/route.js.map +7 -0
- package/dist/modules/cpq/api/product-relationships/route.js +144 -0
- package/dist/modules/cpq/api/product-relationships/route.js.map +7 -0
- package/dist/modules/cpq/api/product-specifications/route.js +292 -0
- package/dist/modules/cpq/api/product-specifications/route.js.map +7 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/cancel-meta/route.js +71 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/cancel-meta/route.js.map +7 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/clone/route.js +29 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/clone/route.js.map +7 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/items/[lineId]/route.js +54 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/items/[lineId]/route.js.map +7 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/items/route.js +27 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/items/route.js.map +7 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/merge-meta/route.js +72 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/merge-meta/route.js.map +7 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/recalculate/route.js +35 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/recalculate/route.js.map +7 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/route.js +102 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/route.js.map +7 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/status/route.js +27 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/status/route.js.map +7 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/target-subscriptions/[targetId]/route.js +79 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/target-subscriptions/[targetId]/route.js.map +7 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/target-subscriptions/route.js +95 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/target-subscriptions/route.js.map +7 -0
- package/dist/modules/cpq/api/quotes/attributes/route.js +52 -0
- package/dist/modules/cpq/api/quotes/attributes/route.js.map +7 -0
- package/dist/modules/cpq/api/quotes/from-subscription/route.js +72 -0
- package/dist/modules/cpq/api/quotes/from-subscription/route.js.map +7 -0
- package/dist/modules/cpq/api/quotes/price/route.js +69 -0
- package/dist/modules/cpq/api/quotes/price/route.js.map +7 -0
- package/dist/modules/cpq/api/quotes/route.js +97 -0
- package/dist/modules/cpq/api/quotes/route.js.map +7 -0
- package/dist/modules/cpq/api/quotes/validate-relationships/route.js +86 -0
- package/dist/modules/cpq/api/quotes/validate-relationships/route.js.map +7 -0
- package/dist/modules/cpq/api/resolveQuotingService.js +7 -0
- package/dist/modules/cpq/api/resolveQuotingService.js.map +7 -0
- package/dist/modules/cpq/api/wizards/resolve/route.js +38 -0
- package/dist/modules/cpq/api/wizards/resolve/route.js.map +7 -0
- package/dist/modules/cpq/api/wizards/route.js +111 -0
- package/dist/modules/cpq/api/wizards/route.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/inventory/AssetsTable.js +136 -0
- package/dist/modules/cpq/backend/cpq/inventory/AssetsTable.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/inventory/SubscriptionsTable.js +185 -0
- package/dist/modules/cpq/backend/cpq/inventory/SubscriptionsTable.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/inventory/assets/[id]/page.js +343 -0
- package/dist/modules/cpq/backend/cpq/inventory/assets/[id]/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/inventory/assets/[id]/page.meta.js +13 -0
- package/dist/modules/cpq/backend/cpq/inventory/assets/[id]/page.meta.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/inventory/page.js +35 -0
- package/dist/modules/cpq/backend/cpq/inventory/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/inventory/page.meta.js +18 -0
- package/dist/modules/cpq/backend/cpq/inventory/page.meta.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/inventory/shared.js +20 -0
- package/dist/modules/cpq/backend/cpq/inventory/shared.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.js +794 -0
- package/dist/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.meta.js +13 -0
- package/dist/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.meta.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/offerings/[id]/page.js +917 -0
- package/dist/modules/cpq/backend/cpq/offerings/[id]/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/offerings/page.js +405 -0
- package/dist/modules/cpq/backend/cpq/offerings/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/offerings/page.meta.js +18 -0
- package/dist/modules/cpq/backend/cpq/offerings/page.meta.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/orders/[id]/page.js +677 -0
- package/dist/modules/cpq/backend/cpq/orders/[id]/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/orders/page.js +134 -0
- package/dist/modules/cpq/backend/cpq/orders/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/orders/page.meta.js +18 -0
- package/dist/modules/cpq/backend/cpq/orders/page.meta.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/price-rules/PriceRuleForm.js +272 -0
- package/dist/modules/cpq/backend/cpq/price-rules/PriceRuleForm.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/price-rules/[id]/page.js +407 -0
- package/dist/modules/cpq/backend/cpq/price-rules/[id]/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/price-rules/[id]/page.meta.js +13 -0
- package/dist/modules/cpq/backend/cpq/price-rules/[id]/page.meta.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/price-rules/page.js +211 -0
- package/dist/modules/cpq/backend/cpq/price-rules/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/price-rules/page.meta.js +18 -0
- package/dist/modules/cpq/backend/cpq/price-rules/page.meta.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/pricing/[id]/EntriesEditor.js +275 -0
- package/dist/modules/cpq/backend/cpq/pricing/[id]/EntriesEditor.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/pricing/[id]/ImportPreview.js +112 -0
- package/dist/modules/cpq/backend/cpq/pricing/[id]/ImportPreview.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/pricing/[id]/page.js +492 -0
- package/dist/modules/cpq/backend/cpq/pricing/[id]/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/pricing/[id]/xlsxExport.js +50 -0
- package/dist/modules/cpq/backend/cpq/pricing/[id]/xlsxExport.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/pricing/[id]/xlsxImport.js +249 -0
- package/dist/modules/cpq/backend/cpq/pricing/[id]/xlsxImport.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/pricing/page.js +87 -0
- package/dist/modules/cpq/backend/cpq/pricing/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/pricing/page.meta.js +18 -0
- package/dist/modules/cpq/backend/cpq/pricing/page.meta.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/ArcQuoteConfigurator.js +652 -0
- package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/ArcQuoteConfigurator.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/quotes/[id]/page.js +1289 -0
- package/dist/modules/cpq/backend/cpq/quotes/[id]/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/quotes/page.js +283 -0
- package/dist/modules/cpq/backend/cpq/quotes/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/quotes/page.meta.js +18 -0
- package/dist/modules/cpq/backend/cpq/quotes/page.meta.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/specifications/[id]/DependsOnRulesEditor.js +214 -0
- package/dist/modules/cpq/backend/cpq/specifications/[id]/DependsOnRulesEditor.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/specifications/[id]/page.js +1399 -0
- package/dist/modules/cpq/backend/cpq/specifications/[id]/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/specifications/page.js +148 -0
- package/dist/modules/cpq/backend/cpq/specifications/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/specifications/page.meta.js +18 -0
- package/dist/modules/cpq/backend/cpq/specifications/page.meta.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/wizards/[definitionCode]/detail/page.js +204 -0
- package/dist/modules/cpq/backend/cpq/wizards/[definitionCode]/detail/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/wizards/[definitionCode]/page.js +191 -0
- package/dist/modules/cpq/backend/cpq/wizards/[definitionCode]/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/wizards/page.js +119 -0
- package/dist/modules/cpq/backend/cpq/wizards/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/wizards/page.meta.js +18 -0
- package/dist/modules/cpq/backend/cpq/wizards/page.meta.js.map +7 -0
- package/dist/modules/cpq/ce.js +151 -0
- package/dist/modules/cpq/ce.js.map +7 -0
- package/dist/modules/cpq/cli.js +11 -0
- package/dist/modules/cpq/cli.js.map +7 -0
- package/dist/modules/cpq/components/CpqListView.js +265 -0
- package/dist/modules/cpq/components/CpqListView.js.map +7 -0
- package/dist/modules/cpq/components/NumberInput.js +95 -0
- package/dist/modules/cpq/components/NumberInput.js.map +7 -0
- package/dist/modules/cpq/components/StatusPath.js +60 -0
- package/dist/modules/cpq/components/StatusPath.js.map +7 -0
- package/dist/modules/cpq/components/statusMaps.js +66 -0
- package/dist/modules/cpq/components/statusMaps.js.map +7 -0
- package/dist/modules/cpq/components/useCpqRowActions.js +125 -0
- package/dist/modules/cpq/components/useCpqRowActions.js.map +7 -0
- package/dist/modules/cpq/data/entities.js +1556 -0
- package/dist/modules/cpq/data/entities.js.map +7 -0
- package/dist/modules/cpq/data/validators.js +575 -0
- package/dist/modules/cpq/data/validators.js.map +7 -0
- package/dist/modules/cpq/di.js +57 -0
- package/dist/modules/cpq/di.js.map +7 -0
- package/dist/modules/cpq/events.js +50 -0
- package/dist/modules/cpq/events.js.map +7 -0
- package/dist/modules/cpq/index.js +16 -0
- package/dist/modules/cpq/index.js.map +7 -0
- package/dist/modules/cpq/lib/seeds/api.js +32 -0
- package/dist/modules/cpq/lib/seeds/api.js.map +7 -0
- package/dist/modules/cpq/lib/seeds/tenant-provisioning.js +158 -0
- package/dist/modules/cpq/lib/seeds/tenant-provisioning.js.map +7 -0
- package/dist/modules/cpq/lib/seeds.js +6 -0
- package/dist/modules/cpq/lib/seeds.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260220220000_cpq.js +40 -0
- package/dist/modules/cpq/migrations/Migration20260220220000_cpq.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260330000000_cpq_product_domain.js +54 -0
- package/dist/modules/cpq/migrations/Migration20260330000000_cpq_product_domain.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260331000000_cpq_charge_unique_per_offering.js +15 -0
- package/dist/modules/cpq/migrations/Migration20260331000000_cpq_charge_unique_per_offering.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260401000000_cpq_quoting_v2.js +62 -0
- package/dist/modules/cpq/migrations/Migration20260401000000_cpq_quoting_v2.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260402000000_cpq_workflows.js +56 -0
- package/dist/modules/cpq/migrations/Migration20260402000000_cpq_workflows.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260407000000_cpq_pricing_tables_v2.js +26 -0
- package/dist/modules/cpq/migrations/Migration20260407000000_cpq_pricing_tables_v2.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260407100000_cpq_price_rules.js +37 -0
- package/dist/modules/cpq/migrations/Migration20260407100000_cpq_price_rules.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260408000000_cpq_price_rules.js +35 -0
- package/dist/modules/cpq/migrations/Migration20260408000000_cpq_price_rules.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260410000000_cpq_drop_datacentres_inventory.js +21 -0
- package/dist/modules/cpq/migrations/Migration20260410000000_cpq_drop_datacentres_inventory.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260410000000_cpq_wizard_rename.js +46 -0
- package/dist/modules/cpq/migrations/Migration20260410000000_cpq_wizard_rename.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260410100000_cpq_inventory.js +118 -0
- package/dist/modules/cpq/migrations/Migration20260410100000_cpq_inventory.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260411000000_cpq_orders.js +63 -0
- package/dist/modules/cpq/migrations/Migration20260411000000_cpq_orders.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260412000000_cpq_bundled_offerings.js +28 -0
- package/dist/modules/cpq/migrations/Migration20260412000000_cpq_bundled_offerings.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260504064621_cpq_arc.js +36 -0
- package/dist/modules/cpq/migrations/Migration20260504064621_cpq_arc.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260514000000_cpq_spec_merge_retired_deprecated.js +14 -0
- package/dist/modules/cpq/migrations/Migration20260514000000_cpq_spec_merge_retired_deprecated.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260514100000_cpq_offering_merge_retired_deprecated.js +14 -0
- package/dist/modules/cpq/migrations/Migration20260514100000_cpq_offering_merge_retired_deprecated.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260514110000_cpq_list_search_indexes.js +58 -0
- package/dist/modules/cpq/migrations/Migration20260514110000_cpq_list_search_indexes.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260515000000_cpq_inventory_subscriptions_search_indexes.js +29 -0
- package/dist/modules/cpq/migrations/Migration20260515000000_cpq_inventory_subscriptions_search_indexes.js.map +7 -0
- package/dist/modules/cpq/services/cpqBundleService.js +447 -0
- package/dist/modules/cpq/services/cpqBundleService.js.map +7 -0
- package/dist/modules/cpq/services/cpqInventoryService.js +1371 -0
- package/dist/modules/cpq/services/cpqInventoryService.js.map +7 -0
- package/dist/modules/cpq/services/cpqOrderService.js +901 -0
- package/dist/modules/cpq/services/cpqOrderService.js.map +7 -0
- package/dist/modules/cpq/services/cpqPricingService.js +289 -0
- package/dist/modules/cpq/services/cpqPricingService.js.map +7 -0
- package/dist/modules/cpq/services/cpqProductService.js +204 -0
- package/dist/modules/cpq/services/cpqProductService.js.map +7 -0
- package/dist/modules/cpq/services/cpqQuotingService.js +1867 -0
- package/dist/modules/cpq/services/cpqQuotingService.js.map +7 -0
- package/dist/modules/cpq/services/cpqValidationService.js +234 -0
- package/dist/modules/cpq/services/cpqValidationService.js.map +7 -0
- package/dist/modules/cpq/services/cpqWizardService.js +137 -0
- package/dist/modules/cpq/services/cpqWizardService.js.map +7 -0
- package/dist/modules/cpq/services/types.js +114 -0
- package/dist/modules/cpq/services/types.js.map +7 -0
- package/dist/modules/cpq/setup.js +49 -0
- package/dist/modules/cpq/setup.js.map +7 -0
- package/dist/modules/cpq/subscribers/subscription-amended-log.js +18 -0
- package/dist/modules/cpq/subscribers/subscription-amended-log.js.map +7 -0
- package/dist/modules/cpq/subscribers/subscription-cancelled-log.js +19 -0
- package/dist/modules/cpq/subscribers/subscription-cancelled-log.js.map +7 -0
- package/dist/modules/cpq/subscribers/subscription-merged-log.js +20 -0
- package/dist/modules/cpq/subscribers/subscription-merged-log.js.map +7 -0
- package/dist/modules/cpq/subscribers/subscription-renewed-log.js +18 -0
- package/dist/modules/cpq/subscribers/subscription-renewed-log.js.map +7 -0
- package/dist/modules/cpq/subscribers/subscription-superseded-log.js +18 -0
- package/dist/modules/cpq/subscribers/subscription-superseded-log.js.map +7 -0
- package/dist/modules/cpq/widgets/injection/customer-inventory/widget.client.js +192 -0
- package/dist/modules/cpq/widgets/injection/customer-inventory/widget.client.js.map +7 -0
- package/dist/modules/cpq/widgets/injection/customer-inventory/widget.js +17 -0
- package/dist/modules/cpq/widgets/injection/customer-inventory/widget.js.map +7 -0
- package/dist/modules/cpq/widgets/injection/order-cpq-tab/widget.client.js +79 -0
- package/dist/modules/cpq/widgets/injection/order-cpq-tab/widget.client.js.map +7 -0
- package/dist/modules/cpq/widgets/injection/order-cpq-tab/widget.js +17 -0
- package/dist/modules/cpq/widgets/injection/order-cpq-tab/widget.js.map +7 -0
- package/dist/modules/cpq/widgets/injection/quote-configurator/widget.client.js +181 -0
- package/dist/modules/cpq/widgets/injection/quote-configurator/widget.client.js.map +7 -0
- package/dist/modules/cpq/widgets/injection/quote-configurator/widget.js +17 -0
- package/dist/modules/cpq/widgets/injection/quote-configurator/widget.js.map +7 -0
- package/dist/modules/cpq/widgets/injection-table.js +44 -0
- package/dist/modules/cpq/widgets/injection-table.js.map +7 -0
- package/dist/modules/cpq/workflows/WizardRunner.js +113 -0
- package/dist/modules/cpq/workflows/WizardRunner.js.map +7 -0
- package/dist/modules/cpq/workflows/WizardTrigger.js +116 -0
- package/dist/modules/cpq/workflows/WizardTrigger.js.map +7 -0
- package/dist/modules/cpq/workflows/engine.js +188 -0
- package/dist/modules/cpq/workflows/engine.js.map +7 -0
- package/dist/modules/cpq/workflows/registry.js +16 -0
- package/dist/modules/cpq/workflows/registry.js.map +7 -0
- package/dist/modules/cpq/workflows/steps/CustomerSelectStep.js +119 -0
- package/dist/modules/cpq/workflows/steps/CustomerSelectStep.js.map +7 -0
- package/dist/modules/cpq/workflows/steps/InventorySelectStep.js +24 -0
- package/dist/modules/cpq/workflows/steps/InventorySelectStep.js.map +7 -0
- package/dist/modules/cpq/workflows/steps/ItemListStep.js +115 -0
- package/dist/modules/cpq/workflows/steps/ItemListStep.js.map +7 -0
- package/dist/modules/cpq/workflows/steps/OfferingSelectStep.js +327 -0
- package/dist/modules/cpq/workflows/steps/OfferingSelectStep.js.map +7 -0
- package/dist/modules/cpq/workflows/steps/ProductConfigureStep.js +231 -0
- package/dist/modules/cpq/workflows/steps/ProductConfigureStep.js.map +7 -0
- package/dist/modules/cpq/workflows/steps/ReviewStep.js +152 -0
- package/dist/modules/cpq/workflows/steps/ReviewStep.js.map +7 -0
- package/dist/modules/cpq/workflows/steps/index.js +49 -0
- package/dist/modules/cpq/workflows/steps/index.js.map +7 -0
- package/dist/modules/cpq/workflows/types.js +1 -0
- package/dist/modules/cpq/workflows/types.js.map +7 -0
- package/package.json +150 -0
- package/src/modules/cpq/__integration__/TC-CPQ-001.spec.ts +177 -0
- package/src/modules/cpq/__integration__/TC-CPQ-002.spec.ts +123 -0
- package/src/modules/cpq/__integration__/TC-CPQ-003.spec.ts +115 -0
- package/src/modules/cpq/__integration__/TC-CPQ-004.spec.ts +184 -0
- package/src/modules/cpq/__integration__/TC-CPQ-005.spec.ts +43 -0
- package/src/modules/cpq/__integration__/TC-CPQ-006.spec.ts +87 -0
- package/src/modules/cpq/__integration__/TC-CPQ-007.spec.ts +79 -0
- package/src/modules/cpq/__integration__/TC-CPQ-008.spec.ts +55 -0
- package/src/modules/cpq/__integration__/TC-CPQ-009.spec.ts +45 -0
- package/src/modules/cpq/__integration__/TC-CPQ-010.spec.ts +54 -0
- package/src/modules/cpq/__integration__/TC-CPQ-011.spec.ts +24 -0
- package/src/modules/cpq/__integration__/TC-CPQ-012.spec.ts +62 -0
- package/src/modules/cpq/__integration__/TC-CPQ-ARC-001.spec.ts +52 -0
- package/src/modules/cpq/__integration__/TC-CPQ-ARC-002.spec.ts +65 -0
- package/src/modules/cpq/__integration__/TC-CPQ-ARC-003.spec.ts +107 -0
- package/src/modules/cpq/__integration__/TC-CPQ-ARC-004.spec.ts +74 -0
- package/src/modules/cpq/__integration__/TC-CPQ-ARC-005.spec.ts +86 -0
- package/src/modules/cpq/__integration__/TC-CPQ-ARC-006.spec.ts +79 -0
- package/src/modules/cpq/__integration__/TC-CPQ-ARC-007.spec.ts +63 -0
- package/src/modules/cpq/__integration__/TC-CPQ-ARC-008.spec.ts +62 -0
- package/src/modules/cpq/__integration__/TC-CPQ-ARC-009.spec.ts +62 -0
- package/src/modules/cpq/__integration__/TC-CPQ-ARC-010.spec.ts +59 -0
- package/src/modules/cpq/__integration__/TC-CPQ-ARC-011.spec.ts +128 -0
- package/src/modules/cpq/__integration__/_helpers/cpqArcFixtures.ts +208 -0
- package/src/modules/cpq/__tests__/package-isolation.test.ts +232 -0
- package/src/modules/cpq/acl.ts +26 -0
- package/src/modules/cpq/api/_helpers/__tests__/handleArcError.test.ts +117 -0
- package/src/modules/cpq/api/_helpers/handleArcError.ts +81 -0
- package/src/modules/cpq/api/attribute-options/route.ts +55 -0
- package/src/modules/cpq/api/bundle-slots/route.ts +112 -0
- package/src/modules/cpq/api/bundle-tree/route.ts +31 -0
- package/src/modules/cpq/api/context.ts +39 -0
- package/src/modules/cpq/api/inventory/assets/route.ts +123 -0
- package/src/modules/cpq/api/inventory/assets/status/route.ts +34 -0
- package/src/modules/cpq/api/inventory/customer/[customerId]/parent-items/route.ts +30 -0
- package/src/modules/cpq/api/inventory/customer/[customerId]/route.ts +31 -0
- package/src/modules/cpq/api/inventory/subscription-items/route.ts +107 -0
- package/src/modules/cpq/api/inventory/subscriptions/[subscriptionId]/change-log/route.ts +64 -0
- package/src/modules/cpq/api/inventory/subscriptions/expiring/route.ts +66 -0
- package/src/modules/cpq/api/inventory/subscriptions/route.ts +126 -0
- package/src/modules/cpq/api/inventory/subscriptions/status/route.ts +34 -0
- package/src/modules/cpq/api/offering-components/route.ts +103 -0
- package/src/modules/cpq/api/orders/[orderId]/activate/route.ts +48 -0
- package/src/modules/cpq/api/orders/[orderId]/route.ts +28 -0
- package/src/modules/cpq/api/orders/[orderId]/status/route.ts +38 -0
- package/src/modules/cpq/api/orders/route.ts +77 -0
- package/src/modules/cpq/api/price-rules/route.ts +210 -0
- package/src/modules/cpq/api/pricing-table-entries/route.ts +159 -0
- package/src/modules/cpq/api/pricing-tables/route.ts +202 -0
- package/src/modules/cpq/api/product-attributes/route.ts +175 -0
- package/src/modules/cpq/api/product-charges/route.ts +181 -0
- package/src/modules/cpq/api/product-offerings/route.ts +329 -0
- package/src/modules/cpq/api/product-relationships/route.ts +156 -0
- package/src/modules/cpq/api/product-specifications/route.ts +325 -0
- package/src/modules/cpq/api/quotes/[quoteId]/cancel-meta/route.ts +77 -0
- package/src/modules/cpq/api/quotes/[quoteId]/clone/route.ts +28 -0
- package/src/modules/cpq/api/quotes/[quoteId]/items/[lineId]/route.ts +55 -0
- package/src/modules/cpq/api/quotes/[quoteId]/items/route.ts +26 -0
- package/src/modules/cpq/api/quotes/[quoteId]/merge-meta/route.ts +78 -0
- package/src/modules/cpq/api/quotes/[quoteId]/recalculate/route.ts +34 -0
- package/src/modules/cpq/api/quotes/[quoteId]/route.ts +109 -0
- package/src/modules/cpq/api/quotes/[quoteId]/status/route.ts +26 -0
- package/src/modules/cpq/api/quotes/[quoteId]/target-subscriptions/[targetId]/route.ts +91 -0
- package/src/modules/cpq/api/quotes/[quoteId]/target-subscriptions/route.ts +107 -0
- package/src/modules/cpq/api/quotes/attributes/route.ts +61 -0
- package/src/modules/cpq/api/quotes/from-subscription/route.ts +85 -0
- package/src/modules/cpq/api/quotes/price/route.ts +81 -0
- package/src/modules/cpq/api/quotes/route.ts +114 -0
- package/src/modules/cpq/api/quotes/validate-relationships/route.ts +100 -0
- package/src/modules/cpq/api/resolveQuotingService.ts +11 -0
- package/src/modules/cpq/api/wizards/resolve/route.ts +39 -0
- package/src/modules/cpq/api/wizards/route.ts +127 -0
- package/src/modules/cpq/backend/cpq/inventory/AssetsTable.tsx +166 -0
- package/src/modules/cpq/backend/cpq/inventory/SubscriptionsTable.tsx +251 -0
- package/src/modules/cpq/backend/cpq/inventory/assets/[id]/page.meta.ts +9 -0
- package/src/modules/cpq/backend/cpq/inventory/assets/[id]/page.tsx +440 -0
- package/src/modules/cpq/backend/cpq/inventory/page.meta.ts +16 -0
- package/src/modules/cpq/backend/cpq/inventory/page.tsx +49 -0
- package/src/modules/cpq/backend/cpq/inventory/shared.tsx +32 -0
- package/src/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.meta.ts +9 -0
- package/src/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.tsx +1085 -0
- package/src/modules/cpq/backend/cpq/offerings/[id]/page.tsx +1165 -0
- package/src/modules/cpq/backend/cpq/offerings/page.meta.ts +16 -0
- package/src/modules/cpq/backend/cpq/offerings/page.tsx +468 -0
- package/src/modules/cpq/backend/cpq/orders/[id]/page.tsx +921 -0
- package/src/modules/cpq/backend/cpq/orders/page.meta.ts +16 -0
- package/src/modules/cpq/backend/cpq/orders/page.tsx +182 -0
- package/src/modules/cpq/backend/cpq/price-rules/PriceRuleForm.tsx +310 -0
- package/src/modules/cpq/backend/cpq/price-rules/[id]/page.meta.ts +9 -0
- package/src/modules/cpq/backend/cpq/price-rules/[id]/page.tsx +472 -0
- package/src/modules/cpq/backend/cpq/price-rules/page.meta.ts +16 -0
- package/src/modules/cpq/backend/cpq/price-rules/page.tsx +253 -0
- package/src/modules/cpq/backend/cpq/pricing/[id]/EntriesEditor.tsx +431 -0
- package/src/modules/cpq/backend/cpq/pricing/[id]/ImportPreview.tsx +122 -0
- package/src/modules/cpq/backend/cpq/pricing/[id]/page.tsx +588 -0
- package/src/modules/cpq/backend/cpq/pricing/[id]/xlsxExport.ts +90 -0
- package/src/modules/cpq/backend/cpq/pricing/[id]/xlsxImport.ts +338 -0
- package/src/modules/cpq/backend/cpq/pricing/page.meta.ts +16 -0
- package/src/modules/cpq/backend/cpq/pricing/page.tsx +111 -0
- package/src/modules/cpq/backend/cpq/quotes/[id]/_components/ArcQuoteConfigurator.tsx +737 -0
- package/src/modules/cpq/backend/cpq/quotes/[id]/page.tsx +1721 -0
- package/src/modules/cpq/backend/cpq/quotes/page.meta.ts +16 -0
- package/src/modules/cpq/backend/cpq/quotes/page.tsx +370 -0
- package/src/modules/cpq/backend/cpq/specifications/[id]/DependsOnRulesEditor.tsx +300 -0
- package/src/modules/cpq/backend/cpq/specifications/[id]/page.tsx +1722 -0
- package/src/modules/cpq/backend/cpq/specifications/page.meta.ts +16 -0
- package/src/modules/cpq/backend/cpq/specifications/page.tsx +191 -0
- package/src/modules/cpq/backend/cpq/wizards/[definitionCode]/detail/page.tsx +319 -0
- package/src/modules/cpq/backend/cpq/wizards/[definitionCode]/page.tsx +234 -0
- package/src/modules/cpq/backend/cpq/wizards/page.meta.ts +16 -0
- package/src/modules/cpq/backend/cpq/wizards/page.tsx +141 -0
- package/src/modules/cpq/ce.ts +150 -0
- package/src/modules/cpq/cli.ts +10 -0
- package/src/modules/cpq/components/CpqListView.tsx +431 -0
- package/src/modules/cpq/components/NumberInput.tsx +166 -0
- package/src/modules/cpq/components/StatusPath.tsx +116 -0
- package/src/modules/cpq/components/statusMaps.ts +148 -0
- package/src/modules/cpq/components/useCpqRowActions.tsx +183 -0
- package/src/modules/cpq/data/__tests__/validators.arc.test.ts +271 -0
- package/src/modules/cpq/data/__tests__/validators.test.ts +782 -0
- package/src/modules/cpq/data/entities.ts +1467 -0
- package/src/modules/cpq/data/validators.ts +663 -0
- package/src/modules/cpq/di.ts +70 -0
- package/src/modules/cpq/events.ts +62 -0
- package/src/modules/cpq/index.ts +15 -0
- package/src/modules/cpq/lib/seeds/__tests__/api.test.ts +86 -0
- package/src/modules/cpq/lib/seeds/__tests__/tenant-provisioning.test.ts +349 -0
- package/src/modules/cpq/lib/seeds/api.ts +119 -0
- package/src/modules/cpq/lib/seeds/tenant-provisioning.ts +239 -0
- package/src/modules/cpq/lib/seeds.ts +18 -0
- package/src/modules/cpq/migrations/.snapshot-open-mercato.json +7473 -0
- package/src/modules/cpq/migrations/Migration20260220220000_cpq.ts +51 -0
- package/src/modules/cpq/migrations/Migration20260330000000_cpq_product_domain.ts +70 -0
- package/src/modules/cpq/migrations/Migration20260331000000_cpq_charge_unique_per_offering.ts +15 -0
- package/src/modules/cpq/migrations/Migration20260401000000_cpq_quoting_v2.ts +73 -0
- package/src/modules/cpq/migrations/Migration20260402000000_cpq_workflows.ts +59 -0
- package/src/modules/cpq/migrations/Migration20260407000000_cpq_pricing_tables_v2.ts +30 -0
- package/src/modules/cpq/migrations/Migration20260407100000_cpq_price_rules.ts +36 -0
- package/src/modules/cpq/migrations/Migration20260408000000_cpq_price_rules.ts +33 -0
- package/src/modules/cpq/migrations/Migration20260410000000_cpq_drop_datacentres_inventory.ts +22 -0
- package/src/modules/cpq/migrations/Migration20260410000000_cpq_wizard_rename.ts +56 -0
- package/src/modules/cpq/migrations/Migration20260410100000_cpq_inventory.ts +118 -0
- package/src/modules/cpq/migrations/Migration20260411000000_cpq_orders.ts +62 -0
- package/src/modules/cpq/migrations/Migration20260412000000_cpq_bundled_offerings.ts +33 -0
- package/src/modules/cpq/migrations/Migration20260504064621_cpq_arc.ts +68 -0
- package/src/modules/cpq/migrations/Migration20260514000000_cpq_spec_merge_retired_deprecated.ts +30 -0
- package/src/modules/cpq/migrations/Migration20260514100000_cpq_offering_merge_retired_deprecated.ts +27 -0
- package/src/modules/cpq/migrations/Migration20260514110000_cpq_list_search_indexes.ts +82 -0
- package/src/modules/cpq/migrations/Migration20260515000000_cpq_inventory_subscriptions_search_indexes.ts +52 -0
- package/src/modules/cpq/services/__tests__/_helpers/mockEm.ts +59 -0
- package/src/modules/cpq/services/__tests__/cpqBundleService.test.ts +661 -0
- package/src/modules/cpq/services/__tests__/cpqInventoryService.arc.test.ts +357 -0
- package/src/modules/cpq/services/__tests__/cpqInventoryService.test.ts +718 -0
- package/src/modules/cpq/services/__tests__/cpqOrderService.test.ts +603 -0
- package/src/modules/cpq/services/__tests__/cpqPricingService.test.ts +1012 -0
- package/src/modules/cpq/services/__tests__/cpqProductService.test.ts +603 -0
- package/src/modules/cpq/services/__tests__/cpqQuotingService.arc.test.ts +143 -0
- package/src/modules/cpq/services/__tests__/cpqQuotingService.test.ts +658 -0
- package/src/modules/cpq/services/__tests__/cpqValidationService.test.ts +811 -0
- package/src/modules/cpq/services/__tests__/cpqWizardService.test.ts +389 -0
- package/src/modules/cpq/services/__tests__/types.test.ts +359 -0
- package/src/modules/cpq/services/cpqBundleService.ts +671 -0
- package/src/modules/cpq/services/cpqInventoryService.ts +1929 -0
- package/src/modules/cpq/services/cpqOrderService.ts +1230 -0
- package/src/modules/cpq/services/cpqPricingService.ts +412 -0
- package/src/modules/cpq/services/cpqProductService.ts +311 -0
- package/src/modules/cpq/services/cpqQuotingService.ts +2638 -0
- package/src/modules/cpq/services/cpqValidationService.ts +323 -0
- package/src/modules/cpq/services/cpqWizardService.ts +204 -0
- package/src/modules/cpq/services/types.ts +303 -0
- package/src/modules/cpq/setup.ts +63 -0
- package/src/modules/cpq/subscribers/subscription-amended-log.ts +20 -0
- package/src/modules/cpq/subscribers/subscription-cancelled-log.ts +19 -0
- package/src/modules/cpq/subscribers/subscription-merged-log.ts +22 -0
- package/src/modules/cpq/subscribers/subscription-renewed-log.ts +18 -0
- package/src/modules/cpq/subscribers/subscription-superseded-log.ts +19 -0
- package/src/modules/cpq/widgets/injection/customer-inventory/widget.client.tsx +339 -0
- package/src/modules/cpq/widgets/injection/customer-inventory/widget.ts +16 -0
- package/src/modules/cpq/widgets/injection/order-cpq-tab/widget.client.tsx +96 -0
- package/src/modules/cpq/widgets/injection/order-cpq-tab/widget.ts +16 -0
- package/src/modules/cpq/widgets/injection/quote-configurator/widget.client.tsx +265 -0
- package/src/modules/cpq/widgets/injection/quote-configurator/widget.ts +16 -0
- package/src/modules/cpq/widgets/injection-table.ts +42 -0
- package/src/modules/cpq/workflows/WizardRunner.tsx +158 -0
- package/src/modules/cpq/workflows/WizardTrigger.tsx +142 -0
- package/src/modules/cpq/workflows/engine.tsx +278 -0
- package/src/modules/cpq/workflows/registry.ts +15 -0
- package/src/modules/cpq/workflows/steps/CustomerSelectStep.tsx +136 -0
- package/src/modules/cpq/workflows/steps/InventorySelectStep.tsx +34 -0
- package/src/modules/cpq/workflows/steps/ItemListStep.tsx +146 -0
- package/src/modules/cpq/workflows/steps/OfferingSelectStep.tsx +438 -0
- package/src/modules/cpq/workflows/steps/ProductConfigureStep.tsx +287 -0
- package/src/modules/cpq/workflows/steps/ReviewStep.tsx +219 -0
- package/src/modules/cpq/workflows/steps/index.ts +51 -0
- package/src/modules/cpq/workflows/types.ts +102 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# @dainamite/cpq
|
|
2
|
+
|
|
3
|
+
## 0.2.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 73650dc: Add MIT license for first public release.
|
|
8
|
+
|
|
9
|
+
Switching `packages/cpq/package.json` `license` field from `UNLICENSED` (carry-over from the private era) to `MIT`, and shipping a `packages/cpq/LICENSE` file with the full license text. This matches the `@open-mercato/*` ecosystem and removes the "UNLICENSED" badge that public npm shows on packages without a recognized OSI license.
|
|
10
|
+
|
|
11
|
+
No code or API changes — purely a licensing/metadata clarification ahead of the first publish to https://www.npmjs.com/package/@dainamite/cpq.
|
|
12
|
+
|
|
13
|
+
- 7b09790: Switch publish target from GitHub Packages to public npm.js.
|
|
14
|
+
|
|
15
|
+
Initial publish attempts as `@dainamite/cpq` on GitHub Packages failed
|
|
16
|
+
with `403 Forbidden — installation does not exist`: scope `@dainamite`
|
|
17
|
+
on GitHub belongs to a different (unrelated) "DAInamite" organization
|
|
18
|
+
based in Berlin. Switching to public npm.js, where the `@dainamite`
|
|
19
|
+
scope is free, lets us keep the brand without renaming everything to
|
|
20
|
+
`@dainamite-technologies/cpq`.
|
|
21
|
+
|
|
22
|
+
Open Mercato itself publishes to public npm.js
|
|
23
|
+
(`@open-mercato/core`, etc.), so this is also more consistent with the
|
|
24
|
+
upstream ecosystem and matches the L2 model from SPEC-001.
|
|
25
|
+
|
|
26
|
+
For consumers: install with plain `yarn add @dainamite/cpq` — no
|
|
27
|
+
`.npmrc` auth setup needed.
|
|
28
|
+
|
|
29
|
+
## 0.2.1
|
|
30
|
+
|
|
31
|
+
### Patch Changes
|
|
32
|
+
|
|
33
|
+
- e44dfd1: Fix `repository.url` in package.json to point at
|
|
34
|
+
`dainamite-technologies/dainamite-core` (was `dainamite/dainamite-core`).
|
|
35
|
+
GitHub Packages requires the URL to match the publishing repo;
|
|
36
|
+
mismatch returns `403 Forbidden — installation does not exist`.
|
|
37
|
+
This blocked the inaugural publish of 0.2.0.
|
|
38
|
+
|
|
39
|
+
## 0.2.0
|
|
40
|
+
|
|
41
|
+
### Minor Changes
|
|
42
|
+
|
|
43
|
+
- 41c8b6d: Initial release of `@dainamite/cpq` as a standalone package.
|
|
44
|
+
|
|
45
|
+
Configure-Price-Quote engine for Open Mercato: configurable product
|
|
46
|
+
attributes, multi-charge pricing tables, guided quoting wizards,
|
|
47
|
+
customer inventory & subscription tracking, ARC (Amend / Renew / Cancel)
|
|
48
|
+
flows, quote → order → activation pipeline.
|
|
49
|
+
|
|
50
|
+
This is the first release shipped from the dainamite-core monorepo as
|
|
51
|
+
`@dainamite/cpq` on GitHub Packages. Source previously lived in
|
|
52
|
+
`src/modules/cpq/` (in-tree, `from: '@app'`); now consumed via
|
|
53
|
+
`peerDependencies` and registered as `{ id: 'cpq', from: '@dainamite/cpq' }`.
|
|
54
|
+
|
|
55
|
+
Requires (peerDependencies): `@open-mercato/core ^0.5.0`,
|
|
56
|
+
`@open-mercato/events ^0.5.0`, `@open-mercato/shared ^0.5.0`,
|
|
57
|
+
`@open-mercato/ui ^0.5.0`, `@mikro-orm/core ^6.6.0`,
|
|
58
|
+
`@mikro-orm/postgresql ^6.6.0`, `awilix ^12.0.0`, `next ^16.0.0`,
|
|
59
|
+
`react ^19.0.0`, `react-dom ^19.0.0`, `zod ^4.0.0`, `bcryptjs ^3.0.0`,
|
|
60
|
+
`lucide-react ^0.400.0`.
|
|
61
|
+
|
|
62
|
+
Required Open Mercato modules (declared in `metadata.requires`):
|
|
63
|
+
`auth`, `directory`, `catalog`, `sales`, `customers`, `dictionaries`.
|
|
64
|
+
|
|
65
|
+
### Patch Changes
|
|
66
|
+
|
|
67
|
+
- 8868606: Refresh README to reflect post-extraction state. Removes outdated
|
|
68
|
+
"scaffold only" warning, documents install + register flow, lists
|
|
69
|
+
required Open Mercato modules, and links to the package-isolation
|
|
70
|
+
guard test.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Dainamite Technologies
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/MIGRATION.md
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
# Migration plan — `src/modules/cpq/` → `@dainamite/cpq`
|
|
2
|
+
|
|
3
|
+
This document tracks the concrete steps to extract the in-tree CPQ module into
|
|
4
|
+
the `@dainamite/cpq` package, per
|
|
5
|
+
[SPEC-001 — Module Distribution Architecture](../../.ai/specs/SPEC-001-2026-04-23-module-distribution-architecture.md).
|
|
6
|
+
|
|
7
|
+
## Current state (2026-05-04)
|
|
8
|
+
|
|
9
|
+
- CPQ source lives at [`src/modules/cpq/`](../../src/modules/cpq/).
|
|
10
|
+
- Registered as `{ id: 'cpq', from: '@app' }` in
|
|
11
|
+
[`src/modules.ts`](../../src/modules.ts).
|
|
12
|
+
- `packages/cpq/` is a structural placeholder only (this directory).
|
|
13
|
+
- `dainamite-core` repo is the L3 customer demo (Demo Netia) per SPEC-001 Q4.
|
|
14
|
+
- **Customer demo data does NOT live in `cpq/`** (since XD-276). GIX and
|
|
15
|
+
Puffin Cloud catalog seeds live in `src/modules/demo_gix/` and
|
|
16
|
+
`src/modules/demo_puffin/`, registered as use cases via
|
|
17
|
+
`cpq/lib/seeds/api.ts` and orchestrated by `src/modules/demo_tenants/`.
|
|
18
|
+
When extracting `@dainamite/cpq`, only the registry API ships; the demo
|
|
19
|
+
modules stay in the customer repo.
|
|
20
|
+
|
|
21
|
+
## Target state
|
|
22
|
+
|
|
23
|
+
- CPQ source lives at `packages/cpq/src/modules/cpq/`.
|
|
24
|
+
- `dainamite-core` consumes it via `peerDependencies` and registers
|
|
25
|
+
`{ id: 'cpq', from: '@dainamite/cpq' }`.
|
|
26
|
+
- Package is published to **GitHub Packages** under `@dainamite/cpq`.
|
|
27
|
+
- Other customer apps install it the same way.
|
|
28
|
+
|
|
29
|
+
## Phased migration
|
|
30
|
+
|
|
31
|
+
### Phase 0 — Scaffold (this commit)
|
|
32
|
+
|
|
33
|
+
- [x] Copy CPQ module from `open-mercato-cpq-v0` to `src/modules/cpq/`.
|
|
34
|
+
- [x] Copy specs (`specs/`), manuals (`manuals/`), and SPEC-001 to `.ai/specs/`.
|
|
35
|
+
- [x] Create `packages/cpq/package.json` placeholder with target `@dainamite/cpq`
|
|
36
|
+
identity, peer deps, exports.
|
|
37
|
+
- [x] Document plan (this file).
|
|
38
|
+
|
|
39
|
+
### Phase 1 — Standalone build (XD-270, 2026-05-08)
|
|
40
|
+
|
|
41
|
+
- [x] Promote root to a Yarn workspace (`workspaces: ["packages/*"]` in root
|
|
42
|
+
`package.json`).
|
|
43
|
+
- [x] Add `packages/cpq/tsconfig.json` (extends root) and
|
|
44
|
+
`packages/cpq/tsconfig.build.json`.
|
|
45
|
+
- [x] Add `packages/cpq/build.mjs` (esbuild → `dist/`, mirrors
|
|
46
|
+
`@open-mercato/core/build.mjs` — only `.js` emit, no `.d.ts`).
|
|
47
|
+
Per Open Mercato convention, the package ships `src/` for types
|
|
48
|
+
and `dist/` for runtime — exports map `types → ./src/*.ts`,
|
|
49
|
+
`default → ./dist/*.js`.
|
|
50
|
+
- [x] Move `src/modules/cpq/` → `packages/cpq/src/modules/cpq/` (single
|
|
51
|
+
`git mv` — history preserved, all 136 source files renamed).
|
|
52
|
+
- [x] Update `src/modules.ts` entry to `{ id: 'cpq', from: '@dainamite/cpq' }`.
|
|
53
|
+
- [x] Patch `@open-mercato/cli@0.5.0` to allow the `@dainamite/` prefix in
|
|
54
|
+
`GENERATED_MODULE_SPECIFIER_PREFIXES` (the CLI rejects unknown package
|
|
55
|
+
scopes when emitting `.mercato/generated/`). Patch lives at
|
|
56
|
+
`.yarn/patches/@open-mercato-cli-npm-0.5.0-*.patch`. **Will be
|
|
57
|
+
fixed upstream in the next framework release** — patch can be
|
|
58
|
+
removed at that point.
|
|
59
|
+
- [x] Rewrite cross-module imports in `demo_gix`, `demo_puffin`,
|
|
60
|
+
`demo_tenants`: `'../../cpq/...'` → `'@dainamite/cpq/modules/cpq/...'`
|
|
61
|
+
(26 files). Demo modules now consume CPQ via the public package
|
|
62
|
+
surface — no in-repo coupling left.
|
|
63
|
+
- [x] Extend root `jest.config.cjs` `testMatch` to discover tests under
|
|
64
|
+
`packages/*/src/**/__tests__/`. Without this, the 27 CPQ test files
|
|
65
|
+
moved with `git mv` were silently skipped.
|
|
66
|
+
- [x] `yarn install && yarn workspace @dainamite/cpq build && yarn generate && yarn typecheck && yarn test` — all green (26 suites, 531 tests).
|
|
67
|
+
- [ ] Smoke-test backend: `yarn dev`, list/create offering, run a quote
|
|
68
|
+
wizard, check ARC subscription detail page. **(manual, blocks merge)**
|
|
69
|
+
|
|
70
|
+
### Phase 2 — Audit & lint cross-package coupling (XD-270, 2026-05-09)
|
|
71
|
+
|
|
72
|
+
- [x] Grep for `@ManyToOne`, `@OneToMany`, `@ManyToMany`, `@OneToOne` —
|
|
73
|
+
zero violations (CPQ already uses FK string columns).
|
|
74
|
+
- [x] Grep for cross-module imports (`@/modules/<x>`, `src/modules/<x>`,
|
|
75
|
+
relative escapes) — zero violations.
|
|
76
|
+
- [x] Audit deep imports into `@open-mercato/core/modules/<x>` — found
|
|
77
|
+
`auth` and `directory` usages not declared in `metadata.requires`.
|
|
78
|
+
Fix: extended [`packages/cpq/src/modules/cpq/index.ts`](src/modules/cpq/index.ts)
|
|
79
|
+
`requires` to `['auth', 'directory', 'catalog', 'sales', 'customers', 'dictionaries']`.
|
|
80
|
+
- [x] Audit external deps used by package — found `bcryptjs` imported in
|
|
81
|
+
`lib/seeds/tenant-provisioning.ts` but missing from `peerDependencies`.
|
|
82
|
+
Fix: added `bcryptjs ^3.0.0` to `peerDependencies`. Also added
|
|
83
|
+
`lucide-react ^0.400.0` (used by sidebar icons in `backend/**/page.meta.ts`).
|
|
84
|
+
- [x] Add guard test:
|
|
85
|
+
[`packages/cpq/src/modules/cpq/__tests__/package-isolation.test.ts`](src/modules/cpq/__tests__/package-isolation.test.ts) —
|
|
86
|
+
static analysis of every `.ts`/`.tsx` in the package, asserting:
|
|
87
|
+
no forbidden cross-module imports; only allowed import prefixes
|
|
88
|
+
(mirroring `peerDependencies`); deep core imports declared in
|
|
89
|
+
`requires`; zero ORM relations; module index loads cleanly. Future
|
|
90
|
+
regressions caught by CI.
|
|
91
|
+
- [x] Removed `@open-mercato/core` patch (nav sidebar order tweak) — was
|
|
92
|
+
cosmetic; not worth the upstream-PR cost.
|
|
93
|
+
|
|
94
|
+
### Phase 3 — Publish (XD-270, 2026-05-09)
|
|
95
|
+
|
|
96
|
+
- [x] Flip `private: true` → `false` in `packages/cpq/package.json`.
|
|
97
|
+
- [x] Install + init `@changesets/cli` — config in `.changeset/config.json`
|
|
98
|
+
with `access: restricted` → later switched to `public`,
|
|
99
|
+
`baseBranch: main`, `dainamite-core` automatically skipped (private workspace).
|
|
100
|
+
- [x] First changeset: `.changeset/initial-release.md` for
|
|
101
|
+
`@dainamite/cpq` initial release.
|
|
102
|
+
- [x] CI release workflow at `.github/workflows/release.yml` —
|
|
103
|
+
on push to `main`, runs `changesets/action@v1` which either opens a
|
|
104
|
+
"Version Packages" PR (when changesets exist) or runs
|
|
105
|
+
`yarn changeset publish` (when version PR is merged).
|
|
106
|
+
- [x] **Switched publish target from GitHub Packages → public npm.js.**
|
|
107
|
+
First publish attempts as `@dainamite/cpq` on GitHub Packages failed
|
|
108
|
+
with `403 Forbidden — installation does not exist`: scope `@dainamite`
|
|
109
|
+
on GitHub belongs to a different (unrelated) "DAInamite" organization
|
|
110
|
+
based in Berlin (dainamite.de). Switching to public npm.js, where the
|
|
111
|
+
`@dainamite` scope is free, lets us keep the brand without renaming
|
|
112
|
+
everything to `@dainamite-technologies/cpq`. Open Mercato itself
|
|
113
|
+
publishes to npm.js (`@open-mercato/core` etc.) so this is also more
|
|
114
|
+
consistent with the upstream ecosystem.
|
|
115
|
+
- [ ] **Manual / first-time setup before merge to main:**
|
|
116
|
+
- **npm.js account + org** — sign up at https://www.npmjs.com/signup
|
|
117
|
+
if needed, then create the `dainamite` org at
|
|
118
|
+
https://www.npmjs.com/org/create (Free plan — public packages only,
|
|
119
|
+
which is fine since CPQ is public).
|
|
120
|
+
- **`NPM_TOKEN` secret** — at https://www.npmjs.com/settings/<your-username>/tokens
|
|
121
|
+
click "Generate New Token" → type `Automation` → Add as repo secret
|
|
122
|
+
named `NPM_TOKEN`.
|
|
123
|
+
- **`RELEASE_TOKEN` PAT** — required for "Version Packages" PRs to
|
|
124
|
+
trigger CI automatically. Without it, you must push an empty
|
|
125
|
+
commit to `changeset-release/main` each release to trigger CI
|
|
126
|
+
(the default `GITHUB_TOKEN` cannot trigger workflows on PRs it
|
|
127
|
+
opens, anti-recursion safety). Setup:
|
|
128
|
+
1. Settings → Developer settings → Personal access tokens →
|
|
129
|
+
Tokens (classic) → Generate new (classic)
|
|
130
|
+
2. Scope: `repo` (full)
|
|
131
|
+
3. Expiration: 90+ days, set a calendar reminder to rotate
|
|
132
|
+
4. Repo settings → Secrets and variables → Actions → New
|
|
133
|
+
repository secret → name `RELEASE_TOKEN`, value the PAT
|
|
134
|
+
- **License decision** — `packages/cpq/package.json` still has
|
|
135
|
+
`"license": "UNLICENSED"` from when the package was private.
|
|
136
|
+
For a public npm package pick a real OSI license (MIT recommended
|
|
137
|
+
for ecosystem consistency with `@open-mercato/*`) and update
|
|
138
|
+
before merging.
|
|
139
|
+
- [ ] **First publish flow** (after this branch lands on main):
|
|
140
|
+
1. Push to main triggers release workflow.
|
|
141
|
+
2. Workflow sees pending changesets and opens a
|
|
142
|
+
"Version Packages" PR that bumps `@dainamite/cpq` and writes
|
|
143
|
+
`packages/cpq/CHANGELOG.md`.
|
|
144
|
+
3. Merge that PR → release workflow re-runs, this time runs
|
|
145
|
+
`yarn changeset publish` → `@dainamite/cpq` lands on
|
|
146
|
+
https://www.npmjs.com/package/@dainamite/cpq.
|
|
147
|
+
- [ ] Update SPEC-001 changelog.
|
|
148
|
+
|
|
149
|
+
> **Note:** SPEC-001 references a future `dainamite-product/` repo as a
|
|
150
|
+
> Phase 4 destination. **That plan is dropped** — `dainamite-core` IS the
|
|
151
|
+
> Dainamite product monorepo, and `packages/cpq/` (plus any future
|
|
152
|
+
> `@dainamite/*` packages) stay here permanently. Other customer apps
|
|
153
|
+
> install from npm.js with no auth setup needed (public package).
|
|
154
|
+
|
|
155
|
+
## Risks (carried from SPEC-001)
|
|
156
|
+
|
|
157
|
+
| Risk | Mitigation |
|
|
158
|
+
|---|---|
|
|
159
|
+
| Cross-package ORM relations leak in | Lint rule + isolation bootstrap test |
|
|
160
|
+
| Two CPQ instances in `node_modules` | `peerDependencies` only, narrow ranges |
|
|
161
|
+
| Breaking schema migration on customer DB | Migrations ship in package, document upgrade in CHANGELOG |
|
|
162
|
+
| Custom @app code drifts from package | Audit every 6 months, promote duplicated features into the package |
|
|
163
|
+
|
|
164
|
+
## Schema / API changelog (track breaking changes here)
|
|
165
|
+
|
|
166
|
+
### 2026-05-04 — XD-250 ARC (Amend / Renew / Cancel)
|
|
167
|
+
|
|
168
|
+
Additive only. Every existing CPQ contract is preserved.
|
|
169
|
+
|
|
170
|
+
**New entities** (require migration):
|
|
171
|
+
- `cpq_quote_target_subscriptions` — junction quote ↔ subscription target
|
|
172
|
+
- `cpq_subscription_change_logs` — append-only audit per ARC operation
|
|
173
|
+
|
|
174
|
+
**New columns on existing entities** (additive, default-safe):
|
|
175
|
+
- `cpq_quote_configurations`: `quote_type` (default `'new'`), `arc_reason_*`,
|
|
176
|
+
`arc_etf_*`, `arc_merge_new_term_*`, `arc_merge_new_sub_*`
|
|
177
|
+
- `cpq_quote_line_configurations`: `target_subscription_id`,
|
|
178
|
+
`source_subscription_item_id`
|
|
179
|
+
- `cpq_inventory_subscriptions`: `current_term_start`,
|
|
180
|
+
`merged_into_subscription_id`, `last_change_log_id`,
|
|
181
|
+
`version` (MikroORM optimistic lock)
|
|
182
|
+
|
|
183
|
+
**Status enum extensions**:
|
|
184
|
+
- `INVENTORY_SUBSCRIPTION_STATUSES` adds `'superseded'` (terminal,
|
|
185
|
+
reachable only via merge-renewal — sources transition there).
|
|
186
|
+
- Subscription items mirror parent via the same `'superseded'` status.
|
|
187
|
+
|
|
188
|
+
**New events** in `cpq.events.ts` (NEW file — first events for the module):
|
|
189
|
+
- `cpq.subscription.amended`
|
|
190
|
+
- `cpq.subscription.renewed`
|
|
191
|
+
- `cpq.subscription.merged`
|
|
192
|
+
- `cpq.subscription.cancelled`
|
|
193
|
+
- `cpq.subscription.superseded`
|
|
194
|
+
|
|
195
|
+
All five include a `proration` payload + ChangeLog id, persistent +
|
|
196
|
+
`clientBroadcast: true`.
|
|
197
|
+
|
|
198
|
+
**New API endpoints** (all under `src/modules/cpq/api/`):
|
|
199
|
+
- `POST /api/cpq/quotes/from-subscription`
|
|
200
|
+
- `GET / POST /api/cpq/quotes/[quoteId]/target-subscriptions`
|
|
201
|
+
- `PATCH / DELETE /api/cpq/quotes/[quoteId]/target-subscriptions/[targetId]`
|
|
202
|
+
- `POST /api/cpq/quotes/[quoteId]/cancel-meta`
|
|
203
|
+
- `POST /api/cpq/quotes/[quoteId]/merge-meta`
|
|
204
|
+
- `PATCH /api/cpq/quotes/[quoteId]` — extended to accept `quoteType`
|
|
205
|
+
(one-way `new → amend|renew|cancel`)
|
|
206
|
+
- `GET /api/cpq/inventory/subscriptions/[subscriptionId]/change-log`
|
|
207
|
+
- `GET /api/cpq/inventory/subscriptions/expiring`
|
|
208
|
+
|
|
209
|
+
**New ACL features** (in `acl.ts`, granted to admin + employee in `setup.ts`):
|
|
210
|
+
- `cpq.arc.amend.manage`
|
|
211
|
+
- `cpq.arc.renew.manage`
|
|
212
|
+
- `cpq.arc.cancel.manage`
|
|
213
|
+
- `cpq.arc.changelog.view`
|
|
214
|
+
- `cpq.inventory.expiring.view`
|
|
215
|
+
|
|
216
|
+
**Service surface additions** (no new top-level services — methods on existing):
|
|
217
|
+
- `cpqInventoryService.applyAmendment / applyRenewal / applyMergeRenewal /
|
|
218
|
+
applyCancel` — idempotent on `(sourceOrderId, subscriptionId)`.
|
|
219
|
+
- `cpqInventoryService.findExpiringSubscriptions / listChangeLog`.
|
|
220
|
+
- `cpqQuotingService.createQuoteFromSubscription / setQuoteType /
|
|
221
|
+
attachTargetSubscription / detachTargetSubscription /
|
|
222
|
+
updateTargetSubscription / setCancelMeta / setMergeMeta /
|
|
223
|
+
validateArcQuote`.
|
|
224
|
+
- `cpqOrderService.activateOrder` — extended to branch on `quoteType` and
|
|
225
|
+
invoke the right `apply*` per attached target. Events emit AFTER commit.
|
|
226
|
+
|
|
227
|
+
**Backwards compatibility**: existing `quote_type='new'` quotes flow through
|
|
228
|
+
the unchanged path. `autoRenew` column on subscriptions is preserved but no
|
|
229
|
+
longer consulted (no scheduler).
|
|
230
|
+
|
|
231
|
+
## Open decisions (per SPEC-001 §Open Questions)
|
|
232
|
+
|
|
233
|
+
- Q3 — Monorepo tooling: yarn workspaces alone vs Nx/Turborepo. Default to
|
|
234
|
+
workspaces; revisit at >15 packages.
|
|
235
|
+
- Q5 — Licensing model (per-package vs per-tenant). **Deferred.**
|
|
236
|
+
- Q6 — Customer repo commit access (us only vs customer too). **Deferred.**
|
package/README.md
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# @dainamite/cpq
|
|
2
|
+
|
|
3
|
+
Dainamite **CPQ** (Configure, Price, Quote) module for Open Mercato —
|
|
4
|
+
configurable product attributes, multi-charge pricing tables, guided
|
|
5
|
+
quoting wizards, customer inventory & subscription tracking, ARC
|
|
6
|
+
(Amend / Renew / Cancel) flows, quote → order → activation pipeline.
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
Requires access to the `@dainamite` GitHub Packages scope. Configure
|
|
11
|
+
`.npmrc` to point `@dainamite` at `https://npm.pkg.github.com`, then:
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
yarn add @dainamite/cpq
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Register the module in your host app's `src/modules.ts`:
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
{ id: 'cpq', from: '@dainamite/cpq' }
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Run framework migrations to install CPQ's schema:
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
yarn mercato db migrate
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## What's inside
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
packages/cpq/src/modules/cpq/
|
|
33
|
+
├── index.ts module metadata + requires
|
|
34
|
+
├── acl.ts ACL feature definitions
|
|
35
|
+
├── ce.ts custom entity / field set declarations
|
|
36
|
+
├── di.ts Awilix DI registrations
|
|
37
|
+
├── setup.ts tenant init, role features, seed data
|
|
38
|
+
├── data/ entities, validators, enrichers
|
|
39
|
+
├── api/ REST routes (resource-style: api/<resource>/route.ts)
|
|
40
|
+
├── backend/ admin UI pages (auto-discovered)
|
|
41
|
+
├── services/ pricing, quoting, validation, product, wizard, inventory, order, bundle
|
|
42
|
+
├── widgets/ injection: customer-inventory, order-cpq-tab, quote-configurator
|
|
43
|
+
├── workflows/ quote → order step components
|
|
44
|
+
├── lib/seeds/ use-case registry API
|
|
45
|
+
└── migrations/ own MikroORM migrations (never hand-write — `yarn mercato db generate`)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The package ships `src/` (for TypeScript consumers' types) and
|
|
49
|
+
`dist/` (esbuild-built JS for runtime). Following the
|
|
50
|
+
[`@open-mercato/core`](https://www.npmjs.com/package/@open-mercato/core)
|
|
51
|
+
build convention, no `.d.ts` is emitted — `exports.types` resolves
|
|
52
|
+
directly to source.
|
|
53
|
+
|
|
54
|
+
## Distribution model (per SPEC-001)
|
|
55
|
+
|
|
56
|
+
- **L1** — Open Mercato core consumed from `@open-mercato/*` (npm).
|
|
57
|
+
- **L2** — Dainamite product modules (this package + sibling
|
|
58
|
+
`@dainamite/*`), published to **GitHub Packages** under the
|
|
59
|
+
`@dainamite` scope.
|
|
60
|
+
- **L3** — `dainamite-core` is the first L3 customer app
|
|
61
|
+
("Demo Netia"); other customer repos consume `@dainamite/cpq` via
|
|
62
|
+
`yarn add` and register it the same way.
|
|
63
|
+
|
|
64
|
+
## Hard rules (carried over from SPEC-001)
|
|
65
|
+
|
|
66
|
+
- **No ORM relations across packages.** Cross-module references are FK
|
|
67
|
+
strings only (`productId: string`), never `@ManyToOne`.
|
|
68
|
+
- **`peerDependencies`, never `dependencies`** for sibling
|
|
69
|
+
`@dainamite/*` and `@open-mercato/*` — guarantees a single shared
|
|
70
|
+
instance in `node_modules`.
|
|
71
|
+
- **Each major bump ships its own migrations** under
|
|
72
|
+
`src/modules/cpq/migrations/`; document upgrade path in
|
|
73
|
+
`CHANGELOG.md`.
|
|
74
|
+
- **No customer-specific logic here.** Tenant-specific overrides live
|
|
75
|
+
in the consuming app under `src/modules/@app/<feature>/`.
|
|
76
|
+
|
|
77
|
+
## Required Open Mercato modules
|
|
78
|
+
|
|
79
|
+
CPQ declares the following in `metadata.requires` and will fail to
|
|
80
|
+
bootstrap if any are missing from the host app's `src/modules.ts`:
|
|
81
|
+
|
|
82
|
+
`auth`, `directory`, `catalog`, `sales`, `customers`, `dictionaries`.
|
|
83
|
+
|
|
84
|
+
## Package isolation guard
|
|
85
|
+
|
|
86
|
+
Static lint test at
|
|
87
|
+
[`src/modules/cpq/__tests__/package-isolation.test.ts`](src/modules/cpq/__tests__/package-isolation.test.ts)
|
|
88
|
+
asserts the package never imports from sibling app modules, never
|
|
89
|
+
deep-imports `@open-mercato/core/modules/<x>` for an undeclared
|
|
90
|
+
dependency, and contains zero cross-entity ORM relations. Runs on
|
|
91
|
+
every CI build — protects future contributors from accidentally
|
|
92
|
+
breaking the package boundary.
|
|
93
|
+
|
|
94
|
+
## Versioning
|
|
95
|
+
|
|
96
|
+
Versioned via [changesets](https://github.com/changesets/changesets).
|
|
97
|
+
Add a changeset alongside any change in `packages/cpq/`:
|
|
98
|
+
|
|
99
|
+
```sh
|
|
100
|
+
yarn changeset
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Bumps and the GitHub Packages publish are handled by the release
|
|
104
|
+
workflow on push to `main`.
|
|
105
|
+
|
|
106
|
+
## License
|
|
107
|
+
|
|
108
|
+
Proprietary — internal Dainamite use only.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const features = [
|
|
2
|
+
{ id: "cpq.quotes.view", title: "View CPQ Quotes", module: "cpq" },
|
|
3
|
+
{ id: "cpq.quotes.manage", title: "Manage CPQ Quotes", module: "cpq" },
|
|
4
|
+
{ id: "cpq.pricing.view", title: "View Pricing", module: "cpq" },
|
|
5
|
+
{ id: "cpq.pricing.manage", title: "Manage Pricing", module: "cpq" },
|
|
6
|
+
{ id: "cpq.products.view", title: "View CPQ Product Config", module: "cpq" },
|
|
7
|
+
{ id: "cpq.products.manage", title: "Manage CPQ Product Config", module: "cpq" },
|
|
8
|
+
{ id: "cpq.specifications.view", title: "View Product Specifications", module: "cpq" },
|
|
9
|
+
{ id: "cpq.specifications.manage", title: "Manage Product Specifications", module: "cpq" },
|
|
10
|
+
{ id: "cpq.offerings.view", title: "View Product Offerings", module: "cpq" },
|
|
11
|
+
{ id: "cpq.offerings.manage", title: "Manage Product Offerings", module: "cpq" },
|
|
12
|
+
{ id: "cpq.wizards.view", title: "View Wizards", module: "cpq" },
|
|
13
|
+
{ id: "cpq.wizards.manage", title: "Manage Wizards", module: "cpq" },
|
|
14
|
+
{ id: "cpq.orders.view", title: "View CPQ Orders", module: "cpq" },
|
|
15
|
+
{ id: "cpq.orders.manage", title: "Manage CPQ Orders", module: "cpq" },
|
|
16
|
+
// XD-250 ARC (Amend / Renew / Cancel)
|
|
17
|
+
{ id: "cpq.arc.amend.manage", title: "Manage Amend Quotes", module: "cpq" },
|
|
18
|
+
{ id: "cpq.arc.renew.manage", title: "Manage Renew Quotes", module: "cpq" },
|
|
19
|
+
{ id: "cpq.arc.cancel.manage", title: "Manage Cancel Quotes", module: "cpq" },
|
|
20
|
+
{ id: "cpq.arc.changelog.view", title: "View Subscription Change History", module: "cpq" }
|
|
21
|
+
// Expiring-subscriptions feature retired — the dedicated /expiring page
|
|
22
|
+
// was replaced by an "Expiring within (days)" filter + saved perspective
|
|
23
|
+
// on the main subscriptions list, which uses `cpq.inventory.view`.
|
|
24
|
+
];
|
|
25
|
+
var acl_default = features;
|
|
26
|
+
export {
|
|
27
|
+
acl_default as default,
|
|
28
|
+
features
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=acl.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/modules/cpq/acl.ts"],
|
|
4
|
+
"sourcesContent": ["export const features = [\n { id: 'cpq.quotes.view', title: 'View CPQ Quotes', module: 'cpq' },\n { id: 'cpq.quotes.manage', title: 'Manage CPQ Quotes', module: 'cpq' },\n { id: 'cpq.pricing.view', title: 'View Pricing', module: 'cpq' },\n { id: 'cpq.pricing.manage', title: 'Manage Pricing', module: 'cpq' },\n { id: 'cpq.products.view', title: 'View CPQ Product Config', module: 'cpq' },\n { id: 'cpq.products.manage', title: 'Manage CPQ Product Config', module: 'cpq' },\n { id: 'cpq.specifications.view', title: 'View Product Specifications', module: 'cpq' },\n { id: 'cpq.specifications.manage', title: 'Manage Product Specifications', module: 'cpq' },\n { id: 'cpq.offerings.view', title: 'View Product Offerings', module: 'cpq' },\n { id: 'cpq.offerings.manage', title: 'Manage Product Offerings', module: 'cpq' },\n { id: 'cpq.wizards.view', title: 'View Wizards', module: 'cpq' },\n { id: 'cpq.wizards.manage', title: 'Manage Wizards', module: 'cpq' },\n { id: 'cpq.orders.view', title: 'View CPQ Orders', module: 'cpq' },\n { id: 'cpq.orders.manage', title: 'Manage CPQ Orders', module: 'cpq' },\n // XD-250 ARC (Amend / Renew / Cancel)\n { id: 'cpq.arc.amend.manage', title: 'Manage Amend Quotes', module: 'cpq' },\n { id: 'cpq.arc.renew.manage', title: 'Manage Renew Quotes', module: 'cpq' },\n { id: 'cpq.arc.cancel.manage', title: 'Manage Cancel Quotes', module: 'cpq' },\n { id: 'cpq.arc.changelog.view', title: 'View Subscription Change History', module: 'cpq' },\n // Expiring-subscriptions feature retired \u2014 the dedicated /expiring page\n // was replaced by an \"Expiring within (days)\" filter + saved perspective\n // on the main subscriptions list, which uses `cpq.inventory.view`.\n]\n\nexport default features\n"],
|
|
5
|
+
"mappings": "AAAO,MAAM,WAAW;AAAA,EACtB,EAAE,IAAI,mBAAmB,OAAO,mBAAmB,QAAQ,MAAM;AAAA,EACjE,EAAE,IAAI,qBAAqB,OAAO,qBAAqB,QAAQ,MAAM;AAAA,EACrE,EAAE,IAAI,oBAAoB,OAAO,gBAAgB,QAAQ,MAAM;AAAA,EAC/D,EAAE,IAAI,sBAAsB,OAAO,kBAAkB,QAAQ,MAAM;AAAA,EACnE,EAAE,IAAI,qBAAqB,OAAO,2BAA2B,QAAQ,MAAM;AAAA,EAC3E,EAAE,IAAI,uBAAuB,OAAO,6BAA6B,QAAQ,MAAM;AAAA,EAC/E,EAAE,IAAI,2BAA2B,OAAO,+BAA+B,QAAQ,MAAM;AAAA,EACrF,EAAE,IAAI,6BAA6B,OAAO,iCAAiC,QAAQ,MAAM;AAAA,EACzF,EAAE,IAAI,sBAAsB,OAAO,0BAA0B,QAAQ,MAAM;AAAA,EAC3E,EAAE,IAAI,wBAAwB,OAAO,4BAA4B,QAAQ,MAAM;AAAA,EAC/E,EAAE,IAAI,oBAAoB,OAAO,gBAAgB,QAAQ,MAAM;AAAA,EAC/D,EAAE,IAAI,sBAAsB,OAAO,kBAAkB,QAAQ,MAAM;AAAA,EACnE,EAAE,IAAI,mBAAmB,OAAO,mBAAmB,QAAQ,MAAM;AAAA,EACjE,EAAE,IAAI,qBAAqB,OAAO,qBAAqB,QAAQ,MAAM;AAAA;AAAA,EAErE,EAAE,IAAI,wBAAwB,OAAO,uBAAuB,QAAQ,MAAM;AAAA,EAC1E,EAAE,IAAI,wBAAwB,OAAO,uBAAuB,QAAQ,MAAM;AAAA,EAC1E,EAAE,IAAI,yBAAyB,OAAO,wBAAwB,QAAQ,MAAM;AAAA,EAC5E,EAAE,IAAI,0BAA0B,OAAO,oCAAoC,QAAQ,MAAM;AAAA;AAAA;AAAA;AAI3F;AAEA,IAAO,cAAQ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { NextResponse } from "next/server";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { OptimisticLockError } from "@mikro-orm/core";
|
|
4
|
+
import { QuotingError } from "../../services/cpqQuotingService.js";
|
|
5
|
+
function handleArcError(err, ctx) {
|
|
6
|
+
if (err instanceof z.ZodError) {
|
|
7
|
+
return NextResponse.json(
|
|
8
|
+
{ error: "Validation error", details: err.issues },
|
|
9
|
+
{ status: 400 }
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
if (err instanceof QuotingError) {
|
|
13
|
+
const body = { error: err.message };
|
|
14
|
+
if (err.cpqStatus) body.cpqStatus = err.cpqStatus;
|
|
15
|
+
if (err.details) Object.assign(body, err.details);
|
|
16
|
+
return NextResponse.json(body, { status: err.status });
|
|
17
|
+
}
|
|
18
|
+
if (err instanceof OptimisticLockError || err && typeof err === "object" && typeof err.constructor?.name === "string" && err.constructor.name === "OptimisticLockError") {
|
|
19
|
+
return NextResponse.json(
|
|
20
|
+
{ error: "Concurrent modification detected", details: err.message },
|
|
21
|
+
{ status: 409 }
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
if (err && typeof err === "object" && "status" in err && typeof err.status === "number") {
|
|
25
|
+
const e = err;
|
|
26
|
+
const message = e.message ?? e.error ?? "Conflict";
|
|
27
|
+
const body = { error: message };
|
|
28
|
+
if (e.details && typeof e.details === "object") Object.assign(body, e.details);
|
|
29
|
+
return NextResponse.json(body, { status: e.status });
|
|
30
|
+
}
|
|
31
|
+
console.error(`[${ctx}]`, err);
|
|
32
|
+
return NextResponse.json({ error: "Internal error" }, { status: 500 });
|
|
33
|
+
}
|
|
34
|
+
export {
|
|
35
|
+
handleArcError
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=handleArcError.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/modules/cpq/api/_helpers/handleArcError.ts"],
|
|
4
|
+
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport { OptimisticLockError } from '@mikro-orm/core'\nimport { QuotingError } from '../../services/cpqQuotingService'\n\n/**\n * Shared error \u2192 JSON-response converter for ARC routes (XD-250).\n *\n * Handles three families:\n * 1. Zod validation errors \u2192 400 with `details` array.\n * 2. Service-layer `QuotingError` (matched both via `instanceof` AND via\n * duck-typing on `name === 'QuotingError'`) \u2192 propagates `err.status`.\n * The duck-typing fallback exists because Turbopack hot-reload can\n * produce two distinct class instances for the same source file\n * across module boundaries, breaking `instanceof` checks at runtime.\n * 3. cpqInventoryService throws plain `{ status, error }` objects \u2192\n * propagate the embedded status.\n * 4. Anything else \u2192 500 + console.error with the route context.\n *\n * Returning the response keeps route handlers terse:\n * `} catch (err) { return handleArcError(err, 'cpq/quotes/from-subscription.POST') }`\n */\nexport function handleArcError(err: unknown, ctx: string): NextResponse {\n if (err instanceof z.ZodError) {\n return NextResponse.json(\n { error: 'Validation error', details: err.issues },\n { status: 400 },\n )\n }\n\n if (err instanceof QuotingError) {\n const body: Record<string, unknown> = { error: err.message }\n if (err.cpqStatus) body.cpqStatus = err.cpqStatus\n if (err.details) Object.assign(body, err.details)\n return NextResponse.json(body, { status: err.status })\n }\n\n // MikroORM optimistic-lock collision on subscription.version (XD-250 spec\n // \u00A7 Risks \"Order activation racing with another mutation\"). Both\n // `instanceof OptimisticLockError` AND constructor-name fallback to\n // survive Turbopack class drift.\n if (\n err instanceof OptimisticLockError ||\n (err &&\n typeof err === 'object' &&\n typeof (err as { constructor?: { name?: string } }).constructor?.name === 'string' &&\n (err as { constructor: { name: string } }).constructor.name === 'OptimisticLockError')\n ) {\n return NextResponse.json(\n { error: 'Concurrent modification detected', details: (err as Error).message },\n { status: 409 },\n )\n }\n\n // Duck-typed QuotingError (Turbopack instanceof drift) and inventory-service\n // plain throw shape `{ status, error }`. Both surface a numeric `status`.\n // Also propagates `details` (object) into response body \u2014 preserves the\n // structured payload (e.g. `existingQuoteId`) that the typed branch above\n // would have surfaced if instanceof had matched.\n if (\n err &&\n typeof err === 'object' &&\n 'status' in err &&\n typeof (err as { status: unknown }).status === 'number'\n ) {\n const e = err as {\n status: number\n message?: string\n error?: string\n name?: string\n details?: Record<string, unknown>\n }\n const message = e.message ?? e.error ?? 'Conflict'\n const body: Record<string, unknown> = { error: message }\n if (e.details && typeof e.details === 'object') Object.assign(body, e.details)\n return NextResponse.json(body, { status: e.status })\n }\n\n console.error(`[${ctx}]`, err)\n return NextResponse.json({ error: 'Internal error' }, { status: 500 })\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS;AAClB,SAAS,2BAA2B;AACpC,SAAS,oBAAoB;AAmBtB,SAAS,eAAe,KAAc,KAA2B;AACtE,MAAI,eAAe,EAAE,UAAU;AAC7B,WAAO,aAAa;AAAA,MAClB,EAAE,OAAO,oBAAoB,SAAS,IAAI,OAAO;AAAA,MACjD,EAAE,QAAQ,IAAI;AAAA,IAChB;AAAA,EACF;AAEA,MAAI,eAAe,cAAc;AAC/B,UAAM,OAAgC,EAAE,OAAO,IAAI,QAAQ;AAC3D,QAAI,IAAI,UAAW,MAAK,YAAY,IAAI;AACxC,QAAI,IAAI,QAAS,QAAO,OAAO,MAAM,IAAI,OAAO;AAChD,WAAO,aAAa,KAAK,MAAM,EAAE,QAAQ,IAAI,OAAO,CAAC;AAAA,EACvD;AAMA,MACE,eAAe,uBACd,OACC,OAAO,QAAQ,YACf,OAAQ,IAA4C,aAAa,SAAS,YACzE,IAA0C,YAAY,SAAS,uBAClE;AACA,WAAO,aAAa;AAAA,MAClB,EAAE,OAAO,oCAAoC,SAAU,IAAc,QAAQ;AAAA,MAC7E,EAAE,QAAQ,IAAI;AAAA,IAChB;AAAA,EACF;AAOA,MACE,OACA,OAAO,QAAQ,YACf,YAAY,OACZ,OAAQ,IAA4B,WAAW,UAC/C;AACA,UAAM,IAAI;AAOV,UAAM,UAAU,EAAE,WAAW,EAAE,SAAS;AACxC,UAAM,OAAgC,EAAE,OAAO,QAAQ;AACvD,QAAI,EAAE,WAAW,OAAO,EAAE,YAAY,SAAU,QAAO,OAAO,MAAM,EAAE,OAAO;AAC7E,WAAO,aAAa,KAAK,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC;AAAA,EACrD;AAEA,UAAQ,MAAM,IAAI,GAAG,KAAK,GAAG;AAC7B,SAAO,aAAa,KAAK,EAAE,OAAO,iBAAiB,GAAG,EAAE,QAAQ,IAAI,CAAC;AACvE;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { NextResponse } from "next/server";
|
|
2
|
+
import { resolveCpqRouteContext } from "../context.js";
|
|
3
|
+
import { DefaultCpqValidationService } from "../../services/cpqValidationService.js";
|
|
4
|
+
const metadata = {
|
|
5
|
+
GET: { requireAuth: true, requireFeatures: ["cpq.quotes.view"] }
|
|
6
|
+
};
|
|
7
|
+
async function GET(req) {
|
|
8
|
+
try {
|
|
9
|
+
const ctx = await resolveCpqRouteContext(req);
|
|
10
|
+
if (!ctx.auth) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
11
|
+
const url = new URL(req.url);
|
|
12
|
+
const productId = url.searchParams.get("productId");
|
|
13
|
+
const attributeCode = url.searchParams.get("attributeCode");
|
|
14
|
+
const configParam = url.searchParams.get("configuration");
|
|
15
|
+
if (!productId || !attributeCode) {
|
|
16
|
+
return NextResponse.json(
|
|
17
|
+
{ error: "productId and attributeCode are required" },
|
|
18
|
+
{ status: 400 }
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
let configuration = {};
|
|
22
|
+
if (configParam) {
|
|
23
|
+
try {
|
|
24
|
+
configuration = JSON.parse(configParam);
|
|
25
|
+
} catch {
|
|
26
|
+
return NextResponse.json({ error: "Invalid configuration JSON" }, { status: 400 });
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const validationService = new DefaultCpqValidationService(ctx.em);
|
|
30
|
+
const options = await validationService.getAttributeOptions({
|
|
31
|
+
productId,
|
|
32
|
+
attributeCode,
|
|
33
|
+
currentConfiguration: configuration,
|
|
34
|
+
tenantId: ctx.tenantId,
|
|
35
|
+
organizationId: ctx.organizationId
|
|
36
|
+
});
|
|
37
|
+
return NextResponse.json({ items: options });
|
|
38
|
+
} catch (err) {
|
|
39
|
+
console.error("[cpq/attribute-options.GET]", err);
|
|
40
|
+
return NextResponse.json({ error: "Internal error" }, { status: 500 });
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export {
|
|
44
|
+
GET,
|
|
45
|
+
metadata
|
|
46
|
+
};
|
|
47
|
+
//# sourceMappingURL=route.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/modules/cpq/api/attribute-options/route.ts"],
|
|
4
|
+
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { resolveCpqRouteContext } from '../context'\nimport { DefaultCpqValidationService } from '../../services/cpqValidationService'\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['cpq.quotes.view'] },\n}\n\n/**\n * Returns resolved options for an attribute, including dynamic options from\n * pricing tables (e.g. cloud_region filtered by cloud_provider).\n * Used by the quoting wizard to render picklists for attributes with\n * dynamicOptionsSource or dependsOn constraints.\n */\nexport async function GET(req: Request) {\n try {\n const ctx = await resolveCpqRouteContext(req)\n if (!ctx.auth) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n\n const url = new URL(req.url)\n const productId = url.searchParams.get('productId')\n const attributeCode = url.searchParams.get('attributeCode')\n const configParam = url.searchParams.get('configuration')\n\n if (!productId || !attributeCode) {\n return NextResponse.json(\n { error: 'productId and attributeCode are required' },\n { status: 400 },\n )\n }\n\n let configuration: Record<string, unknown> = {}\n if (configParam) {\n try {\n configuration = JSON.parse(configParam) as Record<string, unknown>\n } catch {\n return NextResponse.json({ error: 'Invalid configuration JSON' }, { status: 400 })\n }\n }\n\n const validationService = new DefaultCpqValidationService(ctx.em)\n const options = await validationService.getAttributeOptions({\n productId,\n attributeCode,\n currentConfiguration: configuration,\n tenantId: ctx.tenantId,\n organizationId: ctx.organizationId,\n })\n\n return NextResponse.json({ items: options })\n } catch (err) {\n console.error('[cpq/attribute-options.GET]', err)\n return NextResponse.json({ error: 'Internal error' }, { status: 500 })\n }\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,8BAA8B;AACvC,SAAS,mCAAmC;AAErC,MAAM,WAAW;AAAA,EACtB,KAAK,EAAE,aAAa,MAAM,iBAAiB,CAAC,iBAAiB,EAAE;AACjE;AAQA,eAAsB,IAAI,KAAc;AACtC,MAAI;AACF,UAAM,MAAM,MAAM,uBAAuB,GAAG;AAC5C,QAAI,CAAC,IAAI,KAAM,QAAO,aAAa,KAAK,EAAE,OAAO,eAAe,GAAG,EAAE,QAAQ,IAAI,CAAC;AAElF,UAAM,MAAM,IAAI,IAAI,IAAI,GAAG;AAC3B,UAAM,YAAY,IAAI,aAAa,IAAI,WAAW;AAClD,UAAM,gBAAgB,IAAI,aAAa,IAAI,eAAe;AAC1D,UAAM,cAAc,IAAI,aAAa,IAAI,eAAe;AAExD,QAAI,CAAC,aAAa,CAAC,eAAe;AAChC,aAAO,aAAa;AAAA,QAClB,EAAE,OAAO,2CAA2C;AAAA,QACpD,EAAE,QAAQ,IAAI;AAAA,MAChB;AAAA,IACF;AAEA,QAAI,gBAAyC,CAAC;AAC9C,QAAI,aAAa;AACf,UAAI;AACF,wBAAgB,KAAK,MAAM,WAAW;AAAA,MACxC,QAAQ;AACN,eAAO,aAAa,KAAK,EAAE,OAAO,6BAA6B,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,MACnF;AAAA,IACF;AAEA,UAAM,oBAAoB,IAAI,4BAA4B,IAAI,EAAE;AAChE,UAAM,UAAU,MAAM,kBAAkB,oBAAoB;AAAA,MAC1D;AAAA,MACA;AAAA,MACA,sBAAsB;AAAA,MACtB,UAAU,IAAI;AAAA,MACd,gBAAgB,IAAI;AAAA,IACtB,CAAC;AAED,WAAO,aAAa,KAAK,EAAE,OAAO,QAAQ,CAAC;AAAA,EAC7C,SAAS,KAAK;AACZ,YAAQ,MAAM,+BAA+B,GAAG;AAChD,WAAO,aAAa,KAAK,EAAE,OAAO,iBAAiB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACvE;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|