@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
@@ -0,0 +1,130 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { useT } from "@open-mercato/shared/lib/i18n/context";
5
+ import { apiCall } from "@open-mercato/ui/backend/utils/apiCall";
6
+ import { useConfirmDialog } from "@open-mercato/ui/backend/confirm-dialog";
7
+ import { flash } from "@open-mercato/ui/backend/FlashMessages";
8
+ import {
9
+ ADJUSTMENT_ERROR_FALLBACKS,
10
+ adjustmentAccess,
11
+ adjustmentErrorCode,
12
+ canDeleteInvalidAdjustment,
13
+ collectAdjustmentErrors
14
+ } from "../../../../../lib/priceAdjustmentView.js";
15
+ import { PriceAdjustmentDialog } from "./PriceAdjustmentDialog.js";
16
+ function usePriceAdjustments({ quote, quoteType, canAdjust, onQuote, reloadQuote }) {
17
+ const t = useT();
18
+ const { confirm, ConfirmDialogElement } = useConfirmDialog();
19
+ const [list, setList] = React.useState(null);
20
+ const [dialog, setDialog] = React.useState(null);
21
+ const quoteId = quote?.id ?? null;
22
+ const revision = quote?.pricingRevision ?? 0;
23
+ const loadList = React.useCallback(async () => {
24
+ if (!quoteId) return;
25
+ const call = await apiCall(`/api/cpq/quotes/${quoteId}/price-adjustments?pageSize=100`);
26
+ if (call.ok && call.result) setList(call.result);
27
+ else setList({ items: [], total: 0, pricingRevision: 0, enabled: false });
28
+ }, [quoteId]);
29
+ React.useEffect(() => {
30
+ void loadList();
31
+ }, [loadList, revision]);
32
+ const reasons = React.useMemo(() => list?.reasons ?? [], [list]);
33
+ const reasonLabels = React.useMemo(() => Object.fromEntries(reasons.map((reason) => [reason.value, reason.label])), [reasons]);
34
+ const errorsById = React.useMemo(() => collectAdjustmentErrors(quote), [quote]);
35
+ const accessInput = {
36
+ enabled: list ? list.enabled : null,
37
+ canAdjust,
38
+ cpqStatus: quote?.cpqStatus ?? "new",
39
+ convertedOrderId: quote?.convertedOrderId ?? null
40
+ };
41
+ const access = adjustmentAccess(accessInput);
42
+ const remove = React.useCallback(async (adjustmentId) => {
43
+ if (!quoteId) return;
44
+ const ok = await confirm({
45
+ title: t("cpq.priceAdjustments.deleteConfirm.title", "Remove this price adjustment?"),
46
+ text: t("cpq.priceAdjustments.deleteConfirm.text", "The charge goes back to its standard price."),
47
+ confirmText: t("cpq.priceAdjustments.deleteConfirm.confirm", "Remove"),
48
+ variant: "destructive"
49
+ });
50
+ if (!ok) return;
51
+ const call = await apiCall(`/api/cpq/quotes/${quoteId}/price-adjustments/${adjustmentId}?expectedRevision=${revision}`, { method: "DELETE" });
52
+ if (call.ok && call.result?.quote) {
53
+ onQuote(call.result.quote);
54
+ return;
55
+ }
56
+ const code = adjustmentErrorCode(call.status, call.result);
57
+ flash(t(`cpq.priceAdjustments.errors.${code}`, ADJUSTMENT_ERROR_FALLBACKS[code] ?? code), "error");
58
+ if (code === "STALE_REVISION") await reloadQuote();
59
+ }, [quoteId, revision, confirm, t, onQuote, reloadQuote]);
60
+ const ui = {
61
+ access,
62
+ quoteType,
63
+ cpqStatus: accessInput.cpqStatus,
64
+ reasonLabels,
65
+ invalidIds: new Set(errorsById.keys()),
66
+ canDeleteInvalid: canDeleteInvalidAdjustment(accessInput),
67
+ openCharge: (line, charge) => {
68
+ const existing = list?.items.find((item) => item.level === "charge" && item.quoteLineId === line.lineId && item.chargeCode === charge.chargeCode);
69
+ setDialog({
70
+ target: { level: "charge", quoteLineId: line.lineId, chargeCode: charge.chargeCode },
71
+ targetLabel: `${line.offeringName} \xB7 ${charge.chargeName}`,
72
+ charge,
73
+ existing: existing ?? null
74
+ });
75
+ },
76
+ openLine: (line) => {
77
+ const existing = list?.items.find((item) => item.level === "line" && item.quoteLineId === line.lineId);
78
+ setDialog({ target: { level: "line", quoteLineId: line.lineId }, targetLabel: line.offeringName, existing: existing ?? null });
79
+ },
80
+ edit: (adjustmentId) => {
81
+ const item = list?.items.find((entry) => entry.id === adjustmentId);
82
+ const line = quote?.lines.find((entry) => entry.lineId === item?.quoteLineId);
83
+ if (!item || !line) return;
84
+ const charge = item.chargeCode ? line.charges.find((entry) => entry.chargeCode === item.chargeCode) : void 0;
85
+ setDialog({
86
+ target: item.level === "charge" && item.chargeCode ? { level: "charge", quoteLineId: item.quoteLineId, chargeCode: item.chargeCode } : { level: "line", quoteLineId: item.quoteLineId },
87
+ targetLabel: charge ? `${line.offeringName} \xB7 ${charge.chargeName}` : line.offeringName,
88
+ charge,
89
+ existing: item
90
+ });
91
+ },
92
+ remove: (adjustmentId) => {
93
+ void remove(adjustmentId);
94
+ }
95
+ };
96
+ const dialogElement = quote && dialog ? /* @__PURE__ */ jsx(
97
+ PriceAdjustmentDialog,
98
+ {
99
+ open: true,
100
+ quoteId: quote.id,
101
+ currency: quote.currencyCode,
102
+ pricingRevision: revision,
103
+ target: dialog.target,
104
+ targetLabel: dialog.targetLabel,
105
+ charge: dialog.charge,
106
+ existing: dialog.existing,
107
+ storedAdjustmentIds: list?.items.map((item) => item.id) ?? [],
108
+ reasons,
109
+ onClose: () => setDialog(null),
110
+ onSaved: (next) => onQuote(next),
111
+ onStale: () => {
112
+ void reloadQuote();
113
+ }
114
+ }
115
+ ) : null;
116
+ return {
117
+ ui,
118
+ items: list?.items ?? [],
119
+ total: list?.total ?? 0,
120
+ errorsById,
121
+ elements: /* @__PURE__ */ jsxs(Fragment, { children: [
122
+ dialogElement,
123
+ ConfirmDialogElement
124
+ ] })
125
+ };
126
+ }
127
+ export {
128
+ usePriceAdjustments
129
+ };
130
+ //# sourceMappingURL=usePriceAdjustments.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../../../src/modules/cpq/backend/cpq/quotes/%5Bid%5D/_components/usePriceAdjustments.tsx"],
4
+ "sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport {\n ADJUSTMENT_ERROR_FALLBACKS,\n adjustmentAccess,\n adjustmentErrorCode,\n canDeleteInvalidAdjustment,\n collectAdjustmentErrors,\n type AdjustmentErrorSourceQuote,\n type AdjustmentTarget,\n} from '../../../../../lib/priceAdjustmentView'\nimport { PriceAdjustmentDialog, type AdjustmentReason, type ExistingAdjustment } from './PriceAdjustmentDialog'\nimport type { AdjustableCharge, AdjustableLine, PriceAdjustmentUi } from './priceAdjustmentContext'\nimport type { StoredAdjustment } from './PriceAdjustmentsPanel'\n\ntype ControllerQuote = {\n id: string\n cpqStatus: string\n currencyCode: string\n convertedOrderId: string | null\n pricingRevision?: number\n adjustmentErrors?: Array<{ adjustmentId: string; code: string }>\n lines: Array<AdjustableLine & { mrcTotal: number; nrcTotal: number; charges: AdjustableCharge[] }>\n}\n\ntype ListResponse = {\n items: StoredAdjustment[]\n total: number\n pricingRevision: number\n enabled: boolean\n reasons?: AdjustmentReason[]\n}\n\ntype DialogState = {\n target: AdjustmentTarget\n targetLabel: string\n charge?: AdjustableCharge\n existing?: ExistingAdjustment | null\n}\n\n/**\n * Owns negotiated-price state for the quote page: the adjustment list,\n * reason options, the dialog and delete confirmation. Every write returns the\n * repriced quote, which is handed back through `onQuote`.\n */\nexport function usePriceAdjustments<Q extends ControllerQuote>({ quote, quoteType, canAdjust, onQuote, reloadQuote }: {\n quote: Q | null\n quoteType: string\n canAdjust: boolean\n onQuote: (quote: Q) => void\n reloadQuote: () => Promise<void>\n}) {\n const t = useT()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const [list, setList] = React.useState<ListResponse | null>(null)\n const [dialog, setDialog] = React.useState<DialogState | null>(null)\n const quoteId = quote?.id ?? null\n const revision = quote?.pricingRevision ?? 0\n\n const loadList = React.useCallback(async () => {\n if (!quoteId) return\n const call = await apiCall<ListResponse>(`/api/cpq/quotes/${quoteId}/price-adjustments?pageSize=100`)\n if (call.ok && call.result) setList(call.result)\n else setList({ items: [], total: 0, pricingRevision: 0, enabled: false })\n }, [quoteId])\n\n // Refresh whenever the quote's pricing revision moves (own writes, line edits, recalculation).\n React.useEffect(() => { void loadList() }, [loadList, revision])\n\n const reasons = React.useMemo(() => list?.reasons ?? [], [list])\n const reasonLabels = React.useMemo(() => Object.fromEntries(reasons.map((reason) => [reason.value, reason.label])), [reasons])\n const errorsById = React.useMemo(() => collectAdjustmentErrors(quote as AdjustmentErrorSourceQuote | null), [quote])\n\n const accessInput = {\n enabled: list ? list.enabled : null,\n canAdjust,\n cpqStatus: quote?.cpqStatus ?? 'new',\n convertedOrderId: quote?.convertedOrderId ?? null,\n }\n const access = adjustmentAccess(accessInput)\n\n const remove = React.useCallback(async (adjustmentId: string) => {\n if (!quoteId) return\n const ok = await confirm({\n title: t('cpq.priceAdjustments.deleteConfirm.title', 'Remove this price adjustment?'),\n text: t('cpq.priceAdjustments.deleteConfirm.text', 'The charge goes back to its standard price.'),\n confirmText: t('cpq.priceAdjustments.deleteConfirm.confirm', 'Remove'),\n variant: 'destructive',\n })\n if (!ok) return\n const call = await apiCall<{ quote: Q }>(`/api/cpq/quotes/${quoteId}/price-adjustments/${adjustmentId}?expectedRevision=${revision}`, { method: 'DELETE' })\n if (call.ok && call.result?.quote) { onQuote(call.result.quote); return }\n const code = adjustmentErrorCode(call.status, call.result)\n flash(t(`cpq.priceAdjustments.errors.${code}`, ADJUSTMENT_ERROR_FALLBACKS[code] ?? code), 'error')\n if (code === 'STALE_REVISION') await reloadQuote()\n }, [quoteId, revision, confirm, t, onQuote, reloadQuote])\n\n const ui: PriceAdjustmentUi = {\n access,\n quoteType,\n cpqStatus: accessInput.cpqStatus,\n reasonLabels,\n invalidIds: new Set(errorsById.keys()),\n canDeleteInvalid: canDeleteInvalidAdjustment(accessInput),\n openCharge: (line, charge) => {\n const existing = list?.items.find((item) => item.level === 'charge' && item.quoteLineId === line.lineId && item.chargeCode === charge.chargeCode)\n setDialog({\n target: { level: 'charge', quoteLineId: line.lineId, chargeCode: charge.chargeCode },\n targetLabel: `${line.offeringName} \u00B7 ${charge.chargeName}`,\n charge,\n existing: existing ?? null,\n })\n },\n openLine: (line) => {\n const existing = list?.items.find((item) => item.level === 'line' && item.quoteLineId === line.lineId)\n setDialog({ target: { level: 'line', quoteLineId: line.lineId }, targetLabel: line.offeringName, existing: existing ?? null })\n },\n edit: (adjustmentId) => {\n const item = list?.items.find((entry) => entry.id === adjustmentId)\n const line = quote?.lines.find((entry) => entry.lineId === item?.quoteLineId)\n if (!item || !line) return\n const charge = item.chargeCode ? line.charges.find((entry) => entry.chargeCode === item.chargeCode) : undefined\n setDialog({\n target: item.level === 'charge' && item.chargeCode\n ? { level: 'charge', quoteLineId: item.quoteLineId, chargeCode: item.chargeCode }\n : { level: 'line', quoteLineId: item.quoteLineId },\n targetLabel: charge ? `${line.offeringName} \u00B7 ${charge.chargeName}` : line.offeringName,\n charge,\n existing: item,\n })\n },\n remove: (adjustmentId) => { void remove(adjustmentId) },\n }\n\n const dialogElement = quote && dialog ? (\n <PriceAdjustmentDialog<Q>\n open\n quoteId={quote.id}\n currency={quote.currencyCode}\n pricingRevision={revision}\n target={dialog.target}\n targetLabel={dialog.targetLabel}\n charge={dialog.charge}\n existing={dialog.existing}\n storedAdjustmentIds={list?.items.map((item) => item.id) ?? []}\n reasons={reasons}\n onClose={() => setDialog(null)}\n onSaved={(next) => onQuote(next)}\n onStale={() => { void reloadQuote() }}\n />\n ) : null\n\n return {\n ui,\n items: list?.items ?? [],\n total: list?.total ?? 0,\n errorsById,\n elements: <>{dialogElement}{ConfirmDialogElement}</>,\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }