@dainamite/cpq 0.4.0 → 0.6.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 (273) hide show
  1. package/CHANGELOG.md +70 -0
  2. package/MIGRATION.md +101 -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/handleArcError.js +2 -2
  8. package/dist/modules/cpq/api/_helpers/handleArcError.js.map +2 -2
  9. package/dist/modules/cpq/api/_helpers/quoteMutationGuard.js +23 -0
  10. package/dist/modules/cpq/api/_helpers/quoteMutationGuard.js.map +7 -0
  11. package/dist/modules/cpq/api/_helpers/quoteRouteOpenApi.js +19 -0
  12. package/dist/modules/cpq/api/_helpers/quoteRouteOpenApi.js.map +7 -0
  13. package/dist/modules/cpq/api/orders/[orderId]/activate/route.js +2 -2
  14. package/dist/modules/cpq/api/orders/[orderId]/activate/route.js.map +2 -2
  15. package/dist/modules/cpq/api/orders/[orderId]/route.js +19 -3
  16. package/dist/modules/cpq/api/orders/[orderId]/route.js.map +2 -2
  17. package/dist/modules/cpq/api/orders/[orderId]/status/route.js +2 -2
  18. package/dist/modules/cpq/api/orders/[orderId]/status/route.js.map +2 -2
  19. package/dist/modules/cpq/api/orders/route.js +49 -4
  20. package/dist/modules/cpq/api/orders/route.js.map +2 -2
  21. package/dist/modules/cpq/api/quotes/[quoteId]/clone/route.js +2 -2
  22. package/dist/modules/cpq/api/quotes/[quoteId]/clone/route.js.map +2 -2
  23. package/dist/modules/cpq/api/quotes/[quoteId]/items/[lineId]/restore/route.js +54 -0
  24. package/dist/modules/cpq/api/quotes/[quoteId]/items/[lineId]/restore/route.js.map +7 -0
  25. package/dist/modules/cpq/api/quotes/[quoteId]/items/[lineId]/route.js +45 -5
  26. package/dist/modules/cpq/api/quotes/[quoteId]/items/[lineId]/route.js.map +2 -2
  27. package/dist/modules/cpq/api/quotes/[quoteId]/items/route.js +27 -2
  28. package/dist/modules/cpq/api/quotes/[quoteId]/items/route.js.map +2 -2
  29. package/dist/modules/cpq/api/quotes/[quoteId]/price-adjustments/[adjustmentId]/route.js +47 -0
  30. package/dist/modules/cpq/api/quotes/[quoteId]/price-adjustments/[adjustmentId]/route.js.map +7 -0
  31. package/dist/modules/cpq/api/quotes/[quoteId]/price-adjustments/preview/route.js +30 -0
  32. package/dist/modules/cpq/api/quotes/[quoteId]/price-adjustments/preview/route.js.map +7 -0
  33. package/dist/modules/cpq/api/quotes/[quoteId]/price-adjustments/route.js +47 -0
  34. package/dist/modules/cpq/api/quotes/[quoteId]/price-adjustments/route.js.map +7 -0
  35. package/dist/modules/cpq/api/quotes/[quoteId]/recalculate/route.js +34 -4
  36. package/dist/modules/cpq/api/quotes/[quoteId]/recalculate/route.js.map +2 -2
  37. package/dist/modules/cpq/api/quotes/[quoteId]/route.js +2 -2
  38. package/dist/modules/cpq/api/quotes/[quoteId]/route.js.map +2 -2
  39. package/dist/modules/cpq/api/quotes/[quoteId]/status/route.js +33 -2
  40. package/dist/modules/cpq/api/quotes/[quoteId]/status/route.js.map +2 -2
  41. package/dist/modules/cpq/api/quotes/price/route.js +43 -3
  42. package/dist/modules/cpq/api/quotes/price/route.js.map +2 -2
  43. package/dist/modules/cpq/api/quotes/route.js +2 -2
  44. package/dist/modules/cpq/api/quotes/route.js.map +2 -2
  45. package/dist/modules/cpq/backend/cpq/inventory/AssetsTable.js.map +1 -1
  46. package/dist/modules/cpq/backend/cpq/inventory/SubscriptionsTable.js.map +1 -1
  47. package/dist/modules/cpq/backend/cpq/inventory/page.meta.js +1 -1
  48. package/dist/modules/cpq/backend/cpq/inventory/page.meta.js.map +1 -1
  49. package/dist/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.js +22 -8
  50. package/dist/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.js.map +2 -2
  51. package/dist/modules/cpq/backend/cpq/offerings/page.js.map +1 -1
  52. package/dist/modules/cpq/backend/cpq/orders/[id]/page.js +89 -232
  53. package/dist/modules/cpq/backend/cpq/orders/[id]/page.js.map +2 -2
  54. package/dist/modules/cpq/backend/cpq/orders/page.js.map +1 -1
  55. package/dist/modules/cpq/backend/cpq/orders/page.meta.js +1 -1
  56. package/dist/modules/cpq/backend/cpq/orders/page.meta.js.map +1 -1
  57. package/dist/modules/cpq/backend/cpq/price-rules/page.js.map +1 -1
  58. package/dist/modules/cpq/backend/cpq/pricing/page.js.map +1 -1
  59. package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/PriceAdjustmentDialog.js +205 -0
  60. package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/PriceAdjustmentDialog.js.map +7 -0
  61. package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/PriceAdjustmentsPanel.js +79 -0
  62. package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/PriceAdjustmentsPanel.js.map +7 -0
  63. package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/arcLineRemoval.js +53 -0
  64. package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/arcLineRemoval.js.map +7 -0
  65. package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/priceAdjustmentContext.js +107 -0
  66. package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/priceAdjustmentContext.js.map +7 -0
  67. package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/usePriceAdjustments.js +130 -0
  68. package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/usePriceAdjustments.js.map +7 -0
  69. package/dist/modules/cpq/backend/cpq/quotes/[id]/page.js +144 -221
  70. package/dist/modules/cpq/backend/cpq/quotes/[id]/page.js.map +3 -3
  71. package/dist/modules/cpq/backend/cpq/quotes/page.js.map +1 -1
  72. package/dist/modules/cpq/backend/cpq/quotes/page.meta.js +1 -1
  73. package/dist/modules/cpq/backend/cpq/quotes/page.meta.js.map +1 -1
  74. package/dist/modules/cpq/backend/cpq/specifications/page.js.map +1 -1
  75. package/dist/modules/cpq/backend/cpq/wizards/page.js.map +1 -1
  76. package/dist/modules/cpq/ce.js +8 -0
  77. package/dist/modules/cpq/ce.js.map +2 -2
  78. package/dist/modules/cpq/cli.js +34 -1
  79. package/dist/modules/cpq/cli.js.map +2 -2
  80. package/dist/modules/cpq/commands/price-adjustments.js +107 -0
  81. package/dist/modules/cpq/commands/price-adjustments.js.map +7 -0
  82. package/dist/modules/cpq/components/ArcLineDiff.js +53 -0
  83. package/dist/modules/cpq/components/ArcLineDiff.js.map +7 -0
  84. package/dist/modules/cpq/components/ChargeBreakdownTable.js +154 -0
  85. package/dist/modules/cpq/components/ChargeBreakdownTable.js.map +7 -0
  86. package/dist/modules/cpq/components/CpqListView.js.map +2 -2
  87. package/dist/modules/cpq/components/PriceWaterfall.js +66 -0
  88. package/dist/modules/cpq/components/PriceWaterfall.js.map +7 -0
  89. package/dist/modules/cpq/components/PricingSummaryCard.js +117 -0
  90. package/dist/modules/cpq/components/PricingSummaryCard.js.map +7 -0
  91. package/dist/modules/cpq/components/useGrantedFeatures.js +27 -0
  92. package/dist/modules/cpq/components/useGrantedFeatures.js.map +7 -0
  93. package/dist/modules/cpq/data/entities.js +97 -0
  94. package/dist/modules/cpq/data/entities.js.map +2 -2
  95. package/dist/modules/cpq/data/price-adjustments.js +70 -0
  96. package/dist/modules/cpq/data/price-adjustments.js.map +7 -0
  97. package/dist/modules/cpq/data/validators.js +4 -0
  98. package/dist/modules/cpq/data/validators.js.map +2 -2
  99. package/dist/modules/cpq/di.js +6 -0
  100. package/dist/modules/cpq/di.js.map +2 -2
  101. package/dist/modules/cpq/events.js +47 -0
  102. package/dist/modules/cpq/events.js.map +2 -2
  103. package/dist/modules/cpq/index.js +1 -1
  104. package/dist/modules/cpq/index.js.map +2 -2
  105. package/dist/modules/cpq/lib/auditActor.js +10 -0
  106. package/dist/modules/cpq/lib/auditActor.js.map +7 -0
  107. package/dist/modules/cpq/lib/formatMoney.js +7 -0
  108. package/dist/modules/cpq/lib/formatMoney.js.map +7 -0
  109. package/dist/modules/cpq/lib/priceAdjustmentDefaults.js +60 -0
  110. package/dist/modules/cpq/lib/priceAdjustmentDefaults.js.map +7 -0
  111. package/dist/modules/cpq/lib/priceAdjustmentView.js +169 -0
  112. package/dist/modules/cpq/lib/priceAdjustmentView.js.map +7 -0
  113. package/dist/modules/cpq/lib/quotePermissions.js +13 -0
  114. package/dist/modules/cpq/lib/quotePermissions.js.map +7 -0
  115. package/dist/modules/cpq/lib/quoteSummaryView.js +28 -0
  116. package/dist/modules/cpq/lib/quoteSummaryView.js.map +7 -0
  117. package/dist/modules/cpq/migrations/Migration20261110213052.js +22 -0
  118. package/dist/modules/cpq/migrations/Migration20261110213052.js.map +7 -0
  119. package/dist/modules/cpq/services/arcLineRemoval.js +53 -0
  120. package/dist/modules/cpq/services/arcLineRemoval.js.map +7 -0
  121. package/dist/modules/cpq/services/arcPriceFreeze.js +79 -0
  122. package/dist/modules/cpq/services/arcPriceFreeze.js.map +7 -0
  123. package/dist/modules/cpq/services/cpqOrderService.js +34 -30
  124. package/dist/modules/cpq/services/cpqOrderService.js.map +2 -2
  125. package/dist/modules/cpq/services/cpqPricingService.js +7 -0
  126. package/dist/modules/cpq/services/cpqPricingService.js.map +2 -2
  127. package/dist/modules/cpq/services/cpqQuotingService.js +339 -111
  128. package/dist/modules/cpq/services/cpqQuotingService.js.map +2 -2
  129. package/dist/modules/cpq/services/orderPricingSummary.js +26 -0
  130. package/dist/modules/cpq/services/orderPricingSummary.js.map +7 -0
  131. package/dist/modules/cpq/services/priceAdjustments/adjustmentService.js +264 -0
  132. package/dist/modules/cpq/services/priceAdjustments/adjustmentService.js.map +7 -0
  133. package/dist/modules/cpq/services/priceAdjustments/chargeWaterfall.js +25 -0
  134. package/dist/modules/cpq/services/priceAdjustments/chargeWaterfall.js.map +7 -0
  135. package/dist/modules/cpq/services/priceAdjustments/loadQuoteAdjustments.js +38 -0
  136. package/dist/modules/cpq/services/priceAdjustments/loadQuoteAdjustments.js.map +7 -0
  137. package/dist/modules/cpq/services/priceAdjustments/pricingSnapshot.js +104 -0
  138. package/dist/modules/cpq/services/priceAdjustments/pricingSnapshot.js.map +7 -0
  139. package/dist/modules/cpq/services/priceAdjustments/quoteAdjustmentLifecycle.js +102 -0
  140. package/dist/modules/cpq/services/priceAdjustments/quoteAdjustmentLifecycle.js.map +7 -0
  141. package/dist/modules/cpq/services/priceAdjustments/quotePricingEvents.js +52 -0
  142. package/dist/modules/cpq/services/priceAdjustments/quotePricingEvents.js.map +7 -0
  143. package/dist/modules/cpq/services/priceAdjustments/quotePricingWrite.js +37 -0
  144. package/dist/modules/cpq/services/priceAdjustments/quotePricingWrite.js.map +7 -0
  145. package/dist/modules/cpq/services/priceAdjustments/resolveManualAdjustments.js +107 -0
  146. package/dist/modules/cpq/services/priceAdjustments/resolveManualAdjustments.js.map +7 -0
  147. package/dist/modules/cpq/services/priceAdjustments/storedAdjustmentFailure.js +30 -0
  148. package/dist/modules/cpq/services/priceAdjustments/storedAdjustmentFailure.js.map +7 -0
  149. package/dist/modules/cpq/services/types.js.map +2 -2
  150. package/dist/modules/cpq/setup.js +6 -0
  151. package/dist/modules/cpq/setup.js.map +2 -2
  152. package/package.json +9 -9
  153. package/src/modules/cpq/__integration__/TC-CPQ-002.spec.ts +8 -5
  154. package/src/modules/cpq/__integration__/TC-CPQ-ARC-012.spec.ts +134 -0
  155. package/src/modules/cpq/acl.ts +1 -0
  156. package/src/modules/cpq/api/__tests__/adjustmentRoutes.test.ts +79 -0
  157. package/src/modules/cpq/api/__tests__/quoteWriteGuards.test.ts +100 -0
  158. package/src/modules/cpq/api/_helpers/__tests__/quoteMutationGuard.test.ts +48 -0
  159. package/src/modules/cpq/api/_helpers/adjustmentCommandRoute.ts +45 -0
  160. package/src/modules/cpq/api/_helpers/handleArcError.ts +12 -12
  161. package/src/modules/cpq/api/_helpers/quoteMutationGuard.ts +38 -0
  162. package/src/modules/cpq/api/_helpers/quoteRouteOpenApi.ts +19 -0
  163. package/src/modules/cpq/api/orders/[orderId]/activate/route.ts +2 -2
  164. package/src/modules/cpq/api/orders/[orderId]/route.ts +20 -2
  165. package/src/modules/cpq/api/orders/[orderId]/status/route.ts +2 -2
  166. package/src/modules/cpq/api/orders/route.ts +53 -3
  167. package/src/modules/cpq/api/quotes/[quoteId]/clone/route.ts +2 -2
  168. package/src/modules/cpq/api/quotes/[quoteId]/items/[lineId]/restore/route.ts +56 -0
  169. package/src/modules/cpq/api/quotes/[quoteId]/items/[lineId]/route.ts +51 -4
  170. package/src/modules/cpq/api/quotes/[quoteId]/items/route.ts +31 -1
  171. package/src/modules/cpq/api/quotes/[quoteId]/price-adjustments/[adjustmentId]/route.ts +39 -0
  172. package/src/modules/cpq/api/quotes/[quoteId]/price-adjustments/preview/route.ts +24 -0
  173. package/src/modules/cpq/api/quotes/[quoteId]/price-adjustments/route.ts +40 -0
  174. package/src/modules/cpq/api/quotes/[quoteId]/recalculate/__tests__/route.test.ts +95 -0
  175. package/src/modules/cpq/api/quotes/[quoteId]/recalculate/route.ts +42 -3
  176. package/src/modules/cpq/api/quotes/[quoteId]/route.ts +2 -2
  177. package/src/modules/cpq/api/quotes/[quoteId]/status/__tests__/route.test.ts +74 -0
  178. package/src/modules/cpq/api/quotes/[quoteId]/status/route.ts +37 -1
  179. package/src/modules/cpq/api/quotes/price/__tests__/route.test.ts +37 -0
  180. package/src/modules/cpq/api/quotes/price/route.ts +28 -2
  181. package/src/modules/cpq/api/quotes/route.ts +2 -2
  182. package/src/modules/cpq/backend/cpq/inventory/AssetsTable.tsx +1 -1
  183. package/src/modules/cpq/backend/cpq/inventory/SubscriptionsTable.tsx +1 -1
  184. package/src/modules/cpq/backend/cpq/inventory/page.meta.ts +1 -1
  185. package/src/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.tsx +32 -10
  186. package/src/modules/cpq/backend/cpq/offerings/page.tsx +1 -1
  187. package/src/modules/cpq/backend/cpq/orders/[id]/page.tsx +60 -269
  188. package/src/modules/cpq/backend/cpq/orders/page.meta.ts +1 -1
  189. package/src/modules/cpq/backend/cpq/orders/page.tsx +1 -1
  190. package/src/modules/cpq/backend/cpq/price-rules/page.tsx +1 -1
  191. package/src/modules/cpq/backend/cpq/pricing/page.tsx +1 -1
  192. package/src/modules/cpq/backend/cpq/quotes/[id]/_components/PriceAdjustmentDialog.tsx +260 -0
  193. package/src/modules/cpq/backend/cpq/quotes/[id]/_components/PriceAdjustmentsPanel.tsx +124 -0
  194. package/src/modules/cpq/backend/cpq/quotes/[id]/_components/__tests__/PriceAdjustmentsPanel.test.tsx +76 -0
  195. package/src/modules/cpq/backend/cpq/quotes/[id]/_components/arcLineRemoval.tsx +76 -0
  196. package/src/modules/cpq/backend/cpq/quotes/[id]/_components/priceAdjustmentContext.tsx +133 -0
  197. package/src/modules/cpq/backend/cpq/quotes/[id]/_components/usePriceAdjustments.tsx +165 -0
  198. package/src/modules/cpq/backend/cpq/quotes/[id]/page.tsx +178 -266
  199. package/src/modules/cpq/backend/cpq/quotes/page.meta.ts +1 -1
  200. package/src/modules/cpq/backend/cpq/quotes/page.tsx +1 -1
  201. package/src/modules/cpq/backend/cpq/specifications/page.tsx +1 -1
  202. package/src/modules/cpq/backend/cpq/wizards/page.tsx +1 -1
  203. package/src/modules/cpq/ce.ts +8 -0
  204. package/src/modules/cpq/cli.ts +48 -1
  205. package/src/modules/cpq/commands/__tests__/price-adjustments.test.ts +54 -0
  206. package/src/modules/cpq/commands/price-adjustments.ts +90 -0
  207. package/src/modules/cpq/components/ArcLineDiff.tsx +87 -0
  208. package/src/modules/cpq/components/ChargeBreakdownTable.tsx +201 -0
  209. package/src/modules/cpq/components/CpqListView.tsx +2 -1
  210. package/src/modules/cpq/components/PriceWaterfall.tsx +94 -0
  211. package/src/modules/cpq/components/PricingSummaryCard.tsx +128 -0
  212. package/src/modules/cpq/components/__tests__/PriceWaterfall.test.tsx +38 -0
  213. package/src/modules/cpq/components/useGrantedFeatures.ts +35 -0
  214. package/src/modules/cpq/data/__tests__/price-adjustment-migration.test.ts +11 -0
  215. package/src/modules/cpq/data/__tests__/price-adjustments.test.ts +26 -0
  216. package/src/modules/cpq/data/entities.ts +83 -0
  217. package/src/modules/cpq/data/price-adjustments.ts +67 -0
  218. package/src/modules/cpq/data/validators.ts +3 -0
  219. package/src/modules/cpq/di.ts +6 -0
  220. package/src/modules/cpq/events.ts +53 -2
  221. package/src/modules/cpq/index.ts +1 -1
  222. package/src/modules/cpq/lib/__tests__/auditActor.test.ts +12 -0
  223. package/src/modules/cpq/lib/__tests__/priceAdjustmentDefaults.test.ts +37 -0
  224. package/src/modules/cpq/lib/__tests__/priceAdjustmentView.test.ts +152 -0
  225. package/src/modules/cpq/lib/__tests__/quotePermissions.test.ts +30 -0
  226. package/src/modules/cpq/lib/__tests__/quoteSummaryView.test.ts +56 -0
  227. package/src/modules/cpq/lib/auditActor.ts +13 -0
  228. package/src/modules/cpq/lib/formatMoney.ts +4 -0
  229. package/src/modules/cpq/lib/priceAdjustmentDefaults.ts +36 -0
  230. package/src/modules/cpq/lib/priceAdjustmentView.ts +259 -0
  231. package/src/modules/cpq/lib/quotePermissions.ts +22 -0
  232. package/src/modules/cpq/lib/quoteSummaryView.ts +51 -0
  233. package/src/modules/cpq/migrations/.snapshot-open-mercato.json +3298 -2423
  234. package/src/modules/cpq/migrations/Migration20261110213052.ts +22 -0
  235. package/src/modules/cpq/services/__tests__/_helpers/mockEm.ts +9 -2
  236. package/src/modules/cpq/services/__tests__/adjustmentService.test.ts +183 -0
  237. package/src/modules/cpq/services/__tests__/arcLineRemoval.test.ts +109 -0
  238. package/src/modules/cpq/services/__tests__/arcPriceFreeze.test.ts +141 -0
  239. package/src/modules/cpq/services/__tests__/chargeWaterfall.test.ts +28 -0
  240. package/src/modules/cpq/services/__tests__/cpqOrderService.test.ts +35 -2
  241. package/src/modules/cpq/services/__tests__/cpqPricingService.test.ts +57 -0
  242. package/src/modules/cpq/services/__tests__/cpqQuotingService.arc.test.ts +237 -0
  243. package/src/modules/cpq/services/__tests__/cpqQuotingService.test.ts +58 -3
  244. package/src/modules/cpq/services/__tests__/errorBrands.test.ts +72 -0
  245. package/src/modules/cpq/services/__tests__/orderPricingSummary.test.ts +50 -0
  246. package/src/modules/cpq/services/__tests__/pricingSnapshot.test.ts +62 -0
  247. package/src/modules/cpq/services/__tests__/quoteAdjustmentLifecycle.test.ts +35 -0
  248. package/src/modules/cpq/services/__tests__/quoteAdjustmentPricing.test.ts +65 -0
  249. package/src/modules/cpq/services/__tests__/quoteCloneAdjustments.test.ts +45 -0
  250. package/src/modules/cpq/services/__tests__/quoteDetachTargetAdjustments.test.ts +54 -0
  251. package/src/modules/cpq/services/__tests__/quoteEventsService.test.ts +72 -0
  252. package/src/modules/cpq/services/__tests__/quotePricingEvents.test.ts +126 -0
  253. package/src/modules/cpq/services/__tests__/quotePricingIsolation.test.ts +52 -0
  254. package/src/modules/cpq/services/__tests__/quotePricingWrite.test.ts +74 -0
  255. package/src/modules/cpq/services/__tests__/resolveManualAdjustments.test.ts +90 -0
  256. package/src/modules/cpq/services/__tests__/storedAdjustmentFailure.test.ts +9 -0
  257. package/src/modules/cpq/services/arcLineRemoval.ts +87 -0
  258. package/src/modules/cpq/services/arcPriceFreeze.ts +165 -0
  259. package/src/modules/cpq/services/cpqOrderService.ts +32 -28
  260. package/src/modules/cpq/services/cpqPricingService.ts +8 -0
  261. package/src/modules/cpq/services/cpqQuotingService.ts +388 -125
  262. package/src/modules/cpq/services/orderPricingSummary.ts +47 -0
  263. package/src/modules/cpq/services/priceAdjustments/adjustmentService.ts +249 -0
  264. package/src/modules/cpq/services/priceAdjustments/chargeWaterfall.ts +28 -0
  265. package/src/modules/cpq/services/priceAdjustments/loadQuoteAdjustments.ts +25 -0
  266. package/src/modules/cpq/services/priceAdjustments/pricingSnapshot.ts +86 -0
  267. package/src/modules/cpq/services/priceAdjustments/quoteAdjustmentLifecycle.ts +68 -0
  268. package/src/modules/cpq/services/priceAdjustments/quotePricingEvents.ts +94 -0
  269. package/src/modules/cpq/services/priceAdjustments/quotePricingWrite.ts +51 -0
  270. package/src/modules/cpq/services/priceAdjustments/resolveManualAdjustments.ts +116 -0
  271. package/src/modules/cpq/services/priceAdjustments/storedAdjustmentFailure.ts +31 -0
  272. package/src/modules/cpq/services/types.ts +34 -1
  273. package/src/modules/cpq/setup.ts +7 -1
