@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.
Files changed (368) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/MIGRATION.md +74 -0
  3. package/dist/modules/cpq/acl.js +1 -0
  4. package/dist/modules/cpq/acl.js.map +2 -2
  5. package/dist/modules/cpq/api/_helpers/adjustmentCommandRoute.js +45 -0
  6. package/dist/modules/cpq/api/_helpers/adjustmentCommandRoute.js.map +7 -0
  7. package/dist/modules/cpq/api/_helpers/quoteMutationGuard.js +23 -0
  8. package/dist/modules/cpq/api/_helpers/quoteMutationGuard.js.map +7 -0
  9. package/dist/modules/cpq/api/_helpers/quoteRouteOpenApi.js +19 -0
  10. package/dist/modules/cpq/api/_helpers/quoteRouteOpenApi.js.map +7 -0
  11. package/dist/modules/cpq/api/orders/[orderId]/route.js +17 -1
  12. package/dist/modules/cpq/api/orders/[orderId]/route.js.map +2 -2
  13. package/dist/modules/cpq/api/orders/route.js +47 -2
  14. package/dist/modules/cpq/api/orders/route.js.map +2 -2
  15. package/dist/modules/cpq/api/quotes/[quoteId]/items/[lineId]/restore/route.js +54 -0
  16. package/dist/modules/cpq/api/quotes/[quoteId]/items/[lineId]/restore/route.js.map +7 -0
  17. package/dist/modules/cpq/api/quotes/[quoteId]/items/[lineId]/route.js +42 -2
  18. package/dist/modules/cpq/api/quotes/[quoteId]/items/[lineId]/route.js.map +2 -2
  19. package/dist/modules/cpq/api/quotes/[quoteId]/items/route.js +27 -2
  20. package/dist/modules/cpq/api/quotes/[quoteId]/items/route.js.map +2 -2
  21. package/dist/modules/cpq/api/quotes/[quoteId]/price-adjustments/[adjustmentId]/route.js +47 -0
  22. package/dist/modules/cpq/api/quotes/[quoteId]/price-adjustments/[adjustmentId]/route.js.map +7 -0
  23. package/dist/modules/cpq/api/quotes/[quoteId]/price-adjustments/preview/route.js +30 -0
  24. package/dist/modules/cpq/api/quotes/[quoteId]/price-adjustments/preview/route.js.map +7 -0
  25. package/dist/modules/cpq/api/quotes/[quoteId]/price-adjustments/route.js +47 -0
  26. package/dist/modules/cpq/api/quotes/[quoteId]/price-adjustments/route.js.map +7 -0
  27. package/dist/modules/cpq/api/quotes/[quoteId]/recalculate/route.js +32 -2
  28. package/dist/modules/cpq/api/quotes/[quoteId]/recalculate/route.js.map +2 -2
  29. package/dist/modules/cpq/api/quotes/[quoteId]/status/route.js +33 -2
  30. package/dist/modules/cpq/api/quotes/[quoteId]/status/route.js.map +2 -2
  31. package/dist/modules/cpq/api/quotes/price/route.js +43 -3
  32. package/dist/modules/cpq/api/quotes/price/route.js.map +2 -2
  33. package/dist/modules/cpq/backend/cpq/inventory/AssetsTable.js +3 -9
  34. package/dist/modules/cpq/backend/cpq/inventory/AssetsTable.js.map +2 -2
  35. package/dist/modules/cpq/backend/cpq/inventory/SubscriptionsTable.js +21 -25
  36. package/dist/modules/cpq/backend/cpq/inventory/SubscriptionsTable.js.map +2 -2
  37. package/dist/modules/cpq/backend/cpq/inventory/assets/[id]/page.js +48 -47
  38. package/dist/modules/cpq/backend/cpq/inventory/assets/[id]/page.js.map +2 -2
  39. package/dist/modules/cpq/backend/cpq/inventory/assets/[id]/page.meta.js +1 -1
  40. package/dist/modules/cpq/backend/cpq/inventory/assets/[id]/page.meta.js.map +2 -2
  41. package/dist/modules/cpq/backend/cpq/inventory/page.meta.js +3 -3
  42. package/dist/modules/cpq/backend/cpq/inventory/page.meta.js.map +2 -2
  43. package/dist/modules/cpq/backend/cpq/inventory/shared.js +37 -2
  44. package/dist/modules/cpq/backend/cpq/inventory/shared.js.map +2 -2
  45. package/dist/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.js +174 -184
  46. package/dist/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.js.map +2 -2
  47. package/dist/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.meta.js +1 -1
  48. package/dist/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.meta.js.map +2 -2
  49. package/dist/modules/cpq/backend/cpq/offerings/[id]/page.js +168 -143
  50. package/dist/modules/cpq/backend/cpq/offerings/[id]/page.js.map +2 -2
  51. package/dist/modules/cpq/backend/cpq/offerings/page.js +36 -34
  52. package/dist/modules/cpq/backend/cpq/offerings/page.js.map +2 -2
  53. package/dist/modules/cpq/backend/cpq/orders/[id]/page.js +140 -280
  54. package/dist/modules/cpq/backend/cpq/orders/[id]/page.js.map +2 -2
  55. package/dist/modules/cpq/backend/cpq/orders/page.js +6 -6
  56. package/dist/modules/cpq/backend/cpq/orders/page.js.map +2 -2
  57. package/dist/modules/cpq/backend/cpq/orders/page.meta.js +1 -1
  58. package/dist/modules/cpq/backend/cpq/orders/page.meta.js.map +1 -1
  59. package/dist/modules/cpq/backend/cpq/price-rules/PriceRuleForm.js +41 -36
  60. package/dist/modules/cpq/backend/cpq/price-rules/PriceRuleForm.js.map +2 -2
  61. package/dist/modules/cpq/backend/cpq/price-rules/[id]/page.js +76 -72
  62. package/dist/modules/cpq/backend/cpq/price-rules/[id]/page.js.map +2 -2
  63. package/dist/modules/cpq/backend/cpq/price-rules/[id]/page.meta.js +1 -1
  64. package/dist/modules/cpq/backend/cpq/price-rules/[id]/page.meta.js.map +2 -2
  65. package/dist/modules/cpq/backend/cpq/price-rules/page.js +18 -15
  66. package/dist/modules/cpq/backend/cpq/price-rules/page.js.map +2 -2
  67. package/dist/modules/cpq/backend/cpq/pricing/[id]/EntriesEditor.js +23 -21
  68. package/dist/modules/cpq/backend/cpq/pricing/[id]/EntriesEditor.js.map +2 -2
  69. package/dist/modules/cpq/backend/cpq/pricing/[id]/ImportPreview.js +22 -50
  70. package/dist/modules/cpq/backend/cpq/pricing/[id]/ImportPreview.js.map +2 -2
  71. package/dist/modules/cpq/backend/cpq/pricing/[id]/page.js +74 -52
  72. package/dist/modules/cpq/backend/cpq/pricing/[id]/page.js.map +2 -2
  73. package/dist/modules/cpq/backend/cpq/pricing/[id]/xlsxImport.js +20 -17
  74. package/dist/modules/cpq/backend/cpq/pricing/[id]/xlsxImport.js.map +2 -2
  75. package/dist/modules/cpq/backend/cpq/pricing/page.js +1 -1
  76. package/dist/modules/cpq/backend/cpq/pricing/page.js.map +2 -2
  77. package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/ArcQuoteConfigurator.js +115 -123
  78. package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/ArcQuoteConfigurator.js.map +2 -2
  79. package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/PriceAdjustmentDialog.js +208 -0
  80. package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/PriceAdjustmentDialog.js.map +7 -0
  81. package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/PriceAdjustmentsPanel.js +79 -0
  82. package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/PriceAdjustmentsPanel.js.map +7 -0
  83. package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/arcLineRemoval.js +53 -0
  84. package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/arcLineRemoval.js.map +7 -0
  85. package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/priceAdjustmentContext.js +107 -0
  86. package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/priceAdjustmentContext.js.map +7 -0
  87. package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/usePriceAdjustments.js +130 -0
  88. package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/usePriceAdjustments.js.map +7 -0
  89. package/dist/modules/cpq/backend/cpq/quotes/[id]/page.js +269 -311
  90. package/dist/modules/cpq/backend/cpq/quotes/[id]/page.js.map +3 -3
  91. package/dist/modules/cpq/backend/cpq/quotes/page.js +23 -19
  92. package/dist/modules/cpq/backend/cpq/quotes/page.js.map +2 -2
  93. package/dist/modules/cpq/backend/cpq/quotes/page.meta.js +1 -1
  94. package/dist/modules/cpq/backend/cpq/quotes/page.meta.js.map +1 -1
  95. package/dist/modules/cpq/backend/cpq/specifications/[id]/DependsOnRulesEditor.js +19 -15
  96. package/dist/modules/cpq/backend/cpq/specifications/[id]/DependsOnRulesEditor.js.map +2 -2
  97. package/dist/modules/cpq/backend/cpq/specifications/[id]/page.js +171 -178
  98. package/dist/modules/cpq/backend/cpq/specifications/[id]/page.js.map +2 -2
  99. package/dist/modules/cpq/backend/cpq/specifications/page.js +2 -2
  100. package/dist/modules/cpq/backend/cpq/specifications/page.js.map +2 -2
  101. package/dist/modules/cpq/backend/cpq/wizards/[definitionCode]/detail/page.js +60 -50
  102. package/dist/modules/cpq/backend/cpq/wizards/[definitionCode]/detail/page.js.map +2 -2
  103. package/dist/modules/cpq/backend/cpq/wizards/[definitionCode]/page.js +22 -18
  104. package/dist/modules/cpq/backend/cpq/wizards/[definitionCode]/page.js.map +2 -2
  105. package/dist/modules/cpq/backend/cpq/wizards/page.js +1 -1
  106. package/dist/modules/cpq/backend/cpq/wizards/page.js.map +2 -2
  107. package/dist/modules/cpq/ce.js +8 -0
  108. package/dist/modules/cpq/ce.js.map +2 -2
  109. package/dist/modules/cpq/cli.js +34 -1
  110. package/dist/modules/cpq/cli.js.map +2 -2
  111. package/dist/modules/cpq/commands/price-adjustments.js +107 -0
  112. package/dist/modules/cpq/commands/price-adjustments.js.map +7 -0
  113. package/dist/modules/cpq/components/ArcLineDiff.js +53 -0
  114. package/dist/modules/cpq/components/ArcLineDiff.js.map +7 -0
  115. package/dist/modules/cpq/components/ChargeBreakdownTable.js +148 -0
  116. package/dist/modules/cpq/components/ChargeBreakdownTable.js.map +7 -0
  117. package/dist/modules/cpq/components/PriceWaterfall.js +68 -0
  118. package/dist/modules/cpq/components/PriceWaterfall.js.map +7 -0
  119. package/dist/modules/cpq/components/PricingSummaryCard.js +112 -0
  120. package/dist/modules/cpq/components/PricingSummaryCard.js.map +7 -0
  121. package/dist/modules/cpq/components/StatusPath.js +5 -3
  122. package/dist/modules/cpq/components/StatusPath.js.map +2 -2
  123. package/dist/modules/cpq/components/useCpqRowActions.js +10 -22
  124. package/dist/modules/cpq/components/useCpqRowActions.js.map +2 -2
  125. package/dist/modules/cpq/components/useGrantedFeatures.js +27 -0
  126. package/dist/modules/cpq/components/useGrantedFeatures.js.map +7 -0
  127. package/dist/modules/cpq/data/entities.js +97 -0
  128. package/dist/modules/cpq/data/entities.js.map +2 -2
  129. package/dist/modules/cpq/data/price-adjustments.js +70 -0
  130. package/dist/modules/cpq/data/price-adjustments.js.map +7 -0
  131. package/dist/modules/cpq/data/validators.js +4 -0
  132. package/dist/modules/cpq/data/validators.js.map +2 -2
  133. package/dist/modules/cpq/di.js +6 -0
  134. package/dist/modules/cpq/di.js.map +2 -2
  135. package/dist/modules/cpq/events.js +47 -0
  136. package/dist/modules/cpq/events.js.map +2 -2
  137. package/dist/modules/cpq/i18n/de.json +1220 -0
  138. package/dist/modules/cpq/i18n/en.json +1220 -0
  139. package/dist/modules/cpq/i18n/es.json +1220 -0
  140. package/dist/modules/cpq/i18n/pl.json +1220 -0
  141. package/dist/modules/cpq/index.js +1 -1
  142. package/dist/modules/cpq/index.js.map +2 -2
  143. package/dist/modules/cpq/lib/auditActor.js +10 -0
  144. package/dist/modules/cpq/lib/auditActor.js.map +7 -0
  145. package/dist/modules/cpq/lib/formatMoney.js +7 -0
  146. package/dist/modules/cpq/lib/formatMoney.js.map +7 -0
  147. package/dist/modules/cpq/lib/priceAdjustmentDefaults.js +60 -0
  148. package/dist/modules/cpq/lib/priceAdjustmentDefaults.js.map +7 -0
  149. package/dist/modules/cpq/lib/priceAdjustmentView.js +169 -0
  150. package/dist/modules/cpq/lib/priceAdjustmentView.js.map +7 -0
  151. package/dist/modules/cpq/lib/quotePermissions.js +13 -0
  152. package/dist/modules/cpq/lib/quotePermissions.js.map +7 -0
  153. package/dist/modules/cpq/lib/quoteSummaryView.js +28 -0
  154. package/dist/modules/cpq/lib/quoteSummaryView.js.map +7 -0
  155. package/dist/modules/cpq/migrations/Migration20261110213052.js +22 -0
  156. package/dist/modules/cpq/migrations/Migration20261110213052.js.map +7 -0
  157. package/dist/modules/cpq/services/arcLineRemoval.js +53 -0
  158. package/dist/modules/cpq/services/arcLineRemoval.js.map +7 -0
  159. package/dist/modules/cpq/services/arcPriceFreeze.js +79 -0
  160. package/dist/modules/cpq/services/arcPriceFreeze.js.map +7 -0
  161. package/dist/modules/cpq/services/cpqOrderService.js +25 -28
  162. package/dist/modules/cpq/services/cpqOrderService.js.map +2 -2
  163. package/dist/modules/cpq/services/cpqPricingService.js +7 -0
  164. package/dist/modules/cpq/services/cpqPricingService.js.map +2 -2
  165. package/dist/modules/cpq/services/cpqQuotingService.js +330 -109
  166. package/dist/modules/cpq/services/cpqQuotingService.js.map +2 -2
  167. package/dist/modules/cpq/services/orderPricingSummary.js +26 -0
  168. package/dist/modules/cpq/services/orderPricingSummary.js.map +7 -0
  169. package/dist/modules/cpq/services/priceAdjustments/adjustmentService.js +264 -0
  170. package/dist/modules/cpq/services/priceAdjustments/adjustmentService.js.map +7 -0
  171. package/dist/modules/cpq/services/priceAdjustments/chargeWaterfall.js +25 -0
  172. package/dist/modules/cpq/services/priceAdjustments/chargeWaterfall.js.map +7 -0
  173. package/dist/modules/cpq/services/priceAdjustments/loadQuoteAdjustments.js +38 -0
  174. package/dist/modules/cpq/services/priceAdjustments/loadQuoteAdjustments.js.map +7 -0
  175. package/dist/modules/cpq/services/priceAdjustments/pricingSnapshot.js +104 -0
  176. package/dist/modules/cpq/services/priceAdjustments/pricingSnapshot.js.map +7 -0
  177. package/dist/modules/cpq/services/priceAdjustments/quoteAdjustmentLifecycle.js +102 -0
  178. package/dist/modules/cpq/services/priceAdjustments/quoteAdjustmentLifecycle.js.map +7 -0
  179. package/dist/modules/cpq/services/priceAdjustments/quotePricingEvents.js +52 -0
  180. package/dist/modules/cpq/services/priceAdjustments/quotePricingEvents.js.map +7 -0
  181. package/dist/modules/cpq/services/priceAdjustments/quotePricingWrite.js +37 -0
  182. package/dist/modules/cpq/services/priceAdjustments/quotePricingWrite.js.map +7 -0
  183. package/dist/modules/cpq/services/priceAdjustments/resolveManualAdjustments.js +107 -0
  184. package/dist/modules/cpq/services/priceAdjustments/resolveManualAdjustments.js.map +7 -0
  185. package/dist/modules/cpq/services/priceAdjustments/storedAdjustmentFailure.js +30 -0
  186. package/dist/modules/cpq/services/priceAdjustments/storedAdjustmentFailure.js.map +7 -0
  187. package/dist/modules/cpq/services/types.js.map +2 -2
  188. package/dist/modules/cpq/setup.js +6 -0
  189. package/dist/modules/cpq/setup.js.map +2 -2
  190. package/dist/modules/cpq/widgets/injection/customer-inventory/widget.client.js +39 -31
  191. package/dist/modules/cpq/widgets/injection/customer-inventory/widget.client.js.map +2 -2
  192. package/dist/modules/cpq/widgets/injection/order-cpq-tab/widget.client.js +13 -5
  193. package/dist/modules/cpq/widgets/injection/order-cpq-tab/widget.client.js.map +2 -2
  194. package/dist/modules/cpq/widgets/injection/quote-configurator/widget.client.js +41 -21
  195. package/dist/modules/cpq/widgets/injection/quote-configurator/widget.client.js.map +2 -2
  196. package/dist/modules/cpq/widgets/injection-table.js +2 -2
  197. package/dist/modules/cpq/widgets/injection-table.js.map +2 -2
  198. package/dist/modules/cpq/workflows/WizardRunner.js +10 -8
  199. package/dist/modules/cpq/workflows/WizardRunner.js.map +2 -2
  200. package/dist/modules/cpq/workflows/WizardTrigger.js +15 -9
  201. package/dist/modules/cpq/workflows/WizardTrigger.js.map +2 -2
  202. package/dist/modules/cpq/workflows/steps/CustomerSelectStep.js +9 -7
  203. package/dist/modules/cpq/workflows/steps/CustomerSelectStep.js.map +2 -2
  204. package/dist/modules/cpq/workflows/steps/InventorySelectStep.js +9 -4
  205. package/dist/modules/cpq/workflows/steps/InventorySelectStep.js.map +2 -2
  206. package/dist/modules/cpq/workflows/steps/ItemListStep.js +16 -19
  207. package/dist/modules/cpq/workflows/steps/ItemListStep.js.map +2 -2
  208. package/dist/modules/cpq/workflows/steps/OfferingSelectStep.js +19 -32
  209. package/dist/modules/cpq/workflows/steps/OfferingSelectStep.js.map +2 -2
  210. package/dist/modules/cpq/workflows/steps/ProductConfigureStep.js +8 -6
  211. package/dist/modules/cpq/workflows/steps/ProductConfigureStep.js.map +2 -2
  212. package/dist/modules/cpq/workflows/steps/ReviewStep.js +32 -30
  213. package/dist/modules/cpq/workflows/steps/ReviewStep.js.map +2 -2
  214. package/dist/modules/cpq/workflows/steps/index.js +12 -0
  215. package/dist/modules/cpq/workflows/steps/index.js.map +2 -2
  216. package/package.json +1 -1
  217. package/src/modules/cpq/__integration__/TC-CPQ-ARC-012.spec.ts +134 -0
  218. package/src/modules/cpq/__tests__/i18n/dictionaries.test.ts +62 -0
  219. package/src/modules/cpq/__tests__/i18n/hardcodedStrings.test.ts +35 -0
  220. package/src/modules/cpq/__tests__/i18n/sourceScan.ts +109 -0
  221. package/src/modules/cpq/acl.ts +1 -0
  222. package/src/modules/cpq/api/__tests__/adjustmentRoutes.test.ts +79 -0
  223. package/src/modules/cpq/api/__tests__/quoteWriteGuards.test.ts +100 -0
  224. package/src/modules/cpq/api/_helpers/__tests__/quoteMutationGuard.test.ts +48 -0
  225. package/src/modules/cpq/api/_helpers/adjustmentCommandRoute.ts +45 -0
  226. package/src/modules/cpq/api/_helpers/quoteMutationGuard.ts +38 -0
  227. package/src/modules/cpq/api/_helpers/quoteRouteOpenApi.ts +19 -0
  228. package/src/modules/cpq/api/orders/[orderId]/route.ts +18 -0
  229. package/src/modules/cpq/api/orders/route.ts +51 -1
  230. package/src/modules/cpq/api/quotes/[quoteId]/items/[lineId]/restore/route.ts +56 -0
  231. package/src/modules/cpq/api/quotes/[quoteId]/items/[lineId]/route.ts +48 -1
  232. package/src/modules/cpq/api/quotes/[quoteId]/items/route.ts +31 -1
  233. package/src/modules/cpq/api/quotes/[quoteId]/price-adjustments/[adjustmentId]/route.ts +39 -0
  234. package/src/modules/cpq/api/quotes/[quoteId]/price-adjustments/preview/route.ts +24 -0
  235. package/src/modules/cpq/api/quotes/[quoteId]/price-adjustments/route.ts +40 -0
  236. package/src/modules/cpq/api/quotes/[quoteId]/recalculate/__tests__/route.test.ts +95 -0
  237. package/src/modules/cpq/api/quotes/[quoteId]/recalculate/route.ts +40 -1
  238. package/src/modules/cpq/api/quotes/[quoteId]/status/__tests__/route.test.ts +74 -0
  239. package/src/modules/cpq/api/quotes/[quoteId]/status/route.ts +37 -1
  240. package/src/modules/cpq/api/quotes/price/__tests__/route.test.ts +37 -0
  241. package/src/modules/cpq/api/quotes/price/route.ts +28 -2
  242. package/src/modules/cpq/backend/cpq/inventory/AssetsTable.tsx +3 -9
  243. package/src/modules/cpq/backend/cpq/inventory/SubscriptionsTable.tsx +22 -26
  244. package/src/modules/cpq/backend/cpq/inventory/assets/[id]/page.meta.ts +1 -1
  245. package/src/modules/cpq/backend/cpq/inventory/assets/[id]/page.tsx +43 -46
  246. package/src/modules/cpq/backend/cpq/inventory/page.meta.ts +3 -3
  247. package/src/modules/cpq/backend/cpq/inventory/shared.tsx +37 -1
  248. package/src/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.meta.ts +1 -1
  249. package/src/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.tsx +164 -120
  250. package/src/modules/cpq/backend/cpq/offerings/[id]/page.tsx +169 -130
  251. package/src/modules/cpq/backend/cpq/offerings/page.tsx +34 -24
  252. package/src/modules/cpq/backend/cpq/orders/[id]/page.tsx +122 -308
  253. package/src/modules/cpq/backend/cpq/orders/page.meta.ts +1 -1
  254. package/src/modules/cpq/backend/cpq/orders/page.tsx +6 -6
  255. package/src/modules/cpq/backend/cpq/price-rules/PriceRuleForm.tsx +48 -34
  256. package/src/modules/cpq/backend/cpq/price-rules/[id]/page.meta.ts +1 -1
  257. package/src/modules/cpq/backend/cpq/price-rules/[id]/page.tsx +76 -70
  258. package/src/modules/cpq/backend/cpq/price-rules/page.tsx +25 -16
  259. package/src/modules/cpq/backend/cpq/pricing/[id]/EntriesEditor.tsx +24 -18
  260. package/src/modules/cpq/backend/cpq/pricing/[id]/ImportPreview.tsx +29 -19
  261. package/src/modules/cpq/backend/cpq/pricing/[id]/page.tsx +95 -47
  262. package/src/modules/cpq/backend/cpq/pricing/[id]/xlsxImport.ts +23 -15
  263. package/src/modules/cpq/backend/cpq/pricing/page.tsx +1 -1
  264. package/src/modules/cpq/backend/cpq/quotes/[id]/_components/ArcQuoteConfigurator.tsx +111 -88
  265. package/src/modules/cpq/backend/cpq/quotes/[id]/_components/PriceAdjustmentDialog.tsx +260 -0
  266. package/src/modules/cpq/backend/cpq/quotes/[id]/_components/PriceAdjustmentsPanel.tsx +124 -0
  267. package/src/modules/cpq/backend/cpq/quotes/[id]/_components/__tests__/PriceAdjustmentsPanel.test.tsx +76 -0
  268. package/src/modules/cpq/backend/cpq/quotes/[id]/_components/arcLineRemoval.tsx +76 -0
  269. package/src/modules/cpq/backend/cpq/quotes/[id]/_components/priceAdjustmentContext.tsx +133 -0
  270. package/src/modules/cpq/backend/cpq/quotes/[id]/_components/usePriceAdjustments.tsx +165 -0
  271. package/src/modules/cpq/backend/cpq/quotes/[id]/page.tsx +304 -348
  272. package/src/modules/cpq/backend/cpq/quotes/page.meta.ts +1 -1
  273. package/src/modules/cpq/backend/cpq/quotes/page.tsx +29 -21
  274. package/src/modules/cpq/backend/cpq/specifications/[id]/DependsOnRulesEditor.tsx +19 -15
  275. package/src/modules/cpq/backend/cpq/specifications/[id]/page.tsx +171 -171
  276. package/src/modules/cpq/backend/cpq/specifications/page.tsx +2 -2
  277. package/src/modules/cpq/backend/cpq/wizards/[definitionCode]/detail/page.tsx +51 -41
  278. package/src/modules/cpq/backend/cpq/wizards/[definitionCode]/page.tsx +17 -13
  279. package/src/modules/cpq/backend/cpq/wizards/page.tsx +1 -1
  280. package/src/modules/cpq/ce.ts +8 -0
  281. package/src/modules/cpq/cli.ts +48 -1
  282. package/src/modules/cpq/commands/__tests__/price-adjustments.test.ts +54 -0
  283. package/src/modules/cpq/commands/price-adjustments.ts +90 -0
  284. package/src/modules/cpq/components/ArcLineDiff.tsx +87 -0
  285. package/src/modules/cpq/components/ChargeBreakdownTable.tsx +203 -0
  286. package/src/modules/cpq/components/PriceWaterfall.tsx +96 -0
  287. package/src/modules/cpq/components/PricingSummaryCard.tsx +128 -0
  288. package/src/modules/cpq/components/StatusPath.tsx +7 -4
  289. package/src/modules/cpq/components/__tests__/PriceWaterfall.test.tsx +38 -0
  290. package/src/modules/cpq/components/useCpqRowActions.tsx +17 -25
  291. package/src/modules/cpq/components/useGrantedFeatures.ts +35 -0
  292. package/src/modules/cpq/data/__tests__/price-adjustment-migration.test.ts +11 -0
  293. package/src/modules/cpq/data/__tests__/price-adjustments.test.ts +26 -0
  294. package/src/modules/cpq/data/entities.ts +83 -0
  295. package/src/modules/cpq/data/price-adjustments.ts +67 -0
  296. package/src/modules/cpq/data/validators.ts +3 -0
  297. package/src/modules/cpq/di.ts +6 -0
  298. package/src/modules/cpq/events.ts +53 -2
  299. package/src/modules/cpq/i18n/de.json +1220 -0
  300. package/src/modules/cpq/i18n/en.json +1220 -0
  301. package/src/modules/cpq/i18n/es.json +1220 -0
  302. package/src/modules/cpq/i18n/pl.json +1220 -0
  303. package/src/modules/cpq/index.ts +1 -1
  304. package/src/modules/cpq/lib/__tests__/auditActor.test.ts +12 -0
  305. package/src/modules/cpq/lib/__tests__/priceAdjustmentDefaults.test.ts +37 -0
  306. package/src/modules/cpq/lib/__tests__/priceAdjustmentView.test.ts +152 -0
  307. package/src/modules/cpq/lib/__tests__/quotePermissions.test.ts +30 -0
  308. package/src/modules/cpq/lib/__tests__/quoteSummaryView.test.ts +56 -0
  309. package/src/modules/cpq/lib/auditActor.ts +13 -0
  310. package/src/modules/cpq/lib/formatMoney.ts +4 -0
  311. package/src/modules/cpq/lib/priceAdjustmentDefaults.ts +36 -0
  312. package/src/modules/cpq/lib/priceAdjustmentView.ts +259 -0
  313. package/src/modules/cpq/lib/quotePermissions.ts +22 -0
  314. package/src/modules/cpq/lib/quoteSummaryView.ts +51 -0
  315. package/src/modules/cpq/migrations/.snapshot-open-mercato.json +3298 -2423
  316. package/src/modules/cpq/migrations/Migration20261110213052.ts +22 -0
  317. package/src/modules/cpq/services/__tests__/_helpers/mockEm.ts +9 -2
  318. package/src/modules/cpq/services/__tests__/adjustmentService.test.ts +183 -0
  319. package/src/modules/cpq/services/__tests__/arcLineRemoval.test.ts +109 -0
  320. package/src/modules/cpq/services/__tests__/arcPriceFreeze.test.ts +141 -0
  321. package/src/modules/cpq/services/__tests__/chargeWaterfall.test.ts +28 -0
  322. package/src/modules/cpq/services/__tests__/cpqOrderService.test.ts +35 -2
  323. package/src/modules/cpq/services/__tests__/cpqPricingService.test.ts +57 -0
  324. package/src/modules/cpq/services/__tests__/cpqQuotingService.arc.test.ts +237 -0
  325. package/src/modules/cpq/services/__tests__/cpqQuotingService.test.ts +58 -3
  326. package/src/modules/cpq/services/__tests__/orderPricingSummary.test.ts +50 -0
  327. package/src/modules/cpq/services/__tests__/pricingSnapshot.test.ts +62 -0
  328. package/src/modules/cpq/services/__tests__/quoteAdjustmentLifecycle.test.ts +35 -0
  329. package/src/modules/cpq/services/__tests__/quoteAdjustmentPricing.test.ts +65 -0
  330. package/src/modules/cpq/services/__tests__/quoteCloneAdjustments.test.ts +45 -0
  331. package/src/modules/cpq/services/__tests__/quoteDetachTargetAdjustments.test.ts +54 -0
  332. package/src/modules/cpq/services/__tests__/quoteEventsService.test.ts +72 -0
  333. package/src/modules/cpq/services/__tests__/quotePricingEvents.test.ts +126 -0
  334. package/src/modules/cpq/services/__tests__/quotePricingIsolation.test.ts +52 -0
  335. package/src/modules/cpq/services/__tests__/quotePricingWrite.test.ts +74 -0
  336. package/src/modules/cpq/services/__tests__/resolveManualAdjustments.test.ts +90 -0
  337. package/src/modules/cpq/services/__tests__/storedAdjustmentFailure.test.ts +9 -0
  338. package/src/modules/cpq/services/arcLineRemoval.ts +87 -0
  339. package/src/modules/cpq/services/arcPriceFreeze.ts +165 -0
  340. package/src/modules/cpq/services/cpqOrderService.ts +22 -28
  341. package/src/modules/cpq/services/cpqPricingService.ts +8 -0
  342. package/src/modules/cpq/services/cpqQuotingService.ts +374 -125
  343. package/src/modules/cpq/services/orderPricingSummary.ts +47 -0
  344. package/src/modules/cpq/services/priceAdjustments/adjustmentService.ts +249 -0
  345. package/src/modules/cpq/services/priceAdjustments/chargeWaterfall.ts +28 -0
  346. package/src/modules/cpq/services/priceAdjustments/loadQuoteAdjustments.ts +25 -0
  347. package/src/modules/cpq/services/priceAdjustments/pricingSnapshot.ts +86 -0
  348. package/src/modules/cpq/services/priceAdjustments/quoteAdjustmentLifecycle.ts +68 -0
  349. package/src/modules/cpq/services/priceAdjustments/quotePricingEvents.ts +94 -0
  350. package/src/modules/cpq/services/priceAdjustments/quotePricingWrite.ts +51 -0
  351. package/src/modules/cpq/services/priceAdjustments/resolveManualAdjustments.ts +116 -0
  352. package/src/modules/cpq/services/priceAdjustments/storedAdjustmentFailure.ts +31 -0
  353. package/src/modules/cpq/services/types.ts +34 -1
  354. package/src/modules/cpq/setup.ts +7 -1
  355. package/src/modules/cpq/widgets/injection/customer-inventory/widget.client.tsx +38 -31
  356. package/src/modules/cpq/widgets/injection/order-cpq-tab/widget.client.tsx +7 -5
  357. package/src/modules/cpq/widgets/injection/quote-configurator/widget.client.tsx +36 -21
  358. package/src/modules/cpq/widgets/injection-table.ts +8 -2
  359. package/src/modules/cpq/workflows/WizardRunner.tsx +8 -5
  360. package/src/modules/cpq/workflows/WizardTrigger.tsx +15 -9
  361. package/src/modules/cpq/workflows/steps/CustomerSelectStep.tsx +11 -7
  362. package/src/modules/cpq/workflows/steps/InventorySelectStep.tsx +9 -5
  363. package/src/modules/cpq/workflows/steps/ItemListStep.tsx +18 -12
  364. package/src/modules/cpq/workflows/steps/OfferingSelectStep.tsx +20 -16
  365. package/src/modules/cpq/workflows/steps/ProductConfigureStep.tsx +8 -6
  366. package/src/modules/cpq/workflows/steps/ReviewStep.tsx +33 -18
  367. package/src/modules/cpq/workflows/steps/index.ts +12 -0
  368. package/src/modules/cpq/workflows/types.ts +4 -0
@@ -2,20 +2,33 @@
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { Alert } from "@open-mercato/ui/primitives/alert";
5
+ import { useT } from "@open-mercato/shared/lib/i18n/context";
5
6
  import { NumberInput as BaseNumberInput } from "../../../../../components/NumberInput.js";
6
- const REASON_CODES = [
7
- { value: "upgrade", label: "Upgrade" },
8
- { value: "downgrade", label: "Downgrade" },
9
- { value: "config-change", label: "Configuration change" },
10
- { value: "price-adjustment", label: "Price adjustment" },
11
- { value: "term-extension", label: "Term extension" },
12
- { value: "term-reduction", label: "Term reduction" },
13
- { value: "consolidation", label: "Consolidation" },
14
- { value: "customer-request", label: "Customer request" },
15
- { value: "non-payment", label: "Non-payment" },
16
- { value: "contract-breach", label: "Contract breach" },
17
- { value: "other", label: "Other" }
18
- ];
7
+ function buildReasonCodes(t) {
8
+ return [
9
+ { value: "upgrade", label: t("cpq.quotes.arc.drawer.reasons.upgrade", "Upgrade") },
10
+ { value: "downgrade", label: t("cpq.quotes.arc.drawer.reasons.downgrade", "Downgrade") },
11
+ { value: "config-change", label: t("cpq.quotes.arc.drawer.reasons.configChange", "Configuration change") },
12
+ { value: "price-adjustment", label: t("cpq.quotes.arc.drawer.reasons.priceAdjustment", "Price adjustment") },
13
+ { value: "term-extension", label: t("cpq.quotes.arc.drawer.reasons.termExtension", "Term extension") },
14
+ { value: "term-reduction", label: t("cpq.quotes.arc.drawer.reasons.termReduction", "Term reduction") },
15
+ { value: "consolidation", label: t("cpq.quotes.arc.drawer.reasons.consolidation", "Consolidation") },
16
+ { value: "customer-request", label: t("cpq.quotes.arc.drawer.reasons.customerRequest", "Customer request") },
17
+ { value: "non-payment", label: t("cpq.quotes.arc.drawer.reasons.nonPayment", "Non-payment") },
18
+ { value: "contract-breach", label: t("cpq.quotes.arc.drawer.reasons.contractBreach", "Contract breach") },
19
+ { value: "other", label: t("cpq.quotes.arc.drawer.reasons.other", "Other") }
20
+ ];
21
+ }
22
+ function arcTypeLabel(t, type) {
23
+ switch (type) {
24
+ case "amend":
25
+ return t("cpq.quotes.type.amend", "amend");
26
+ case "renew":
27
+ return t("cpq.quotes.type.renew", "renew");
28
+ case "cancel":
29
+ return t("cpq.quotes.type.cancel", "cancel");
30
+ }
31
+ }
19
32
  function ArcQuoteConfigurator(props) {
20
33
  const {
21
34
  quoteId,
@@ -28,6 +41,8 @@ function ArcQuoteConfigurator(props) {
28
41
  onClose,
29
42
  onChanged
30
43
  } = props;
44
+ const t = useT();
45
+ const reasonCodes = React.useMemo(() => buildReasonCodes(t), [t]);
31
46
  const [step, setStep] = React.useState(
32
47
  initialType === "new" ? "pick-action" : "pick-targets"
33
48
  );
@@ -38,17 +53,17 @@ function ArcQuoteConfigurator(props) {
38
53
  const [eligibleLoading, setEligibleLoading] = React.useState(false);
39
54
  const [picked, setPicked] = React.useState(() => {
40
55
  const seed = {};
41
- for (const t of initialTargets) {
42
- if (t.subscription) {
43
- seed[t.subscriptionId] = {
44
- id: t.subscriptionId,
45
- code: t.subscription.code,
46
- name: t.subscription.name,
56
+ for (const target of initialTargets) {
57
+ if (target.subscription) {
58
+ seed[target.subscriptionId] = {
59
+ id: target.subscriptionId,
60
+ code: target.subscription.code,
61
+ name: target.subscription.name,
47
62
  status: "active",
48
- currencyCode: t.subscription.currencyCode,
49
- billingCycle: t.subscription.billingCycle,
63
+ currencyCode: target.subscription.currencyCode,
64
+ billingCycle: target.subscription.billingCycle,
50
65
  currentTermEnd: null,
51
- mrcAmount: t.subscription.mrcAmount
66
+ mrcAmount: target.subscription.mrcAmount
52
67
  };
53
68
  }
54
69
  }
@@ -111,14 +126,14 @@ function ArcQuoteConfigurator(props) {
111
126
  });
112
127
  if (!r.ok) {
113
128
  const body = await r.json().catch(() => ({}));
114
- throw new Error(body.error ?? `PATCH /quotes/${quoteId} failed`);
129
+ throw new Error(body.error ?? t("cpq.quotes.arc.drawer.errors.patchFailed", "PATCH /quotes/{quoteId} failed", { quoteId }));
115
130
  }
116
131
  }
117
- const initialTargetIds = new Set(initialTargets.map((t) => t.subscriptionId));
132
+ const initialTargetIds = new Set(initialTargets.map((target) => target.subscriptionId));
118
133
  const pickedIds = new Set(pickedList.map((s) => s.id));
119
- for (const t of initialTargets) {
120
- if (!pickedIds.has(t.subscriptionId)) {
121
- await fetch(`/api/cpq/quotes/${quoteId}/target-subscriptions/${t.id}`, { method: "DELETE" });
134
+ for (const target of initialTargets) {
135
+ if (!pickedIds.has(target.subscriptionId)) {
136
+ await fetch(`/api/cpq/quotes/${quoteId}/target-subscriptions/${target.id}`, { method: "DELETE" });
122
137
  }
123
138
  }
124
139
  for (const s of pickedList) {
@@ -142,7 +157,7 @@ function ArcQuoteConfigurator(props) {
142
157
  });
143
158
  if (!r.ok) {
144
159
  const errBody = await r.json().catch(() => ({}));
145
- throw new Error(errBody.error ?? `POST /target-subscriptions failed`);
160
+ throw new Error(errBody.error ?? t("cpq.quotes.arc.drawer.errors.attachFailed", "POST /target-subscriptions failed"));
146
161
  }
147
162
  }
148
163
  }
@@ -161,7 +176,7 @@ function ArcQuoteConfigurator(props) {
161
176
  });
162
177
  if (!r.ok) {
163
178
  const errBody = await r.json().catch(() => ({}));
164
- throw new Error(errBody.error ?? `POST /merge-meta failed`);
179
+ throw new Error(errBody.error ?? t("cpq.quotes.arc.drawer.errors.mergeMetaFailed", "POST /merge-meta failed"));
165
180
  }
166
181
  }
167
182
  if (type === "cancel") {
@@ -176,7 +191,7 @@ function ArcQuoteConfigurator(props) {
176
191
  });
177
192
  if (!r.ok) {
178
193
  const errBody = await r.json().catch(() => ({}));
179
- throw new Error(errBody.error ?? `POST /cancel-meta failed`);
194
+ throw new Error(errBody.error ?? t("cpq.quotes.arc.drawer.errors.cancelMetaFailed", "POST /cancel-meta failed"));
180
195
  }
181
196
  }
182
197
  await onChanged();
@@ -195,13 +210,14 @@ function ArcQuoteConfigurator(props) {
195
210
  singleTerm,
196
211
  mergeTerm,
197
212
  cancelMeta,
198
- onChanged
213
+ onChanged,
214
+ t
199
215
  ]);
200
216
  return /* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-50 flex", role: "dialog", "aria-modal": "true", children: [
201
217
  /* @__PURE__ */ jsx(
202
218
  "button",
203
219
  {
204
- "aria-label": "Close drawer",
220
+ "aria-label": t("cpq.quotes.arc.drawer.close", "Close drawer"),
205
221
  className: "absolute inset-0 bg-black/40",
206
222
  onClick: onClose
207
223
  }
@@ -209,7 +225,7 @@ function ArcQuoteConfigurator(props) {
209
225
  /* @__PURE__ */ jsxs("div", { className: "ml-auto h-full w-full max-w-2xl bg-card shadow-xl border-l overflow-y-auto relative flex flex-col", children: [
210
226
  /* @__PURE__ */ jsxs("header", { className: "border-b px-5 py-4 flex items-start justify-between", children: [
211
227
  /* @__PURE__ */ jsxs("div", { children: [
212
- /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold", children: "Modify subscription" }),
228
+ /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold", children: t("cpq.quotes.arc.drawer.title", "Modify subscription") }),
213
229
  /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground mt-0.5", children: [
214
230
  customerName ?? customerId.slice(0, 12) + "\u2026",
215
231
  " \u2022 ",
@@ -227,20 +243,20 @@ function ArcQuoteConfigurator(props) {
227
243
  ] }),
228
244
  /* @__PURE__ */ jsxs("div", { className: "flex-1 px-5 py-4 space-y-4", children: [
229
245
  /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
230
- "Step: ",
246
+ t("cpq.quotes.arc.drawer.stepLabel", "Step:"),
247
+ " ",
231
248
  /* @__PURE__ */ jsx("span", { className: "font-mono", children: step }),
232
249
  type && /* @__PURE__ */ jsxs("span", { children: [
233
250
  " \u2022 ",
234
- type
251
+ arcTypeLabel(t, type)
235
252
  ] }),
236
253
  pickedList.length > 0 && /* @__PURE__ */ jsxs("span", { children: [
237
254
  " \u2022 ",
238
- pickedList.length,
239
- " target(s)"
255
+ t("cpq.quotes.arc.drawer.targetCount", "{count} target(s)", { count: pickedList.length })
240
256
  ] })
241
257
  ] }),
242
258
  step === "pick-action" && /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
243
- /* @__PURE__ */ jsx("p", { className: "text-sm", children: "Pick the kind of change you want to make:" }),
259
+ /* @__PURE__ */ jsx("p", { className: "text-sm", children: t("cpq.quotes.arc.drawer.pickAction", "Pick the kind of change you want to make:") }),
244
260
  ["amend", "renew", "cancel"].map((opt) => /* @__PURE__ */ jsxs(
245
261
  "button",
246
262
  {
@@ -250,11 +266,11 @@ function ArcQuoteConfigurator(props) {
250
266
  },
251
267
  className: "block w-full text-left rounded-md border border-input px-4 py-3 hover:bg-muted",
252
268
  children: [
253
- /* @__PURE__ */ jsx("span", { className: "font-medium capitalize", children: opt }),
269
+ /* @__PURE__ */ jsx("span", { className: "font-medium capitalize", children: arcTypeLabel(t, opt) }),
254
270
  /* @__PURE__ */ jsxs("span", { className: "block text-xs text-muted-foreground mt-0.5", children: [
255
- opt === "amend" && "Add or remove items on existing subscriptions. Term untouched.",
256
- opt === "renew" && "Extend term. With 2+ targets, merges them into a new contract.",
257
- opt === "cancel" && "Terminate one or more subscriptions."
271
+ opt === "amend" && t("cpq.quotes.arc.drawer.actions.amendHint", "Add or remove items on existing subscriptions. Term untouched."),
272
+ opt === "renew" && t("cpq.quotes.arc.drawer.actions.renewHint", "Extend term. With 2+ targets, merges them into a new contract."),
273
+ opt === "cancel" && t("cpq.quotes.arc.drawer.actions.cancelHint", "Terminate one or more subscriptions.")
258
274
  ] })
259
275
  ]
260
276
  },
@@ -262,7 +278,7 @@ function ArcQuoteConfigurator(props) {
262
278
  ))
263
279
  ] }),
264
280
  step === "pick-targets" && type && /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
265
- eligibleLoading ? /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: "Loading subscriptions\u2026" }) : eligible.length === 0 ? /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: "No subscriptions for this customer." }) : /* @__PURE__ */ jsx("div", { className: "space-y-1", children: eligible.map((s) => {
281
+ eligibleLoading ? /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: t("cpq.quotes.arc.drawer.loadingSubscriptions", "Loading subscriptions\u2026") }) : eligible.length === 0 ? /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: t("cpq.quotes.arc.drawer.noSubscriptions", "No subscriptions for this customer.") }) : /* @__PURE__ */ jsx("div", { className: "space-y-1", children: eligible.map((s) => {
266
282
  const currencyMismatch = s.currencyCode !== currencyCode;
267
283
  const isPicked = !!picked[s.id];
268
284
  return /* @__PURE__ */ jsxs(
@@ -296,48 +312,39 @@ function ArcQuoteConfigurator(props) {
296
312
  s.status,
297
313
  " \u2022 ",
298
314
  s.billingCycle,
299
- " \u2022 MRC ",
315
+ " \u2022 ",
316
+ t("cpq.lines.mrc", "MRC"),
317
+ " ",
300
318
  s.mrcAmount.toFixed(2),
301
319
  " ",
302
320
  s.currencyCode,
303
- s.currentTermEnd ? ` \u2022 Term ends ${new Date(s.currentTermEnd).toLocaleDateString()}` : ""
321
+ s.currentTermEnd ? " \u2022 " : "",
322
+ s.currentTermEnd ? t("cpq.quotes.arc.drawer.termEnds", "Term ends {date}", { date: new Date(s.currentTermEnd).toLocaleDateString() }) : ""
304
323
  ] }),
305
- currencyMismatch && /* @__PURE__ */ jsxs("div", { className: "text-xs text-status-warning-text mt-1", children: [
306
- "Currency mismatch (",
307
- s.currencyCode,
308
- " vs ",
309
- currencyCode,
310
- ") \u2014 cannot include"
311
- ] })
324
+ currencyMismatch && /* @__PURE__ */ jsx("div", { className: "text-xs text-status-warning-text mt-1", children: t("cpq.quotes.arc.drawer.currencyMismatch", "Currency mismatch ({subscriptionCurrency} vs {quoteCurrency}) \u2014 cannot include", { subscriptionCurrency: s.currencyCode, quoteCurrency: currencyCode }) })
312
325
  ] })
313
326
  ]
314
327
  },
315
328
  s.id
316
329
  );
317
330
  }) }),
