@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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../src/modules/cpq/backend/cpq/orders/%5Bid%5D/page.tsx"],
4
- "sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { useRouter, useParams } from 'next/navigation'\nimport { ArrowRight, ExternalLink, Play, X } from 'lucide-react'\nimport { Alert } from '@open-mercato/ui/primitives/alert'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Tag } from '@open-mercato/ui/primitives/tag'\nimport { FormHeader } from '@open-mercato/ui/backend/forms'\nimport {\n formatStatusLabel,\n orderCpqStatusMap,\n type OrderCpqStatus,\n} from '../../../../components/statusMaps'\nimport { StatusPath } from '../../../../components/StatusPath'\n\n// \u2500\u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ntype ArcLineSource = {\n subscriptionItemId: string\n name: string\n mrcAmount: number\n nrcAmount: number\n quantity: number\n}\n\ntype TierBreakdownEntry = { tier: number; from: number; to: number; pricePerUnit: number; quantity: number; subtotal: number }\ntype RuleAdjustment = { ruleCode: string; ruleName: string; ruleType: string; value: number; unitPriceBefore: number; unitPriceAfter: number; delta: number }\n\ntype ResolvedCharge = {\n chargeName?: string\n chargeType?: string\n pricingMethod?: 'flat' | 'tiered' | 'per_unit'\n unitPrice?: number\n quantity?: number | null\n totalPrice?: number | null\n note?: string | null\n breakdown?: { tiers: TierBreakdownEntry[] } | null\n adjustments?: RuleAdjustment[] | null\n}\n\ntype OrderLineResult = {\n lineId: string\n offeringId: string | null\n offeringName: string\n offeringType: string | null\n productId: string | null\n specId: string | null\n action: string\n parentLineId: string | null\n quantity: number\n configuration: Record<string, unknown>\n startDate: string | null\n termMonths: number | null\n endDate: string | null\n nrcTotal: number\n mrcTotal: number\n charges: ResolvedCharge[]\n sourceQuoteLineId: string | null\n arcSource: ArcLineSource | null\n}\n\ntype OrderResult = {\n id: string\n orderId: string\n orderNumber: string\n customerId: string\n cpqStatus: string\n sourceQuoteId: string | null\n quoteType: string\n currencyCode: string\n pricingSummary: {\n nrcTotal: number\n mrcTotal: number\n currencyCode: string\n }\n activatedAt: string | null\n createdAt: string\n lines: OrderLineResult[]\n}\n\nconst ARC_BADGE_VARIANTS: Record<string, 'brand' | 'success' | 'error'> = {\n amend: 'brand',\n renew: 'success',\n cancel: 'error',\n}\n\nconst RULE_TYPE_LABELS: Record<string, string> = {\n discount_percent: '% discount',\n discount_absolute: 'fixed discount',\n surcharge_percent: '% surcharge',\n surcharge_absolute: 'fixed surcharge',\n price_override: 'override',\n}\n\nfunction fmtRuleValue(adj: RuleAdjustment, currency?: string): string {\n if (adj.ruleType === 'discount_percent' || adj.ruleType === 'surcharge_percent') return `${adj.value}%`\n if (currency) return fmt(adj.value, currency)\n return String(adj.value)\n}\n\n// \u2500\u2500\u2500 Constants \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction fmt(amount: number, currency: string): string {\n return new Intl.NumberFormat('en-US', { style: 'currency', currency }).format(amount)\n}\n\nasync function apiJson<T>(url: string, init?: RequestInit): Promise<T> {\n const res = await fetch(url, init)\n const json = await res.json()\n if (!res.ok) throw new Error(json?.error ?? `Request failed (${res.status})`)\n return json as T\n}\n\n// \u2500\u2500\u2500 Main Page \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport default function CpqOrderDetailPage(props: { params?: { id?: string } }) {\n const router = useRouter()\n const urlParams = useParams()\n const cpqOrderId = (props.params?.id ?? urlParams?.id) as string\n\n const [order, setOrder] = React.useState<OrderResult | null>(null)\n const [loading, setLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [activating, setActivating] = React.useState(false)\n const [expandedLines, setExpandedLines] = React.useState<Set<string>>(new Set())\n const [pricingDetail, setPricingDetail] = React.useState<{ lineIdx: number; chargeIdx: number } | null>(null)\n const [customerName, setCustomerName] = React.useState<string | null>(null)\n const [linkedSubscriptions, setLinkedSubscriptions] = React.useState<Array<{\n id: string\n name: string\n code: string\n status: string\n }>>([])\n\n // Find every subscription this order touches. NEW orders write\n // `sourceOrderId` on the freshly-created subscription, so a\n // `?sourceOrderId=\u2026` filter is enough there. ARC orders (amend /\n // renew / cancel) mutate existing subscriptions in place \u2014 the\n // subscription's `sourceOrderId` stays pinned to the original\n // order, so we also resolve targets via the source quote.\n const fetchLinkedSubscriptions = React.useCallback(\n async (orderConfigId: string, sourceQuoteId: string | null) => {\n const byOrderId = fetch(\n `/api/cpq/inventory/subscriptions?sourceOrderId=${orderConfigId}&pageSize=10`,\n )\n .then((r) => (r.ok ? r.json() : null))\n .then((d) => (d?.items ?? (Array.isArray(d) ? d : [])) as Array<{ id: string; name: string; code: string; status: string }>)\n .catch(() => [])\n\n const byTargets = sourceQuoteId\n ? fetch(`/api/cpq/quotes/${sourceQuoteId}/target-subscriptions`)\n .then((r) => (r.ok ? r.json() : null))\n .then(async (d) => {\n const targets: Array<{ subscriptionId: string }> = d?.items ?? []\n const fetched = await Promise.all(\n targets.map((t) =>\n fetch(`/api/cpq/inventory/subscriptions?id=${t.subscriptionId}`)\n .then((r) => (r.ok ? r.json() : null))\n .catch(() => null),\n ),\n )\n return fetched.filter(Boolean) as Array<{ id: string; name: string; code: string; status: string }>\n })\n .catch(() => [] as Array<{ id: string; name: string; code: string; status: string }>)\n : Promise.resolve([] as Array<{ id: string; name: string; code: string; status: string }>)\n\n const [a, b] = await Promise.all([byOrderId, byTargets])\n // Dedupe by id \u2014 a single subscription may appear in both lists\n // (e.g. a NEW order that was later amended into the same sub).\n const seen = new Set<string>()\n const merged: Array<{ id: string; name: string; code: string; status: string }> = []\n for (const sub of [...a, ...b]) {\n if (!sub || seen.has(sub.id)) continue\n seen.add(sub.id)\n merged.push({ id: sub.id, name: sub.name, code: sub.code, status: sub.status })\n }\n setLinkedSubscriptions(merged)\n },\n [],\n )\n\n React.useEffect(() => {\n let cancelled = false\n async function load() {\n try {\n const result = await apiJson<OrderResult>(`/api/cpq/orders/${cpqOrderId}`)\n if (!cancelled) {\n setOrder(result)\n fetch(`/api/customers/companies?id=${result.customerId}&pageSize=1`)\n .then((r) => r.json())\n .then((data) => {\n const items = data.items ?? data ?? []\n const c = items[0]\n if (c && !cancelled) setCustomerName(c.display_name || c.displayName || c.name || null)\n })\n .catch(() => {})\n if (result.cpqStatus === 'active' || result.cpqStatus === 'fulfilled') {\n void fetchLinkedSubscriptions(result.id, result.sourceQuoteId)\n }\n }\n } catch (err) {\n if (!cancelled) setError((err as Error).message)\n } finally {\n if (!cancelled) setLoading(false)\n }\n }\n load()\n return () => { cancelled = true }\n }, [cpqOrderId, fetchLinkedSubscriptions])\n\n const activateOrder = async () => {\n if (!order) return\n try {\n setActivating(true)\n setError(null)\n const result = await apiJson<OrderResult>(`/api/cpq/orders/${order.id}/activate`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({}),\n })\n setOrder(result)\n void fetchLinkedSubscriptions(result.id, result.sourceQuoteId)\n } catch (err) {\n setError((err as Error).message)\n } finally {\n setActivating(false)\n }\n }\n\n const cancelOrder = async () => {\n if (!order) return\n try {\n setError(null)\n const result = await apiJson<OrderResult>(`/api/cpq/orders/${order.id}/status`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ targetStatus: 'cancelled' }),\n })\n setOrder(result)\n } catch (err) {\n setError((err as Error).message)\n }\n }\n\n const toggleLine = (id: string) => {\n setExpandedLines((prev) => { const n = new Set(prev); n.has(id) ? n.delete(id) : n.add(id); return n })\n }\n\n // \u2500\u2500\u2500 Render: loading / error \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n if (loading) {\n return (\n <div className=\"flex items-center gap-2 py-12 justify-center text-sm text-muted-foreground\">\n <Spinner /> Loading\u2026\n </div>\n )\n }\n\n if (!order) {\n return (\n <div className=\"space-y-4\">\n <button onClick={() => router.push('/backend/cpq/orders')} className=\"text-sm text-muted-foreground hover:text-foreground\">\u2190 Back to Orders</button>\n {error && <ErrorBanner message={error} />}\n <div className=\"rounded-lg border bg-card p-6 text-center text-sm text-muted-foreground\">Order not found.</div>\n </div>\n )\n }\n\n // \u2500\u2500\u2500 Render: detail \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n const canActivate = order.cpqStatus === 'draft' || order.cpqStatus === 'pending_activation'\n const canCancel = order.cpqStatus === 'draft' || order.cpqStatus === 'pending_activation' || order.cpqStatus === 'active'\n const currency = order.currencyCode\n\n const togglePricingDetail = (lineIdx: number, chargeIdx: number) => {\n setPricingDetail((prev) =>\n prev?.lineIdx === lineIdx && prev?.chargeIdx === chargeIdx ? null : { lineIdx, chargeIdx },\n )\n }\n\n return (\n <div className=\"space-y-6\">\n {/* Header \u2014 standard FormHeader detail mode, mirrors the CPQ quote\n layout so order \u2194 quote stays consistent. Title is just the order\n number; status / ARC / converted tags sit underneath; primary\n actions (Activate, then Cancel) live on the right next to the\n View Sales Order / Source Quote utility links. */}\n <FormHeader\n mode=\"detail\"\n backHref=\"/backend/cpq/orders\"\n backLabel=\"Back to CPQ Orders\"\n entityTypeLabel=\"CPQ Order\"\n title={order.orderNumber || order.orderId.slice(0, 8)}\n statusBadge={\n <div className=\"flex flex-wrap items-center gap-2 pt-1\">\n <Tag variant={orderCpqStatusMap[order.cpqStatus as OrderCpqStatus] ?? 'neutral'} dot>\n {formatStatusLabel(order.cpqStatus)}\n </Tag>\n {order.quoteType && order.quoteType !== 'new' && (\n <Tag variant={ARC_BADGE_VARIANTS[order.quoteType] ?? 'neutral'} className=\"uppercase\">\n {order.quoteType}\n </Tag>\n )}\n </div>\n }\n actionsContent={\n <>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => router.push(`/backend/sales/orders/${order.orderId}`)}\n >\n <ExternalLink className=\"h-3.5 w-3.5\" />\n View Sales Order\n </Button>\n {order.sourceQuoteId && (\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => router.push(`/backend/cpq/quotes/${order.sourceQuoteId}`)}\n >\n Source Quote\n </Button>\n )}\n {canActivate && (\n <Button type=\"button\" onClick={activateOrder} disabled={activating}>\n {activating ? <Spinner /> : <Play className=\"h-4 w-4\" />}\n Activate\n </Button>\n )}\n {canCancel && (\n <Button type=\"button\" variant=\"destructive-outline\" onClick={cancelOrder}>\n <X className=\"h-4 w-4\" />\n Cancel\n </Button>\n )}\n </>\n }\n />\n\n {/* Status path \u2014 visual progress only. Orders advance via the\n dedicated Activate / Cancel buttons because activation has\n backend side effects (subscription / asset creation). */}\n <div className=\"flex items-center gap-3 flex-wrap\">\n <StatusPath\n // Order path is read-only \u2014 activation has backend side effects\n // (subscription / asset creation) so transitions go through the\n // dedicated Activate / Cancel buttons.\n current={order.cpqStatus}\n path={['draft', 'pending_activation', 'active', 'fulfilled']}\n terminals={['cancelled']}\n statusMap={orderCpqStatusMap}\n ariaLabel=\"Order status path\"\n />\n </div>\n\n {error && <ErrorBanner message={error} onDismiss={() => setError(null)} />}\n\n {/* Linked subscriptions \u2014 one card per subscription this order\n touches. NEW orders write one fresh subscription; ARC orders\n (amend / renew / cancel) reach one or more existing\n subscriptions through the source quote's target list. */}\n {linkedSubscriptions.length > 0 && (\n <div className=\"space-y-2\">\n {linkedSubscriptions.map((sub) => (\n <div\n key={sub.id}\n className=\"rounded-lg border bg-card p-4 flex items-center gap-4\"\n >\n <div className=\"flex-1 min-w-0 space-y-1\">\n <div className=\"flex items-center gap-2 flex-wrap\">\n <span className=\"text-[10px] font-medium uppercase tracking-wide text-muted-foreground\">\n Linked Subscription\n </span>\n <Tag\n variant={sub.status === 'active' ? 'success' : 'info'}\n dot\n className=\"text-[10px] px-1.5\"\n >\n {sub.status}\n </Tag>\n </div>\n <div className=\"text-sm font-medium\">\n {sub.name}{' '}\n <span className=\"text-muted-foreground font-mono text-xs\">({sub.code})</span>\n </div>\n {order.activatedAt && (\n <div className=\"text-xs text-muted-foreground\">\n Activated on {new Date(order.activatedAt).toLocaleString()}\n </div>\n )}\n </div>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => router.push(`/backend/cpq/inventory/subscriptions/${sub.id}`)}\n >\n <ArrowRight className=\"h-3.5 w-3.5\" />\n Open\n </Button>\n </div>\n ))}\n </div>\n )}\n\n {/* Meta cards \u2014 secondary reference info, matches the quote layout. */}\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3\">\n <MetaCard label=\"Customer\">\n {customerName ? (\n <span className=\"font-medium\">{customerName}</span>\n ) : (\n <span className=\"font-mono text-xs text-muted-foreground\">\n {order.customerId.slice(0, 8)}\u2026\n </span>\n )}\n </MetaCard>\n <MetaCard label=\"Created\">\n <span className=\"font-medium\">{new Date(order.createdAt).toLocaleDateString()}</span>\n </MetaCard>\n <MetaCard label=\"Currency\">\n <span className=\"font-medium\">{currency}</span>\n </MetaCard>\n </div>\n\n {/* Pricing Summary Card */}\n <div className=\"rounded-lg border bg-card p-4\">\n <h3 className=\"text-sm font-medium mb-3\">Pricing Summary</h3>\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <p className=\"text-xs text-muted-foreground\">Non-Recurring (NRC)</p>\n <p className=\"text-lg font-semibold font-mono\">{fmt(order.pricingSummary.nrcTotal, currency)}</p>\n </div>\n <div>\n <p className=\"text-xs text-muted-foreground\">Monthly Recurring (MRC)</p>\n <p className=\"text-lg font-semibold font-mono\">{fmt(order.pricingSummary.mrcTotal, currency)}</p>\n </div>\n </div>\n </div>\n\n {/* Order Lines */}\n <OrderLineTree\n lines={order.lines}\n currency={currency}\n expandedLines={expandedLines}\n pricingDetail={pricingDetail}\n onToggleLine={toggleLine}\n onTogglePricingDetail={togglePricingDetail}\n />\n </div>\n )\n}\n\nfunction MetaCard({ label, children }: { label: string; children: React.ReactNode }) {\n return (\n <div className=\"rounded-lg border bg-card p-4\">\n <div className=\"text-[10px] font-medium uppercase tracking-wide text-muted-foreground\">\n {label}\n </div>\n <div className=\"mt-1 text-sm\">{children}</div>\n </div>\n )\n}\n\n// \u2500\u2500\u2500 Sub-components \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction OrderLineTree({\n lines,\n currency,\n expandedLines,\n pricingDetail,\n onToggleLine,\n onTogglePricingDetail,\n}: {\n lines: OrderLineResult[]\n currency: string\n expandedLines: Set<string>\n pricingDetail: { lineIdx: number; chargeIdx: number } | null\n onToggleLine: (id: string) => void\n onTogglePricingDetail: (lineIdx: number, chargeIdx: number) => void\n}) {\n const rootLines = lines.filter((l) => !l.parentLineId)\n const childrenByParent = new Map<string, OrderLineResult[]>()\n for (const line of lines) {\n if (line.parentLineId) {\n const arr = childrenByParent.get(line.parentLineId) ?? []\n arr.push(line)\n childrenByParent.set(line.parentLineId, arr)\n }\n }\n\n // Stable index per visible line so the pricing-detail toggle can be\n // keyed by (lineIdx, chargeIdx) the same way the quote page does.\n const indexOf = new Map<string, number>()\n lines.forEach((l, i) => indexOf.set(l.lineId, i))\n\n return (\n <div>\n <h3 className=\"text-sm font-medium mb-2 px-1\">Line Items ({lines.length})</h3>\n {lines.length === 0 ? (\n <div className=\"rounded-lg border bg-card py-8 text-center text-sm text-muted-foreground\">\n No line items.\n </div>\n ) : (\n <div className=\"rounded-lg border bg-card divide-y\">\n {rootLines.map((line) => {\n const isBundle = line.offeringType === 'bundle'\n const children = childrenByParent.get(line.lineId) ?? []\n const isExpanded = expandedLines.has(line.lineId)\n const lineIdx = indexOf.get(line.lineId) ?? 0\n return (\n <div key={line.lineId}>\n <OrderLineRow\n line={line}\n lineIdx={lineIdx}\n currency={currency}\n isExpanded={isExpanded}\n isBundle={isBundle}\n childCount={children.length}\n indent={0}\n pricingDetail={pricingDetail}\n onToggle={() => onToggleLine(line.lineId)}\n onTogglePricingDetail={onTogglePricingDetail}\n />\n {isBundle && isExpanded && children.length > 0 && (\n <div className=\"border-t border-dashed border-brand-violet/30 bg-brand-violet/5\">\n <div className=\"px-6 py-1.5\">\n <span className=\"text-[10px] font-medium text-brand-violet uppercase tracking-wider\">Bundle Components ({children.length})</span>\n </div>\n {children.map((child) => {\n const childIdx = indexOf.get(child.lineId) ?? 0\n return (\n <OrderLineRow\n key={child.lineId}\n line={child}\n lineIdx={childIdx}\n currency={currency}\n isExpanded={expandedLines.has(child.lineId)}\n isBundle={false}\n childCount={0}\n indent={1}\n pricingDetail={pricingDetail}\n onToggle={() => onToggleLine(child.lineId)}\n onTogglePricingDetail={onTogglePricingDetail}\n />\n )\n })}\n </div>\n )}\n </div>\n )\n })}\n </div>\n )}\n </div>\n )\n}\n\nfunction OrderLineRow({ line, lineIdx, currency, isExpanded, isBundle, childCount, indent, pricingDetail, onToggle, onTogglePricingDetail }: {\n line: OrderLineResult; lineIdx: number; currency: string; isExpanded: boolean; isBundle: boolean; childCount: number; indent: number\n pricingDetail: { lineIdx: number; chargeIdx: number } | null\n onToggle: () => void\n onTogglePricingDetail: (lineIdx: number, chargeIdx: number) => void\n}) {\n const paddingLeft = indent > 0 ? `${indent * 2 + 1}rem` : undefined\n\n return (\n <div>\n <div\n className=\"flex items-center gap-3 px-4 py-3 hover:bg-muted/30 transition-colors cursor-pointer\"\n style={paddingLeft ? { paddingLeft } : undefined}\n onClick={onToggle}\n >\n <button className=\"flex h-5 w-5 shrink-0 items-center justify-center rounded text-muted-foreground hover:text-foreground\">\n <svg className={`h-4 w-4 transition-transform ${isExpanded ? 'rotate-90' : ''}`} fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth=\"2\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M8.25 4.5l7.5 7.5-7.5 7.5\" />\n </svg>\n </button>\n\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n {indent > 0 && <span className=\"text-muted-foreground text-xs\">\u2514</span>}\n {isBundle && (\n <Tag variant=\"brand\" className=\"px-1.5 text-xs\">bundle</Tag>\n )}\n <span className=\"font-medium text-sm\">{line.offeringName}</span>\n {line.quantity > 1 && <span className=\"rounded bg-muted px-1.5 py-0.5 text-xs font-medium\">\u00D7{line.quantity}</span>}\n <Tag variant=\"info\" className=\"px-1.5 text-xs\">{line.action}</Tag>\n {isBundle && <span className=\"text-xs text-muted-foreground\">{childCount} component{childCount !== 1 ? 's' : ''}</span>}\n </div>\n </div>\n\n <div className=\"shrink-0 text-right text-xs space-y-0.5\">\n {line.nrcTotal > 0 && <div><span className=\"text-muted-foreground\">NRC </span><span className=\"font-mono font-medium\">{fmt(line.nrcTotal, currency)}</span></div>}\n {line.mrcTotal > 0 && <div><span className=\"text-muted-foreground\">MRC </span><span className=\"font-mono font-medium\">{fmt(line.mrcTotal, currency)}</span></div>}\n </div>\n </div>\n\n {isExpanded && (() => {\n const internalKeys = new Set(['_arcMirroredName', '_arcMirroredFromItemId', 'offeringName'])\n const visibleConfigEntries = Object.entries(line.configuration).filter(\n ([key]) => !internalKeys.has(key),\n )\n const hasConfig = visibleConfigEntries.length > 0\n const hasCharges = line.charges.length > 0\n const hasTerm = !!(line.startDate || line.termMonths || line.endDate)\n const hasArcDiff = !!line.arcSource\n const mirroredFromItemId = (line.configuration?._arcMirroredFromItemId as string | undefined) ?? null\n const isEmpty = !hasConfig && !hasCharges && !hasTerm && !hasArcDiff\n\n return (\n <div\n className=\"border-t bg-muted/10 px-12 py-3 space-y-3\"\n style={paddingLeft ? { paddingLeft: `calc(${paddingLeft} + 2rem)` } : undefined}\n >\n {hasArcDiff && (\n <ArcLineDiff line={line} currency={currency} />\n )}\n {isEmpty ? (\n <div className=\"text-xs text-muted-foreground space-y-1\">\n <div>\n No detailed breakdown for this line.\n {mirroredFromItemId && ' Mirrored from existing subscription item.'}\n </div>\n {(line.nrcTotal > 0 || line.mrcTotal > 0) && (\n <div className=\"flex gap-4\">\n {line.nrcTotal > 0 && (\n <span>NRC <span className=\"font-mono font-medium text-foreground\">{fmt(line.nrcTotal, currency)}</span></span>\n )}\n {line.mrcTotal > 0 && (\n <span>MRC <span className=\"font-mono font-medium text-foreground\">{fmt(line.mrcTotal, currency)}</span></span>\n )}\n </div>\n )}\n </div>\n ) : (\n <>\n {hasConfig && (\n <div>\n <p className=\"text-xs font-medium text-muted-foreground mb-1\">Configuration</p>\n <div className=\"grid grid-cols-2 sm:grid-cols-3 gap-x-4 gap-y-1\">\n {visibleConfigEntries.map(([key, value]) => (\n <div key={key} className=\"text-xs\">\n <span className=\"text-muted-foreground\">{key}: </span>\n <span className=\"font-medium\">{String(value)}</span>\n </div>\n ))}\n </div>\n </div>\n )}\n\n {hasCharges && (\n <div>\n <p className=\"text-xs font-medium text-muted-foreground mb-1\">Charges</p>\n <ChargeBreakdown\n line={line}\n lineIdx={lineIdx}\n currency={currency}\n pricingDetail={pricingDetail}\n onTogglePricingDetail={onTogglePricingDetail}\n />\n </div>\n )}\n\n {hasTerm && (\n <div className=\"flex gap-4 text-xs text-muted-foreground\">\n {line.startDate && <span>Start: {new Date(line.startDate).toLocaleDateString()}</span>}\n {line.termMonths && <span>Term: {line.termMonths}mo</span>}\n {line.endDate && <span>End: {new Date(line.endDate).toLocaleDateString()}</span>}\n </div>\n )}\n </>\n )}\n </div>\n )\n })()}\n </div>\n )\n}\n\n// Charge breakdown table with the waterfall (\"show pricing details\")\n// toggle. Same shape as the quote page so a charge looks identical on\n// both surfaces, including tier-by-tier subtotals and any price-rule\n// adjustments that fired during calculation.\nfunction ChargeBreakdown({ line, lineIdx, currency, pricingDetail, onTogglePricingDetail }: {\n line: OrderLineResult; lineIdx: number; currency: string\n pricingDetail: { lineIdx: number; chargeIdx: number } | null\n onTogglePricingDetail: (lineIdx: number, chargeIdx: number) => void\n}) {\n return (\n <table className=\"w-full text-xs\">\n <thead>\n <tr className=\"text-muted-foreground\">\n <th className=\"text-left py-1 font-medium\">Charge</th>\n <th className=\"text-left py-1 font-medium\">Type</th>\n <th className=\"text-right py-1 font-medium\">Unit Price</th>\n <th className=\"text-right py-1 font-medium\">Qty</th>\n <th className=\"text-right py-1 font-medium\">Total</th>\n <th className=\"w-8\" />\n </tr>\n </thead>\n <tbody>\n {line.charges.map((c, i) => {\n const hasDetail = !!(c.breakdown?.tiers?.length || c.adjustments?.length)\n const isDetailOpen = pricingDetail?.lineIdx === lineIdx && pricingDetail?.chargeIdx === i\n return (\n <React.Fragment key={i}>\n <tr className=\"border-t border-dashed border-border/50\">\n <td className=\"py-1\">{c.chargeName ?? '\u2014'}</td>\n <td className=\"py-1 uppercase\">{c.chargeType ?? '\u2014'}</td>\n <td className=\"py-1 text-right font-mono\">{c.unitPrice != null ? fmt(c.unitPrice, currency) : '\u2014'}</td>\n <td className=\"py-1 text-right font-mono\">{c.quantity ?? '\u2014'}</td>\n <td className=\"py-1 text-right font-mono\">{c.totalPrice != null ? fmt(c.totalPrice, currency) : c.note ?? '\u2014'}</td>\n <td className=\"py-1 text-center\">\n {hasDetail && (\n <button\n onClick={() => onTogglePricingDetail(lineIdx, i)}\n className=\"inline-flex items-center justify-center rounded p-0.5 hover:bg-accent text-muted-foreground hover:text-foreground transition-colors\"\n title=\"Show pricing breakdown\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth={1.5} stroke=\"currentColor\" className=\"w-3.5 h-3.5\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z\" />\n </svg>\n </button>\n )}\n </td>\n </tr>\n {isDetailOpen && (\n <tr>\n <td colSpan={6} className=\"pb-3 pt-1\">\n <div className=\"rounded border bg-background p-3 space-y-3 text-xs\">\n <div className=\"flex items-center justify-between\">\n <span className=\"font-semibold text-sm\">Pricing Details \u2014 {c.chargeName}</span>\n <span className=\"text-muted-foreground\">{c.pricingMethod ?? 'flat'}</span>\n </div>\n\n {c.breakdown?.tiers && c.breakdown.tiers.length > 0 && (\n <div>\n <div className=\"font-medium text-muted-foreground mb-1\">Tier Breakdown</div>\n <table className=\"w-full\">\n <thead>\n <tr className=\"text-muted-foreground\">\n <th className=\"text-left py-0.5 font-medium\">Tier</th>\n <th className=\"text-right py-0.5 font-medium\">Range</th>\n <th className=\"text-right py-0.5 font-medium\">Price/Unit</th>\n <th className=\"text-right py-0.5 font-medium\">Qty</th>\n <th className=\"text-right py-0.5 font-medium\">Subtotal</th>\n </tr>\n </thead>\n <tbody>\n {c.breakdown.tiers.map((t) => (\n <tr key={t.tier} className=\"border-t border-border/30\">\n <td className=\"py-0.5\">{t.tier}</td>\n <td className=\"py-0.5 text-right font-mono\">{t.from}\u2013{t.to}</td>\n <td className=\"py-0.5 text-right font-mono\">{fmt(t.pricePerUnit, currency)}</td>\n <td className=\"py-0.5 text-right font-mono\">{t.quantity}</td>\n <td className=\"py-0.5 text-right font-mono\">{fmt(t.subtotal, currency)}</td>\n </tr>\n ))}\n <tr className=\"border-t font-medium\">\n <td colSpan={4} className=\"py-0.5 text-right\">Tiered Total</td>\n <td className=\"py-0.5 text-right font-mono\">\n {fmt(c.breakdown.tiers.reduce((s, t) => s + t.subtotal, 0), currency)}\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n )}\n\n {c.adjustments && c.adjustments.length > 0 && (\n <div>\n <div className=\"font-medium text-muted-foreground mb-1\">Applied Price Rules</div>\n <table className=\"w-full\">\n <thead>\n <tr className=\"text-muted-foreground\">\n <th className=\"text-left py-0.5 font-medium\">Rule</th>\n <th className=\"text-left py-0.5 font-medium\">Type</th>\n <th className=\"text-right py-0.5 font-medium\">Value</th>\n <th className=\"text-right py-0.5 font-medium\">Before</th>\n <th className=\"text-right py-0.5 font-medium\">After</th>\n <th className=\"text-right py-0.5 font-medium\">Delta</th>\n </tr>\n </thead>\n <tbody>\n {c.adjustments.map((adj, ai) => (\n <tr key={ai} className=\"border-t border-border/30\">\n <td className=\"py-0.5\">{adj.ruleName}</td>\n <td className=\"py-0.5\">{RULE_TYPE_LABELS[adj.ruleType] ?? adj.ruleType}</td>\n <td className=\"py-0.5 text-right font-mono\">{fmtRuleValue(adj, currency)}</td>\n <td className=\"py-0.5 text-right font-mono\">{fmt(adj.unitPriceBefore, currency)}</td>\n <td className=\"py-0.5 text-right font-mono\">{fmt(adj.unitPriceAfter, currency)}</td>\n <td className={`py-0.5 text-right font-mono ${adj.delta < 0 ? 'text-destructive' : adj.delta > 0 ? 'text-status-success-text' : ''}`}>\n {adj.delta > 0 ? '+' : ''}{fmt(adj.delta, currency)}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n\n <div className=\"flex items-center justify-between pt-1 border-t text-sm font-semibold\">\n <span>Final Total</span>\n <span className=\"font-mono\">{c.totalPrice != null ? fmt(c.totalPrice, currency) : '\u2014'}</span>\n </div>\n </div>\n </td>\n </tr>\n )}\n </React.Fragment>\n )\n })}\n </tbody>\n </table>\n )\n}\n\nfunction Spinner() {\n return (\n <svg className=\"h-4 w-4 animate-spin\" viewBox=\"0 0 24 24\" fill=\"none\">\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path className=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z\" />\n </svg>\n )\n}\n\nfunction ErrorBanner({ message, onDismiss }: { message: string; onDismiss?: () => void }) {\n return (\n <Alert variant=\"destructive\" className=\"flex items-start gap-2\">\n <span className=\"flex-1\">{message}</span>\n {onDismiss && (\n <button\n onClick={onDismiss}\n className=\"text-destructive/70 hover:text-destructive text-sm font-bold\"\n aria-label=\"Dismiss\"\n >\n \u00D7\n </button>\n )}\n </Alert>\n )\n}\n\n// XD-250 ARC: side-by-side \"Before / After\" snapshot for a quote / order line\n// that mirrors an existing subscription item. \"Before\" comes from the live\n// CpqInventorySubscriptionItem at render time; \"After\" is what the line will\n// apply on activation. For 'cancel' lines the after column is greyed out.\nfunction ArcLineDiff({ line, currency }: { line: OrderLineResult; currency: string }) {\n const src = line.arcSource\n if (!src) return null\n const isCancel = line.action === 'cancel'\n\n const beforeMrc = src.mrcAmount\n const beforeNrc = src.nrcAmount\n const beforeQty = src.quantity\n const afterMrc = isCancel ? 0 : line.mrcTotal\n const afterNrc = isCancel ? 0 : line.nrcTotal\n const afterQty = isCancel ? 0 : line.quantity\n const mrcDelta = afterMrc - beforeMrc\n const nrcDelta = afterNrc - beforeNrc\n const qtyDelta = afterQty - beforeQty\n\n return (\n <div>\n <p className=\"text-xs font-medium text-muted-foreground mb-1.5\">Change Preview</p>\n <div className=\"rounded border bg-background overflow-hidden\">\n <table className=\"w-full text-xs\">\n <thead className=\"bg-muted/40\">\n <tr className=\"text-muted-foreground\">\n <th className=\"text-left px-3 py-1.5 font-medium\" />\n <th className=\"text-right px-3 py-1.5 font-medium\">Before</th>\n <th className=\"text-right px-3 py-1.5 font-medium\">After</th>\n <th className=\"text-right px-3 py-1.5 font-medium\">\u0394</th>\n </tr>\n </thead>\n <tbody>\n <ArcDiffRow label=\"Quantity\" before={beforeQty} after={afterQty} delta={qtyDelta} currency={null} dimAfter={isCancel} />\n <ArcDiffRow label=\"MRC\" before={beforeMrc} after={afterMrc} delta={mrcDelta} currency={currency} dimAfter={isCancel} />\n <ArcDiffRow label=\"NRC\" before={beforeNrc} after={afterNrc} delta={nrcDelta} currency={currency} dimAfter={isCancel} />\n </tbody>\n </table>\n </div>\n {isCancel && (\n <p className=\"text-xs text-destructive mt-1 italic\">\n Cancellation \u2014 item will be terminated on activation.\n </p>\n )}\n </div>\n )\n}\n\nfunction ArcDiffRow({\n label,\n before,\n after,\n delta,\n currency,\n dimAfter,\n}: {\n label: string\n before: number\n after: number\n delta: number\n currency: string | null\n dimAfter: boolean\n}) {\n const fmtVal = (v: number) => (currency ? fmt(v, currency) : String(v))\n const showDelta = delta !== 0\n return (\n <tr className=\"border-t border-dashed border-border/40\">\n <td className=\"px-3 py-1 text-muted-foreground\">{label}</td>\n <td className=\"px-3 py-1 text-right font-mono\">{fmtVal(before)}</td>\n <td className={`px-3 py-1 text-right font-mono ${dimAfter ? 'text-muted-foreground line-through' : ''}`}>\n {fmtVal(after)}\n </td>\n <td className={`px-3 py-1 text-right font-mono font-medium ${showDelta ? (delta > 0 ? 'text-status-success-text' : 'text-destructive') : 'text-muted-foreground'}`}>\n {showDelta ? `${delta > 0 ? '+' : ''}${fmtVal(delta)}` : '\u2014'}\n </td>\n </tr>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { useRouter, useParams } from 'next/navigation'\nimport { ArrowRight, ExternalLink, Play, X } from 'lucide-react'\nimport { Alert } from '@open-mercato/ui/primitives/alert'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Tag } from '@open-mercato/ui/primitives/tag'\nimport { FormHeader } from '@open-mercato/ui/backend/forms'\nimport {\n formatStatusLabel,\n orderCpqStatusMap,\n type OrderCpqStatus,\n} from '../../../../components/statusMaps'\nimport { StatusPath } from '../../../../components/StatusPath'\nimport { ChargeBreakdownTable, type ChargeRowView } from '../../../../components/ChargeBreakdownTable'\nimport { PricingSummaryCard, type PricingSummaryView } from '../../../../components/PricingSummaryCard'\nimport { ArcLineDiff, LineActionBadge } from '../../../../components/ArcLineDiff'\nimport { arcRecurringDelta } from '../../../../lib/quoteSummaryView'\nimport { isArcCancelledLine } from '../../../../services/arcLineRemoval'\nimport { useT, type TranslateFn } from '@open-mercato/shared/lib/i18n/context'\n\n// \u2500\u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ntype ArcLineSource = {\n subscriptionItemId: string\n name: string\n mrcAmount: number\n nrcAmount: number\n quantity: number\n}\n\ntype TierBreakdownEntry = { tier: number; from: number; to: number; pricePerUnit: number; quantity: number; subtotal: number }\ntype RuleAdjustment = { ruleCode: string; ruleName: string; ruleType: string; value: number; unitPriceBefore: number; unitPriceAfter: number; delta: number; origin?: 'rule' | 'manual'; adjustmentId?: string; reasonCode?: string }\n\ntype ResolvedCharge = {\n chargeName?: string\n chargeType?: string\n pricingMethod?: 'flat' | 'tiered' | 'per_unit'\n unitPrice?: number\n quantity?: number | null\n totalPrice?: number | null\n note?: string | null\n breakdown?: { tiers: TierBreakdownEntry[] } | null\n adjustments?: RuleAdjustment[] | null\n listUnitPrice?: number\n listTotalPrice?: number | null\n standardUnitPrice?: number\n standardTotalPrice?: number | null\n}\n\n/** Order lines carry the quote's stored waterfall verbatim (no recalculation at conversion). */\nfunction toChargeRow(c: ResolvedCharge): ChargeRowView {\n return { ...c, chargeName: c.chargeName ?? '\u2014', chargeType: (c.chargeType ?? 'mrc') as 'nrc' | 'mrc' | 'usage', unitPrice: c.unitPrice ?? 0, totalPrice: c.totalPrice ?? null }\n}\n\ntype OrderLineResult = {\n lineId: string\n offeringId: string | null\n offeringName: string\n offeringType: string | null\n productId: string | null\n specId: string | null\n action: string\n parentLineId: string | null\n quantity: number\n configuration: Record<string, unknown>\n startDate: string | null\n termMonths: number | null\n endDate: string | null\n nrcTotal: number\n mrcTotal: number\n charges: ResolvedCharge[]\n sourceQuoteLineId: string | null\n arcSource: ArcLineSource | null\n}\n\ntype OrderResult = {\n id: string\n orderId: string\n orderNumber: string\n customerId: string\n cpqStatus: string\n sourceQuoteId: string | null\n quoteType: string\n currencyCode: string\n pricingSummary: PricingSummaryView & { currencyCode: string }\n activatedAt: string | null\n createdAt: string\n lines: OrderLineResult[]\n}\n\nconst ARC_BADGE_VARIANTS: Record<string, 'brand' | 'success' | 'error'> = {\n amend: 'brand',\n renew: 'success',\n cancel: 'error',\n}\n\nfunction quoteTypeLabel(t: TranslateFn, quoteType: string): string {\n switch (quoteType) {\n case 'amend':\n return t('cpq.quotes.type.amend', 'amend')\n case 'renew':\n return t('cpq.quotes.type.renew', 'renew')\n case 'cancel':\n return t('cpq.quotes.type.cancel', 'cancel')\n default:\n return quoteType\n }\n}\n\n\n// \u2500\u2500\u2500 Constants \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction fmt(amount: number, currency: string): string {\n return new Intl.NumberFormat('en-US', { style: 'currency', currency }).format(amount)\n}\n\nasync function apiJson<T>(t: TranslateFn, url: string, init?: RequestInit): Promise<T> {\n const res = await fetch(url, init)\n const json = await res.json()\n if (!res.ok) throw new Error(json?.error ?? t('cpq.common.requestFailed', 'Request failed ({status})', { status: res.status }))\n return json as T\n}\n\n// \u2500\u2500\u2500 Main Page \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport default function CpqOrderDetailPage(props: { params?: { id?: string } }) {\n const router = useRouter()\n const t = useT()\n const urlParams = useParams()\n const cpqOrderId = (props.params?.id ?? urlParams?.id) as string\n\n const [order, setOrder] = React.useState<OrderResult | null>(null)\n const [loading, setLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [activating, setActivating] = React.useState(false)\n const [expandedLines, setExpandedLines] = React.useState<Set<string>>(new Set())\n const [pricingDetail, setPricingDetail] = React.useState<{ lineIdx: number; chargeIdx: number } | null>(null)\n const [customerName, setCustomerName] = React.useState<string | null>(null)\n const [linkedSubscriptions, setLinkedSubscriptions] = React.useState<Array<{\n id: string\n name: string\n code: string\n status: string\n }>>([])\n\n // Find every subscription this order touches. NEW orders write\n // `sourceOrderId` on the freshly-created subscription, so a\n // `?sourceOrderId=\u2026` filter is enough there. ARC orders (amend /\n // renew / cancel) mutate existing subscriptions in place \u2014 the\n // subscription's `sourceOrderId` stays pinned to the original\n // order, so we also resolve targets via the source quote.\n const fetchLinkedSubscriptions = React.useCallback(\n async (orderConfigId: string, sourceQuoteId: string | null) => {\n const byOrderId = fetch(\n `/api/cpq/inventory/subscriptions?sourceOrderId=${orderConfigId}&pageSize=10`,\n )\n .then((r) => (r.ok ? r.json() : null))\n .then((d) => (d?.items ?? (Array.isArray(d) ? d : [])) as Array<{ id: string; name: string; code: string; status: string }>)\n .catch(() => [])\n\n const byTargets = sourceQuoteId\n ? fetch(`/api/cpq/quotes/${sourceQuoteId}/target-subscriptions`)\n .then((r) => (r.ok ? r.json() : null))\n .then(async (d) => {\n const targets: Array<{ subscriptionId: string }> = d?.items ?? []\n const fetched = await Promise.all(\n targets.map((target) =>\n fetch(`/api/cpq/inventory/subscriptions?id=${target.subscriptionId}`)\n .then((r) => (r.ok ? r.json() : null))\n .catch(() => null),\n ),\n )\n return fetched.filter(Boolean) as Array<{ id: string; name: string; code: string; status: string }>\n })\n .catch(() => [] as Array<{ id: string; name: string; code: string; status: string }>)\n : Promise.resolve([] as Array<{ id: string; name: string; code: string; status: string }>)\n\n const [a, b] = await Promise.all([byOrderId, byTargets])\n // Dedupe by id \u2014 a single subscription may appear in both lists\n // (e.g. a NEW order that was later amended into the same sub).\n const seen = new Set<string>()\n const merged: Array<{ id: string; name: string; code: string; status: string }> = []\n for (const sub of [...a, ...b]) {\n if (!sub || seen.has(sub.id)) continue\n seen.add(sub.id)\n merged.push({ id: sub.id, name: sub.name, code: sub.code, status: sub.status })\n }\n setLinkedSubscriptions(merged)\n },\n [],\n )\n\n React.useEffect(() => {\n let cancelled = false\n async function load() {\n try {\n const result = await apiJson<OrderResult>(t, `/api/cpq/orders/${cpqOrderId}`)\n if (!cancelled) {\n setOrder(result)\n fetch(`/api/customers/companies?id=${result.customerId}&pageSize=1`)\n .then((r) => r.json())\n .then((data) => {\n const items = data.items ?? data ?? []\n const c = items[0]\n if (c && !cancelled) setCustomerName(c.display_name || c.displayName || c.name || null)\n })\n .catch(() => {})\n if (result.cpqStatus === 'active' || result.cpqStatus === 'fulfilled') {\n void fetchLinkedSubscriptions(result.id, result.sourceQuoteId)\n }\n }\n } catch (err) {\n if (!cancelled) setError((err as Error).message)\n } finally {\n if (!cancelled) setLoading(false)\n }\n }\n load()\n return () => { cancelled = true }\n }, [cpqOrderId, fetchLinkedSubscriptions, t])\n\n const activateOrder = async () => {\n if (!order) return\n try {\n setActivating(true)\n setError(null)\n const result = await apiJson<OrderResult>(t, `/api/cpq/orders/${order.id}/activate`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({}),\n })\n setOrder(result)\n void fetchLinkedSubscriptions(result.id, result.sourceQuoteId)\n } catch (err) {\n setError((err as Error).message)\n } finally {\n setActivating(false)\n }\n }\n\n const cancelOrder = async () => {\n if (!order) return\n try {\n setError(null)\n const result = await apiJson<OrderResult>(t, `/api/cpq/orders/${order.id}/status`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ targetStatus: 'cancelled' }),\n })\n setOrder(result)\n } catch (err) {\n setError((err as Error).message)\n }\n }\n\n const toggleLine = (id: string) => {\n setExpandedLines((prev) => { const n = new Set(prev); n.has(id) ? n.delete(id) : n.add(id); return n })\n }\n\n // \u2500\u2500\u2500 Render: loading / error \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n if (loading) {\n return (\n <div className=\"flex items-center gap-2 py-12 justify-center text-sm text-muted-foreground\">\n <Spinner /> {t('cpq.orders.detail.loading', 'Loading\u2026')}\n </div>\n )\n }\n\n if (!order) {\n return (\n <div className=\"space-y-4\">\n <button onClick={() => router.push('/backend/cpq/orders')} className=\"text-sm text-muted-foreground hover:text-foreground\">{t('cpq.orders.detail.backToOrders', '\u2190 Back to Orders')}</button>\n {error && <ErrorBanner message={error} />}\n <div className=\"rounded-lg border bg-card p-6 text-center text-sm text-muted-foreground\">{t('cpq.orders.detail.notFound', 'Order not found.')}</div>\n </div>\n )\n }\n\n // \u2500\u2500\u2500 Render: detail \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n const canActivate = order.cpqStatus === 'draft' || order.cpqStatus === 'pending_activation'\n const canCancel = order.cpqStatus === 'draft' || order.cpqStatus === 'pending_activation' || order.cpqStatus === 'active'\n const currency = order.currencyCode\n\n const togglePricingDetail = (lineIdx: number, chargeIdx: number) => {\n setPricingDetail((prev) =>\n prev?.lineIdx === lineIdx && prev?.chargeIdx === chargeIdx ? null : { lineIdx, chargeIdx },\n )\n }\n\n return (\n <div className=\"space-y-6\">\n {/* Header \u2014 standard FormHeader detail mode, mirrors the CPQ quote\n layout so order \u2194 quote stays consistent. Title is just the order\n number; status / ARC / converted tags sit underneath; primary\n actions (Activate, then Cancel) live on the right next to the\n View Sales Order / Source Quote utility links. */}\n <FormHeader\n mode=\"detail\"\n backHref=\"/backend/cpq/orders\"\n backLabel={t('cpq.orders.detail.backLabel', 'Back to CPQ Orders')}\n entityTypeLabel={t('cpq.orders.detail.entityType', 'CPQ Order')}\n title={order.orderNumber || order.orderId.slice(0, 8)}\n statusBadge={\n <div className=\"flex flex-wrap items-center gap-2 pt-1\">\n <Tag variant={orderCpqStatusMap[order.cpqStatus as OrderCpqStatus] ?? 'neutral'} dot>\n {formatStatusLabel(order.cpqStatus)}\n </Tag>\n {order.quoteType && order.quoteType !== 'new' && (\n <Tag variant={ARC_BADGE_VARIANTS[order.quoteType] ?? 'neutral'} className=\"uppercase\">\n {quoteTypeLabel(t, order.quoteType)}\n </Tag>\n )}\n </div>\n }\n actionsContent={\n <>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => router.push(`/backend/sales/orders/${order.orderId}`)}\n >\n <ExternalLink className=\"h-3.5 w-3.5\" />\n {t('cpq.orders.detail.viewSalesOrder', 'View Sales Order')}\n </Button>\n {order.sourceQuoteId && (\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => router.push(`/backend/cpq/quotes/${order.sourceQuoteId}`)}\n >\n {t('cpq.orders.detail.sourceQuote', 'Source Quote')}\n </Button>\n )}\n {canActivate && (\n <Button type=\"button\" onClick={activateOrder} disabled={activating}>\n {activating ? <Spinner /> : <Play className=\"h-4 w-4\" />}\n {t('cpq.orders.detail.activate', 'Activate')}\n </Button>\n )}\n {canCancel && (\n <Button type=\"button\" variant=\"destructive-outline\" onClick={cancelOrder}>\n <X className=\"h-4 w-4\" />\n {t('cpq.common.cancel', 'Cancel')}\n </Button>\n )}\n </>\n }\n />\n\n {/* Status path \u2014 visual progress only. Orders advance via the\n dedicated Activate / Cancel buttons because activation has\n backend side effects (subscription / asset creation). */}\n <div className=\"flex items-center gap-3 flex-wrap\">\n <StatusPath\n // Order path is read-only \u2014 activation has backend side effects\n // (subscription / asset creation) so transitions go through the\n // dedicated Activate / Cancel buttons.\n current={order.cpqStatus}\n path={['draft', 'pending_activation', 'active', 'fulfilled']}\n terminals={['cancelled']}\n statusMap={orderCpqStatusMap}\n ariaLabel={t('cpq.orders.detail.statusPath', 'Order status path')}\n />\n </div>\n\n {error && <ErrorBanner message={error} onDismiss={() => setError(null)} />}\n\n {/* Linked subscriptions \u2014 one card per subscription this order\n touches. NEW orders write one fresh subscription; ARC orders\n (amend / renew / cancel) reach one or more existing\n subscriptions through the source quote's target list. */}\n {linkedSubscriptions.length > 0 && (\n <div className=\"space-y-2\">\n {linkedSubscriptions.map((sub) => (\n <div\n key={sub.id}\n className=\"rounded-lg border bg-card p-4 flex items-center gap-4\"\n >\n <div className=\"flex-1 min-w-0 space-y-1\">\n <div className=\"flex items-center gap-2 flex-wrap\">\n <span className=\"text-[10px] font-medium uppercase tracking-wide text-muted-foreground\">\n {t('cpq.orders.detail.linkedSubscription', 'Linked Subscription')}\n </span>\n <Tag\n variant={sub.status === 'active' ? 'success' : 'info'}\n dot\n className=\"text-[10px] px-1.5\"\n >\n {sub.status}\n </Tag>\n </div>\n <div className=\"text-sm font-medium\">\n {sub.name}{' '}\n <span className=\"text-muted-foreground font-mono text-xs\">({sub.code})</span>\n </div>\n {order.activatedAt && (\n <div className=\"text-xs text-muted-foreground\">\n {t('cpq.orders.detail.activatedOn', 'Activated on {date}', { date: new Date(order.activatedAt).toLocaleString() })}\n </div>\n )}\n </div>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => router.push(`/backend/cpq/inventory/subscriptions/${sub.id}`)}\n >\n <ArrowRight className=\"h-3.5 w-3.5\" />\n {t('cpq.orders.actions.open', 'Open')}\n </Button>\n </div>\n ))}\n </div>\n )}\n\n {/* Meta cards \u2014 secondary reference info, matches the quote layout. */}\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3\">\n <MetaCard label={t('cpq.orders.detail.meta.customer', 'Customer')}>\n {customerName ? (\n <span className=\"font-medium\">{customerName}</span>\n ) : (\n <span className=\"font-mono text-xs text-muted-foreground\">\n {order.customerId.slice(0, 8)}\u2026\n </span>\n )}\n </MetaCard>\n <MetaCard label={t('cpq.orders.detail.meta.created', 'Created')}>\n <span className=\"font-medium\">{new Date(order.createdAt).toLocaleDateString()}</span>\n </MetaCard>\n <MetaCard label={t('cpq.orders.detail.meta.currency', 'Currency')}>\n <span className=\"font-medium\">{currency}</span>\n </MetaCard>\n </div>\n\n <PricingSummaryCard\n summary={order.pricingSummary}\n currency={currency}\n arcDelta={order.quoteType === 'amend' || order.quoteType === 'renew'\n ? arcRecurringDelta(order.lines.map((l) => ({ ...l, action: l.action as 'add' | 'modify' | 'cancel' })))\n : null}\n />\n\n {/* Order Lines */}\n <OrderLineTree\n lines={order.lines}\n quoteType={order.quoteType}\n currency={currency}\n expandedLines={expandedLines}\n pricingDetail={pricingDetail}\n onToggleLine={toggleLine}\n onTogglePricingDetail={togglePricingDetail}\n />\n </div>\n )\n}\n\nfunction MetaCard({ label, children }: { label: string; children: React.ReactNode }) {\n return (\n <div className=\"rounded-lg border bg-card p-4\">\n <div className=\"text-[10px] font-medium uppercase tracking-wide text-muted-foreground\">\n {label}\n </div>\n <div className=\"mt-1 text-sm\">{children}</div>\n </div>\n )\n}\n\n// \u2500\u2500\u2500 Sub-components \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction OrderLineTree({\n lines,\n quoteType,\n currency,\n expandedLines,\n pricingDetail,\n onToggleLine,\n onTogglePricingDetail,\n}: {\n lines: OrderLineResult[]\n quoteType: string\n currency: string\n expandedLines: Set<string>\n pricingDetail: { lineIdx: number; chargeIdx: number } | null\n onToggleLine: (id: string) => void\n onTogglePricingDetail: (lineIdx: number, chargeIdx: number) => void\n}) {\n const t = useT()\n const rootLines = lines.filter((l) => !l.parentLineId)\n const childrenByParent = new Map<string, OrderLineResult[]>()\n for (const line of lines) {\n if (line.parentLineId) {\n const arr = childrenByParent.get(line.parentLineId) ?? []\n arr.push(line)\n childrenByParent.set(line.parentLineId, arr)\n }\n }\n\n // Stable index per visible line so the pricing-detail toggle can be\n // keyed by (lineIdx, chargeIdx) the same way the quote page does.\n const indexOf = new Map<string, number>()\n lines.forEach((l, i) => indexOf.set(l.lineId, i))\n\n return (\n <div>\n <h3 className=\"text-sm font-medium mb-2 px-1\">{t('cpq.orders.detail.lineItems', 'Line Items ({count})', { count: lines.length })}</h3>\n {lines.length === 0 ? (\n <div className=\"rounded-lg border bg-card py-8 text-center text-sm text-muted-foreground\">\n {t('cpq.orders.detail.noLineItems', 'No line items.')}\n </div>\n ) : (\n <div className=\"rounded-lg border bg-card divide-y\">\n {rootLines.map((line) => {\n const isBundle = line.offeringType === 'bundle'\n const children = childrenByParent.get(line.lineId) ?? []\n const isExpanded = expandedLines.has(line.lineId)\n const lineIdx = indexOf.get(line.lineId) ?? 0\n return (\n <div key={line.lineId}>\n <OrderLineRow\n line={line}\n lineIdx={lineIdx}\n quoteType={quoteType}\n currency={currency}\n isExpanded={isExpanded}\n isBundle={isBundle}\n childCount={children.length}\n indent={0}\n pricingDetail={pricingDetail}\n onToggle={() => onToggleLine(line.lineId)}\n onTogglePricingDetail={onTogglePricingDetail}\n />\n {isBundle && isExpanded && children.length > 0 && (\n <div className=\"border-t border-dashed border-brand-violet/30 bg-brand-violet/5\">\n <div className=\"px-6 py-1.5\">\n <span className=\"text-[10px] font-medium text-brand-violet uppercase tracking-wider\">{t('cpq.lines.bundleComponents', 'Bundle Components ({count})', { count: children.length })}</span>\n </div>\n {children.map((child) => {\n const childIdx = indexOf.get(child.lineId) ?? 0\n return (\n <OrderLineRow\n key={child.lineId}\n line={child}\n lineIdx={childIdx}\n quoteType={quoteType}\n currency={currency}\n isExpanded={expandedLines.has(child.lineId)}\n isBundle={false}\n childCount={0}\n indent={1}\n pricingDetail={pricingDetail}\n onToggle={() => onToggleLine(child.lineId)}\n onTogglePricingDetail={onTogglePricingDetail}\n />\n )\n })}\n </div>\n )}\n </div>\n )\n })}\n </div>\n )}\n </div>\n )\n}\n\nfunction OrderLineRow({ line, lineIdx, quoteType, currency, isExpanded, isBundle, childCount, indent, pricingDetail, onToggle, onTogglePricingDetail }: {\n line: OrderLineResult; lineIdx: number; quoteType: string; currency: string; isExpanded: boolean; isBundle: boolean; childCount: number; indent: number\n pricingDetail: { lineIdx: number; chargeIdx: number } | null\n onToggle: () => void\n onTogglePricingDetail: (lineIdx: number, chargeIdx: number) => void\n}) {\n const t = useT()\n const paddingLeft = indent > 0 ? `${indent * 2 + 1}rem` : undefined\n // Same presentation as the quote page: an existing item removed on an\n // Amend / Renew quote reads as \"remove\", struck through.\n const isRemoved = isArcCancelledLine(line, quoteType)\n\n return (\n <div>\n <div\n className={`flex items-center gap-3 px-4 py-3 hover:bg-muted/30 transition-colors cursor-pointer ${isRemoved ? 'bg-muted/20' : ''}`}\n style={paddingLeft ? { paddingLeft } : undefined}\n onClick={onToggle}\n data-testid=\"cpq-order-line\"\n data-removed={isRemoved ? 'true' : undefined}\n >\n <button className=\"flex h-5 w-5 shrink-0 items-center justify-center rounded text-muted-foreground hover:text-foreground\">\n <svg className={`h-4 w-4 transition-transform ${isExpanded ? 'rotate-90' : ''}`} fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth=\"2\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M8.25 4.5l7.5 7.5-7.5 7.5\" />\n </svg>\n </button>\n\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n {indent > 0 && <span className=\"text-muted-foreground text-xs\">\u2514</span>}\n {isBundle && (\n <Tag variant=\"brand\" className=\"px-1.5 text-xs\">{t('cpq.lines.bundle', 'bundle')}</Tag>\n )}\n <span className={`font-medium text-sm ${isRemoved ? 'text-muted-foreground line-through' : ''}`}>{line.offeringName}</span>\n {line.quantity > 1 && <span className=\"rounded bg-muted px-1.5 py-0.5 text-xs font-medium\">\u00D7{line.quantity}</span>}\n <LineActionBadge\n action={line.action}\n label={isRemoved ? t('cpq.quotes.arc.lineRemoved', 'remove') : undefined}\n title={isRemoved ? t('cpq.quotes.arc.lineRemovedHint', 'This item is cancelled on the subscription when the order is activated') : undefined}\n />\n {isBundle && (\n <span className=\"text-xs text-muted-foreground\">\n {childCount !== 1\n ? t('cpq.lines.componentCount.other', '{count} components', { count: childCount })\n : t('cpq.lines.componentCount.one', '{count} component', { count: childCount })}\n </span>\n )}\n </div>\n </div>\n\n <div className=\"shrink-0 text-right text-xs space-y-0.5\">\n {isRemoved && line.arcSource && line.arcSource.mrcAmount > 0 && (\n <div>\n <span className=\"text-muted-foreground\">{t('cpq.lines.mrc', 'MRC')} </span>\n <span className=\"font-mono text-muted-foreground line-through\">{fmt(line.arcSource.mrcAmount, currency)}</span>\n </div>\n )}\n {line.nrcTotal > 0 && <div><span className=\"text-muted-foreground\">{t('cpq.lines.nrc', 'NRC')} </span><span className=\"font-mono font-medium\">{fmt(line.nrcTotal, currency)}</span></div>}\n {line.mrcTotal > 0 && <div><span className=\"text-muted-foreground\">{t('cpq.lines.mrc', 'MRC')} </span><span className=\"font-mono font-medium\">{fmt(line.mrcTotal, currency)}</span></div>}\n </div>\n </div>\n\n {isExpanded && (() => {\n const internalKeys = new Set(['_arcMirroredName', '_arcMirroredFromItemId', '_arcPriceFrozen', '_arcRepriced', 'offeringName'])\n const visibleConfigEntries = Object.entries(line.configuration).filter(\n ([key]) => !internalKeys.has(key),\n )\n const hasConfig = visibleConfigEntries.length > 0\n const hasCharges = line.charges.length > 0\n const hasTerm = !!(line.startDate || line.termMonths || line.endDate)\n const hasArcDiff = !!line.arcSource\n const mirroredFromItemId = (line.configuration?._arcMirroredFromItemId as string | undefined) ?? null\n const isEmpty = !hasConfig && !hasCharges && !hasTerm && !hasArcDiff\n\n return (\n <div\n className=\"border-t bg-muted/10 px-12 py-3 space-y-3\"\n style={paddingLeft ? { paddingLeft: `calc(${paddingLeft} + 2rem)` } : undefined}\n >\n {isEmpty ? (\n <div className=\"text-xs text-muted-foreground space-y-1\">\n <div>\n {t('cpq.orders.detail.noBreakdown', 'No detailed breakdown for this line.')}\n {mirroredFromItemId && ' '}\n {mirroredFromItemId && t('cpq.orders.detail.mirroredItem', 'Mirrored from existing subscription item.')}\n </div>\n {(line.nrcTotal > 0 || line.mrcTotal > 0) && (\n <div className=\"flex gap-4\">\n {line.nrcTotal > 0 && (\n <span>{t('cpq.lines.nrc', 'NRC')} <span className=\"font-mono font-medium text-foreground\">{fmt(line.nrcTotal, currency)}</span></span>\n )}\n {line.mrcTotal > 0 && (\n <span>{t('cpq.lines.mrc', 'MRC')} <span className=\"font-mono font-medium text-foreground\">{fmt(line.mrcTotal, currency)}</span></span>\n )}\n </div>\n )}\n </div>\n ) : (\n <>\n {hasConfig && (\n <div>\n <p className=\"text-xs font-medium text-muted-foreground mb-1\">{t('cpq.lines.configuration', 'Configuration')}</p>\n <div className=\"grid grid-cols-2 sm:grid-cols-3 gap-x-4 gap-y-1\">\n {visibleConfigEntries.map(([key, value]) => (\n <div key={key} className=\"text-xs\">\n <span className=\"text-muted-foreground\">{key}: </span>\n <span className=\"font-medium\">{String(value)}</span>\n </div>\n ))}\n </div>\n </div>\n )}\n\n {hasCharges && (\n <ChargeBreakdownTable\n charges={line.charges.map(toChargeRow)}\n currency={currency}\n openDetailIndex={pricingDetail?.lineIdx === lineIdx ? pricingDetail.chargeIdx : null}\n onToggleDetail={(chargeIdx) => onTogglePricingDetail(lineIdx, chargeIdx)}\n />\n )}\n\n {hasTerm && (\n <div className=\"flex gap-4 text-xs text-muted-foreground\">\n {line.startDate && <span>{t('cpq.lines.term.start', 'Start: {date}', { date: new Date(line.startDate).toLocaleDateString() })}</span>}\n {line.termMonths && <span>{t('cpq.lines.term.months', 'Term: {months}mo', { months: line.termMonths })}</span>}\n {line.endDate && <span>{t('cpq.lines.term.end', 'End: {date}', { date: new Date(line.endDate).toLocaleDateString() })}</span>}\n </div>\n )}\n\n {/* XD-250 ARC: before/after preview below the charges, as on the quote. */}\n {hasArcDiff && <ArcLineDiff line={line} currency={currency} />}\n </>\n )}\n </div>\n )\n })()}\n </div>\n )\n}\n\nfunction Spinner() {\n return (\n <svg className=\"h-4 w-4 animate-spin\" viewBox=\"0 0 24 24\" fill=\"none\">\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path className=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z\" />\n </svg>\n )\n}\n\nfunction ErrorBanner({ message, onDismiss }: { message: string; onDismiss?: () => void }) {\n const t = useT()\n return (\n <Alert variant=\"destructive\" className=\"flex items-start gap-2\">\n <span className=\"flex-1\">{message}</span>\n {onDismiss && (\n <button\n onClick={onDismiss}\n className=\"text-destructive/70 hover:text-destructive text-sm font-bold\"\n aria-label={t('cpq.common.dismiss', 'Dismiss')}\n >\n \u00D7\n </button>\n )}\n </Alert>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -34,13 +34,13 @@ function CpqOrdersListPage() {
34
34
  });
35
35
  const statusOptions = React.useMemo(
36
36
  () => [
37
- { value: "draft", label: "Draft" },
38
- { value: "pending_activation", label: "Pending Activation" },
39
- { value: "active", label: "Active" },
40
- { value: "fulfilled", label: "Fulfilled" },
41
- { value: "cancelled", label: "Cancelled" }
37
+ { value: "draft", label: t("cpq.orders.status.draft", "Draft") },
38
+ { value: "pending_activation", label: t("cpq.orders.status.pending_activation", "Pending Activation") },
39
+ { value: "active", label: t("cpq.orders.status.active", "Active") },
40
+ { value: "fulfilled", label: t("cpq.orders.status.fulfilled", "Fulfilled") },
41
+ { value: "cancelled", label: t("cpq.orders.status.cancelled", "Cancelled") }
42
42
  ],
43
- []
43
+ [t]
44
44
  );
45
45
  const filters = React.useMemo(
46
46
  () => [
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/modules/cpq/backend/cpq/orders/page.tsx"],
4
- "sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { useRouter } from 'next/navigation'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'\nimport type { FilterDef, FilterValues } from '@open-mercato/ui/backend/FilterBar'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { Tag } from '@open-mercato/ui/primitives/tag'\nimport { CpqListView, useCpqListData } from '../../../components/CpqListView'\nimport {\n formatStatusLabel,\n orderCpqStatusMap,\n type OrderCpqStatus,\n} from '../../../components/statusMaps'\n\ntype OrderConfig = {\n id: string\n orderId: string\n orderNumber: string | null\n customerId: string\n cpqStatus: string\n currencyCode: string\n pricingSummary: {\n nrcTotal?: number\n mrcTotal?: number\n } | null\n createdAt: string\n activatedAt: string | null\n}\n\nconst PAGE_SIZE = 50\n\nfunction fmt(amount: number | undefined, currency: string): string {\n if (amount == null || amount === 0) return '\u2014'\n return new Intl.NumberFormat('en-US', { style: 'currency', currency }).format(amount)\n}\n\nfunction buildFilterParams(values: FilterValues, params: URLSearchParams) {\n if (typeof values.cpqStatus === 'string' && values.cpqStatus) {\n params.set('cpqStatus', values.cpqStatus)\n }\n if (typeof values.currencyCode === 'string' && values.currencyCode.trim()) {\n params.set('currencyCode', values.currencyCode.trim().toUpperCase())\n }\n}\n\nexport default function CpqOrdersListPage() {\n const router = useRouter()\n const t = useT()\n\n const data = useCpqListData<OrderConfig>({\n endpoint: '/api/cpq/orders',\n pageSize: PAGE_SIZE,\n buildFilterParams,\n loadErrorMessage: t('cpq.orders.list.error.load', 'Failed to load orders'),\n })\n\n const statusOptions = React.useMemo(\n () => [\n { value: 'draft', label: 'Draft' },\n { value: 'pending_activation', label: 'Pending Activation' },\n { value: 'active', label: 'Active' },\n { value: 'fulfilled', label: 'Fulfilled' },\n { value: 'cancelled', label: 'Cancelled' },\n ],\n [],\n )\n\n const filters = React.useMemo<FilterDef[]>(\n () => [\n {\n id: 'cpqStatus',\n label: t('cpq.orders.filters.status', 'Status'),\n type: 'select',\n options: statusOptions,\n },\n {\n id: 'currencyCode',\n label: t('cpq.orders.filters.currency', 'Currency'),\n type: 'text',\n },\n ],\n [statusOptions, t],\n )\n\n const columns = React.useMemo<ColumnDef<OrderConfig>[]>(\n () => [\n {\n id: 'orderNumber',\n header: t('cpq.orders.table.order', 'Order'),\n cell: ({ row }) => (\n <span className=\"text-sm font-medium text-primary\">\n {row.original.orderNumber ?? `${row.original.orderId?.slice(0, 8)}\u2026`}\n </span>\n ),\n },\n {\n accessorKey: 'cpqStatus',\n header: t('cpq.orders.table.status', 'Status'),\n cell: ({ row }) => (\n <Tag variant={orderCpqStatusMap[row.original.cpqStatus as OrderCpqStatus] ?? 'neutral'} dot>\n {formatStatusLabel(row.original.cpqStatus)}\n </Tag>\n ),\n },\n {\n accessorKey: 'currencyCode',\n header: t('cpq.orders.table.currency', 'Currency'),\n cell: ({ row }) => <span className=\"text-muted-foreground\">{row.original.currencyCode}</span>,\n },\n {\n id: 'nrcTotal',\n header: t('cpq.orders.table.nrcTotal', 'NRC Total'),\n cell: ({ row }) => (\n <span className=\"font-mono text-xs\">\n {fmt(row.original.pricingSummary?.nrcTotal, row.original.currencyCode)}\n </span>\n ),\n },\n {\n id: 'mrcTotal',\n header: t('cpq.orders.table.mrcTotal', 'MRC Total'),\n cell: ({ row }) => (\n <span className=\"font-mono text-xs\">\n {fmt(row.original.pricingSummary?.mrcTotal, row.original.currencyCode)}\n </span>\n ),\n },\n {\n accessorKey: 'createdAt',\n header: t('cpq.orders.table.createdAt', 'Created'),\n cell: ({ row }) => (\n <span className=\"text-xs text-muted-foreground\">\n {new Date(row.original.createdAt).toLocaleDateString()}\n </span>\n ),\n },\n {\n accessorKey: 'activatedAt',\n header: t('cpq.orders.table.activatedAt', 'Activated'),\n cell: ({ row }) => (\n <span className=\"text-xs text-muted-foreground\">\n {row.original.activatedAt ? new Date(row.original.activatedAt).toLocaleDateString() : '\u2014'}\n </span>\n ),\n },\n ],\n [t],\n )\n\n return (\n <CpqListView<OrderConfig>\n title={t('cpq.orders.list.title', 'CPQ Orders')}\n tableId=\"cpq.orders.list\"\n data={data}\n columns={columns}\n filters={filters}\n pageSize={PAGE_SIZE}\n searchPlaceholder={t('cpq.orders.search.placeholder', 'Search by order / customer id...')}\n onRowClick={(row) => router.push(`/backend/cpq/orders/${row.id}`)}\n rowActions={(row) => (\n <RowActions\n items={[\n {\n id: 'open',\n label: t('cpq.orders.actions.open', 'Open'),\n href: `/backend/cpq/orders/${row.id}`,\n },\n ]}\n />\n )}\n emptyState={\n <div className=\"rounded-lg border bg-card p-6 text-center text-sm text-muted-foreground\">\n {t(\n 'cpq.orders.empty',\n 'No CPQ orders found. Convert an accepted quote to create an order.',\n )}\n </div>\n }\n />\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { useRouter } from 'next/navigation'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'\nimport type { FilterDef, FilterValues } from '@open-mercato/ui/backend/FilterBar'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { Tag } from '@open-mercato/ui/primitives/tag'\nimport { CpqListView, useCpqListData } from '../../../components/CpqListView'\nimport {\n formatStatusLabel,\n orderCpqStatusMap,\n type OrderCpqStatus,\n} from '../../../components/statusMaps'\n\ntype OrderConfig = {\n id: string\n orderId: string\n orderNumber: string | null\n customerId: string\n cpqStatus: string\n currencyCode: string\n pricingSummary: {\n nrcTotal?: number\n mrcTotal?: number\n } | null\n createdAt: string\n activatedAt: string | null\n}\n\nconst PAGE_SIZE = 50\n\nfunction fmt(amount: number | undefined, currency: string): string {\n if (amount == null || amount === 0) return '\u2014'\n return new Intl.NumberFormat('en-US', { style: 'currency', currency }).format(amount)\n}\n\nfunction buildFilterParams(values: FilterValues, params: URLSearchParams) {\n if (typeof values.cpqStatus === 'string' && values.cpqStatus) {\n params.set('cpqStatus', values.cpqStatus)\n }\n if (typeof values.currencyCode === 'string' && values.currencyCode.trim()) {\n params.set('currencyCode', values.currencyCode.trim().toUpperCase())\n }\n}\n\nexport default function CpqOrdersListPage() {\n const router = useRouter()\n const t = useT()\n\n const data = useCpqListData<OrderConfig>({\n endpoint: '/api/cpq/orders',\n pageSize: PAGE_SIZE,\n buildFilterParams,\n loadErrorMessage: t('cpq.orders.list.error.load', 'Failed to load orders'),\n })\n\n const statusOptions = React.useMemo(\n () => [\n { value: 'draft', label: t('cpq.orders.status.draft', 'Draft') },\n { value: 'pending_activation', label: t('cpq.orders.status.pending_activation', 'Pending Activation') },\n { value: 'active', label: t('cpq.orders.status.active', 'Active') },\n { value: 'fulfilled', label: t('cpq.orders.status.fulfilled', 'Fulfilled') },\n { value: 'cancelled', label: t('cpq.orders.status.cancelled', 'Cancelled') },\n ],\n [t],\n )\n\n const filters = React.useMemo<FilterDef[]>(\n () => [\n {\n id: 'cpqStatus',\n label: t('cpq.orders.filters.status', 'Status'),\n type: 'select',\n options: statusOptions,\n },\n {\n id: 'currencyCode',\n label: t('cpq.orders.filters.currency', 'Currency'),\n type: 'text',\n },\n ],\n [statusOptions, t],\n )\n\n const columns = React.useMemo<ColumnDef<OrderConfig>[]>(\n () => [\n {\n id: 'orderNumber',\n header: t('cpq.orders.table.order', 'Order'),\n cell: ({ row }) => (\n <span className=\"text-sm font-medium text-primary\">\n {row.original.orderNumber ?? `${row.original.orderId?.slice(0, 8)}\u2026`}\n </span>\n ),\n },\n {\n accessorKey: 'cpqStatus',\n header: t('cpq.orders.table.status', 'Status'),\n cell: ({ row }) => (\n <Tag variant={orderCpqStatusMap[row.original.cpqStatus as OrderCpqStatus] ?? 'neutral'} dot>\n {formatStatusLabel(row.original.cpqStatus)}\n </Tag>\n ),\n },\n {\n accessorKey: 'currencyCode',\n header: t('cpq.orders.table.currency', 'Currency'),\n cell: ({ row }) => <span className=\"text-muted-foreground\">{row.original.currencyCode}</span>,\n },\n {\n id: 'nrcTotal',\n header: t('cpq.orders.table.nrcTotal', 'NRC Total'),\n cell: ({ row }) => (\n <span className=\"font-mono text-xs\">\n {fmt(row.original.pricingSummary?.nrcTotal, row.original.currencyCode)}\n </span>\n ),\n },\n {\n id: 'mrcTotal',\n header: t('cpq.orders.table.mrcTotal', 'MRC Total'),\n cell: ({ row }) => (\n <span className=\"font-mono text-xs\">\n {fmt(row.original.pricingSummary?.mrcTotal, row.original.currencyCode)}\n </span>\n ),\n },\n {\n accessorKey: 'createdAt',\n header: t('cpq.orders.table.createdAt', 'Created'),\n cell: ({ row }) => (\n <span className=\"text-xs text-muted-foreground\">\n {new Date(row.original.createdAt).toLocaleDateString()}\n </span>\n ),\n },\n {\n accessorKey: 'activatedAt',\n header: t('cpq.orders.table.activatedAt', 'Activated'),\n cell: ({ row }) => (\n <span className=\"text-xs text-muted-foreground\">\n {row.original.activatedAt ? new Date(row.original.activatedAt).toLocaleDateString() : '\u2014'}\n </span>\n ),\n },\n ],\n [t],\n )\n\n return (\n <CpqListView<OrderConfig>\n title={t('cpq.orders.list.title', 'CPQ Orders')}\n tableId=\"cpq.orders.list\"\n data={data}\n columns={columns}\n filters={filters}\n pageSize={PAGE_SIZE}\n searchPlaceholder={t('cpq.orders.search.placeholder', 'Search by order / customer id...')}\n onRowClick={(row) => router.push(`/backend/cpq/orders/${row.id}`)}\n rowActions={(row) => (\n <RowActions\n items={[\n {\n id: 'open',\n label: t('cpq.orders.actions.open', 'Open'),\n href: `/backend/cpq/orders/${row.id}`,\n },\n ]}\n />\n )}\n emptyState={\n <div className=\"rounded-lg border bg-card p-6 text-center text-sm text-muted-foreground\">\n {t(\n 'cpq.orders.empty',\n 'No CPQ orders found. Convert an accepted quote to create an order.',\n )}\n </div>\n }\n />\n )\n}\n"],
5
+ "mappings": ";AA2FU;AA1FV,YAAY,WAAW;AACvB,SAAS,iBAAiB;AAC1B,SAAS,YAAY;AAGrB,SAAS,kBAAkB;AAC3B,SAAS,WAAW;AACpB,SAAS,aAAa,sBAAsB;AAC5C;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AAiBP,MAAM,YAAY;AAElB,SAAS,IAAI,QAA4B,UAA0B;AACjE,MAAI,UAAU,QAAQ,WAAW,EAAG,QAAO;AAC3C,SAAO,IAAI,KAAK,aAAa,SAAS,EAAE,OAAO,YAAY,SAAS,CAAC,EAAE,OAAO,MAAM;AACtF;AAEA,SAAS,kBAAkB,QAAsB,QAAyB;AACxE,MAAI,OAAO,OAAO,cAAc,YAAY,OAAO,WAAW;AAC5D,WAAO,IAAI,aAAa,OAAO,SAAS;AAAA,EAC1C;AACA,MAAI,OAAO,OAAO,iBAAiB,YAAY,OAAO,aAAa,KAAK,GAAG;AACzE,WAAO,IAAI,gBAAgB,OAAO,aAAa,KAAK,EAAE,YAAY,CAAC;AAAA,EACrE;AACF;AAEe,SAAR,oBAAqC;AAC1C,QAAM,SAAS,UAAU;AACzB,QAAM,IAAI,KAAK;AAEf,QAAM,OAAO,eAA4B;AAAA,IACvC,UAAU;AAAA,IACV,UAAU;AAAA,IACV;AAAA,IACA,kBAAkB,EAAE,8BAA8B,uBAAuB;AAAA,EAC3E,CAAC;AAED,QAAM,gBAAgB,MAAM;AAAA,IAC1B,MAAM;AAAA,MACJ,EAAE,OAAO,SAAS,OAAO,EAAE,2BAA2B,OAAO,EAAE;AAAA,MAC/D,EAAE,OAAO,sBAAsB,OAAO,EAAE,wCAAwC,oBAAoB,EAAE;AAAA,MACtG,EAAE,OAAO,UAAU,OAAO,EAAE,4BAA4B,QAAQ,EAAE;AAAA,MAClE,EAAE,OAAO,aAAa,OAAO,EAAE,+BAA+B,WAAW,EAAE;AAAA,MAC3E,EAAE,OAAO,aAAa,OAAO,EAAE,+BAA+B,WAAW,EAAE;AAAA,IAC7E;AAAA,IACA,CAAC,CAAC;AAAA,EACJ;AAEA,QAAM,UAAU,MAAM;AAAA,IACpB,MAAM;AAAA,MACJ;AAAA,QACE,IAAI;AAAA,QACJ,OAAO,EAAE,6BAA6B,QAAQ;AAAA,QAC9C,MAAM;AAAA,QACN,SAAS;AAAA,MACX;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,OAAO,EAAE,+BAA+B,UAAU;AAAA,QAClD,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,CAAC,eAAe,CAAC;AAAA,EACnB;AAEA,QAAM,UAAU,MAAM;AAAA,IACpB,MAAM;AAAA,MACJ;AAAA,QACE,IAAI;AAAA,QACJ,QAAQ,EAAE,0BAA0B,OAAO;AAAA,QAC3C,MAAM,CAAC,EAAE,IAAI,MACX,oBAAC,UAAK,WAAU,oCACb,cAAI,SAAS,eAAe,GAAG,IAAI,SAAS,SAAS,MAAM,GAAG,CAAC,CAAC,UACnE;AAAA,MAEJ;AAAA,MACA;AAAA,QACE,aAAa;AAAA,QACb,QAAQ,EAAE,2BAA2B,QAAQ;AAAA,QAC7C,MAAM,CAAC,EAAE,IAAI,MACX,oBAAC,OAAI,SAAS,kBAAkB,IAAI,SAAS,SAA2B,KAAK,WAAW,KAAG,MACxF,4BAAkB,IAAI,SAAS,SAAS,GAC3C;AAAA,MAEJ;AAAA,MACA;AAAA,QACE,aAAa;AAAA,QACb,QAAQ,EAAE,6BAA6B,UAAU;AAAA,QACjD,MAAM,CAAC,EAAE,IAAI,MAAM,oBAAC,UAAK,WAAU,yBAAyB,cAAI,SAAS,cAAa;AAAA,MACxF;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,QAAQ,EAAE,6BAA6B,WAAW;AAAA,QAClD,MAAM,CAAC,EAAE,IAAI,MACX,oBAAC,UAAK,WAAU,qBACb,cAAI,IAAI,SAAS,gBAAgB,UAAU,IAAI,SAAS,YAAY,GACvE;AAAA,MAEJ;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,QAAQ,EAAE,6BAA6B,WAAW;AAAA,QAClD,MAAM,CAAC,EAAE,IAAI,MACX,oBAAC,UAAK,WAAU,qBACb,cAAI,IAAI,SAAS,gBAAgB,UAAU,IAAI,SAAS,YAAY,GACvE;AAAA,MAEJ;AAAA,MACA;AAAA,QACE,aAAa;AAAA,QACb,QAAQ,EAAE,8BAA8B,SAAS;AAAA,QACjD,MAAM,CAAC,EAAE,IAAI,MACX,oBAAC,UAAK,WAAU,iCACb,cAAI,KAAK,IAAI,SAAS,SAAS,EAAE,mBAAmB,GACvD;AAAA,MAEJ;AAAA,MACA;AAAA,QACE,aAAa;AAAA,QACb,QAAQ,EAAE,gCAAgC,WAAW;AAAA,QACrD,MAAM,CAAC,EAAE,IAAI,MACX,oBAAC,UAAK,WAAU,iCACb,cAAI,SAAS,cAAc,IAAI,KAAK,IAAI,SAAS,WAAW,EAAE,mBAAmB,IAAI,UACxF;AAAA,MAEJ;AAAA,IACF;AAAA,IACA,CAAC,CAAC;AAAA,EACJ;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,EAAE,yBAAyB,YAAY;AAAA,MAC9C,SAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV,mBAAmB,EAAE,iCAAiC,kCAAkC;AAAA,MACxF,YAAY,CAAC,QAAQ,OAAO,KAAK,uBAAuB,IAAI,EAAE,EAAE;AAAA,MAChE,YAAY,CAAC,QACX;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,YACL;AAAA,cACE,IAAI;AAAA,cACJ,OAAO,EAAE,2BAA2B,MAAM;AAAA,cAC1C,MAAM,uBAAuB,IAAI,EAAE;AAAA,YACrC;AAAA,UACF;AAAA;AAAA,MACF;AAAA,MAEF,YACE,oBAAC,SAAI,WAAU,2EACZ;AAAA,QACC;AAAA,QACA;AAAA,MACF,GACF;AAAA;AAAA,EAEJ;AAEJ;",
6
6
  "names": []
7
7
  }
@@ -8,7 +8,7 @@ const metadata = {
8
8
  pageTitleKey: "cpq.orders.title",
9
9
  pageGroup: "CPQ",
10
10
  pageGroupKey: "customers~sales~cpq.nav.group",
11
- pageOrder: 91,
11
+ pageOrder: 2,
12
12
  icon: ordersIcon,
13
13
  breadcrumb: [{ label: "CPQ Orders", labelKey: "cpq.orders.title" }]
14
14
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/modules/cpq/backend/cpq/orders/page.meta.ts"],
4
- "sourcesContent": ["import React from 'react'\nimport { ClipboardList } from 'lucide-react'\n\nconst ordersIcon = React.createElement(ClipboardList, { size: 16 })\n\nexport const metadata = {\n requireAuth: true,\n requireFeatures: ['cpq.orders.view'],\n pageTitle: 'CPQ Orders',\n pageTitleKey: 'cpq.orders.title',\n pageGroup: 'CPQ',\n pageGroupKey: 'customers~sales~cpq.nav.group',\n pageOrder: 91,\n icon: ordersIcon,\n breadcrumb: [{ label: 'CPQ Orders', labelKey: 'cpq.orders.title' }],\n} as const\n"],
4
+ "sourcesContent": ["import React from 'react'\nimport { ClipboardList } from 'lucide-react'\n\nconst ordersIcon = React.createElement(ClipboardList, { size: 16 })\n\nexport const metadata = {\n requireAuth: true,\n requireFeatures: ['cpq.orders.view'],\n pageTitle: 'CPQ Orders',\n pageTitleKey: 'cpq.orders.title',\n pageGroup: 'CPQ',\n pageGroupKey: 'customers~sales~cpq.nav.group',\n pageOrder: 2,\n icon: ordersIcon,\n breadcrumb: [{ label: 'CPQ Orders', labelKey: 'cpq.orders.title' }],\n} as const\n"],
5
5
  "mappings": "AAAA,OAAO,WAAW;AAClB,SAAS,qBAAqB;AAE9B,MAAM,aAAa,MAAM,cAAc,eAAe,EAAE,MAAM,GAAG,CAAC;AAE3D,MAAM,WAAW;AAAA,EACtB,aAAa;AAAA,EACb,iBAAiB,CAAC,iBAAiB;AAAA,EACnC,WAAW;AAAA,EACX,cAAc;AAAA,EACd,WAAW;AAAA,EACX,cAAc;AAAA,EACd,WAAW;AAAA,EACX,MAAM;AAAA,EACN,YAAY,CAAC,EAAE,OAAO,cAAc,UAAU,mBAAmB,CAAC;AACpE;",
6
6
  "names": []
7
7
  }