@@ -12,6 +12,12 @@ import {
12
12
  type OrderCpqStatus,
13
13
  } from '../../../../components/statusMaps'
14
14
  import { StatusPath } from '../../../../components/StatusPath'
15
+ import { ChargeBreakdownTable, type ChargeRowView } from '../../../../components/ChargeBreakdownTable'
16
+ import { PricingSummaryCard, type PricingSummaryView } from '../../../../components/PricingSummaryCard'
17
+ import { ArcLineDiff, LineActionBadge } from '../../../../components/ArcLineDiff'
18
+ import { arcRecurringDelta } from '../../../../lib/quoteSummaryView'
19
+ import { isArcCancelledLine } from '../../../../services/arcLineRemoval'
20
+ import { useT } from '@open-mercato/shared/lib/i18n/context'
15
21
 
16
22
  // ─── Types ───────────────────────────────────────────────────────
17
23
 
@@ -24,7 +30,7 @@ type ArcLineSource = {
24
30
  }
25
31
 
26
32
  type TierBreakdownEntry = { tier: number; from: number; to: number; pricePerUnit: number; quantity: number; subtotal: number }
27
- type RuleAdjustment = { ruleCode: string; ruleName: string; ruleType: string; value: number; unitPriceBefore: number; unitPriceAfter: number; delta: number }
33
+ type RuleAdjustment = { ruleCode: string; ruleName: string; ruleType: string; value: number; unitPriceBefore: number; unitPriceAfter: number; delta: number; origin?: 'rule' | 'manual'; adjustmentId?: string; reasonCode?: string }
28
34
 