318
- !cyclesMatch && /* @__PURE__ */ jsx(Alert, { variant: "warning", className: "text-xs", children: "Picked targets have different billing cycles \u2014 merge requires matching cycles." }),
319
- isMergeRenew && /* @__PURE__ */ jsxs(Alert, { variant: "warning", className: "text-xs", children: [
320
- "Merging ",
321
- pickedList.length,
322
- " contracts into a new one \u2014 sources will be marked Merged at activation."
323
- ] })
331
+ !cyclesMatch && /* @__PURE__ */ jsx(Alert, { variant: "warning", className: "text-xs", children: t("cpq.quotes.arc.drawer.cyclesMismatch", "Picked targets have different billing cycles \u2014 merge requires matching cycles.") }),
332
+ isMergeRenew && /* @__PURE__ */ jsx(Alert, { variant: "warning", className: "text-xs", children: t("cpq.quotes.arc.drawer.mergeWarning", "Merging {count} contracts into a new one \u2014 sources will be marked Merged at activation.", { count: pickedList.length }) })
324
333
  ] }),
325
334
  step === "config-renew" && type === "renew" && !isMergeRenew && /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
326
- /* @__PURE__ */ jsxs("p", { className: "text-sm", children: [
327
- "New contract term for ",
328
- pickedList[0]?.name,
329
- ":"
330
- ] }),
335
+ /* @__PURE__ */ jsx("p", { className: "text-sm", children: t("cpq.quotes.arc.drawer.renew.singleTitle", "New contract term for {name}:", { name: pickedList[0]?.name ?? "" }) }),
331
336
  /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
332
- "Pre-filled with same length as the current term, starting at the current term end. Type a new value in ",
333
- /* @__PURE__ */ jsx("span", { className: "font-medium", children: "Months" }),
334
- " to auto-shift the end date, or edit start/end directly."
337
+ t("cpq.quotes.arc.drawer.renew.singleHintBefore", "Pre-filled with same length as the current term, starting at the current term end. Type a new value in"),
338
+ " ",
339
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: t("cpq.quotes.arc.drawer.fields.months", "Months") }),
340
+ " ",
341
+ t("cpq.quotes.arc.drawer.renew.singleHintAfter", "to auto-shift the end date, or edit start/end directly.")
335
342
  ] }),
336
343
  /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-3", children: [
337
344
  /* @__PURE__ */ jsx(
338
345
  DateInput,
339
346
  {
340
- label: "Start",
347
+ label: t("cpq.quotes.arc.drawer.fields.start", "Start"),
341
348
  value: singleTerm.start,
342
349
  onChange: (v) => {
343
350
  const months = singleTerm.months ? Number(singleTerm.months) : null;
@@ -349,7 +356,7 @@ function ArcQuoteConfigurator(props) {
349
356
  /* @__PURE__ */ jsx(
350
357
  DateInput,
351
358
  {
352
- label: "End",
359
+ label: t("cpq.quotes.arc.drawer.fields.end", "End"),
353
360
  value: singleTerm.end,
354
361
  onChange: (v) => setSingleTerm({ ...singleTerm, end: v })
355
362
  }
@@ -357,7 +364,7 @@ function ArcQuoteConfigurator(props) {
357
364
  /* @__PURE__ */ jsx(
358
365
  NumberInput,
359
366
  {
360
- label: "Months",
367
+ label: t("cpq.quotes.arc.drawer.fields.months", "Months"),
361
368
  value: singleTerm.months,
362
369
  onChange: (v) => {
363
370
  const months = v ? Number(v) : null;
@@ -369,21 +376,19 @@ function ArcQuoteConfigurator(props) {
369
376
  ] })
370
377
  ] }),
371
378
  step === "config-renew" && type === "renew" && isMergeRenew && /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
372
- /* @__PURE__ */ jsxs("p", { className: "text-sm", children: [
373
- "New contract details (merge of ",
374
- pickedList.length,
375
- " subscriptions):"
376
- ] }),
379
+ /* @__PURE__ */ jsx("p", { className: "text-sm", children: t("cpq.quotes.arc.drawer.renew.mergeTitle", "New contract details (merge of {count} subscriptions):", { count: pickedList.length }) }),
377
380
  /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
378
- "Type a value into ",
379
- /* @__PURE__ */ jsx("span", { className: "font-medium", children: "Months" }),
380
- " to auto-fill both dates \u2014 start defaults to today, end is start + months."
381
+ t("cpq.quotes.arc.drawer.renew.mergeHintBefore", "Type a value into"),
382
+ " ",
383
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: t("cpq.quotes.arc.drawer.fields.months", "Months") }),
384
+ " ",
385
+ t("cpq.quotes.arc.drawer.renew.mergeHintAfter", "to auto-fill both dates \u2014 start defaults to today, end is start + months.")
381
386
  ] }),