@@ -10,14 +10,17 @@ import {
10
10
  SelectTrigger,
11
11
  SelectValue
12
12
  } from "@open-mercato/ui/primitives/select";
13
+ import { useT } from "@open-mercato/shared/lib/i18n/context";
13
14
  import { NumberInput } from "../../../components/NumberInput.js";
14
- const RULE_TYPE_LABELS = {
15
- discount_percent: "Discount %",
16
- discount_absolute: "Discount $",
17
- surcharge_percent: "Surcharge %",
18
- surcharge_absolute: "Surcharge $",
19
- price_override: "Override"
20
- };
15
+ function buildRuleTypeLabels(t) {
16
+ return {
17
+ discount_percent: t("cpq.priceRules.ruleTypes.discountPercent", "Discount %"),
18
+ discount_absolute: t("cpq.priceRules.ruleTypes.discountAbsolute", "Discount $"),
19
+ surcharge_percent: t("cpq.priceRules.ruleTypes.surchargePercent", "Surcharge %"),
20
+ surcharge_absolute: t("cpq.priceRules.ruleTypes.surchargeAbsolute", "Surcharge $"),
21
+ price_override: t("cpq.priceRules.ruleTypes.priceOverride", "Override")
22
+ };
23
+ }
21
24
  const emptyPriceRuleForm = {
22
25
  code: "",
23
26
  name: "",
@@ -85,12 +88,14 @@ function PriceRuleForm({
85
88
  onSave,
86
89
  onCancel
87
90
  }) {
91
+ const t = useT();
92
+ const ruleTypeLabels = buildRuleTypeLabels(t);
88
93
  return /* @__PURE__ */ jsxs("div", { className: "rounded-lg border bg-card p-6 space-y-4", children: [
89
- /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold", children: editingId ? "Edit Rule" : "New Rule" }),
94
+ /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold", children: editingId ? t("cpq.priceRules.form.editTitle", "Edit Rule") : t("cpq.priceRules.form.newTitle", "New Rule") }),
90
95
  error && /* @__PURE__ */ jsx("div", { className: "rounded-md bg-destructive/10 p-3 text-sm text-destructive", children: error }),
91
96
  /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
92
97
  /* @__PURE__ */ jsxs("label", { className: "space-y-1", children: [
93
- /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: "Code" }),
98
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: t("cpq.priceRules.form.code", "Code") }),
94
99
  /* @__PURE__ */ jsx(
95
100
  Input,
96
101
  {
@@ -101,7 +106,7 @@ function PriceRuleForm({
101
106
  )
102
107
  ] }),
103
108
  /* @__PURE__ */ jsxs("label", { className: "space-y-1", children: [
104
- /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: "Name" }),
109
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: t("cpq.priceRules.form.name", "Name") }),
105
110
  /* @__PURE__ */ jsx(
106
111
  Input,
107
112
  {
@@ -111,7 +116,7 @@ function PriceRuleForm({
111
116
  )
112
117
  ] }),
113
118
  /* @__PURE__ */ jsxs("label", { className: "space-y-1", children: [
114
- /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: "Rule Type" }),
119
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: t("cpq.priceRules.form.ruleType", "Rule Type") }),
115
120
  /* @__PURE__ */ jsxs(
116
121
  Select,
117
122
  {
@@ -119,13 +124,13 @@ function PriceRuleForm({
119
124
  onValueChange: (value) => onFormChange({ ...form, ruleType: value }),
120
125
  children: [
121
126
  /* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, {}) }),
122
- /* @__PURE__ */ jsx(SelectContent, { children: Object.entries(RULE_TYPE_LABELS).map(([k, v]) => /* @__PURE__ */ jsx(SelectItem, { value: k, children: v }, k)) })
127
+ /* @__PURE__ */ jsx(SelectContent, { children: Object.entries(ruleTypeLabels).map(([k, v]) => /* @__PURE__ */ jsx(SelectItem, { value: k, children: v }, k)) })
123
128
  ]
124
129
  }
125
130
  )
126
131
  ] }),
127
132
  /* @__PURE__ */ jsxs("label", { className: "space-y-1", children: [
128
- /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: "Value" }),
133
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: t("cpq.priceRules.form.value", "Value") }),
129
134
  /* @__PURE__ */ jsx(
130
135
  NumberInput,
131
136
  {
@@ -135,7 +140,7 @@ function PriceRuleForm({
135
140
  )
136
141
  ] }),
137
142
  /* @__PURE__ */ jsxs("label", { className: "space-y-1", children: [
138
- /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: "Charge Type Filter" }),
143
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: t("cpq.priceRules.form.chargeTypeFilter", "Charge Type Filter") }),
139
144
  /* @__PURE__ */ jsxs(
140
145
  Select,
141
146
  {
@@ -144,28 +149,28 @@ function PriceRuleForm({
144
149
  children: [
145
150
  /* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, {}) }),
146
151
  /* @__PURE__ */ jsxs(SelectContent, { children: [
147
- /* @__PURE__ */ jsx(SelectItem, { value: "__all__", children: "All charge types" }),
148
- /* @__PURE__ */ jsx(SelectItem, { value: "nrc", children: "NRC only" }),
149
- /* @__PURE__ */ jsx(SelectItem, { value: "mrc", children: "MRC only" }),
150
- /* @__PURE__ */ jsx(SelectItem, { value: "usage", children: "Usage only" })
152
+ /* @__PURE__ */ jsx(SelectItem, { value: "__all__", children: t("cpq.priceRules.form.allChargeTypes", "All charge types") }),
153
+ /* @__PURE__ */ jsx(SelectItem, { value: "nrc", children: t("cpq.priceRules.form.nrcOnly", "NRC only") }),
154
+ /* @__PURE__ */ jsx(SelectItem, { value: "mrc", children: t("cpq.priceRules.form.mrcOnly", "MRC only") }),
155
+ /* @__PURE__ */ jsx(SelectItem, { value: "usage", children: t("cpq.priceRules.form.usageOnly", "Usage only") })
151
156
  ] })
152
157
  ]
153
158
  }
154
159
  )
155
160
  ] }),
