@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/inventory/subscriptions/%5Bid%5D/page.tsx"],
4
- "sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { useRouter, useParams } from 'next/navigation'\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 subscriptionStatusMap,\n type SubscriptionStatus,\n} from '../../../../../components/statusMaps'\nimport { StatusPath } from '../../../../../components/StatusPath'\n\n// XD-250 \u2014 ARC integration on subscription detail.\n// \u2022 header buttons (Amend / Renew / Cancel) call /from-subscription\n// and redirect to the new ARC quote\n// \u2022 \"Change History\" section reads /change-log\n\ntype SnapshotItem = {\n id: string\n name?: string\n mrcAmount?: number | string\n nrcAmount?: number | string\n quantity?: number\n status?: string\n}\n\ntype SubscriptionSnapshot = {\n id?: string\n currencyCode?: string\n items?: SnapshotItem[]\n} | null\n\ntype LineChangeEntry = {\n action: 'add' | 'modify' | 'cancel'\n itemId?: string\n quoteLineId?: string | null\n mrcDelta?: number\n mrcAmount?: number\n nrcAmount?: number\n quantity?: number\n}\n\ntype ChangeLogRow = {\n id: string\n changeType: string\n sourceQuoteId: string | null\n sourceOrderId: string | null\n performedByUserId: string | null\n effectiveAt: string\n createdAt: string\n reasonCode: string | null\n reasonText: string | null\n etfAmount: string | null\n etfCurrency: string | null\n termChange: Record<string, unknown> | null\n lineChanges: LineChangeEntry[] | null\n beforeSnapshot: SubscriptionSnapshot\n afterSnapshot: SubscriptionSnapshot\n mergedIntoSubscriptionId: string | null\n mergedFromSubscriptionIds: string[] | null\n}\n\nconst CHANGE_TYPE_LABELS: Record<string, string> = {\n created: 'Created',\n amend: 'Amended',\n renew: 'Renewed',\n cancel: 'Cancelled',\n 'merge-result': 'Created from merging contracts',\n 'merge-source': 'Merged into a new contract',\n}\n\nconst CHANGE_TYPE_VARIANTS: Record<string, 'info' | 'success' | 'error' | 'brand' | 'warning' | 'neutral'> = {\n created: 'neutral',\n amend: 'info',\n renew: 'success',\n cancel: 'error',\n 'merge-result': 'brand',\n 'merge-source': 'warning',\n}\n\ntype SubscriptionItem = {\n id: string\n subscriptionId: string\n parentItemId: string | null\n productId: string | null\n offeringId: string | null\n specId: string | null\n name: string\n status: string\n configuration: Record<string, unknown>\n charges: Array<Record<string, unknown>> | null\n mrcAmount: number\n nrcAmount: number\n currencyCode: string\n quantity: number\n capacityTotal: string | null\n capacityUsed: string | null\n capacityUnit: string | null\n sourceQuoteLineId: string | null\n metadata: Record<string, unknown> | null\n sortOrder: number\n createdAt: string\n updatedAt: string\n children?: SubscriptionItem[]\n}\n\ntype LinkedAsset = {\n id: string\n code: string\n name: string\n status: string\n assetType: string\n currencyCode: string\n purchasePrice: number\n quantity: number\n subscriptionItemId: string | null\n createdAt: string\n}\n\ntype SubscriptionDetail = {\n id: string\n customerId: string\n code: string\n name: string\n description: string | null\n status: string\n billingCycle: string\n currencyCode: string\n mrcAmount: number\n nrcAmount: number\n startDate: string | null\n currentTermEnd: string | null\n termMonths: number | null\n autoRenew: boolean\n activatedAt: string | null\n suspendedAt: string | null\n terminatedAt: string | null\n pricingSummary: Record<string, unknown> | null\n sourceQuoteId: string | null\n sourceOrderId: string | null\n metadata: Record<string, unknown> | null\n createdAt: string\n updatedAt: string\n items: SubscriptionItem[]\n}\n\nconst ALLOWED_TRANSITIONS: Record<string, string[]> = {\n pending: ['active', 'terminated'],\n active: ['suspended', 'terminated', 'expired'],\n suspended: ['active', 'terminated'],\n terminated: [],\n expired: [],\n}\n\nconst STATUS_LABELS: Record<string, string> = {\n pending: 'Pending',\n active: 'Active',\n suspended: 'Suspended',\n terminated: 'Terminated',\n expired: 'Expired',\n}\n\nfunction fmt(amount: number | string, currency: string): string {\n return new Intl.NumberFormat('en-US', { style: 'currency', currency }).format(Number(amount))\n}\n\nfunction StatusBadge({ status }: { status: string }) {\n return (\n <Tag variant={subscriptionStatusMap[status as SubscriptionStatus] ?? 'neutral'} dot>\n {formatStatusLabel(status)}\n </Tag>\n )\n}\n\nexport default function SubscriptionDetailPage(props: { params?: { id?: string } }) {\n const router = useRouter()\n const urlParams = useParams()\n const subId = (props.params?.id ?? urlParams?.id) as string\n\n const [sub, setSub] = React.useState<SubscriptionDetail | null>(null)\n const [loading, setLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [customerName, setCustomerName] = React.useState<string | null>(null)\n const [assets, setAssets] = React.useState<LinkedAsset[]>([])\n const [expandedItems, setExpandedItems] = React.useState<Set<string>>(new Set())\n const [transitioning, setTransitioning] = React.useState(false)\n // Resolved display names for ID references \u2014 fetched alongside the main\n // subscription record so the UI never shows \"62e90a3d\u2026\" placeholders.\n const [sourceQuoteNumber, setSourceQuoteNumber] = React.useState<string | null>(null)\n const [sourceOrderNumber, setSourceOrderNumber] = React.useState<string | null>(null)\n const [productNames, setProductNames] = React.useState<Record<string, string>>({})\n const [offeringNames, setOfferingNames] = React.useState<Record<string, string>>({})\n const [specNames, setSpecNames] = React.useState<Record<string, string>>({})\n // Resolved quote / order numbers per change log row (id \u2192 number).\n const [logQuoteNumbers, setLogQuoteNumbers] = React.useState<Record<string, string>>({})\n const [logOrderNumbers, setLogOrderNumbers] = React.useState<Record<string, string>>({})\n // XD-250 ARC state\n const [arcInFlight, setArcInFlight] = React.useState<'amend' | 'renew' | 'cancel' | null>(null)\n const [changeLog, setChangeLog] = React.useState<ChangeLogRow[]>([])\n const [changeLogLoading, setChangeLogLoading] = React.useState(false)\n\n const startArcQuote = React.useCallback(\n async (type: 'amend' | 'renew' | 'cancel') => {\n if (!sub) return\n setArcInFlight(type)\n try {\n const res = await fetch('/api/cpq/quotes/from-subscription', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ subscriptionId: sub.id, type }),\n })\n if (!res.ok) {\n const body = await res.json().catch(() => ({})) as { error?: string; existingQuoteId?: string }\n // XD-250 spec \u00A7 UI: when the subscription already has a non-terminal\n // ARC quote attached, the server returns 409 with `existingQuoteId`.\n // Offer to navigate to that quote instead of showing a dead alert.\n if (body.existingQuoteId) {\n const ok = window.confirm(\n `${body.error ?? 'Subscription has another ARC quote in progress.'}\\n\\n` +\n `Open the existing quote now?`,\n )\n if (ok) {\n router.push(`/backend/cpq/quotes/${body.existingQuoteId}`)\n }\n return\n }\n alert(`Failed to start ${type} quote: ${body.error ?? res.statusText}`)\n return\n }\n const data = await res.json()\n router.push(`/backend/cpq/quotes/${data.quoteId}`)\n } finally {\n setArcInFlight(null)\n }\n },\n [router, sub],\n )\n\n const transitionStatus = async (targetStatus: string) => {\n if (!sub) return\n try {\n setTransitioning(true)\n setError(null)\n const res = await fetch('/api/cpq/inventory/subscriptions/status', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ id: sub.id, targetStatus }),\n })\n const data = await res.json()\n if (!res.ok) throw new Error(data?.error ?? 'Status transition failed')\n // The status endpoint cascades to items and linked assets server-side,\n // but only returns the subscription scalar fields. Re-fetch the full\n // detail (which includes the item tree) and the asset list so the UI\n // reflects every cascaded change without a hard refresh.\n const [freshSub, freshAssets] = await Promise.all([\n fetch(`/api/cpq/inventory/subscriptions?id=${sub.id}`).then((r) => (r.ok ? r.json() : null)),\n fetch(`/api/cpq/inventory/assets?subscriptionId=${sub.id}&pageSize=50`)\n .then((r) => (r.ok ? r.json() : null))\n .then((r) => (r?.items ?? []) as LinkedAsset[]),\n ])\n if (freshSub) {\n setSub(freshSub)\n } else {\n setSub((prev) => prev ? { ...prev, ...data } : prev)\n }\n setAssets(freshAssets)\n } catch (err) {\n setError((err as Error).message)\n } finally {\n setTransitioning(false)\n }\n }\n\n React.useEffect(() => {\n let cancelled = false\n async function loadLog() {\n setChangeLogLoading(true)\n try {\n const r = await fetch(`/api/cpq/inventory/subscriptions/${subId}/change-log?pageSize=50`)\n if (r.ok && !cancelled) {\n const data = await r.json()\n const rows: ChangeLogRow[] = data.items ?? []\n setChangeLog(rows)\n // Resolve the quote / order numbers referenced by each row so\n // the history list shows \"Quote QUOTE-\u2026-00005\" instead of\n // \"Quote 270b8e08\u2026\".\n const qIds = new Set(rows.map((r2) => r2.sourceQuoteId).filter((x): x is string => !!x))\n const oIds = new Set(rows.map((r2) => r2.sourceOrderId).filter((x): x is string => !!x))\n for (const qId of qIds) {\n fetch(`/api/cpq/quotes/${qId}`)\n .then((r2) => (r2.ok ? r2.json() : null))\n .then((q) => {\n if (q?.quoteNumber && !cancelled) {\n setLogQuoteNumbers((prev) => ({ ...prev, [qId]: q.quoteNumber }))\n }\n })\n .catch(() => {})\n }\n for (const oId of oIds) {\n fetch(`/api/cpq/orders/${oId}`)\n .then((r2) => (r2.ok ? r2.json() : null))\n .then((o) => {\n if (o?.orderNumber && !cancelled) {\n setLogOrderNumbers((prev) => ({ ...prev, [oId]: o.orderNumber }))\n }\n })\n .catch(() => {})\n }\n }\n } finally {\n if (!cancelled) setChangeLogLoading(false)\n }\n }\n if (subId) void loadLog()\n return () => { cancelled = true }\n }, [subId])\n\n React.useEffect(() => {\n let cancelled = false\n async function load() {\n try {\n const res = await fetch(`/api/cpq/inventory/subscriptions?id=${subId}`)\n if (!res.ok) throw new Error('Subscription not found')\n const data: SubscriptionDetail = await res.json()\n if (!cancelled) {\n setSub(data)\n fetch(`/api/customers/companies?id=${data.customerId}&pageSize=1`)\n .then((r) => r.json())\n .then((result) => {\n const items = result.items ?? result ?? []\n const c = items[0]\n if (c && !cancelled) setCustomerName(c.display_name || c.displayName || c.name || null)\n })\n .catch(() => {})\n fetch(`/api/cpq/inventory/assets?subscriptionId=${subId}&pageSize=50`)\n .then((r) => r.json())\n .then((result) => {\n if (!cancelled) setAssets(result.items ?? [])\n })\n .catch(() => {})\n\n // Resolve display names for the ID references shown in the\n // header and on every item row. Each lookup is fire-and-forget;\n // the UI falls back to a short UUID until the name lands.\n if (data.sourceQuoteId) {\n fetch(`/api/cpq/quotes/${data.sourceQuoteId}`)\n .then((r) => (r.ok ? r.json() : null))\n .then((q) => {\n if (q && !cancelled) setSourceQuoteNumber(q.quoteNumber ?? null)\n })\n .catch(() => {})\n }\n if (data.sourceOrderId) {\n fetch(`/api/cpq/orders/${data.sourceOrderId}`)\n .then((r) => (r.ok ? r.json() : null))\n .then((o) => {\n if (o && !cancelled) setSourceOrderNumber(o.orderNumber ?? null)\n })\n .catch(() => {})\n }\n\n // For items, dedupe IDs across the tree and resolve each once.\n const flatChildren = (nodes: SubscriptionItem[]): SubscriptionItem[] =>\n nodes.flatMap((n) => [n, ...flatChildren(n.children ?? [])])\n const allItems = flatChildren(data.items ?? [])\n const productIds = new Set(allItems.map((i) => i.productId).filter((x): x is string => !!x))\n const offeringIds = new Set(allItems.map((i) => i.offeringId).filter((x): x is string => !!x))\n const specIds = new Set(allItems.map((i) => i.specId).filter((x): x is string => !!x))\n\n for (const offeringId of offeringIds) {\n fetch(`/api/cpq/product-offerings?id=${offeringId}`)\n .then((r) => (r.ok ? r.json() : null))\n .then((o) => {\n if (!o || cancelled) return\n if (o.name) setOfferingNames((prev) => ({ ...prev, [offeringId]: o.name }))\n if (o.specification?.name) setSpecNames((prev) => ({ ...prev, [o.specification.id]: o.specification.name }))\n })\n .catch(() => {})\n }\n for (const specId of specIds) {\n fetch(`/api/cpq/product-specifications?id=${specId}`)\n .then((r) => (r.ok ? r.json() : null))\n .then((s) => {\n if (s?.name && !cancelled) setSpecNames((prev) => ({ ...prev, [specId]: s.name }))\n })\n .catch(() => {})\n }\n for (const productId of productIds) {\n // Catalog products route is paginated \u2014 `?id=\u2026` filters to one\n // row but the response is still `{ items: [\u2026] }`.\n fetch(`/api/catalog/products?id=${productId}`)\n .then((r) => (r.ok ? r.json() : null))\n .then((res) => {\n if (!res || cancelled) return\n const p = (res.items ?? res)[0] ?? res\n const name = p?.title ?? p?.name ?? p?.handle ?? null\n if (name) setProductNames((prev) => ({ ...prev, [productId]: name }))\n })\n .catch(() => {})\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 }, [subId])\n\n const toggleItem = (id: string) => {\n setExpandedItems((prev) => { const n = new Set(prev); n.has(id) ? n.delete(id) : n.add(id); return n })\n }\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 (!sub) {\n return (\n <div className=\"space-y-4\">\n <button onClick={() => router.push('/backend/cpq/inventory')} className=\"text-sm text-muted-foreground hover:text-foreground\">\u2190 Back</button>\n {error && <ErrorBanner message={error} />}\n <div className=\"rounded-lg border bg-card p-6 text-center text-sm text-muted-foreground\">Subscription not found.</div>\n </div>\n )\n }\n\n const currency = sub.currencyCode || 'USD'\n const flatItems = flattenItems(sub.items)\n\n const canArc = sub.status === 'active' || sub.status === 'suspended'\n const statusTransitions = ALLOWED_TRANSITIONS[sub.status] ?? []\n\n return (\n <div className=\"space-y-6\">\n {/* Header \u2014 standard FormHeader detail mode, mirrors the CPQ quote /\n order layout. Title is the human subscription name; status /\n cycle tags sit under it; ARC actions (Amend / Renew / Cancel)\n + a \"Change status\" dropdown live on the right. The short\n subscription code lives in the Subscription Details card\n below \u2014 it's reference info, not header content. */}\n <FormHeader\n mode=\"detail\"\n backHref=\"/backend/cpq/inventory\"\n backLabel=\"Back to Customer Inventory\"\n entityTypeLabel=\"Subscription\"\n title={sub.name}\n statusBadge={\n <div className=\"flex flex-wrap items-center gap-2 pt-1\">\n <Tag variant={subscriptionStatusMap[sub.status as SubscriptionStatus] ?? 'neutral'} dot>\n {STATUS_LABELS[sub.status] ?? formatStatusLabel(sub.status)}\n </Tag>\n <Tag variant=\"neutral\" className=\"capitalize\">{sub.billingCycle}</Tag>\n {transitioning && <Spinner />}\n </div>\n }\n actionsContent={\n canArc ? (\n <>\n <Button\n type=\"button\"\n variant=\"outline\"\n disabled={arcInFlight !== null}\n onClick={() => startArcQuote('amend')}\n >\n Amend\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n disabled={arcInFlight !== null}\n onClick={() => startArcQuote('renew')}\n >\n Renew\n </Button>\n <Button\n type=\"button\"\n variant=\"destructive-outline\"\n disabled={arcInFlight !== null}\n onClick={() => startArcQuote('cancel')}\n >\n Cancel\n </Button>\n </>\n ) : null\n }\n />\n\n {/* Status path \u2014 visual progress only, like the order page.\n Transitions still happen via the dedicated endpoints. */}\n <div className=\"flex items-center gap-3 flex-wrap\">\n <StatusPath\n current={sub.status}\n path={['pending', 'active']}\n terminals={['suspended', 'terminated', 'expired']}\n statusMap={subscriptionStatusMap}\n labels={STATUS_LABELS}\n onTransition={transitionStatus}\n allowedTransitions={statusTransitions}\n disabled={transitioning}\n ariaLabel=\"Subscription status path\"\n />\n </div>\n\n {error && <ErrorBanner message={error} />}\n\n {/* Detail Cards */}\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div className=\"rounded-lg border bg-card p-4 space-y-3\">\n <h3 className=\"text-sm font-medium\">Subscription Details</h3>\n <div className=\"grid grid-cols-2 gap-x-4 gap-y-2\">\n <Field label=\"Code\" value={sub.code} mono />\n <Field label=\"Status\" value={sub.status} />\n <Field label=\"Billing Cycle\" value={sub.billingCycle} />\n <Field label=\"Currency\" value={currency} />\n <Field label=\"Auto-Renew\" value={sub.autoRenew ? 'Yes' : 'No'} />\n {sub.termMonths != null && <Field label=\"Term\" value={`${sub.termMonths} months`} />}\n {sub.startDate && <Field label=\"Start Date\" value={new Date(sub.startDate).toLocaleDateString()} />}\n {sub.currentTermEnd && <Field label=\"Term End\" value={new Date(sub.currentTermEnd).toLocaleDateString()} />}\n {sub.activatedAt && <Field label=\"Activated\" value={new Date(sub.activatedAt).toLocaleString()} />}\n {sub.suspendedAt && <Field label=\"Suspended\" value={new Date(sub.suspendedAt).toLocaleString()} />}\n {sub.terminatedAt && <Field label=\"Terminated\" value={new Date(sub.terminatedAt).toLocaleString()} />}\n </div>\n {sub.description && (\n <div className=\"pt-1\">\n <p className=\"text-xs text-muted-foreground\">Description</p>\n <p className=\"text-sm\">{sub.description}</p>\n </div>\n )}\n </div>\n\n <div className=\"rounded-lg border bg-card p-4 space-y-3\">\n <h3 className=\"text-sm font-medium\">Pricing & References</h3>\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <p className=\"text-xs text-muted-foreground\">Monthly Recurring (MRC)</p>\n <p className=\"text-lg font-semibold font-mono\">{fmt(sub.mrcAmount, currency)}</p>\n </div>\n <div>\n <p className=\"text-xs text-muted-foreground\">Non-Recurring (NRC)</p>\n <p className=\"text-lg font-semibold font-mono\">{fmt(sub.nrcAmount, currency)}</p>\n </div>\n </div>\n <div className=\"grid grid-cols-2 gap-x-4 gap-y-2 pt-1\">\n <Field label=\"Customer\" value={customerName ?? sub.customerId.slice(0, 12) + '\u2026'} />\n <Field label=\"Created\" value={new Date(sub.createdAt).toLocaleString()} />\n {sub.sourceQuoteId && (\n <div>\n <p className=\"text-xs text-muted-foreground\">Source Quote</p>\n <button\n onClick={() => router.push(`/backend/cpq/quotes/${sub.sourceQuoteId}`)}\n className=\"text-sm text-primary hover:underline\"\n >\n {sourceQuoteNumber ?? `${sub.sourceQuoteId.slice(0, 8)}\u2026`}\n </button>\n </div>\n )}\n {sub.sourceOrderId && (\n <div>\n <p className=\"text-xs text-muted-foreground\">Source Order</p>\n <button\n onClick={() => router.push(`/backend/cpq/orders/${sub.sourceOrderId}`)}\n className=\"text-sm text-primary hover:underline\"\n >\n {sourceOrderNumber ?? `${sub.sourceOrderId.slice(0, 8)}\u2026`}\n </button>\n </div>\n )}\n </div>\n </div>\n </div>\n\n {/* Metadata */}\n {sub.metadata && Object.keys(sub.metadata).length > 0 && (\n <div className=\"rounded-lg border bg-card p-4\">\n <h3 className=\"text-sm font-medium mb-2\">Metadata</h3>\n <div className=\"grid grid-cols-2 sm:grid-cols-3 gap-x-4 gap-y-1\">\n {Object.entries(sub.metadata).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 {/* Subscription Items */}\n <div>\n <h3 className=\"text-sm font-medium mb-2 px-1\">Subscription Items ({flatItems.length})</h3>\n {flatItems.length === 0 ? (\n <div className=\"rounded-lg border bg-card py-8 text-center text-sm text-muted-foreground\">No items.</div>\n ) : (\n <div className=\"rounded-lg border bg-card divide-y\">\n {flatItems.map((item) => {\n const isExpanded = expandedItems.has(item.id)\n const indent = item._depth ?? 0\n return (\n <div key={item.id}>\n <div\n className=\"flex items-center gap-3 px-4 py-3 hover:bg-muted/30 transition-colors cursor-pointer\"\n style={{ paddingLeft: `${16 + indent * 24}px` }}\n onClick={() => toggleItem(item.id)}\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 <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium text-sm\">{item.name}</span>\n {item.quantity > 1 && <span className=\"rounded bg-muted px-1.5 py-0.5 text-xs font-medium\">x{item.quantity}</span>}\n <StatusBadge status={item.status} />\n </div>\n </div>\n <div className=\"shrink-0 text-right text-xs space-y-0.5\">\n {Number(item.mrcAmount) > 0 && <div><span className=\"text-muted-foreground\">MRC </span><span className=\"font-mono font-medium\">{fmt(item.mrcAmount, item.currencyCode || currency)}</span></div>}\n {Number(item.nrcAmount) > 0 && <div><span className=\"text-muted-foreground\">NRC </span><span className=\"font-mono font-medium\">{fmt(item.nrcAmount, item.currencyCode || currency)}</span></div>}\n </div>\n </div>\n\n {isExpanded && (\n <div className=\"border-t bg-muted/10 px-12 py-3 space-y-3\" style={{ paddingLeft: `${40 + indent * 24}px` }}>\n <div className=\"grid grid-cols-2 sm:grid-cols-3 gap-x-4 gap-y-2\">\n {item.offeringId && (\n <RefField\n label=\"Offering\"\n name={offeringNames[item.offeringId]}\n fallback={item.offeringId}\n onClick={() => router.push(`/backend/cpq/offerings/${item.offeringId}`)}\n />\n )}\n {item.specId && (\n <RefField\n label=\"Specification\"\n name={specNames[item.specId]}\n fallback={item.specId}\n onClick={() => router.push(`/backend/cpq/specifications/${item.specId}`)}\n />\n )}\n {item.productId && (\n <RefField\n label=\"Product\"\n name={productNames[item.productId]}\n fallback={item.productId}\n onClick={() => router.push(`/backend/catalog/products/${item.productId}`)}\n />\n )}\n <Field label=\"Currency\" value={item.currencyCode || currency} />\n <Field label=\"Quantity\" value={String(item.quantity)} />\n {item.capacityTotal && <Field label=\"Capacity\" value={`${item.capacityUsed ?? '0'} / ${item.capacityTotal} ${item.capacityUnit ?? ''}`} />}\n </div>\n\n {item.configuration && Object.keys(item.configuration).length > 0 && (\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 {Object.entries(item.configuration).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 {item.charges && item.charges.length > 0 && (\n <div>\n <p className=\"text-xs font-medium text-muted-foreground mb-1\">Charges</p>\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 </tr>\n </thead>\n <tbody>\n {item.charges.map((c, i) => (\n <tr key={i} className=\"border-t border-dashed border-border/50\">\n <td className=\"py-1\">{(c as any).chargeName ?? '\u2014'}</td>\n <td className=\"py-1 uppercase\">{(c as any).chargeType ?? '\u2014'}</td>\n <td className=\"py-1 text-right font-mono\">{(c as any).unitPrice != null ? fmt((c as any).unitPrice, currency) : '\u2014'}</td>\n <td className=\"py-1 text-right font-mono\">{(c as any).quantity ?? '\u2014'}</td>\n <td className=\"py-1 text-right font-mono\">{(c as any).totalPrice != null ? fmt((c as any).totalPrice, currency) : '\u2014'}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n\n {item.metadata && Object.keys(item.metadata).length > 0 && (\n <div>\n <p className=\"text-xs font-medium text-muted-foreground mb-1\">Metadata</p>\n <div className=\"grid grid-cols-2 sm:grid-cols-3 gap-x-4 gap-y-1\">\n {Object.entries(item.metadata).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 <div className=\"flex gap-4 text-xs text-muted-foreground\">\n <span>Created: {new Date(item.createdAt).toLocaleString()}</span>\n <span>Updated: {new Date(item.updatedAt).toLocaleString()}</span>\n </div>\n </div>\n )}\n </div>\n )\n })}\n </div>\n )}\n </div>\n\n {/* XD-250 Change History */}\n <div>\n <h3 className=\"text-sm font-medium mb-2 px-1\">Change History ({changeLog.length})</h3>\n {changeLogLoading ? (\n <div className=\"rounded-lg border bg-card py-6 text-center text-sm text-muted-foreground\">Loading\u2026</div>\n ) : changeLog.length === 0 ? (\n <div className=\"rounded-lg border bg-card py-6 text-center text-sm text-muted-foreground\">No ARC changes yet.</div>\n ) : (\n <div className=\"rounded-lg border bg-card divide-y\">\n {changeLog.map((row) => (\n <div key={row.id} className=\"px-4 py-3 space-y-1\">\n <div className=\"flex items-center gap-2\">\n <Tag variant={CHANGE_TYPE_VARIANTS[row.changeType] ?? 'neutral'}>\n {CHANGE_TYPE_LABELS[row.changeType] ?? row.changeType}\n </Tag>\n <span className=\"text-xs text-muted-foreground\">\n {new Date(row.effectiveAt).toLocaleString()}\n </span>\n {row.sourceQuoteId && (\n <button\n onClick={() => router.push(`/backend/cpq/quotes/${row.sourceQuoteId}`)}\n className=\"text-xs text-primary hover:underline\"\n >\n Quote {logQuoteNumbers[row.sourceQuoteId] ?? `${row.sourceQuoteId.slice(0, 8)}\u2026`}\n </button>\n )}\n {row.sourceOrderId && (\n <button\n onClick={() => router.push(`/backend/cpq/orders/${row.sourceOrderId}`)}\n className=\"text-xs text-primary hover:underline\"\n >\n Order {logOrderNumbers[row.sourceOrderId] ?? `${row.sourceOrderId.slice(0, 8)}\u2026`}\n </button>\n )}\n </div>\n <ChangeLogLineDetails row={row} currency={currency} />\n {row.termChange && (\n <div className=\"text-xs text-muted-foreground\">\n Term: {String(row.termChange.oldTermEnd ?? '\u2014')} \u2192 {String(row.termChange.newTermEnd ?? '\u2014')}\n </div>\n )}\n {row.reasonCode && (\n <div className=\"text-xs text-muted-foreground\">\n Reason: {row.reasonCode}{row.reasonText ? ` \u2014 ${row.reasonText}` : ''}\n </div>\n )}\n {row.etfAmount && (\n <div className=\"text-xs text-muted-foreground\">\n ETF: {row.etfAmount} {row.etfCurrency ?? ''}\n </div>\n )}\n {row.mergedIntoSubscriptionId && (\n <div className=\"text-xs text-muted-foreground\">\n Merged into{' '}\n <button\n onClick={() =>\n router.push(`/backend/cpq/inventory/subscriptions/${row.mergedIntoSubscriptionId}`)\n }\n className=\"text-primary hover:underline\"\n >\n subscription {row.mergedIntoSubscriptionId.slice(0, 8)}\u2026\n </button>\n </div>\n )}\n {row.mergedFromSubscriptionIds && row.mergedFromSubscriptionIds.length > 0 && (\n <div className=\"text-xs text-muted-foreground\">\n Merged from {row.mergedFromSubscriptionIds.length} subscriptions\n </div>\n )}\n </div>\n ))}\n </div>\n )}\n </div>\n\n {/* Linked Assets */}\n <div>\n <h3 className=\"text-sm font-medium mb-2 px-1\">Linked Assets ({assets.length})</h3>\n {assets.length === 0 ? (\n <div className=\"rounded-lg border bg-card py-8 text-center text-sm text-muted-foreground\">No assets linked to this subscription.</div>\n ) : (\n <div className=\"rounded-lg border\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b bg-muted/50\">\n <th className=\"px-4 py-3 text-left font-medium\">Code</th>\n <th className=\"px-4 py-3 text-left font-medium\">Name</th>\n <th className=\"px-4 py-3 text-left font-medium\">Type</th>\n <th className=\"px-4 py-3 text-left font-medium\">Status</th>\n <th className=\"px-4 py-3 text-right font-medium\">Price</th>\n <th className=\"px-4 py-3 text-right font-medium\">Qty</th>\n </tr>\n </thead>\n <tbody>\n {assets.map((a) => (\n <tr key={a.id} onClick={() => router.push(`/backend/cpq/inventory/assets/${a.id}`)} className=\"border-b cursor-pointer hover:bg-muted/30 transition-colors\">\n <td className=\"px-4 py-3 text-muted-foreground\">{a.code}</td>\n <td className=\"px-4 py-3 font-medium text-primary\">{a.name}</td>\n <td className=\"px-4 py-3\">{a.assetType.replace(/_/g, ' ')}</td>\n <td className=\"px-4 py-3\"><StatusBadge status={a.status} /></td>\n <td className=\"px-4 py-3 text-right font-mono\">{fmt(a.purchasePrice, a.currencyCode || currency)}</td>\n <td className=\"px-4 py-3 text-right font-mono\">{a.quantity}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </div>\n </div>\n )\n}\n\ntype FlatItem = SubscriptionItem & { _depth: number }\n\nfunction flattenItems(items: SubscriptionItem[], depth = 0): FlatItem[] {\n const result: FlatItem[] = []\n for (const item of items) {\n result.push({ ...item, _depth: depth })\n if (item.children && item.children.length > 0) {\n result.push(...flattenItems(item.children, depth + 1))\n }\n }\n return result\n}\n\nfunction Field({ label, value, mono }: { label: string; value: string; mono?: boolean }) {\n return (\n <div>\n <p className=\"text-xs text-muted-foreground\">{label}</p>\n <p className={`text-sm ${mono ? 'font-mono' : ''}`}>{value}</p>\n </div>\n )\n}\n\n// Field for a foreign-key reference: shows the resolved display name as\n// a primary-coloured link, falling back to a short UUID until the name\n// lands. Clicking navigates to the referenced record.\nfunction RefField({\n label,\n name,\n fallback,\n onClick,\n}: {\n label: string\n name: string | undefined\n fallback: string\n onClick: () => void\n}) {\n return (\n <div>\n <p className=\"text-xs text-muted-foreground\">{label}</p>\n <button\n type=\"button\"\n onClick={onClick}\n className=\"text-sm text-primary hover:underline text-left truncate max-w-full\"\n title={name ?? fallback}\n >\n {name ?? `${fallback.slice(0, 12)}\u2026`}\n </button>\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 }: { message: string }) {\n return <Alert variant=\"destructive\">{message}</Alert>\n}\n\n// XD-250 \u2014 render the per-line summary of an ARC change, with inline product\n// names and before/after MRC values. Falls back gracefully when snapshots are\n// missing (older log rows) or when lineChanges is null (cancel / merge).\nfunction ChangeLogLineDetails({ row, currency }: { row: ChangeLogRow; currency: string }) {\n const beforeItems = new Map<string, SnapshotItem>(\n (row.beforeSnapshot?.items ?? []).map((it) => [it.id, it]),\n )\n const afterItems = new Map<string, SnapshotItem>(\n (row.afterSnapshot?.items ?? []).map((it) => [it.id, it]),\n )\n\n type DerivedChange = {\n key: string\n action: 'add' | 'modify' | 'cancel'\n name: string\n beforeMrc: number | null\n afterMrc: number | null\n delta: number | null\n }\n\n const derived: DerivedChange[] = []\n\n if (row.lineChanges && row.lineChanges.length > 0) {\n for (let i = 0; i < row.lineChanges.length; i++) {\n const lc = row.lineChanges[i]\n const itemId = lc.itemId ?? ''\n const before = beforeItems.get(itemId)\n const after = afterItems.get(itemId)\n const item = after ?? before\n const beforeMrc = before ? Number(before.mrcAmount ?? 0) : null\n const afterMrc = after ? Number(after.mrcAmount ?? 0) : null\n const explicitDelta = lc.mrcDelta != null ? Number(lc.mrcDelta) : null\n const computedDelta =\n beforeMrc != null && afterMrc != null ? afterMrc - beforeMrc : null\n derived.push({\n key: `${itemId}-${i}`,\n action: lc.action,\n name: item?.name ?? (lc.action === 'add' ? 'New item' : 'Item'),\n beforeMrc,\n afterMrc:\n lc.action === 'add' && afterMrc == null && lc.mrcAmount != null\n ? Number(lc.mrcAmount)\n : afterMrc,\n delta: explicitDelta ?? computedDelta,\n })\n }\n } else if (row.changeType === 'cancel' && row.beforeSnapshot?.items) {\n // applyCancel writes lineChanges=null; surface the items that got terminated.\n for (const it of row.beforeSnapshot.items) {\n const mrc = Number(it.mrcAmount ?? 0)\n derived.push({\n key: it.id,\n action: 'cancel',\n name: it.name ?? 'Item',\n beforeMrc: mrc,\n afterMrc: 0,\n delta: -mrc,\n })\n }\n } else if (row.changeType === 'merge-result' && row.afterSnapshot?.items) {\n for (const it of row.afterSnapshot.items) {\n const mrc = Number(it.mrcAmount ?? 0)\n derived.push({\n key: it.id,\n action: 'add',\n name: it.name ?? 'Item',\n beforeMrc: null,\n afterMrc: mrc,\n delta: null,\n })\n }\n } else if (row.changeType === 'merge-source' && row.beforeSnapshot?.items) {\n for (const it of row.beforeSnapshot.items) {\n const mrc = Number(it.mrcAmount ?? 0)\n derived.push({\n key: it.id,\n action: 'cancel',\n name: it.name ?? 'Item',\n beforeMrc: mrc,\n afterMrc: 0,\n delta: -mrc,\n })\n }\n }\n\n if (derived.length === 0) {\n // Amend / renew without any actual line edits \u2014 service writes lineChanges=[]\n // because line 1641 of cpqInventoryService.applyLineChanges only records modify\n // entries with a real delta. Show an explicit note so the operator knows\n // the activation happened but nothing on items moved.\n if (row.changeType === 'amend' || row.changeType === 'renew') {\n return (\n <div className=\"mt-1.5 text-xs text-muted-foreground italic\">\n No item-level changes recorded.\n </div>\n )\n }\n return null\n }\n\n return (\n <div className=\"mt-1.5 rounded border bg-muted/20 px-3 py-2 space-y-1\">\n {derived.map((d) => (\n <ChangeLogLineRow key={d.key} change={d} currency={currency} />\n ))}\n </div>\n )\n}\n\nconst ACTION_GLYPH: Record<'add' | 'modify' | 'cancel', { sign: string; color: string; label: string }> = {\n add: { sign: '+', color: 'text-status-success-text', label: 'added' },\n modify: { sign: '~', color: 'text-status-info-text', label: 'modified' },\n cancel: { sign: '\u2212', color: 'text-destructive', label: 'removed' },\n}\n\nfunction ChangeLogLineRow({\n change,\n currency,\n}: {\n change: {\n action: 'add' | 'modify' | 'cancel'\n name: string\n beforeMrc: number | null\n afterMrc: number | null\n delta: number | null\n }\n currency: string\n}) {\n const glyph = ACTION_GLYPH[change.action]\n const showPriceChange =\n change.action === 'modify' &&\n change.beforeMrc != null &&\n change.afterMrc != null &&\n change.beforeMrc !== change.afterMrc\n const showSinglePrice =\n !showPriceChange &&\n ((change.action === 'add' && change.afterMrc != null && change.afterMrc > 0) ||\n (change.action === 'cancel' && change.beforeMrc != null && change.beforeMrc > 0))\n const showDelta = change.delta != null && change.delta !== 0\n const isNoopModify =\n change.action === 'modify' && !showPriceChange && !showDelta\n\n return (\n <div className=\"flex flex-wrap items-center gap-x-2 gap-y-0.5 text-xs\">\n <span className={`font-bold w-3 text-center ${glyph.color}`} title={glyph.label}>\n {glyph.sign}\n </span>\n <span className=\"font-medium text-foreground\">{change.name}</span>\n {showPriceChange && (\n <span className=\"font-mono text-muted-foreground\">\n {fmt(change.beforeMrc!, currency)} \u2192 {fmt(change.afterMrc!, currency)}/mo\n </span>\n )}\n {showSinglePrice && change.action === 'add' && (\n <span className=\"font-mono text-muted-foreground\">\n {fmt(change.afterMrc!, currency)}/mo\n </span>\n )}\n {showSinglePrice && change.action === 'cancel' && (\n <span className=\"font-mono text-muted-foreground\">\n was {fmt(change.beforeMrc!, currency)}/mo\n </span>\n )}\n {showDelta && (\n <span\n className={`font-mono font-medium ${change.delta! > 0 ? 'text-status-success-text' : 'text-destructive'}`}\n >\n ({change.delta! > 0 ? '+' : ''}\n {fmt(change.delta!, currency)}/mo)\n </span>\n )}\n {isNoopModify && (\n <span className=\"text-muted-foreground italic\">no price change</span>\n )}\n </div>\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 { useT, type TranslateFn } from '@open-mercato/shared/lib/i18n/context'\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 subscriptionStatusMap,\n type SubscriptionStatus,\n} from '../../../../../components/statusMaps'\nimport { StatusPath } from '../../../../../components/StatusPath'\nimport { DepthBadge, PriceWaterfall } from '../../../../../components/PriceWaterfall'\nimport { parseStoredCharge } from '../../../../../lib/priceAdjustmentView'\nimport { buildInventoryStatusLabels, inventoryStatusLabel } from '../../shared'\n\n// XD-250 \u2014 ARC integration on subscription detail.\n// \u2022 header buttons (Amend / Renew / Cancel) call /from-subscription\n// and redirect to the new ARC quote\n// \u2022 \"Change History\" section reads /change-log\n\ntype SnapshotItem = {\n id: string\n name?: string\n mrcAmount?: number | string\n nrcAmount?: number | string\n quantity?: number\n status?: string\n}\n\ntype SubscriptionSnapshot = {\n id?: string\n currencyCode?: string\n items?: SnapshotItem[]\n} | null\n\ntype LineChangeEntry = {\n action: 'add' | 'modify' | 'cancel'\n itemId?: string\n quoteLineId?: string | null\n mrcDelta?: number\n mrcAmount?: number\n nrcAmount?: number\n quantity?: number\n}\n\ntype ChangeLogRow = {\n id: string\n changeType: string\n sourceQuoteId: string | null\n sourceOrderId: string | null\n performedByUserId: string | null\n effectiveAt: string\n createdAt: string\n reasonCode: string | null\n reasonText: string | null\n etfAmount: string | null\n etfCurrency: string | null\n termChange: Record<string, unknown> | null\n lineChanges: LineChangeEntry[] | null\n beforeSnapshot: SubscriptionSnapshot\n afterSnapshot: SubscriptionSnapshot\n mergedIntoSubscriptionId: string | null\n mergedFromSubscriptionIds: string[] | null\n}\n\nfunction changeTypeLabel(t: TranslateFn, changeType: string): string {\n switch (changeType) {\n case 'created': return t('cpq.inventory.subscriptions.detail.changeType.created', 'Created')\n case 'amend': return t('cpq.inventory.subscriptions.detail.changeType.amend', 'Amended')\n case 'renew': return t('cpq.inventory.subscriptions.detail.changeType.renew', 'Renewed')\n case 'cancel': return t('cpq.inventory.subscriptions.detail.changeType.cancel', 'Cancelled')\n case 'merge-result': return t('cpq.inventory.subscriptions.detail.changeType.mergeResult', 'Created from merging contracts')\n case 'merge-source': return t('cpq.inventory.subscriptions.detail.changeType.mergeSource', 'Merged into a new contract')\n default: return changeType\n }\n}\n\nconst CHANGE_TYPE_VARIANTS: Record<string, 'info' | 'success' | 'error' | 'brand' | 'warning' | 'neutral'> = {\n created: 'neutral',\n amend: 'info',\n renew: 'success',\n cancel: 'error',\n 'merge-result': 'brand',\n 'merge-source': 'warning',\n}\n\ntype SubscriptionItem = {\n id: string\n subscriptionId: string\n parentItemId: string | null\n productId: string | null\n offeringId: string | null\n specId: string | null\n name: string\n status: string\n configuration: Record<string, unknown>\n charges: Array<Record<string, unknown>> | null\n mrcAmount: number\n nrcAmount: number\n currencyCode: string\n quantity: number\n capacityTotal: string | null\n capacityUsed: string | null\n capacityUnit: string | null\n sourceQuoteLineId: string | null\n metadata: Record<string, unknown> | null\n sortOrder: number\n createdAt: string\n updatedAt: string\n children?: SubscriptionItem[]\n}\n\ntype LinkedAsset = {\n id: string\n code: string\n name: string\n status: string\n assetType: string\n currencyCode: string\n purchasePrice: number\n quantity: number\n subscriptionItemId: string | null\n createdAt: string\n}\n\ntype SubscriptionDetail = {\n id: string\n customerId: string\n code: string\n name: string\n description: string | null\n status: string\n billingCycle: string\n currencyCode: string\n mrcAmount: number\n nrcAmount: number\n startDate: string | null\n currentTermEnd: string | null\n termMonths: number | null\n autoRenew: boolean\n activatedAt: string | null\n suspendedAt: string | null\n terminatedAt: string | null\n pricingSummary: Record<string, unknown> | null\n sourceQuoteId: string | null\n sourceOrderId: string | null\n metadata: Record<string, unknown> | null\n createdAt: string\n updatedAt: string\n items: SubscriptionItem[]\n}\n\nconst ALLOWED_TRANSITIONS: Record<string, string[]> = {\n pending: ['active', 'terminated'],\n active: ['suspended', 'terminated', 'expired'],\n suspended: ['active', 'terminated'],\n terminated: [],\n expired: [],\n}\n\nconst SUBSCRIPTION_STATUSES = ['pending', 'active', 'suspended', 'terminated', 'expired'] as const\n\nfunction fmt(amount: number | string, currency: string): string {\n return new Intl.NumberFormat('en-US', { style: 'currency', currency }).format(Number(amount))\n}\n\nfunction StatusBadge({ status }: { status: string }) {\n const t = useT()\n return (\n <Tag variant={subscriptionStatusMap[status as SubscriptionStatus] ?? 'neutral'} dot>\n {inventoryStatusLabel(t, status)}\n </Tag>\n )\n}\n\nexport default function SubscriptionDetailPage(props: { params?: { id?: string } }) {\n const t = useT()\n const router = useRouter()\n const urlParams = useParams()\n const subId = (props.params?.id ?? urlParams?.id) as string\n\n const [sub, setSub] = React.useState<SubscriptionDetail | null>(null)\n const [loading, setLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [customerName, setCustomerName] = React.useState<string | null>(null)\n const [assets, setAssets] = React.useState<LinkedAsset[]>([])\n const [expandedItems, setExpandedItems] = React.useState<Set<string>>(new Set())\n const [transitioning, setTransitioning] = React.useState(false)\n // Resolved display names for ID references \u2014 fetched alongside the main\n // subscription record so the UI never shows \"62e90a3d\u2026\" placeholders.\n const [sourceQuoteNumber, setSourceQuoteNumber] = React.useState<string | null>(null)\n const [sourceOrderNumber, setSourceOrderNumber] = React.useState<string | null>(null)\n const [productNames, setProductNames] = React.useState<Record<string, string>>({})\n const [offeringNames, setOfferingNames] = React.useState<Record<string, string>>({})\n const [specNames, setSpecNames] = React.useState<Record<string, string>>({})\n // Resolved quote / order numbers per change log row (id \u2192 number).\n const [logQuoteNumbers, setLogQuoteNumbers] = React.useState<Record<string, string>>({})\n const [logOrderNumbers, setLogOrderNumbers] = React.useState<Record<string, string>>({})\n // XD-250 ARC state\n const [arcInFlight, setArcInFlight] = React.useState<'amend' | 'renew' | 'cancel' | null>(null)\n const [changeLog, setChangeLog] = React.useState<ChangeLogRow[]>([])\n const [changeLogLoading, setChangeLogLoading] = React.useState(false)\n\n const startArcQuote = React.useCallback(\n async (type: 'amend' | 'renew' | 'cancel') => {\n if (!sub) return\n setArcInFlight(type)\n try {\n const res = await fetch('/api/cpq/quotes/from-subscription', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ subscriptionId: sub.id, type }),\n })\n if (!res.ok) {\n const body = await res.json().catch(() => ({})) as { error?: string; existingQuoteId?: string }\n // XD-250 spec \u00A7 UI: when the subscription already has a non-terminal\n // ARC quote attached, the server returns 409 with `existingQuoteId`.\n // Offer to navigate to that quote instead of showing a dead alert.\n if (body.existingQuoteId) {\n const ok = window.confirm(\n t('cpq.inventory.subscriptions.detail.arc.existingQuoteConfirm', '{error}\\n\\nOpen the existing quote now?', {\n error: body.error ?? t('cpq.inventory.subscriptions.detail.arc.existingQuoteInProgress', 'Subscription has another ARC quote in progress.'),\n }),\n )\n if (ok) {\n router.push(`/backend/cpq/quotes/${body.existingQuoteId}`)\n }\n return\n }\n alert(t('cpq.inventory.subscriptions.detail.arc.startFailed', 'Failed to start {type} quote: {error}', { type, error: body.error ?? res.statusText }))\n return\n }\n const data = await res.json()\n router.push(`/backend/cpq/quotes/${data.quoteId}`)\n } finally {\n setArcInFlight(null)\n }\n },\n [router, sub, t],\n )\n\n const transitionStatus = async (targetStatus: string) => {\n if (!sub) return\n try {\n setTransitioning(true)\n setError(null)\n const res = await fetch('/api/cpq/inventory/subscriptions/status', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ id: sub.id, targetStatus }),\n })\n const data = await res.json()\n if (!res.ok) throw new Error(data?.error ?? t('cpq.inventory.subscriptions.detail.error.transitionFailed', 'Status transition failed'))\n // The status endpoint cascades to items and linked assets server-side,\n // but only returns the subscription scalar fields. Re-fetch the full\n // detail (which includes the item tree) and the asset list so the UI\n // reflects every cascaded change without a hard refresh.\n const [freshSub, freshAssets] = await Promise.all([\n fetch(`/api/cpq/inventory/subscriptions?id=${sub.id}`).then((r) => (r.ok ? r.json() : null)),\n fetch(`/api/cpq/inventory/assets?subscriptionId=${sub.id}&pageSize=50`)\n .then((r) => (r.ok ? r.json() : null))\n .then((r) => (r?.items ?? []) as LinkedAsset[]),\n ])\n if (freshSub) {\n setSub(freshSub)\n } else {\n setSub((prev) => prev ? { ...prev, ...data } : prev)\n }\n setAssets(freshAssets)\n } catch (err) {\n setError((err as Error).message)\n } finally {\n setTransitioning(false)\n }\n }\n\n React.useEffect(() => {\n let cancelled = false\n async function loadLog() {\n setChangeLogLoading(true)\n try {\n const r = await fetch(`/api/cpq/inventory/subscriptions/${subId}/change-log?pageSize=50`)\n if (r.ok && !cancelled) {\n const data = await r.json()\n const rows: ChangeLogRow[] = data.items ?? []\n setChangeLog(rows)\n // Resolve the quote / order numbers referenced by each row so\n // the history list shows \"Quote QUOTE-\u2026-00005\" instead of\n // \"Quote 270b8e08\u2026\".\n const qIds = new Set(rows.map((r2) => r2.sourceQuoteId).filter((x): x is string => !!x))\n const oIds = new Set(rows.map((r2) => r2.sourceOrderId).filter((x): x is string => !!x))\n for (const qId of qIds) {\n fetch(`/api/cpq/quotes/${qId}`)\n .then((r2) => (r2.ok ? r2.json() : null))\n .then((q) => {\n if (q?.quoteNumber && !cancelled) {\n setLogQuoteNumbers((prev) => ({ ...prev, [qId]: q.quoteNumber }))\n }\n })\n .catch(() => {})\n }\n for (const oId of oIds) {\n fetch(`/api/cpq/orders/${oId}`)\n .then((r2) => (r2.ok ? r2.json() : null))\n .then((o) => {\n if (o?.orderNumber && !cancelled) {\n setLogOrderNumbers((prev) => ({ ...prev, [oId]: o.orderNumber }))\n }\n })\n .catch(() => {})\n }\n }\n } finally {\n if (!cancelled) setChangeLogLoading(false)\n }\n }\n if (subId) void loadLog()\n return () => { cancelled = true }\n }, [subId])\n\n React.useEffect(() => {\n let cancelled = false\n async function load() {\n try {\n const res = await fetch(`/api/cpq/inventory/subscriptions?id=${subId}`)\n if (!res.ok) throw new Error(t('cpq.inventory.subscriptions.detail.error.notFound', 'Subscription not found'))\n const data: SubscriptionDetail = await res.json()\n if (!cancelled) {\n setSub(data)\n fetch(`/api/customers/companies?id=${data.customerId}&pageSize=1`)\n .then((r) => r.json())\n .then((result) => {\n const items = result.items ?? result ?? []\n const c = items[0]\n if (c && !cancelled) setCustomerName(c.display_name || c.displayName || c.name || null)\n })\n .catch(() => {})\n fetch(`/api/cpq/inventory/assets?subscriptionId=${subId}&pageSize=50`)\n .then((r) => r.json())\n .then((result) => {\n if (!cancelled) setAssets(result.items ?? [])\n })\n .catch(() => {})\n\n // Resolve display names for the ID references shown in the\n // header and on every item row. Each lookup is fire-and-forget;\n // the UI falls back to a short UUID until the name lands.\n if (data.sourceQuoteId) {\n fetch(`/api/cpq/quotes/${data.sourceQuoteId}`)\n .then((r) => (r.ok ? r.json() : null))\n .then((q) => {\n if (q && !cancelled) setSourceQuoteNumber(q.quoteNumber ?? null)\n })\n .catch(() => {})\n }\n if (data.sourceOrderId) {\n fetch(`/api/cpq/orders/${data.sourceOrderId}`)\n .then((r) => (r.ok ? r.json() : null))\n .then((o) => {\n if (o && !cancelled) setSourceOrderNumber(o.orderNumber ?? null)\n })\n .catch(() => {})\n }\n\n // For items, dedupe IDs across the tree and resolve each once.\n const flatChildren = (nodes: SubscriptionItem[]): SubscriptionItem[] =>\n nodes.flatMap((n) => [n, ...flatChildren(n.children ?? [])])\n const allItems = flatChildren(data.items ?? [])\n const productIds = new Set(allItems.map((i) => i.productId).filter((x): x is string => !!x))\n const offeringIds = new Set(allItems.map((i) => i.offeringId).filter((x): x is string => !!x))\n const specIds = new Set(allItems.map((i) => i.specId).filter((x): x is string => !!x))\n\n for (const offeringId of offeringIds) {\n fetch(`/api/cpq/product-offerings?id=${offeringId}`)\n .then((r) => (r.ok ? r.json() : null))\n .then((o) => {\n if (!o || cancelled) return\n if (o.name) setOfferingNames((prev) => ({ ...prev, [offeringId]: o.name }))\n if (o.specification?.name) setSpecNames((prev) => ({ ...prev, [o.specification.id]: o.specification.name }))\n })\n .catch(() => {})\n }\n for (const specId of specIds) {\n fetch(`/api/cpq/product-specifications?id=${specId}`)\n .then((r) => (r.ok ? r.json() : null))\n .then((s) => {\n if (s?.name && !cancelled) setSpecNames((prev) => ({ ...prev, [specId]: s.name }))\n })\n .catch(() => {})\n }\n for (const productId of productIds) {\n // Catalog products route is paginated \u2014 `?id=\u2026` filters to one\n // row but the response is still `{ items: [\u2026] }`.\n fetch(`/api/catalog/products?id=${productId}`)\n .then((r) => (r.ok ? r.json() : null))\n .then((res) => {\n if (!res || cancelled) return\n const p = (res.items ?? res)[0] ?? res\n const name = p?.title ?? p?.name ?? p?.handle ?? null\n if (name) setProductNames((prev) => ({ ...prev, [productId]: name }))\n })\n .catch(() => {})\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 }, [subId, t])\n\n const toggleItem = (id: string) => {\n setExpandedItems((prev) => { const n = new Set(prev); n.has(id) ? n.delete(id) : n.add(id); return n })\n }\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.inventory.subscriptions.detail.loading', 'Loading\u2026')}\n </div>\n )\n }\n\n if (!sub) {\n return (\n <div className=\"space-y-4\">\n <button onClick={() => router.push('/backend/cpq/inventory')} className=\"text-sm text-muted-foreground hover:text-foreground\">\u2190 {t('cpq.common.back', 'Back')}</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.inventory.subscriptions.detail.notFound', 'Subscription not found.')}</div>\n </div>\n )\n }\n\n const currency = sub.currencyCode || 'USD'\n const flatItems = flattenItems(sub.items)\n\n const canArc = sub.status === 'active' || sub.status === 'suspended'\n const statusTransitions = ALLOWED_TRANSITIONS[sub.status] ?? []\n const statusLabels = buildInventoryStatusLabels(t, SUBSCRIPTION_STATUSES)\n\n return (\n <div className=\"space-y-6\">\n {/* Header \u2014 standard FormHeader detail mode, mirrors the CPQ quote /\n order layout. Title is the human subscription name; status /\n cycle tags sit under it; ARC actions (Amend / Renew / Cancel)\n + a \"Change status\" dropdown live on the right. The short\n subscription code lives in the Subscription Details card\n below \u2014 it's reference info, not header content. */}\n <FormHeader\n mode=\"detail\"\n backHref=\"/backend/cpq/inventory\"\n backLabel={t('cpq.inventory.detail.backToInventory', 'Back to Customer Inventory')}\n entityTypeLabel={t('cpq.inventory.subscriptions.detail.entityType', 'Subscription')}\n title={sub.name}\n statusBadge={\n <div className=\"flex flex-wrap items-center gap-2 pt-1\">\n <Tag variant={subscriptionStatusMap[sub.status as SubscriptionStatus] ?? 'neutral'} dot>\n {inventoryStatusLabel(t, sub.status)}\n </Tag>\n <Tag variant=\"neutral\" className=\"capitalize\">{sub.billingCycle}</Tag>\n {transitioning && <Spinner />}\n </div>\n }\n actionsContent={\n canArc ? (\n <>\n <Button\n type=\"button\"\n variant=\"outline\"\n disabled={arcInFlight !== null}\n onClick={() => startArcQuote('amend')}\n >\n {t('cpq.inventory.subscriptions.detail.arc.amend', 'Amend')}\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n disabled={arcInFlight !== null}\n onClick={() => startArcQuote('renew')}\n >\n {t('cpq.inventory.subscriptions.detail.arc.renew', 'Renew')}\n </Button>\n <Button\n type=\"button\"\n variant=\"destructive-outline\"\n disabled={arcInFlight !== null}\n onClick={() => startArcQuote('cancel')}\n >\n {t('cpq.inventory.subscriptions.detail.arc.cancel', 'Cancel')}\n </Button>\n </>\n ) : null\n }\n />\n\n {/* Status path \u2014 visual progress only, like the order page.\n Transitions still happen via the dedicated endpoints. */}\n <div className=\"flex items-center gap-3 flex-wrap\">\n <StatusPath\n current={sub.status}\n path={['pending', 'active']}\n terminals={['suspended', 'terminated', 'expired']}\n statusMap={subscriptionStatusMap}\n labels={statusLabels}\n onTransition={transitionStatus}\n allowedTransitions={statusTransitions}\n disabled={transitioning}\n ariaLabel={t('cpq.inventory.subscriptions.detail.statusPath', 'Subscription status path')}\n />\n </div>\n\n {error && <ErrorBanner message={error} />}\n\n {/* Detail Cards */}\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div className=\"rounded-lg border bg-card p-4 space-y-3\">\n <h3 className=\"text-sm font-medium\">{t('cpq.inventory.subscriptions.detail.sections.details', 'Subscription Details')}</h3>\n <div className=\"grid grid-cols-2 gap-x-4 gap-y-2\">\n <Field label={t('cpq.inventory.subscriptions.detail.fields.code', 'Code')} value={sub.code} mono />\n <Field label={t('cpq.inventory.subscriptions.detail.fields.status', 'Status')} value={sub.status} />\n <Field label={t('cpq.inventory.subscriptions.detail.fields.billingCycle', 'Billing Cycle')} value={sub.billingCycle} />\n <Field label={t('cpq.inventory.subscriptions.detail.fields.currency', 'Currency')} value={currency} />\n <Field label={t('cpq.inventory.subscriptions.detail.fields.autoRenew', 'Auto-Renew')} value={sub.autoRenew ? t('cpq.common.yes', 'Yes') : t('cpq.common.no', 'No')} />\n {sub.termMonths != null && <Field label={t('cpq.inventory.subscriptions.detail.fields.term', 'Term')} value={t('cpq.inventory.subscriptions.detail.fields.termMonths', '{count} months', { count: sub.termMonths })} />}\n {sub.startDate && <Field label={t('cpq.inventory.subscriptions.detail.fields.startDate', 'Start Date')} value={new Date(sub.startDate).toLocaleDateString()} />}\n {sub.currentTermEnd && <Field label={t('cpq.inventory.subscriptions.detail.fields.termEnd', 'Term End')} value={new Date(sub.currentTermEnd).toLocaleDateString()} />}\n {sub.activatedAt && <Field label={t('cpq.inventory.subscriptions.detail.fields.activated', 'Activated')} value={new Date(sub.activatedAt).toLocaleString()} />}\n {sub.suspendedAt && <Field label={t('cpq.inventory.subscriptions.detail.fields.suspended', 'Suspended')} value={new Date(sub.suspendedAt).toLocaleString()} />}\n {sub.terminatedAt && <Field label={t('cpq.inventory.subscriptions.detail.fields.terminated', 'Terminated')} value={new Date(sub.terminatedAt).toLocaleString()} />}\n </div>\n {sub.description && (\n <div className=\"pt-1\">\n <p className=\"text-xs text-muted-foreground\">{t('cpq.inventory.subscriptions.detail.fields.description', 'Description')}</p>\n <p className=\"text-sm\">{sub.description}</p>\n </div>\n )}\n </div>\n\n <div className=\"rounded-lg border bg-card p-4 space-y-3\">\n <h3 className=\"text-sm font-medium\">{t('cpq.inventory.subscriptions.detail.sections.pricing', 'Pricing & References')}</h3>\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <p className=\"text-xs text-muted-foreground\">{t('cpq.inventory.subscriptions.detail.fields.mrc', 'Monthly Recurring (MRC)')}</p>\n <p className=\"text-lg font-semibold font-mono\">{fmt(sub.mrcAmount, currency)}</p>\n </div>\n <div>\n <p className=\"text-xs text-muted-foreground\">{t('cpq.inventory.subscriptions.detail.fields.nrc', 'Non-Recurring (NRC)')}</p>\n <p className=\"text-lg font-semibold font-mono\">{fmt(sub.nrcAmount, currency)}</p>\n </div>\n </div>\n <div className=\"grid grid-cols-2 gap-x-4 gap-y-2 pt-1\">\n <Field label={t('cpq.inventory.subscriptions.detail.fields.customer', 'Customer')} value={customerName ?? sub.customerId.slice(0, 12) + '\u2026'} />\n <Field label={t('cpq.inventory.subscriptions.detail.fields.created', 'Created')} value={new Date(sub.createdAt).toLocaleString()} />\n {sub.sourceQuoteId && (\n <div>\n <p className=\"text-xs text-muted-foreground\">{t('cpq.inventory.subscriptions.detail.fields.sourceQuote', 'Source Quote')}</p>\n <button\n onClick={() => router.push(`/backend/cpq/quotes/${sub.sourceQuoteId}`)}\n className=\"text-sm text-primary hover:underline\"\n >\n {sourceQuoteNumber ?? `${sub.sourceQuoteId.slice(0, 8)}\u2026`}\n </button>\n </div>\n )}\n {sub.sourceOrderId && (\n <div>\n <p className=\"text-xs text-muted-foreground\">{t('cpq.inventory.subscriptions.detail.fields.sourceOrder', 'Source Order')}</p>\n <button\n onClick={() => router.push(`/backend/cpq/orders/${sub.sourceOrderId}`)}\n className=\"text-sm text-primary hover:underline\"\n >\n {sourceOrderNumber ?? `${sub.sourceOrderId.slice(0, 8)}\u2026`}\n </button>\n </div>\n )}\n </div>\n </div>\n </div>\n\n {/* Metadata */}\n {sub.metadata && Object.keys(sub.metadata).length > 0 && (\n <div className=\"rounded-lg border bg-card p-4\">\n <h3 className=\"text-sm font-medium mb-2\">{t('cpq.inventory.subscriptions.detail.sections.metadata', 'Metadata')}</h3>\n <div className=\"grid grid-cols-2 sm:grid-cols-3 gap-x-4 gap-y-1\">\n {Object.entries(sub.metadata).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 {/* Subscription Items */}\n <div>\n <h3 className=\"text-sm font-medium mb-2 px-1\">{t('cpq.inventory.subscriptions.detail.items.title', 'Subscription Items ({count})', { count: flatItems.length })}</h3>\n {flatItems.length === 0 ? (\n <div className=\"rounded-lg border bg-card py-8 text-center text-sm text-muted-foreground\">{t('cpq.inventory.subscriptions.detail.items.empty', 'No items.')}</div>\n ) : (\n <div className=\"rounded-lg border bg-card divide-y\">\n {flatItems.map((item) => {\n const isExpanded = expandedItems.has(item.id)\n const indent = item._depth ?? 0\n return (\n <div key={item.id}>\n <div\n className=\"flex items-center gap-3 px-4 py-3 hover:bg-muted/30 transition-colors cursor-pointer\"\n style={{ paddingLeft: `${16 + indent * 24}px` }}\n onClick={() => toggleItem(item.id)}\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 <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium text-sm\">{item.name}</span>\n {item.quantity > 1 && <span className=\"rounded bg-muted px-1.5 py-0.5 text-xs font-medium\">x{item.quantity}</span>}\n <StatusBadge status={item.status} />\n </div>\n </div>\n <div className=\"shrink-0 text-right text-xs space-y-0.5\">\n {Number(item.mrcAmount) > 0 && <div><span className=\"text-muted-foreground\">{t('cpq.inventory.subscriptions.detail.items.mrc', 'MRC')}{' '}</span><span className=\"font-mono font-medium\">{fmt(item.mrcAmount, item.currencyCode || currency)}</span></div>}\n {Number(item.nrcAmount) > 0 && <div><span className=\"text-muted-foreground\">{t('cpq.inventory.subscriptions.detail.items.nrc', 'NRC')}{' '}</span><span className=\"font-mono font-medium\">{fmt(item.nrcAmount, item.currencyCode || currency)}</span></div>}\n </div>\n </div>\n\n {isExpanded && (\n <div className=\"border-t bg-muted/10 px-12 py-3 space-y-3\" style={{ paddingLeft: `${40 + indent * 24}px` }}>\n <div className=\"grid grid-cols-2 sm:grid-cols-3 gap-x-4 gap-y-2\">\n {item.offeringId && (\n <RefField\n label={t('cpq.inventory.subscriptions.detail.fields.offering', 'Offering')}\n name={offeringNames[item.offeringId]}\n fallback={item.offeringId}\n onClick={() => router.push(`/backend/cpq/offerings/${item.offeringId}`)}\n />\n )}\n {item.specId && (\n <RefField\n label={t('cpq.inventory.subscriptions.detail.fields.specification', 'Specification')}\n name={specNames[item.specId]}\n fallback={item.specId}\n onClick={() => router.push(`/backend/cpq/specifications/${item.specId}`)}\n />\n )}\n {item.productId && (\n <RefField\n label={t('cpq.inventory.subscriptions.detail.fields.product', 'Product')}\n name={productNames[item.productId]}\n fallback={item.productId}\n onClick={() => router.push(`/backend/catalog/products/${item.productId}`)}\n />\n )}\n <Field label={t('cpq.inventory.subscriptions.detail.fields.currency', 'Currency')} value={item.currencyCode || currency} />\n <Field label={t('cpq.inventory.subscriptions.detail.fields.quantity', 'Quantity')} value={String(item.quantity)} />\n {item.capacityTotal && <Field label={t('cpq.inventory.subscriptions.detail.fields.capacity', 'Capacity')} value={`${item.capacityUsed ?? '0'} / ${item.capacityTotal} ${item.capacityUnit ?? ''}`} />}\n </div>\n\n {item.configuration && Object.keys(item.configuration).length > 0 && (\n <div>\n <p className=\"text-xs font-medium text-muted-foreground mb-1\">{t('cpq.inventory.subscriptions.detail.items.configuration', 'Configuration')}</p>\n <div className=\"grid grid-cols-2 sm:grid-cols-3 gap-x-4 gap-y-1\">\n {Object.entries(item.configuration).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 {item.charges && item.charges.length > 0 && (\n <div>\n <p className=\"text-xs font-medium text-muted-foreground mb-1\">{t('cpq.inventory.subscriptions.detail.items.charges', 'Charges')}</p>\n <table className=\"w-full text-xs\">\n <thead>\n <tr className=\"text-muted-foreground\">\n <th className=\"text-left py-1 font-medium\">{t('cpq.inventory.subscriptions.detail.charges.charge', 'Charge')}</th>\n <th className=\"text-left py-1 font-medium\">{t('cpq.inventory.subscriptions.detail.charges.type', 'Type')}</th>\n <th className=\"text-right py-1 font-medium\">{t('cpq.inventory.subscriptions.detail.charges.list', 'List')}</th>\n <th className=\"text-right py-1 font-medium\">{t('cpq.inventory.subscriptions.detail.charges.offer', 'Offer')}</th>\n <th className=\"text-right py-1 font-medium\">{t('cpq.inventory.subscriptions.detail.charges.qty', 'Qty')}</th>\n <th className=\"text-right py-1 font-medium\">{t('cpq.inventory.subscriptions.detail.charges.total', 'Total')}</th>\n </tr>\n </thead>\n <tbody>\n {item.charges.map((raw, i) => {\n const c = parseStoredCharge(raw)\n if (!c) return null\n return (\n <React.Fragment key={i}>\n <tr className=\"border-t border-dashed border-border/50\">\n <td className=\"py-1\">{c.chargeName}</td>\n <td className=\"py-1 uppercase\">{c.chargeType}</td>\n <td className=\"py-1 text-right font-mono text-muted-foreground\">{fmt(c.listUnitPrice ?? c.unitPrice, currency)}</td>\n <td className=\"py-1 text-right font-mono\">\n <span className=\"inline-flex items-center gap-1\">\n <DepthBadge before={c.listUnitPrice ?? c.unitPrice} after={c.unitPrice} />\n {fmt(c.unitPrice, currency)}\n </span>\n </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) : '\u2014'}</td>\n </tr>\n {(c.adjustments?.length ?? 0) > 0 && (\n <tr>\n <td colSpan={6} className=\"pb-2 pl-4\">\n <PriceWaterfall charge={c} currency={currency} />\n </td>\n </tr>\n )}\n </React.Fragment>\n )\n })}\n </tbody>\n </table>\n </div>\n )}\n\n {item.metadata && Object.keys(item.metadata).length > 0 && (\n <div>\n <p className=\"text-xs font-medium text-muted-foreground mb-1\">{t('cpq.inventory.subscriptions.detail.items.metadata', 'Metadata')}</p>\n <div className=\"grid grid-cols-2 sm:grid-cols-3 gap-x-4 gap-y-1\">\n {Object.entries(item.metadata).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 <div className=\"flex gap-4 text-xs text-muted-foreground\">\n <span>{t('cpq.inventory.subscriptions.detail.items.createdAt', 'Created: {date}', { date: new Date(item.createdAt).toLocaleString() })}</span>\n <span>{t('cpq.inventory.subscriptions.detail.items.updatedAt', 'Updated: {date}', { date: new Date(item.updatedAt).toLocaleString() })}</span>\n </div>\n </div>\n )}\n </div>\n )\n })}\n </div>\n )}\n </div>\n\n {/* XD-250 Change History */}\n <div>\n <h3 className=\"text-sm font-medium mb-2 px-1\">{t('cpq.inventory.subscriptions.detail.changeLog.title', 'Change History ({count})', { count: changeLog.length })}</h3>\n {changeLogLoading ? (\n <div className=\"rounded-lg border bg-card py-6 text-center text-sm text-muted-foreground\">{t('cpq.inventory.subscriptions.detail.loading', 'Loading\u2026')}</div>\n ) : changeLog.length === 0 ? (\n <div className=\"rounded-lg border bg-card py-6 text-center text-sm text-muted-foreground\">{t('cpq.inventory.subscriptions.detail.changeLog.empty', 'No ARC changes yet.')}</div>\n ) : (\n <div className=\"rounded-lg border bg-card divide-y\">\n {changeLog.map((row) => (\n <div key={row.id} className=\"px-4 py-3 space-y-1\">\n <div className=\"flex items-center gap-2\">\n <Tag variant={CHANGE_TYPE_VARIANTS[row.changeType] ?? 'neutral'}>\n {changeTypeLabel(t, row.changeType)}\n </Tag>\n <span className=\"text-xs text-muted-foreground\">\n {new Date(row.effectiveAt).toLocaleString()}\n </span>\n {row.sourceQuoteId && (\n <button\n onClick={() => router.push(`/backend/cpq/quotes/${row.sourceQuoteId}`)}\n className=\"text-xs text-primary hover:underline\"\n >\n {t('cpq.inventory.subscriptions.detail.changeLog.quote', 'Quote {number}', { number: logQuoteNumbers[row.sourceQuoteId] ?? `${row.sourceQuoteId.slice(0, 8)}\u2026` })}\n </button>\n )}\n {row.sourceOrderId && (\n <button\n onClick={() => router.push(`/backend/cpq/orders/${row.sourceOrderId}`)}\n className=\"text-xs text-primary hover:underline\"\n >\n {t('cpq.inventory.subscriptions.detail.changeLog.order', 'Order {number}', { number: logOrderNumbers[row.sourceOrderId] ?? `${row.sourceOrderId.slice(0, 8)}\u2026` })}\n </button>\n )}\n </div>\n <ChangeLogLineDetails row={row} currency={currency} />\n {row.termChange && (\n <div className=\"text-xs text-muted-foreground\">\n {t('cpq.inventory.subscriptions.detail.changeLog.term', 'Term: {from} \u2192 {to}', {\n from: String(row.termChange.oldTermEnd ?? '\u2014'),\n to: String(row.termChange.newTermEnd ?? '\u2014'),\n })}\n </div>\n )}\n {row.reasonCode && (\n <div className=\"text-xs text-muted-foreground\">\n {row.reasonText\n ? t('cpq.inventory.subscriptions.detail.changeLog.reasonWithText', 'Reason: {code} \u2014 {text}', { code: row.reasonCode, text: row.reasonText })\n : t('cpq.inventory.subscriptions.detail.changeLog.reason', 'Reason: {code}', { code: row.reasonCode })}\n </div>\n )}\n {row.etfAmount && (\n <div className=\"text-xs text-muted-foreground\">\n {t('cpq.inventory.subscriptions.detail.changeLog.etf', 'ETF: {amount} {currency}', { amount: row.etfAmount, currency: row.etfCurrency ?? '' })}\n </div>\n )}\n {row.mergedIntoSubscriptionId && (\n <div className=\"text-xs text-muted-foreground\">\n {t('cpq.inventory.subscriptions.detail.changeLog.mergedInto', 'Merged into')}{' '}\n <button\n onClick={() =>\n router.push(`/backend/cpq/inventory/subscriptions/${row.mergedIntoSubscriptionId}`)\n }\n className=\"text-primary hover:underline\"\n >\n {t('cpq.inventory.subscriptions.detail.changeLog.mergedIntoSubscription', 'subscription {id}\u2026', { id: row.mergedIntoSubscriptionId.slice(0, 8) })}\n </button>\n </div>\n )}\n {row.mergedFromSubscriptionIds && row.mergedFromSubscriptionIds.length > 0 && (\n <div className=\"text-xs text-muted-foreground\">\n {t('cpq.inventory.subscriptions.detail.changeLog.mergedFrom', 'Merged from {count} subscriptions', { count: row.mergedFromSubscriptionIds.length })}\n </div>\n )}\n </div>\n ))}\n </div>\n )}\n </div>\n\n {/* Linked Assets */}\n <div>\n <h3 className=\"text-sm font-medium mb-2 px-1\">{t('cpq.inventory.subscriptions.detail.assets.title', 'Linked Assets ({count})', { count: assets.length })}</h3>\n {assets.length === 0 ? (\n <div className=\"rounded-lg border bg-card py-8 text-center text-sm text-muted-foreground\">{t('cpq.inventory.subscriptions.detail.assets.empty', 'No assets linked to this subscription.')}</div>\n ) : (\n <div className=\"rounded-lg border\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b bg-muted/50\">\n <th className=\"px-4 py-3 text-left font-medium\">{t('cpq.inventory.subscriptions.detail.assets.table.code', 'Code')}</th>\n <th className=\"px-4 py-3 text-left font-medium\">{t('cpq.inventory.subscriptions.detail.assets.table.name', 'Name')}</th>\n <th className=\"px-4 py-3 text-left font-medium\">{t('cpq.inventory.subscriptions.detail.assets.table.type', 'Type')}</th>\n <th className=\"px-4 py-3 text-left font-medium\">{t('cpq.inventory.subscriptions.detail.assets.table.status', 'Status')}</th>\n <th className=\"px-4 py-3 text-right font-medium\">{t('cpq.inventory.subscriptions.detail.assets.table.price', 'Price')}</th>\n <th className=\"px-4 py-3 text-right font-medium\">{t('cpq.inventory.subscriptions.detail.assets.table.qty', 'Qty')}</th>\n </tr>\n </thead>\n <tbody>\n {assets.map((a) => (\n <tr key={a.id} onClick={() => router.push(`/backend/cpq/inventory/assets/${a.id}`)} className=\"border-b cursor-pointer hover:bg-muted/30 transition-colors\">\n <td className=\"px-4 py-3 text-muted-foreground\">{a.code}</td>\n <td className=\"px-4 py-3 font-medium text-primary\">{a.name}</td>\n <td className=\"px-4 py-3\">{a.assetType.replace(/_/g, ' ')}</td>\n <td className=\"px-4 py-3\"><StatusBadge status={a.status} /></td>\n <td className=\"px-4 py-3 text-right font-mono\">{fmt(a.purchasePrice, a.currencyCode || currency)}</td>\n <td className=\"px-4 py-3 text-right font-mono\">{a.quantity}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </div>\n </div>\n )\n}\n\ntype FlatItem = SubscriptionItem & { _depth: number }\n\nfunction flattenItems(items: SubscriptionItem[], depth = 0): FlatItem[] {\n const result: FlatItem[] = []\n for (const item of items) {\n result.push({ ...item, _depth: depth })\n if (item.children && item.children.length > 0) {\n result.push(...flattenItems(item.children, depth + 1))\n }\n }\n return result\n}\n\nfunction Field({ label, value, mono }: { label: string; value: string; mono?: boolean }) {\n return (\n <div>\n <p className=\"text-xs text-muted-foreground\">{label}</p>\n <p className={`text-sm ${mono ? 'font-mono' : ''}`}>{value}</p>\n </div>\n )\n}\n\n// Field for a foreign-key reference: shows the resolved display name as\n// a primary-coloured link, falling back to a short UUID until the name\n// lands. Clicking navigates to the referenced record.\nfunction RefField({\n label,\n name,\n fallback,\n onClick,\n}: {\n label: string\n name: string | undefined\n fallback: string\n onClick: () => void\n}) {\n return (\n <div>\n <p className=\"text-xs text-muted-foreground\">{label}</p>\n <button\n type=\"button\"\n onClick={onClick}\n className=\"text-sm text-primary hover:underline text-left truncate max-w-full\"\n title={name ?? fallback}\n >\n {name ?? `${fallback.slice(0, 12)}\u2026`}\n </button>\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 }: { message: string }) {\n return <Alert variant=\"destructive\">{message}</Alert>\n}\n\n// XD-250 \u2014 render the per-line summary of an ARC change, with inline product\n// names and before/after MRC values. Falls back gracefully when snapshots are\n// missing (older log rows) or when lineChanges is null (cancel / merge).\nfunction ChangeLogLineDetails({ row, currency }: { row: ChangeLogRow; currency: string }) {\n const t = useT()\n const itemFallback = t('cpq.inventory.subscriptions.detail.changeLog.item', 'Item')\n const beforeItems = new Map<string, SnapshotItem>(\n (row.beforeSnapshot?.items ?? []).map((it) => [it.id, it]),\n )\n const afterItems = new Map<string, SnapshotItem>(\n (row.afterSnapshot?.items ?? []).map((it) => [it.id, it]),\n )\n\n type DerivedChange = {\n key: string\n action: 'add' | 'modify' | 'cancel'\n name: string\n beforeMrc: number | null\n afterMrc: number | null\n delta: number | null\n }\n\n const derived: DerivedChange[] = []\n\n if (row.lineChanges && row.lineChanges.length > 0) {\n for (let i = 0; i < row.lineChanges.length; i++) {\n const lc = row.lineChanges[i]\n const itemId = lc.itemId ?? ''\n const before = beforeItems.get(itemId)\n const after = afterItems.get(itemId)\n const item = after ?? before\n const beforeMrc = before ? Number(before.mrcAmount ?? 0) : null\n const afterMrc = after ? Number(after.mrcAmount ?? 0) : null\n const explicitDelta = lc.mrcDelta != null ? Number(lc.mrcDelta) : null\n const computedDelta =\n beforeMrc != null && afterMrc != null ? afterMrc - beforeMrc : null\n derived.push({\n key: `${itemId}-${i}`,\n action: lc.action,\n name: item?.name ?? (lc.action === 'add' ? t('cpq.inventory.subscriptions.detail.changeLog.newItem', 'New item') : itemFallback),\n beforeMrc,\n afterMrc:\n lc.action === 'add' && afterMrc == null && lc.mrcAmount != null\n ? Number(lc.mrcAmount)\n : afterMrc,\n delta: explicitDelta ?? computedDelta,\n })\n }\n } else if (row.changeType === 'cancel' && row.beforeSnapshot?.items) {\n // applyCancel writes lineChanges=null; surface the items that got terminated.\n for (const it of row.beforeSnapshot.items) {\n const mrc = Number(it.mrcAmount ?? 0)\n derived.push({\n key: it.id,\n action: 'cancel',\n name: it.name ?? itemFallback,\n beforeMrc: mrc,\n afterMrc: 0,\n delta: -mrc,\n })\n }\n } else if (row.changeType === 'merge-result' && row.afterSnapshot?.items) {\n for (const it of row.afterSnapshot.items) {\n const mrc = Number(it.mrcAmount ?? 0)\n derived.push({\n key: it.id,\n action: 'add',\n name: it.name ?? itemFallback,\n beforeMrc: null,\n afterMrc: mrc,\n delta: null,\n })\n }\n } else if (row.changeType === 'merge-source' && row.beforeSnapshot?.items) {\n for (const it of row.beforeSnapshot.items) {\n const mrc = Number(it.mrcAmount ?? 0)\n derived.push({\n key: it.id,\n action: 'cancel',\n name: it.name ?? itemFallback,\n beforeMrc: mrc,\n afterMrc: 0,\n delta: -mrc,\n })\n }\n }\n\n if (derived.length === 0) {\n // Amend / renew without any actual line edits \u2014 service writes lineChanges=[]\n // because line 1641 of cpqInventoryService.applyLineChanges only records modify\n // entries with a real delta. Show an explicit note so the operator knows\n // the activation happened but nothing on items moved.\n if (row.changeType === 'amend' || row.changeType === 'renew') {\n return (\n <div className=\"mt-1.5 text-xs text-muted-foreground italic\">\n {t('cpq.inventory.subscriptions.detail.changeLog.noItemChanges', 'No item-level changes recorded.')}\n </div>\n )\n }\n return null\n }\n\n return (\n <div className=\"mt-1.5 rounded border bg-muted/20 px-3 py-2 space-y-1\">\n {derived.map((d) => (\n <ChangeLogLineRow key={d.key} change={d} currency={currency} />\n ))}\n </div>\n )\n}\n\nconst ACTION_GLYPH: Record<'add' | 'modify' | 'cancel', { sign: string; color: string }> = {\n add: { sign: '+', color: 'text-status-success-text' },\n modify: { sign: '~', color: 'text-status-info-text' },\n cancel: { sign: '\u2212', color: 'text-destructive' },\n}\n\nfunction actionGlyphLabel(t: TranslateFn, action: 'add' | 'modify' | 'cancel'): string {\n switch (action) {\n case 'add': return t('cpq.inventory.subscriptions.detail.changeLog.action.add', 'added')\n case 'modify': return t('cpq.inventory.subscriptions.detail.changeLog.action.modify', 'modified')\n case 'cancel': return t('cpq.inventory.subscriptions.detail.changeLog.action.cancel', 'removed')\n }\n}\n\nfunction ChangeLogLineRow({\n change,\n currency,\n}: {\n change: {\n action: 'add' | 'modify' | 'cancel'\n name: string\n beforeMrc: number | null\n afterMrc: number | null\n delta: number | null\n }\n currency: string\n}) {\n const t = useT()\n const glyph = ACTION_GLYPH[change.action]\n const showPriceChange =\n change.action === 'modify' &&\n change.beforeMrc != null &&\n change.afterMrc != null &&\n change.beforeMrc !== change.afterMrc\n const showSinglePrice =\n !showPriceChange &&\n ((change.action === 'add' && change.afterMrc != null && change.afterMrc > 0) ||\n (change.action === 'cancel' && change.beforeMrc != null && change.beforeMrc > 0))\n const showDelta = change.delta != null && change.delta !== 0\n const isNoopModify =\n change.action === 'modify' && !showPriceChange && !showDelta\n\n return (\n <div className=\"flex flex-wrap items-center gap-x-2 gap-y-0.5 text-xs\">\n <span className={`font-bold w-3 text-center ${glyph.color}`} title={actionGlyphLabel(t, change.action)}>\n {glyph.sign}\n </span>\n <span className=\"font-medium text-foreground\">{change.name}</span>\n {showPriceChange && (\n <span className=\"font-mono text-muted-foreground\">\n {t('cpq.inventory.subscriptions.detail.changeLog.priceChangePerMonth', '{before} \u2192 {after}/mo', {\n before: fmt(change.beforeMrc!, currency),\n after: fmt(change.afterMrc!, currency),\n })}\n </span>\n )}\n {showSinglePrice && change.action === 'add' && (\n <span className=\"font-mono text-muted-foreground\">\n {t('cpq.inventory.subscriptions.detail.changeLog.pricePerMonth', '{price}/mo', { price: fmt(change.afterMrc!, currency) })}\n </span>\n )}\n {showSinglePrice && change.action === 'cancel' && (\n <span className=\"font-mono text-muted-foreground\">\n {t('cpq.inventory.subscriptions.detail.changeLog.wasPricePerMonth', 'was {price}/mo', { price: fmt(change.beforeMrc!, currency) })}\n </span>\n )}\n {showDelta && (\n <span\n className={`font-mono font-medium ${change.delta! > 0 ? 'text-status-success-text' : 'text-destructive'}`}\n >\n {t('cpq.inventory.subscriptions.detail.changeLog.deltaPerMonth', '({delta}/mo)', {\n delta: `${change.delta! > 0 ? '+' : ''}${fmt(change.delta!, currency)}`,\n })}\n </span>\n )}\n {isNoopModify && (\n <span className=\"text-muted-foreground italic\">{t('cpq.inventory.subscriptions.detail.changeLog.noPriceChange', 'no price change')}</span>\n )}\n </div>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["res"]
7
7
  }
@@ -4,7 +4,7 @@ const metadata = {
4
4
  navHidden: true,
5
5
  breadcrumb: [
6
6
  { label: "Customer Inventory", labelKey: "cpq.inventory.title", href: "/backend/cpq/inventory" },
7
- { label: "Subscription Detail" }
7
+ { label: "Subscription Detail", labelKey: "cpq.inventory.subscriptions.detail.breadcrumb" }
8
8
  ]
9
9
  };
10
10
  export {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../../src/modules/cpq/backend/cpq/inventory/subscriptions/%5Bid%5D/page.meta.ts"],
4
- "sourcesContent": ["export const metadata = {\n requireAuth: true,\n requireFeatures: ['cpq.inventory.view'],\n navHidden: true,\n breadcrumb: [\n { label: 'Customer Inventory', labelKey: 'cpq.inventory.title', href: '/backend/cpq/inventory' },\n { label: 'Subscription Detail' },\n ],\n} as const\n"],
5
- "mappings": "AAAO,MAAM,WAAW;AAAA,EACtB,aAAa;AAAA,EACb,iBAAiB,CAAC,oBAAoB;AAAA,EACtC,WAAW;AAAA,EACX,YAAY;AAAA,IACV,EAAE,OAAO,sBAAsB,UAAU,uBAAuB,MAAM,yBAAyB;AAAA,IAC/F,EAAE,OAAO,sBAAsB;AAAA,EACjC;AACF;",
4
+ "sourcesContent": ["export const metadata = {\n requireAuth: true,\n requireFeatures: ['cpq.inventory.view'],\n navHidden: true,\n breadcrumb: [\n { label: 'Customer Inventory', labelKey: 'cpq.inventory.title', href: '/backend/cpq/inventory' },\n { label: 'Subscription Detail', labelKey: 'cpq.inventory.subscriptions.detail.breadcrumb' },\n ],\n} as const\n"],
5
+ "mappings": "AAAO,MAAM,WAAW;AAAA,EACtB,aAAa;AAAA,EACb,iBAAiB,CAAC,oBAAoB;AAAA,EACtC,WAAW;AAAA,EACX,YAAY;AAAA,IACV,EAAE,OAAO,sBAAsB,UAAU,uBAAuB,MAAM,yBAAyB;AAAA,IAC/F,EAAE,OAAO,uBAAuB,UAAU,gDAAgD;AAAA,EAC5F;AACF;",
6
6
  "names": []
7
7
  }