29
35
  type ResolvedCharge = {
30
36
  chargeName?: string
@@ -36,6 +42,15 @@ type ResolvedCharge = {
36
42
  note?: string | null
37
43
  breakdown?: { tiers: TierBreakdownEntry[] } | null
38
44
  adjustments?: RuleAdjustment[] | null
45
+ listUnitPrice?: number
46
+ listTotalPrice?: number | null
47
+ standardUnitPrice?: number
48
+ standardTotalPrice?: number | null
49
+ }
50
+
51
+ /** Order lines carry the quote's stored waterfall verbatim (no recalculation at conversion). */
52
+ function toChargeRow(c: ResolvedCharge): ChargeRowView {
53
+ return { ...c, chargeName: c.chargeName ?? '—', chargeType: (c.chargeType ?? 'mrc') as 'nrc' | 'mrc' | 'usage', unitPrice: c.unitPrice ?? 0, totalPrice: c.totalPrice ?? null }
39
54
  }
40
55
 
41
56
  type OrderLineResult = {
@@ -68,11 +83,7 @@ type OrderResult = {
68
83
  sourceQuoteId: string | null
69
84
  quoteType: string
70
85
  currencyCode: string
71
- pricingSummary: {
72
- nrcTotal: number
73
- mrcTotal: number
74
- currencyCode: string
75
- }
86
+ pricingSummary: PricingSummaryView & { currencyCode: string }
76
87
  activatedAt: string | null
77
88
  createdAt: string
78
89
  lines: OrderLineResult[]
@@ -84,19 +95,6 @@ const ARC_BADGE_VARIANTS: Record<string, 'brand' | 'success' | 'error'> = {
84
95
  cancel: 'error',
85
96
  }
86
97
 
87
- const RULE_TYPE_LABELS: Record<string, string> = {
88
- discount_percent: '% discount',
89
- discount_absolute: 'fixed discount',
90
- surcharge_percent: '% surcharge',
91
- surcharge_absolute: 'fixed surcharge',
92
- price_override: 'override',
93
- }
94
-
95
- function fmtRuleValue(adj: RuleAdjustment, currency?: string): string {
96
- if (adj.ruleType === 'discount_percent' || adj.ruleType === 'surcharge_percent') return `${adj.value}%`
97
- if (currency) return fmt(adj.value, currency)
98
- return String(adj.value)
99
- }
100
98
 
101
99
  // ─── Constants ───────────────────────────────────────────────────
102
100
 
@@ -422,24 +420,18 @@ export default function CpqOrderDetailPage(props: { params?: { id?: string } })
422
420
  </MetaCard>
423
421
  </div>
424
422
 
425
- {/* Pricing Summary Card */}
426
- <div className="rounded-lg border bg-card p-4">
427
- <h3 className="text-sm font-medium mb-3">Pricing Summary</h3>
428
- <div className="grid grid-cols-2 gap-4">
429
- <div>
430
- <p className="text-xs text-muted-foreground">Non-Recurring (NRC)</p>
431
- <p className="text-lg font-semibold font-mono">{fmt(order.pricingSummary.nrcTotal, currency)}</p>
432
- </div>
433
- <div>
434
- <p className="text-xs text-muted-foreground">Monthly Recurring (MRC)</p>
435
- <p className="text-lg font-semibold font-mono">{fmt(order.pricingSummary.mrcTotal, currency)}</p>
436
- </div>
437
- </div>
438
- </div>
423
+ <PricingSummaryCard
424
+ summary={order.pricingSummary}
425
+ currency={currency}
426
+ arcDelta={order.quoteType === 'amend' || order.quoteType === 'renew'
427
+ ? arcRecurringDelta(order.lines.map((l) => ({ ...l, action: l.action as 'add' | 'modify' | 'cancel' })))
428
+ : null}
429
+ />
439
430
 
440
431
  {/* Order Lines */}
441
432
  <OrderLineTree
442
433
  lines={order.lines}
434
+ quoteType={order.quoteType}
443
435
  currency={currency}
444
436
  expandedLines={expandedLines}
445
437
  pricingDetail={pricingDetail}
@@ -465,6 +457,7 @@ function MetaCard({ label, children }: { label: string; children: React.ReactNod
465
457
 
466
458
  function OrderLineTree({
467
459
  lines,
460
+ quoteType,
468
461
  currency,
469
462
  expandedLines,
470
463
  pricingDetail,
@@ -472,6 +465,7 @@ function OrderLineTree({
472
465
  onTogglePricingDetail,
473
466
  }: {
474
467
  lines: OrderLineResult[]
468
+ quoteType: string
475
469
  currency: string
476
470
  expandedLines: Set<string>
477
471
  pricingDetail: { lineIdx: number; chargeIdx: number } | null
@@ -512,6 +506,7 @@ function OrderLineTree({
512
506
  <OrderLineRow
513
507
  line={line}
514
508
  lineIdx={lineIdx}
509
+ quoteType={quoteType}
515
510
  currency={currency}
516
511
  isExpanded={isExpanded}
517
512
  isBundle={isBundle}
@@ -533,6 +528,7 @@ function OrderLineTree({
533
528
  key={child.lineId}
534
529
  line={child}
535
530
  lineIdx={childIdx}
531
+ quoteType={quoteType}
536
532
  currency={currency}
537
533
  isExpanded={expandedLines.has(child.lineId)}
538
534
  isBundle={false}
@@ -555,20 +551,26 @@ function OrderLineTree({
555
551
  )
556
552
  }
557
553
 
558
- function OrderLineRow({ line, lineIdx, currency, isExpanded, isBundle, childCount, indent, pricingDetail, onToggle, onTogglePricingDetail }: {
559
- line: OrderLineResult; lineIdx: number; currency: string; isExpanded: boolean; isBundle: boolean; childCount: number; indent: number
554
+ function OrderLineRow({ line, lineIdx, quoteType, currency, isExpanded, isBundle, childCount, indent, pricingDetail, onToggle, onTogglePricingDetail }: {
555
+ line: OrderLineResult; lineIdx: number; quoteType: string; currency: string; isExpanded: boolean; isBundle: boolean; childCount: number; indent: number
560
556
  pricingDetail: { lineIdx: number; chargeIdx: number } | null
561
557
  onToggle: () => void
562
558
  onTogglePricingDetail: (lineIdx: number, chargeIdx: number) => void
563
559
  }) {
560
+ const t = useT()
564
561
  const paddingLeft = indent > 0 ? `${indent * 2 + 1}rem` : undefined
562
+ // Same presentation as the quote page: an existing item removed on an
563
+ // Amend / Renew quote reads as "remove", struck through.
564
+ const isRemoved = isArcCancelledLine(line, quoteType)
565
565
 
566
566
  return (
567
567
  <div>
568
568
  <div
569
- className="flex items-center gap-3 px-4 py-3 hover:bg-muted/30 transition-colors cursor-pointer"
569
+ className={`flex items-center gap-3 px-4 py-3 hover:bg-muted/30 transition-colors cursor-pointer ${isRemoved ? 'bg-muted/20' : ''}`}
570
570
  style={paddingLeft ? { paddingLeft } : undefined}
571
571
  onClick={onToggle}
572
+ data-testid="cpq-order-line"
573
+ data-removed={isRemoved ? 'true' : undefined}
572
574
  >
573
575
  <button className="flex h-5 w-5 shrink-0 items-center justify-center rounded text-muted-foreground hover:text-foreground">
574
576
  <svg className={`h-4 w-4 transition-transform ${isExpanded ? 'rotate-90' : ''}`} fill="none" viewBox="0 0 24 24" strokeWidth="2" stroke="currentColor">
@@ -582,21 +584,31 @@ function OrderLineRow({ line, lineIdx, currency, isExpanded, isBundle, childCoun
582
584
  {isBundle && (
583
585
  <Tag variant="brand" className="px-1.5 text-xs">bundle</Tag>
584
586
  )}
585
- <span className="font-medium text-sm">{line.offeringName}</span>
587
+ <span className={`font-medium text-sm ${isRemoved ? 'text-muted-foreground line-through' : ''}`}>{line.offeringName}</span>
586
588
  {line.quantity > 1 && <span className="rounded bg-muted px-1.5 py-0.5 text-xs font-medium">×{line.quantity}</span>}
587
- <Tag variant="info" className="px-1.5 text-xs">{line.action}</Tag>
589
+ <LineActionBadge
590
+ action={line.action}
591
+ label={isRemoved ? t('cpq.quotes.arc.lineRemoved', 'remove') : undefined}
592
+ title={isRemoved ? t('cpq.quotes.arc.lineRemovedHint', 'This item is cancelled on the subscription when the order is activated') : undefined}
593
+ />
588
594
  {isBundle && <span className="text-xs text-muted-foreground">{childCount} component{childCount !== 1 ? 's' : ''}</span>}
589
595
  </div>
590
596
  </div>
591
597
 
592
598
  <div className="shrink-0 text-right text-xs space-y-0.5">
599
+ {isRemoved && line.arcSource && line.arcSource.mrcAmount > 0 && (
600
+ <div>
601
+ <span className="text-muted-foreground">MRC </span>
602
+ <span className="font-mono text-muted-foreground line-through">{fmt(line.arcSource.mrcAmount, currency)}</span>
603
+ </div>
604
+ )}
593
605
  {line.nrcTotal > 0 && <div><span className="text-muted-foreground">NRC </span><span className="font-mono font-medium">{fmt(line.nrcTotal, currency)}</span></div>}
594
606
  {line.mrcTotal > 0 && <div><span className="text-muted-foreground">MRC </span><span className="font-mono font-medium">{fmt(line.mrcTotal, currency)}</span></div>}
595
607
  </div>
596
608
  </div>
597
609
 
598
610
  {isExpanded && (() => {
599
- const internalKeys = new Set(['_arcMirroredName', '_arcMirroredFromItemId', 'offeringName'])
611
+ const internalKeys = new Set(['_arcMirroredName', '_arcMirroredFromItemId', '_arcPriceFrozen', '_arcRepriced', 'offeringName'])
600
612
  const visibleConfigEntries = Object.entries(line.configuration).filter(
601
613
  ([key]) => !internalKeys.has(key),
602
614
  )
@@ -612,9 +624,6 @@ function OrderLineRow({ line, lineIdx, currency, isExpanded, isBundle, childCoun
612
624
  className="border-t bg-muted/10 px-12 py-3 space-y-3"
613
625
  style={paddingLeft ? { paddingLeft: `calc(${paddingLeft} + 2rem)` } : undefined}
614
626
  >
615
- {hasArcDiff && (
616
- <ArcLineDiff line={line} currency={currency} />
617
- )}
618
627
  {isEmpty ? (
619
628
  <div className="text-xs text-muted-foreground space-y-1">
620
629
  <div>
@@ -649,16 +658,12 @@ function OrderLineRow({ line, lineIdx, currency, isExpanded, isBundle, childCoun
649
658
  )}
650
659
 
651
660
  {hasCharges && (
652
- <div>
653
- <p className="text-xs font-medium text-muted-foreground mb-1">Charges</p>
654
- <ChargeBreakdown
655
- line={line}
656
- lineIdx={lineIdx}
657
- currency={currency}
658
- pricingDetail={pricingDetail}
659
- onTogglePricingDetail={onTogglePricingDetail}
660
- />
661
- </div>
661
+ <ChargeBreakdownTable
662
+ charges={line.charges.map(toChargeRow)}
663
+ currency={currency}
664
+ openDetailIndex={pricingDetail?.lineIdx === lineIdx ? pricingDetail.chargeIdx : null}
665
+ onToggleDetail={(chargeIdx) => onTogglePricingDetail(lineIdx, chargeIdx)}
666
+ />
662
667
  )}
663
668
 
664
669
  {hasTerm && (
@@ -668,6 +673,9 @@ function OrderLineRow({ line, lineIdx, currency, isExpanded, isBundle, childCoun
668
673
  {line.endDate && <span>End: {new Date(line.endDate).toLocaleDateString()}</span>}
669
674
  </div>
670
675
  )}
676
+
677
+ {/* XD-250 ARC: before/after preview below the charges, as on the quote. */}
678
+ {hasArcDiff && <ArcLineDiff line={line} currency={currency} />}
671
679
  </>
672
680
  )}
673
681
  </div>
@@ -677,144 +685,6 @@ function OrderLineRow({ line, lineIdx, currency, isExpanded, isBundle, childCoun
677
685
  )
678
686
  }
679
687
 
680
- // Charge breakdown table with the waterfall ("show pricing details")
681
- // toggle. Same shape as the quote page so a charge looks identical on
682
- // both surfaces, including tier-by-tier subtotals and any price-rule
683
- // adjustments that fired during calculation.
684
- function ChargeBreakdown({ line, lineIdx, currency, pricingDetail, onTogglePricingDetail }: {
685
- line: OrderLineResult; lineIdx: number; currency: string
686
- pricingDetail: { lineIdx: number; chargeIdx: number } | null
687
- onTogglePricingDetail: (lineIdx: number, chargeIdx: number) => void
688
- }) {
689
- return (
690
- <table className="w-full text-xs">
691
- <thead>
692
- <tr className="text-muted-foreground">
693
- <th className="text-left py-1 font-medium">Charge</th>
694
- <th className="text-left py-1 font-medium">Type</th>
695
- <th className="text-right py-1 font-medium">Unit Price</th>
696
- <th className="text-right py-1 font-medium">Qty</th>
697
- <th className="text-right py-1 font-medium">Total</th>
698
- <th className="w-8" />
699
- </tr>
700
- </thead>
701
- <tbody>
702
- {line.charges.map((c, i) => {
703
- const hasDetail = !!(c.breakdown?.tiers?.length || c.adjustments?.length)
704
- const isDetailOpen = pricingDetail?.lineIdx === lineIdx && pricingDetail?.chargeIdx === i
705
- return (
706
- <React.Fragment key={i}>
707
- <tr className="border-t border-dashed border-border/50">
708
- <td className="py-1">{c.chargeName ?? '—'}</td>
709
- <td className="py-1 uppercase">{c.chargeType ?? '—'}</td>
710
- <td className="py-1 text-right font-mono">{c.unitPrice != null ? fmt(c.unitPrice, currency) : '—'}</td>
711
- <td className="py-1 text-right font-mono">{c.quantity ?? '—'}</td>
712
- <td className="py-1 text-right font-mono">{c.totalPrice != null ? fmt(c.totalPrice, currency) : c.note ?? '—'}</td>
713
- <td className="py-1 text-center">
714
- {hasDetail && (
715
- <button
716
- onClick={() => onTogglePricingDetail(lineIdx, i)}
717
- className="inline-flex items-center justify-center rounded p-0.5 hover:bg-accent text-muted-foreground hover:text-foreground transition-colors"
718
- title="Show pricing breakdown"
719
- >
720
- <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="w-3.5 h-3.5">
721
- <path strokeLinecap="round" strokeLinejoin="round" d="M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z" />
722
- </svg>
723
- </button>
724
- )}
725
- </td>
726
- </tr>
727
- {isDetailOpen && (
728
- <tr>
729
- <td colSpan={6} className="pb-3 pt-1">
730
- <div className="rounded border bg-background p-3 space-y-3 text-xs">
731
- <div className="flex items-center justify-between">
732
- <span className="font-semibold text-sm">Pricing Details — {c.chargeName}</span>
733
- <span className="text-muted-foreground">{c.pricingMethod ?? 'flat'}</span>
734
- </div>
735
-
736
- {c.breakdown?.tiers && c.breakdown.tiers.length > 0 && (
737
- <div>
738
- <div className="font-medium text-muted-foreground mb-1">Tier Breakdown</div>
739
- <table className="w-full">
740
- <thead>
741
- <tr className="text-muted-foreground">
742
- <th className="text-left py-0.5 font-medium">Tier</th>
743
- <th className="text-right py-0.5 font-medium">Range</th>
744
- <th className="text-right py-0.5 font-medium">Price/Unit</th>
745
- <th className="text-right py-0.5 font-medium">Qty</th>
746
- <th className="text-right py-0.5 font-medium">Subtotal</th>
747
- </tr>
748
- </thead>
749
- <tbody>
750
- {c.breakdown.tiers.map((t) => (
751
- <tr key={t.tier} className="border-t border-border/30">
752
- <td className="py-0.5">{t.tier}</td>
753
- <td className="py-0.5 text-right font-mono">{t.from}–{t.to}</td>
754
- <td className="py-0.5 text-right font-mono">{fmt(t.pricePerUnit, currency)}</td>
755
- <td className="py-0.5 text-right font-mono">{t.quantity}</td>
756
- <td className="py-0.5 text-right font-mono">{fmt(t.subtotal, currency)}</td>
757
- </tr>
758
- ))}
759
- <tr className="border-t font-medium">
760
- <td colSpan={4} className="py-0.5 text-right">Tiered Total</td>
761
- <td className="py-0.5 text-right font-mono">
762
- {fmt(c.breakdown.tiers.reduce((s, t) => s + t.subtotal, 0), currency)}
763
- </td>
764
- </tr>
765
- </tbody>
766
- </table>
767
- </div>
768
- )}
769
-
770
- {c.adjustments && c.adjustments.length > 0 && (
771
- <div>
772
- <div className="font-medium text-muted-foreground mb-1">Applied Price Rules</div>
773
- <table className="w-full">
774
- <thead>
775
- <tr className="text-muted-foreground">
776
- <th className="text-left py-0.5 font-medium">Rule</th>
777
- <th className="text-left py-0.5 font-medium">Type</th>
778
- <th className="text-right py-0.5 font-medium">Value</th>
779
- <th className="text-right py-0.5 font-medium">Before</th>
780
- <th className="text-right py-0.5 font-medium">After</th>
781
- <th className="text-right py-0.5 font-medium">Delta</th>
782
- </tr>
783
- </thead>
784
- <tbody>
785
- {c.adjustments.map((adj, ai) => (
786
- <tr key={ai} className="border-t border-border/30">
787
- <td className="py-0.5">{adj.ruleName}</td>
788
- <td className="py-0.5">{RULE_TYPE_LABELS[adj.ruleType] ?? adj.ruleType}</td>
789
- <td className="py-0.5 text-right font-mono">{fmtRuleValue(adj, currency)}</td>
790
- <td className="py-0.5 text-right font-mono">{fmt(adj.unitPriceBefore, currency)}</td>
791
- <td className="py-0.5 text-right font-mono">{fmt(adj.unitPriceAfter, currency)}</td>
792
- <td className={`py-0.5 text-right font-mono ${adj.delta < 0 ? 'text-destructive' : adj.delta > 0 ? 'text-status-success-text' : ''}`}>
793
- {adj.delta > 0 ? '+' : ''}{fmt(adj.delta, currency)}
794
- </td>
795
- </tr>
796
- ))}
797
- </tbody>
798
- </table>
799
- </div>
800
- )}
801
-
802
- <div className="flex items-center justify-between pt-1 border-t text-sm font-semibold">
803
- <span>Final Total</span>
804
- <span className="font-mono">{c.totalPrice != null ? fmt(c.totalPrice, currency) : '—'}</span>
805
- </div>
806
- </div>
807
- </td>
808
- </tr>
809
- )}
810
- </React.Fragment>
811
- )
812
- })}
813
- </tbody>
814
- </table>
815
- )
816
- }
817
-
818
688
  function Spinner() {
819
689
  return (
820
690
  <svg className="h-4 w-4 animate-spin" viewBox="0 0 24 24" fill="none">
@@ -840,82 +710,3 @@ function ErrorBanner({ message, onDismiss }: { message: string; onDismiss?: () =
840
710
  </Alert>
841
711
  )
842
712
  }
843
-
844
- // XD-250 ARC: side-by-side "Before / After" snapshot for a quote / order line
845
- // that mirrors an existing subscription item. "Before" comes from the live
846
- // CpqInventorySubscriptionItem at render time; "After" is what the line will
847
- // apply on activation. For 'cancel' lines the after column is greyed out.
848
- function ArcLineDiff({ line, currency }: { line: OrderLineResult; currency: string }) {
849
- const src = line.arcSource
850
- if (!src) return null
851
- const isCancel = line.action === 'cancel'
852
-
853
- const beforeMrc = src.mrcAmount
854
- const beforeNrc = src.nrcAmount
855
- const beforeQty = src.quantity
856
- const afterMrc = isCancel ? 0 : line.mrcTotal
857
- const afterNrc = isCancel ? 0 : line.nrcTotal
858
- const afterQty = isCancel ? 0 : line.quantity
859
- const mrcDelta = afterMrc - beforeMrc
860
- const nrcDelta = afterNrc - beforeNrc
861
- const qtyDelta = afterQty - beforeQty
862
-
863
- return (
864
- <div>
865
- <p className="text-xs font-medium text-muted-foreground mb-1.5">Change Preview</p>
866
- <div className="rounded border bg-background overflow-hidden">
867
- <table className="w-full text-xs">
868
- <thead className="bg-muted/40">
869
- <tr className="text-muted-foreground">
870
- <th className="text-left px-3 py-1.5 font-medium" />
871
- <th className="text-right px-3 py-1.5 font-medium">Before</th>
872
- <th className="text-right px-3 py-1.5 font-medium">After</th>
873
- <th className="text-right px-3 py-1.5 font-medium">Δ</th>
874
- </tr>
875
- </thead>
876
- <tbody>
877
- <ArcDiffRow label="Quantity" before={beforeQty} after={afterQty} delta={qtyDelta} currency={null} dimAfter={isCancel} />
878
- <ArcDiffRow label="MRC" before={beforeMrc} after={afterMrc} delta={mrcDelta} currency={currency} dimAfter={isCancel} />
879
- <ArcDiffRow label="NRC" before={beforeNrc} after={afterNrc} delta={nrcDelta} currency={currency} dimAfter={isCancel} />
880
- </tbody>
881
- </table>
882
- </div>
883
- {isCancel && (
884
- <p className="text-xs text-destructive mt-1 italic">
885
- Cancellation — item will be terminated on activation.
886
- </p>
887
- )}
888
- </div>
889
- )
890
- }
891
-
892
- function ArcDiffRow({
893
- label,
894
- before,
895
- after,
896
- delta,
897
- currency,
898
- dimAfter,
899
- }: {
900
- label: string
901
- before: number
902
- after: number
903
- delta: number
904
- currency: string | null
905
- dimAfter: boolean
906
- }) {
907
- const fmtVal = (v: number) => (currency ? fmt(v, currency) : String(v))
908
- const showDelta = delta !== 0
909
- return (
910
- <tr className="border-t border-dashed border-border/40">
911
- <td className="px-3 py-1 text-muted-foreground">{label}</td>
912
- <td className="px-3 py-1 text-right font-mono">{fmtVal(before)}</td>
913
- <td className={`px-3 py-1 text-right font-mono ${dimAfter ? 'text-muted-foreground line-through' : ''}`}>
914
- {fmtVal(after)}
915
- </td>
916
- <td className={`px-3 py-1 text-right font-mono font-medium ${showDelta ? (delta > 0 ? 'text-status-success-text' : 'text-destructive') : 'text-muted-foreground'}`}>
917
- {showDelta ? `${delta > 0 ? '+' : ''}${fmtVal(delta)}` : '—'}
918
- </td>
919
- </tr>
920
- )
921
- }
@@ -10,7 +10,7 @@ export const metadata = {
10
10
  pageTitleKey: 'cpq.orders.title',
11
11
  pageGroup: 'CPQ',
12
12
  pageGroupKey: 'customers~sales~cpq.nav.group',
13
- pageOrder: 91,
13
+ pageOrder: 2,
14
14
  icon: ordersIcon,
15
15
  breadcrumb: [{ label: 'CPQ Orders', labelKey: 'cpq.orders.title' }],
16
16
  } as const
@@ -2,7 +2,7 @@
2
2
  import * as React from 'react'
3
3
  import { useRouter } from 'next/navigation'
4
4
  import { useT } from '@open-mercato/shared/lib/i18n/context'
5
- import type { ColumnDef } from '@tanstack/react-table'
5
+ import type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'
6
6
  import type { FilterDef, FilterValues } from '@open-mercato/ui/backend/FilterBar'
7
7
  import { RowActions } from '@open-mercato/ui/backend/RowActions'
8
8
  import { Tag } from '@open-mercato/ui/primitives/tag'
@@ -2,7 +2,7 @@
2
2
  import * as React from 'react'
3
3
  import { useRouter } from 'next/navigation'
4
4
  import { useT } from '@open-mercato/shared/lib/i18n/context'
5
- import type { ColumnDef } from '@tanstack/react-table'
5
+ import type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'
6
6
  import { Button } from '@open-mercato/ui/primitives/button'
7
7
  import { Tag } from '@open-mercato/ui/primitives/tag'
8
8
  import type { FilterDef, FilterValues } from '@open-mercato/ui/backend/FilterBar'
@@ -2,7 +2,7 @@
2
2
  import * as React from 'react'
3
3
  import { useT } from '@open-mercato/shared/lib/i18n/context'
4
4
  import { useRouter } from 'next/navigation'
5
- import type { ColumnDef } from '@tanstack/react-table'
5
+ import type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'
6
6
  import { Button } from '@open-mercato/ui/primitives/button'
7
7
  import { Tag } from '@open-mercato/ui/primitives/tag'
8
8
  import type { FilterDef, FilterValues } from '@open-mercato/ui/backend/FilterBar'