156
161
  /* @__PURE__ */ jsxs("label", { className: "space-y-1", children: [
157
- /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: "Charge Code Filter" }),
162
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: t("cpq.priceRules.form.chargeCodeFilter", "Charge Code Filter") }),
158
163
  /* @__PURE__ */ jsx(
159
164
  Input,
160
165
  {
161
- placeholder: "e.g. setup_fee (leave empty for all)",
166
+ placeholder: t("cpq.priceRules.form.chargeCodeFilterPlaceholder", "e.g. setup_fee (leave empty for all)"),
162
167
  value: form.chargeCodeFilter,
163
168
  onChange: (e) => onFormChange({ ...form, chargeCodeFilter: e.target.value })
164
169
  }
165
170
  )
166
171
  ] }),
167
172
  /* @__PURE__ */ jsxs("label", { className: "space-y-1", children: [
168
- /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: "Sort Order" }),
173
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: t("cpq.priceRules.form.sortOrder", "Sort Order") }),
169
174
  /* @__PURE__ */ jsx(
170
175
  NumberInput,
171
176
  {
@@ -176,18 +181,18 @@ function PriceRuleForm({
176
181
  )
177
182
  ] }),
178
183
  /* @__PURE__ */ jsxs("label", { className: "space-y-1", children: [
179
- /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: "Description" }),
184
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: t("cpq.priceRules.form.description", "Description") }),
180
185
  /* @__PURE__ */ jsx(
181
186
  Input,
182
187
  {
183
- placeholder: "Optional",
188
+ placeholder: t("cpq.priceRules.form.descriptionPlaceholder", "Optional"),
184
189
  value: form.description,
185
190
  onChange: (e) => onFormChange({ ...form, description: e.target.value })
186
191
  }
187
192
  )