382
387
  /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-3", children: [
383
388
  /* @__PURE__ */ jsx(
384
389
  DateInput,
385
390
  {
386
- label: "Start",
391
+ label: t("cpq.quotes.arc.drawer.fields.start", "Start"),
387
392
  value: mergeTerm.start,
388
393
  onChange: (v) => {
389
394
  const months = mergeTerm.months ? Number(mergeTerm.months) : null;
@@ -395,7 +400,7 @@ function ArcQuoteConfigurator(props) {
395
400
  /* @__PURE__ */ jsx(
396
401
  DateInput,
397
402
  {
398
- label: "End",
403
+ label: t("cpq.quotes.arc.drawer.fields.end", "End"),
399
404
  value: mergeTerm.end,
400
405
  onChange: (v) => setMergeTerm({ ...mergeTerm, end: v })
401
406
  }
@@ -403,7 +408,7 @@ function ArcQuoteConfigurator(props) {
403
408
  /* @__PURE__ */ jsx(
404
409
  NumberInput,
405
410
  {
406
- label: "Months",
411
+ label: t("cpq.quotes.arc.drawer.fields.months", "Months"),
407
412
  value: mergeTerm.months,
408
413
  onChange: (v) => {
409
414
  const months = v ? Number(v) : null;
@@ -418,7 +423,7 @@ function ArcQuoteConfigurator(props) {
418
423
  /* @__PURE__ */ jsx(
419
424
  TextInput,
420
425
  {
421
- label: "New contract code (optional \u2014 auto-generated if blank)",
426
+ label: t("cpq.quotes.arc.drawer.fields.newCode", "New contract code (optional \u2014 auto-generated if blank)"),
422
427
  value: mergeTerm.code,
423
428
  onChange: (v) => setMergeTerm({ ...mergeTerm, code: v })
424
429
  }
@@ -426,7 +431,7 @@ function ArcQuoteConfigurator(props) {
426
431
  /* @__PURE__ */ jsx(
427
432
  TextInput,
428
433
  {
429
- label: "New contract name (optional)",
434
+ label: t("cpq.quotes.arc.drawer.fields.newName", "New contract name (optional)"),
430
435
  value: mergeTerm.name,
431
436
  onChange: (v) => setMergeTerm({ ...mergeTerm, name: v })
432
437
  }
@@ -434,9 +439,9 @@ function ArcQuoteConfigurator(props) {
434
439
  ] })
435
440
  ] }),
436
441
  step === "config-cancel" && type === "cancel" && /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
437
- /* @__PURE__ */ jsx("p", { className: "text-sm", children: "Reason for cancellation:" }),
442
+ /* @__PURE__ */ jsx("p", { className: "text-sm", children: t("cpq.quotes.arc.drawer.cancel.title", "Reason for cancellation:") }),
438
443
  /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
439
- /* @__PURE__ */ jsx("label", { className: "block text-xs text-muted-foreground", children: "Reason code" }),
444
+ /* @__PURE__ */ jsx("label", { className: "block text-xs text-muted-foreground", children: t("cpq.quotes.arc.drawer.cancel.reasonCode", "Reason code") }),
440
445
  /* @__PURE__ */ jsxs(
441
446
  "select",
442
447
  {
@@ -444,8 +449,8 @@ function ArcQuoteConfigurator(props) {
444
449
  onChange: (e) => setCancelMeta({ ...cancelMeta, reasonCode: e.target.value }),
445
450
  className: "w-full rounded-md border border-input bg-background px-2 py-1.5 text-sm",
446
451
  children: [
447
- /* @__PURE__ */ jsx("option", { value: "", children: "\u2014 pick one \u2014" }),
448
- REASON_CODES.map((r) => /* @__PURE__ */ jsx("option", { value: r.value, children: r.label }, r.value))
452
+ /* @__PURE__ */ jsx("option", { value: "", children: t("cpq.quotes.arc.drawer.cancel.pickOne", "\u2014 pick one \u2014") }),
453
+ reasonCodes.map((r) => /* @__PURE__ */ jsx("option", { value: r.value, children: r.label }, r.value))
449
454
  ]
450
455
  }
451
456
  )
@@ -453,7 +458,7 @@ function ArcQuoteConfigurator(props) {
453
458
  /* @__PURE__ */ jsx(
454
459
  TextInput,
455
460
  {
456
- label: "Free text (optional)",
461
+ label: t("cpq.quotes.arc.drawer.cancel.freeText", "Free text (optional)"),
457
462
  value: cancelMeta.reasonText,
458
463
  onChange: (v) => setCancelMeta({ ...cancelMeta, reasonText: v })
459
464
  }
@@ -462,7 +467,7 @@ function ArcQuoteConfigurator(props) {
462
467
  /* @__PURE__ */ jsx(
463
468
  TextInput,
464
469
  {
465
- label: "ETF amount (optional)",
470
+ label: t("cpq.quotes.arc.drawer.cancel.etfAmount", "ETF amount (optional)"),
466
471
  value: cancelMeta.etfAmount,
467
472
  onChange: (v) => setCancelMeta({ ...cancelMeta, etfAmount: v })
468
473
  }
@@ -470,7 +475,7 @@ function ArcQuoteConfigurator(props) {
470
475
  /* @__PURE__ */ jsx(
471
476
  TextInput,
472
477
  {
473
- label: "ETF currency",
478
+ label: t("cpq.quotes.arc.drawer.cancel.etfCurrency", "ETF currency"),
474
479
  value: cancelMeta.etfCurrency,
475
480
  onChange: (v) => setCancelMeta({ ...cancelMeta, etfCurrency: v })
476
481
  }
@@ -478,47 +483,34 @@ function ArcQuoteConfigurator(props) {
478
483
  ] })
479
484
  ] }),
480
485
  step === "review" && /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
481
- /* @__PURE__ */ jsx("p", { className: "text-sm", children: "Review and submit:" }),
486
+ /* @__PURE__ */ jsx("p", { className: "text-sm", children: t("cpq.quotes.arc.drawer.review.title", "Review and submit:") }),
482
487
  /* @__PURE__ */ jsxs("ul", { className: "text-sm space-y-1 list-disc pl-5", children: [
483
- /* @__PURE__ */ jsxs("li", { children: [
484
- "Action: ",
485
- type
486
- ] }),
487
- /* @__PURE__ */ jsxs("li", { children: [
488
- "Targets: ",
489
- pickedList.length
490
- ] }),
488
+ /* @__PURE__ */ jsx("li", { children: t("cpq.quotes.arc.drawer.review.action", "Action: {type}", { type: type ? arcTypeLabel(t, type) : "" }) }),
489
+ /* @__PURE__ */ jsx("li", { children: t("cpq.quotes.arc.drawer.review.targets", "Targets: {count}", { count: pickedList.length }) }),
491
490
  pickedList.map((s) => /* @__PURE__ */ jsxs("li", { className: "text-muted-foreground", children: [
492
491
  s.code,
493
492
  " \u2014 ",
494
493
  s.name
495
494
  ] }, s.id)),
496
- type === "renew" && !isMergeRenew && /* @__PURE__ */ jsxs("li", { children: [
497
- "Term: ",
498
- singleTerm.start,
499
- " \u2192 ",
500
- singleTerm.end,
501
- singleTerm.months ? ` (${singleTerm.months}m)` : ""
502
- ] }),
495
+ type === "renew" && !isMergeRenew && /* @__PURE__ */ jsx("li", { children: singleTerm.months ? t("cpq.quotes.arc.drawer.review.termWithMonths", "Term: {start} \u2192 {end} ({months}m)", { start: singleTerm.start, end: singleTerm.end, months: singleTerm.months }) : t("cpq.quotes.arc.drawer.review.term", "Term: {start} \u2192 {end}", { start: singleTerm.start, end: singleTerm.end }) }),
503
496
  type === "renew" && isMergeRenew && /* @__PURE__ */ jsxs("li", { children: [
504
- "Merge term: ",
505
- mergeTerm.start,
506
- " \u2192 ",
507
- mergeTerm.end,
508
- mergeTerm.code ? ` \u2022 code=${mergeTerm.code}` : "",
509
- mergeTerm.name ? ` \u2022 name=${mergeTerm.name}` : ""
497
+ t("cpq.quotes.arc.drawer.review.mergeTerm", "Merge term: {start} \u2192 {end}", { start: mergeTerm.start, end: mergeTerm.end }),
498
+ mergeTerm.code ? " \u2022 " : "",
499
+ mergeTerm.code ? t("cpq.quotes.arc.drawer.review.mergeCode", "code={code}", { code: mergeTerm.code }) : "",
500
+ mergeTerm.name ? " \u2022 " : "",
501
+ mergeTerm.name ? t("cpq.quotes.arc.drawer.review.mergeName", "name={name}", { name: mergeTerm.name }) : ""
510
502
  ] }),
511
503
  type === "cancel" && /* @__PURE__ */ jsxs("li", { children: [
512
- "Reason: ",
513
- cancelMeta.reasonCode,
514
- cancelMeta.etfAmount ? ` \u2022 ETF ${cancelMeta.etfAmount} ${cancelMeta.etfCurrency}` : ""
504
+ t("cpq.quotes.arc.drawer.review.reason", "Reason: {reason}", { reason: cancelMeta.reasonCode }),
505
+ cancelMeta.etfAmount ? " \u2022 " : "",
506
+ cancelMeta.etfAmount ? t("cpq.quotes.arc.drawer.review.etf", "ETF {amount} {currency}", { amount: cancelMeta.etfAmount, currency: cancelMeta.etfCurrency }) : ""
515
507
  ] })
516
508
  ] }),
517
- /* @__PURE__ */ jsx(Alert, { variant: "warning", className: "text-xs", children: "Submitting locks the quote type. Lines will be edited on the host page after this completes." }),
509
+ /* @__PURE__ */ jsx(Alert, { variant: "warning", className: "text-xs", children: t("cpq.quotes.arc.drawer.review.lockWarning", "Submitting locks the quote type. Lines will be edited on the host page after this completes.") }),
518
510
  submitError && /* @__PURE__ */ jsx(Alert, { variant: "destructive", className: "text-xs", children: submitError })
519
511
  ] }),
520
- step === "submitting" && /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: "Submitting\u2026" }),
521
- step === "done" && /* @__PURE__ */ jsx("div", { className: "text-sm text-status-success-text", children: "Done \u2014 close to return to the quote." })
512
+ step === "submitting" && /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: t("cpq.quotes.arc.drawer.submitting", "Submitting\u2026") }),
513
+ step === "done" && /* @__PURE__ */ jsx("div", { className: "text-sm text-status-success-text", children: t("cpq.quotes.arc.drawer.done", "Done \u2014 close to return to the quote.") })
522
514
  ] }),
523
515
  /* @__PURE__ */ jsxs("footer", { className: "border-t px-5 pt-3 pb-20 flex items-center justify-between", children: [
524
516
  /* @__PURE__ */ jsx(
@@ -538,7 +530,7 @@ function ArcQuoteConfigurator(props) {
538
530
  },
539
531
  disabled: step === "pick-action" || step === "submitting" || step === "done" || step === "pick-targets" && initialType !== "new",
540
532
  className: "text-sm text-muted-foreground hover:text-foreground disabled:opacity-30",
541
- children: "\u2190 Back"
533
+ children: t("cpq.quotes.arc.drawer.back", "\u2190 Back")
542
534
  }
543
535
  ),
544
536
  /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
@@ -547,7 +539,7 @@ function ArcQuoteConfigurator(props) {
547
539
  {
548
540
  onClick: onClose,
549
541
  className: "rounded-md border border-input px-3 py-1.5 text-sm hover:bg-muted",
550
- children: "Cancel"
542
+ children: t("cpq.common.cancel", "Cancel")
551
543
  }
552
544
  ),
553
545
  step === "pick-targets" && /* @__PURE__ */ jsx(
@@ -560,7 +552,7 @@ function ArcQuoteConfigurator(props) {
560
552
  else setStep("review");
561
553
  },
562
554
  className: "rounded-md bg-primary px-3 py-1.5 text-sm text-primary-foreground hover:bg-primary/90 disabled:opacity-50",
563
- children: "Next"
555
+ children: t("cpq.quotes.arc.drawer.next", "Next")
564
556
  }
565
557
  ),
566
558
  (step === "config-renew" || step === "config-cancel") && /* @__PURE__ */ jsx(
@@ -569,7 +561,7 @@ function ArcQuoteConfigurator(props) {
569
561
  disabled: step === "config-renew" && !canProceedFromRenew || step === "config-cancel" && !canProceedFromCancel,
570
562
  onClick: () => setStep("review"),
571
563
  className: "rounded-md bg-primary px-3 py-1.5 text-sm text-primary-foreground hover:bg-primary/90 disabled:opacity-50",
572
- children: "Next"
564
+ children: t("cpq.quotes.arc.drawer.next", "Next")
573
565
  }
574
566
  ),
575
567
  step === "review" && /* @__PURE__ */ jsx(
@@ -578,7 +570,7 @@ function ArcQuoteConfigurator(props) {
578
570
  disabled: !editable,
579
571
  onClick: submit,
580
572
  className: "rounded-md bg-primary px-3 py-1.5 text-sm text-primary-foreground hover:bg-primary/90 disabled:opacity-50",
581
- children: "Submit"
573
+ children: t("cpq.quotes.arc.drawer.submit", "Submit")
582
574
  }
583
575
  ),
584
576
  step === "done" && /* @__PURE__ */ jsx(
@@ -586,7 +578,7 @@ function ArcQuoteConfigurator(props) {
586
578
  {
587
579
  onClick: onClose,
588
580
  className: "rounded-md bg-primary px-3 py-1.5 text-sm text-primary-foreground hover:bg-primary/90",
589
- children: "Close"
581
+ children: t("cpq.quotes.arc.drawer.closeButton", "Close")
590
582
  }
591
583
  )
592
584
  ] })