188
193
  ] }),
189
194
  /* @__PURE__ */ jsxs("label", { className: "space-y-1 col-span-2", children: [
190
- /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: "Product Offering" }),
195
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: t("cpq.priceRules.form.productOffering", "Product Offering") }),
191
196
  /* @__PURE__ */ jsxs(
192
197
  Select,
193
198
  {
@@ -196,7 +201,7 @@ function PriceRuleForm({
196
201
  children: [
197
202
  /* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, {}) }),
198
203
  /* @__PURE__ */ jsxs(SelectContent, { children: [
199
- /* @__PURE__ */ jsx(SelectItem, { value: "__global__", children: "Global (all products)" }),
204
+ /* @__PURE__ */ jsx(SelectItem, { value: "__global__", children: t("cpq.priceRules.form.globalAllProducts", "Global (all products)") }),
200
205
  offerings.map((o) => /* @__PURE__ */ jsxs(SelectItem, { value: o.id, children: [
201
206
  o.name,
202
207
  " (",
@@ -207,16 +212,16 @@ function PriceRuleForm({
207
212
  ]
208
213
  }
209
214
  ),
210
- /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: 'Leave as "Global" to apply to all products, or select a specific offering' })
215
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: t("cpq.priceRules.form.productOfferingHint", 'Leave as "Global" to apply to all products, or select a specific offering') })
211
216
  ] }),
212
217
  /* @__PURE__ */ jsxs("div", { className: "col-span-2 space-y-1", children: [
213
- /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: "Applicability Condition" }),
214
- /* @__PURE__ */ jsx("span", { className: "ml-2 text-xs text-muted-foreground", children: "(optional \u2014 only apply when a product attribute matches)" }),
218
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: t("cpq.priceRules.form.applicabilityCondition", "Applicability Condition") }),
219
+ /* @__PURE__ */ jsx("span", { className: "ml-2 text-xs text-muted-foreground", children: t("cpq.priceRules.form.applicabilityConditionHint", "(optional \u2014 only apply when a product attribute matches)") }),
215
220
  /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-2", children: [
216
221
  /* @__PURE__ */ jsx(
217
222
  Input,
218
223
  {
219
- placeholder: "Attribute (e.g. port_size)",
224
+ placeholder: t("cpq.priceRules.form.conditionAttributePlaceholder", "Attribute (e.g. port_size)"),
220
225
  value: form.conditionAttribute,
221
226
  onChange: (e) => onFormChange({ ...form, conditionAttribute: e.target.value })
222
227
  }
@@ -229,8 +234,8 @@ function PriceRuleForm({
229
234
  children: [
230
235
  /* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, {}) }),
231
236
  /* @__PURE__ */ jsxs(SelectContent, { children: [
232
- /* @__PURE__ */ jsx(SelectItem, { value: "eq", children: "equals (=)" }),
233
- /* @__PURE__ */ jsx(SelectItem, { value: "neq", children: "not equals (\u2260)" })
237
+ /* @__PURE__ */ jsx(SelectItem, { value: "eq", children: t("cpq.priceRules.form.operatorEq", "equals (=)") }),
238
+ /* @__PURE__ */ jsx(SelectItem, { value: "neq", children: t("cpq.priceRules.form.operatorNeq", "not equals (\u2260)") })
234
239
  ] })
235
240
  ]
236
241
  }
@@ -238,7 +243,7 @@ function PriceRuleForm({
238
243
  /* @__PURE__ */ jsx(
239
244
  Input,
240
245
  {
241
- placeholder: "Value (e.g. 100G)",
246
+ placeholder: t("cpq.priceRules.form.conditionValuePlaceholder", "Value (e.g. 100G)"),
242
247
  value: form.conditionValue,
243
248
  onChange: (e) => onFormChange({ ...form, conditionValue: e.target.value })
244
249
  }
@@ -254,17 +259,17 @@ function PriceRuleForm({
254
259
  onCheckedChange: (checked) => onFormChange({ ...form, isActive: checked === true })
255
260
  }
256
261
  ),
257
- "Active"
262
+ t("cpq.common.active", "Active")
258
263
  ] }),
259
264
  /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
260
- /* @__PURE__ */ jsx(Button, { type: "button", onClick: onSave, disabled: saving, children: saving ? "Saving..." : editingId ? "Update" : "Create" }),
261
- /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", onClick: onCancel, children: "Cancel" })
265
+ /* @__PURE__ */ jsx(Button, { type: "button", onClick: onSave, disabled: saving, children: saving ? t("cpq.common.saving", "Saving...") : editingId ? t("cpq.priceRules.form.update", "Update") : t("cpq.priceRules.form.create", "Create") }),
266
+ /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", onClick: onCancel, children: t("cpq.common.cancel", "Cancel") })
262
267
  ] })
263
268
  ] });
264
269
  }
265
270
  export {
266
271
  PriceRuleForm,
267
- RULE_TYPE_LABELS,
272
+ buildRuleTypeLabels,
268
273
  emptyPriceRuleForm,
269
274
  priceRuleFormToPayload,
270
275
  priceRuleToFormData