@dainamite/cpq 0.2.2

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 (504) hide show
  1. package/CHANGELOG.md +70 -0
  2. package/LICENSE +21 -0
  3. package/MIGRATION.md +236 -0
  4. package/README.md +108 -0
  5. package/dist/modules/cpq/acl.js +30 -0
  6. package/dist/modules/cpq/acl.js.map +7 -0
  7. package/dist/modules/cpq/api/_helpers/handleArcError.js +37 -0
  8. package/dist/modules/cpq/api/_helpers/handleArcError.js.map +7 -0
  9. package/dist/modules/cpq/api/attribute-options/route.js +47 -0
  10. package/dist/modules/cpq/api/attribute-options/route.js.map +7 -0
  11. package/dist/modules/cpq/api/bundle-slots/route.js +101 -0
  12. package/dist/modules/cpq/api/bundle-slots/route.js.map +7 -0
  13. package/dist/modules/cpq/api/bundle-tree/route.js +28 -0
  14. package/dist/modules/cpq/api/bundle-tree/route.js.map +7 -0
  15. package/dist/modules/cpq/api/context.js +29 -0
  16. package/dist/modules/cpq/api/context.js.map +7 -0
  17. package/dist/modules/cpq/api/inventory/assets/route.js +113 -0
  18. package/dist/modules/cpq/api/inventory/assets/route.js.map +7 -0
  19. package/dist/modules/cpq/api/inventory/assets/status/route.js +35 -0
  20. package/dist/modules/cpq/api/inventory/assets/status/route.js.map +7 -0
  21. package/dist/modules/cpq/api/inventory/customer/[customerId]/parent-items/route.js +30 -0
  22. package/dist/modules/cpq/api/inventory/customer/[customerId]/parent-items/route.js.map +7 -0
  23. package/dist/modules/cpq/api/inventory/customer/[customerId]/route.js +31 -0
  24. package/dist/modules/cpq/api/inventory/customer/[customerId]/route.js.map +7 -0
  25. package/dist/modules/cpq/api/inventory/subscription-items/route.js +99 -0
  26. package/dist/modules/cpq/api/inventory/subscription-items/route.js.map +7 -0
  27. package/dist/modules/cpq/api/inventory/subscriptions/[subscriptionId]/change-log/route.js +57 -0
  28. package/dist/modules/cpq/api/inventory/subscriptions/[subscriptionId]/change-log/route.js.map +7 -0
  29. package/dist/modules/cpq/api/inventory/subscriptions/expiring/route.js +62 -0
  30. package/dist/modules/cpq/api/inventory/subscriptions/expiring/route.js.map +7 -0
  31. package/dist/modules/cpq/api/inventory/subscriptions/route.js +116 -0
  32. package/dist/modules/cpq/api/inventory/subscriptions/route.js.map +7 -0
  33. package/dist/modules/cpq/api/inventory/subscriptions/status/route.js +35 -0
  34. package/dist/modules/cpq/api/inventory/subscriptions/status/route.js.map +7 -0
  35. package/dist/modules/cpq/api/offering-components/route.js +91 -0
  36. package/dist/modules/cpq/api/offering-components/route.js.map +7 -0
  37. package/dist/modules/cpq/api/orders/[orderId]/activate/route.js +39 -0
  38. package/dist/modules/cpq/api/orders/[orderId]/activate/route.js.map +7 -0
  39. package/dist/modules/cpq/api/orders/[orderId]/route.js +28 -0
  40. package/dist/modules/cpq/api/orders/[orderId]/route.js.map +7 -0
  41. package/dist/modules/cpq/api/orders/[orderId]/status/route.js +38 -0
  42. package/dist/modules/cpq/api/orders/[orderId]/status/route.js.map +7 -0
  43. package/dist/modules/cpq/api/orders/route.js +71 -0
  44. package/dist/modules/cpq/api/orders/route.js.map +7 -0
  45. package/dist/modules/cpq/api/price-rules/route.js +180 -0
  46. package/dist/modules/cpq/api/price-rules/route.js.map +7 -0
  47. package/dist/modules/cpq/api/pricing-table-entries/route.js +142 -0
  48. package/dist/modules/cpq/api/pricing-table-entries/route.js.map +7 -0
  49. package/dist/modules/cpq/api/pricing-tables/route.js +179 -0
  50. package/dist/modules/cpq/api/pricing-tables/route.js.map +7 -0
  51. package/dist/modules/cpq/api/product-attributes/route.js +160 -0
  52. package/dist/modules/cpq/api/product-attributes/route.js.map +7 -0
  53. package/dist/modules/cpq/api/product-charges/route.js +166 -0
  54. package/dist/modules/cpq/api/product-charges/route.js.map +7 -0
  55. package/dist/modules/cpq/api/product-offerings/route.js +294 -0
  56. package/dist/modules/cpq/api/product-offerings/route.js.map +7 -0
  57. package/dist/modules/cpq/api/product-relationships/route.js +144 -0
  58. package/dist/modules/cpq/api/product-relationships/route.js.map +7 -0
  59. package/dist/modules/cpq/api/product-specifications/route.js +292 -0
  60. package/dist/modules/cpq/api/product-specifications/route.js.map +7 -0
  61. package/dist/modules/cpq/api/quotes/[quoteId]/cancel-meta/route.js +71 -0
  62. package/dist/modules/cpq/api/quotes/[quoteId]/cancel-meta/route.js.map +7 -0
  63. package/dist/modules/cpq/api/quotes/[quoteId]/clone/route.js +29 -0
  64. package/dist/modules/cpq/api/quotes/[quoteId]/clone/route.js.map +7 -0
  65. package/dist/modules/cpq/api/quotes/[quoteId]/items/[lineId]/route.js +54 -0
  66. package/dist/modules/cpq/api/quotes/[quoteId]/items/[lineId]/route.js.map +7 -0
  67. package/dist/modules/cpq/api/quotes/[quoteId]/items/route.js +27 -0
  68. package/dist/modules/cpq/api/quotes/[quoteId]/items/route.js.map +7 -0
  69. package/dist/modules/cpq/api/quotes/[quoteId]/merge-meta/route.js +72 -0
  70. package/dist/modules/cpq/api/quotes/[quoteId]/merge-meta/route.js.map +7 -0
  71. package/dist/modules/cpq/api/quotes/[quoteId]/recalculate/route.js +35 -0
  72. package/dist/modules/cpq/api/quotes/[quoteId]/recalculate/route.js.map +7 -0
  73. package/dist/modules/cpq/api/quotes/[quoteId]/route.js +102 -0
  74. package/dist/modules/cpq/api/quotes/[quoteId]/route.js.map +7 -0
  75. package/dist/modules/cpq/api/quotes/[quoteId]/status/route.js +27 -0
  76. package/dist/modules/cpq/api/quotes/[quoteId]/status/route.js.map +7 -0
  77. package/dist/modules/cpq/api/quotes/[quoteId]/target-subscriptions/[targetId]/route.js +79 -0
  78. package/dist/modules/cpq/api/quotes/[quoteId]/target-subscriptions/[targetId]/route.js.map +7 -0
  79. package/dist/modules/cpq/api/quotes/[quoteId]/target-subscriptions/route.js +95 -0
  80. package/dist/modules/cpq/api/quotes/[quoteId]/target-subscriptions/route.js.map +7 -0
  81. package/dist/modules/cpq/api/quotes/attributes/route.js +52 -0
  82. package/dist/modules/cpq/api/quotes/attributes/route.js.map +7 -0
  83. package/dist/modules/cpq/api/quotes/from-subscription/route.js +72 -0
  84. package/dist/modules/cpq/api/quotes/from-subscription/route.js.map +7 -0
  85. package/dist/modules/cpq/api/quotes/price/route.js +69 -0
  86. package/dist/modules/cpq/api/quotes/price/route.js.map +7 -0
  87. package/dist/modules/cpq/api/quotes/route.js +97 -0
  88. package/dist/modules/cpq/api/quotes/route.js.map +7 -0
  89. package/dist/modules/cpq/api/quotes/validate-relationships/route.js +86 -0
  90. package/dist/modules/cpq/api/quotes/validate-relationships/route.js.map +7 -0
  91. package/dist/modules/cpq/api/resolveQuotingService.js +7 -0
  92. package/dist/modules/cpq/api/resolveQuotingService.js.map +7 -0
  93. package/dist/modules/cpq/api/wizards/resolve/route.js +38 -0
  94. package/dist/modules/cpq/api/wizards/resolve/route.js.map +7 -0
  95. package/dist/modules/cpq/api/wizards/route.js +111 -0
  96. package/dist/modules/cpq/api/wizards/route.js.map +7 -0
  97. package/dist/modules/cpq/backend/cpq/inventory/AssetsTable.js +136 -0
  98. package/dist/modules/cpq/backend/cpq/inventory/AssetsTable.js.map +7 -0
  99. package/dist/modules/cpq/backend/cpq/inventory/SubscriptionsTable.js +185 -0
  100. package/dist/modules/cpq/backend/cpq/inventory/SubscriptionsTable.js.map +7 -0
  101. package/dist/modules/cpq/backend/cpq/inventory/assets/[id]/page.js +343 -0
  102. package/dist/modules/cpq/backend/cpq/inventory/assets/[id]/page.js.map +7 -0
  103. package/dist/modules/cpq/backend/cpq/inventory/assets/[id]/page.meta.js +13 -0
  104. package/dist/modules/cpq/backend/cpq/inventory/assets/[id]/page.meta.js.map +7 -0
  105. package/dist/modules/cpq/backend/cpq/inventory/page.js +35 -0
  106. package/dist/modules/cpq/backend/cpq/inventory/page.js.map +7 -0
  107. package/dist/modules/cpq/backend/cpq/inventory/page.meta.js +18 -0
  108. package/dist/modules/cpq/backend/cpq/inventory/page.meta.js.map +7 -0
  109. package/dist/modules/cpq/backend/cpq/inventory/shared.js +20 -0
  110. package/dist/modules/cpq/backend/cpq/inventory/shared.js.map +7 -0
  111. package/dist/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.js +794 -0
  112. package/dist/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.js.map +7 -0
  113. package/dist/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.meta.js +13 -0
  114. package/dist/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.meta.js.map +7 -0
  115. package/dist/modules/cpq/backend/cpq/offerings/[id]/page.js +917 -0
  116. package/dist/modules/cpq/backend/cpq/offerings/[id]/page.js.map +7 -0
  117. package/dist/modules/cpq/backend/cpq/offerings/page.js +405 -0
  118. package/dist/modules/cpq/backend/cpq/offerings/page.js.map +7 -0
  119. package/dist/modules/cpq/backend/cpq/offerings/page.meta.js +18 -0
  120. package/dist/modules/cpq/backend/cpq/offerings/page.meta.js.map +7 -0
  121. package/dist/modules/cpq/backend/cpq/orders/[id]/page.js +677 -0
  122. package/dist/modules/cpq/backend/cpq/orders/[id]/page.js.map +7 -0
  123. package/dist/modules/cpq/backend/cpq/orders/page.js +134 -0
  124. package/dist/modules/cpq/backend/cpq/orders/page.js.map +7 -0
  125. package/dist/modules/cpq/backend/cpq/orders/page.meta.js +18 -0
  126. package/dist/modules/cpq/backend/cpq/orders/page.meta.js.map +7 -0
  127. package/dist/modules/cpq/backend/cpq/price-rules/PriceRuleForm.js +272 -0
  128. package/dist/modules/cpq/backend/cpq/price-rules/PriceRuleForm.js.map +7 -0
  129. package/dist/modules/cpq/backend/cpq/price-rules/[id]/page.js +407 -0
  130. package/dist/modules/cpq/backend/cpq/price-rules/[id]/page.js.map +7 -0
  131. package/dist/modules/cpq/backend/cpq/price-rules/[id]/page.meta.js +13 -0
  132. package/dist/modules/cpq/backend/cpq/price-rules/[id]/page.meta.js.map +7 -0
  133. package/dist/modules/cpq/backend/cpq/price-rules/page.js +211 -0
  134. package/dist/modules/cpq/backend/cpq/price-rules/page.js.map +7 -0
  135. package/dist/modules/cpq/backend/cpq/price-rules/page.meta.js +18 -0
  136. package/dist/modules/cpq/backend/cpq/price-rules/page.meta.js.map +7 -0
  137. package/dist/modules/cpq/backend/cpq/pricing/[id]/EntriesEditor.js +275 -0
  138. package/dist/modules/cpq/backend/cpq/pricing/[id]/EntriesEditor.js.map +7 -0
  139. package/dist/modules/cpq/backend/cpq/pricing/[id]/ImportPreview.js +112 -0
  140. package/dist/modules/cpq/backend/cpq/pricing/[id]/ImportPreview.js.map +7 -0
  141. package/dist/modules/cpq/backend/cpq/pricing/[id]/page.js +492 -0
  142. package/dist/modules/cpq/backend/cpq/pricing/[id]/page.js.map +7 -0
  143. package/dist/modules/cpq/backend/cpq/pricing/[id]/xlsxExport.js +50 -0
  144. package/dist/modules/cpq/backend/cpq/pricing/[id]/xlsxExport.js.map +7 -0
  145. package/dist/modules/cpq/backend/cpq/pricing/[id]/xlsxImport.js +249 -0
  146. package/dist/modules/cpq/backend/cpq/pricing/[id]/xlsxImport.js.map +7 -0
  147. package/dist/modules/cpq/backend/cpq/pricing/page.js +87 -0
  148. package/dist/modules/cpq/backend/cpq/pricing/page.js.map +7 -0
  149. package/dist/modules/cpq/backend/cpq/pricing/page.meta.js +18 -0
  150. package/dist/modules/cpq/backend/cpq/pricing/page.meta.js.map +7 -0
  151. package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/ArcQuoteConfigurator.js +652 -0
  152. package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/ArcQuoteConfigurator.js.map +7 -0
  153. package/dist/modules/cpq/backend/cpq/quotes/[id]/page.js +1289 -0
  154. package/dist/modules/cpq/backend/cpq/quotes/[id]/page.js.map +7 -0
  155. package/dist/modules/cpq/backend/cpq/quotes/page.js +283 -0
  156. package/dist/modules/cpq/backend/cpq/quotes/page.js.map +7 -0
  157. package/dist/modules/cpq/backend/cpq/quotes/page.meta.js +18 -0
  158. package/dist/modules/cpq/backend/cpq/quotes/page.meta.js.map +7 -0
  159. package/dist/modules/cpq/backend/cpq/specifications/[id]/DependsOnRulesEditor.js +214 -0
  160. package/dist/modules/cpq/backend/cpq/specifications/[id]/DependsOnRulesEditor.js.map +7 -0
  161. package/dist/modules/cpq/backend/cpq/specifications/[id]/page.js +1399 -0
  162. package/dist/modules/cpq/backend/cpq/specifications/[id]/page.js.map +7 -0
  163. package/dist/modules/cpq/backend/cpq/specifications/page.js +148 -0
  164. package/dist/modules/cpq/backend/cpq/specifications/page.js.map +7 -0
  165. package/dist/modules/cpq/backend/cpq/specifications/page.meta.js +18 -0
  166. package/dist/modules/cpq/backend/cpq/specifications/page.meta.js.map +7 -0
  167. package/dist/modules/cpq/backend/cpq/wizards/[definitionCode]/detail/page.js +204 -0
  168. package/dist/modules/cpq/backend/cpq/wizards/[definitionCode]/detail/page.js.map +7 -0
  169. package/dist/modules/cpq/backend/cpq/wizards/[definitionCode]/page.js +191 -0
  170. package/dist/modules/cpq/backend/cpq/wizards/[definitionCode]/page.js.map +7 -0
  171. package/dist/modules/cpq/backend/cpq/wizards/page.js +119 -0
  172. package/dist/modules/cpq/backend/cpq/wizards/page.js.map +7 -0
  173. package/dist/modules/cpq/backend/cpq/wizards/page.meta.js +18 -0
  174. package/dist/modules/cpq/backend/cpq/wizards/page.meta.js.map +7 -0
  175. package/dist/modules/cpq/ce.js +151 -0
  176. package/dist/modules/cpq/ce.js.map +7 -0
  177. package/dist/modules/cpq/cli.js +11 -0
  178. package/dist/modules/cpq/cli.js.map +7 -0
  179. package/dist/modules/cpq/components/CpqListView.js +265 -0
  180. package/dist/modules/cpq/components/CpqListView.js.map +7 -0
  181. package/dist/modules/cpq/components/NumberInput.js +95 -0
  182. package/dist/modules/cpq/components/NumberInput.js.map +7 -0
  183. package/dist/modules/cpq/components/StatusPath.js +60 -0
  184. package/dist/modules/cpq/components/StatusPath.js.map +7 -0
  185. package/dist/modules/cpq/components/statusMaps.js +66 -0
  186. package/dist/modules/cpq/components/statusMaps.js.map +7 -0
  187. package/dist/modules/cpq/components/useCpqRowActions.js +125 -0
  188. package/dist/modules/cpq/components/useCpqRowActions.js.map +7 -0
  189. package/dist/modules/cpq/data/entities.js +1556 -0
  190. package/dist/modules/cpq/data/entities.js.map +7 -0
  191. package/dist/modules/cpq/data/validators.js +575 -0
  192. package/dist/modules/cpq/data/validators.js.map +7 -0
  193. package/dist/modules/cpq/di.js +57 -0
  194. package/dist/modules/cpq/di.js.map +7 -0
  195. package/dist/modules/cpq/events.js +50 -0
  196. package/dist/modules/cpq/events.js.map +7 -0
  197. package/dist/modules/cpq/index.js +16 -0
  198. package/dist/modules/cpq/index.js.map +7 -0
  199. package/dist/modules/cpq/lib/seeds/api.js +32 -0
  200. package/dist/modules/cpq/lib/seeds/api.js.map +7 -0
  201. package/dist/modules/cpq/lib/seeds/tenant-provisioning.js +158 -0
  202. package/dist/modules/cpq/lib/seeds/tenant-provisioning.js.map +7 -0
  203. package/dist/modules/cpq/lib/seeds.js +6 -0
  204. package/dist/modules/cpq/lib/seeds.js.map +7 -0
  205. package/dist/modules/cpq/migrations/Migration20260220220000_cpq.js +40 -0
  206. package/dist/modules/cpq/migrations/Migration20260220220000_cpq.js.map +7 -0
  207. package/dist/modules/cpq/migrations/Migration20260330000000_cpq_product_domain.js +54 -0
  208. package/dist/modules/cpq/migrations/Migration20260330000000_cpq_product_domain.js.map +7 -0
  209. package/dist/modules/cpq/migrations/Migration20260331000000_cpq_charge_unique_per_offering.js +15 -0
  210. package/dist/modules/cpq/migrations/Migration20260331000000_cpq_charge_unique_per_offering.js.map +7 -0
  211. package/dist/modules/cpq/migrations/Migration20260401000000_cpq_quoting_v2.js +62 -0
  212. package/dist/modules/cpq/migrations/Migration20260401000000_cpq_quoting_v2.js.map +7 -0
  213. package/dist/modules/cpq/migrations/Migration20260402000000_cpq_workflows.js +56 -0
  214. package/dist/modules/cpq/migrations/Migration20260402000000_cpq_workflows.js.map +7 -0
  215. package/dist/modules/cpq/migrations/Migration20260407000000_cpq_pricing_tables_v2.js +26 -0
  216. package/dist/modules/cpq/migrations/Migration20260407000000_cpq_pricing_tables_v2.js.map +7 -0
  217. package/dist/modules/cpq/migrations/Migration20260407100000_cpq_price_rules.js +37 -0
  218. package/dist/modules/cpq/migrations/Migration20260407100000_cpq_price_rules.js.map +7 -0
  219. package/dist/modules/cpq/migrations/Migration20260408000000_cpq_price_rules.js +35 -0
  220. package/dist/modules/cpq/migrations/Migration20260408000000_cpq_price_rules.js.map +7 -0
  221. package/dist/modules/cpq/migrations/Migration20260410000000_cpq_drop_datacentres_inventory.js +21 -0
  222. package/dist/modules/cpq/migrations/Migration20260410000000_cpq_drop_datacentres_inventory.js.map +7 -0
  223. package/dist/modules/cpq/migrations/Migration20260410000000_cpq_wizard_rename.js +46 -0
  224. package/dist/modules/cpq/migrations/Migration20260410000000_cpq_wizard_rename.js.map +7 -0
  225. package/dist/modules/cpq/migrations/Migration20260410100000_cpq_inventory.js +118 -0
  226. package/dist/modules/cpq/migrations/Migration20260410100000_cpq_inventory.js.map +7 -0
  227. package/dist/modules/cpq/migrations/Migration20260411000000_cpq_orders.js +63 -0
  228. package/dist/modules/cpq/migrations/Migration20260411000000_cpq_orders.js.map +7 -0
  229. package/dist/modules/cpq/migrations/Migration20260412000000_cpq_bundled_offerings.js +28 -0
  230. package/dist/modules/cpq/migrations/Migration20260412000000_cpq_bundled_offerings.js.map +7 -0
  231. package/dist/modules/cpq/migrations/Migration20260504064621_cpq_arc.js +36 -0
  232. package/dist/modules/cpq/migrations/Migration20260504064621_cpq_arc.js.map +7 -0
  233. package/dist/modules/cpq/migrations/Migration20260514000000_cpq_spec_merge_retired_deprecated.js +14 -0
  234. package/dist/modules/cpq/migrations/Migration20260514000000_cpq_spec_merge_retired_deprecated.js.map +7 -0
  235. package/dist/modules/cpq/migrations/Migration20260514100000_cpq_offering_merge_retired_deprecated.js +14 -0
  236. package/dist/modules/cpq/migrations/Migration20260514100000_cpq_offering_merge_retired_deprecated.js.map +7 -0
  237. package/dist/modules/cpq/migrations/Migration20260514110000_cpq_list_search_indexes.js +58 -0
  238. package/dist/modules/cpq/migrations/Migration20260514110000_cpq_list_search_indexes.js.map +7 -0
  239. package/dist/modules/cpq/migrations/Migration20260515000000_cpq_inventory_subscriptions_search_indexes.js +29 -0
  240. package/dist/modules/cpq/migrations/Migration20260515000000_cpq_inventory_subscriptions_search_indexes.js.map +7 -0
  241. package/dist/modules/cpq/services/cpqBundleService.js +447 -0
  242. package/dist/modules/cpq/services/cpqBundleService.js.map +7 -0
  243. package/dist/modules/cpq/services/cpqInventoryService.js +1371 -0
  244. package/dist/modules/cpq/services/cpqInventoryService.js.map +7 -0
  245. package/dist/modules/cpq/services/cpqOrderService.js +901 -0
  246. package/dist/modules/cpq/services/cpqOrderService.js.map +7 -0
  247. package/dist/modules/cpq/services/cpqPricingService.js +289 -0
  248. package/dist/modules/cpq/services/cpqPricingService.js.map +7 -0
  249. package/dist/modules/cpq/services/cpqProductService.js +204 -0
  250. package/dist/modules/cpq/services/cpqProductService.js.map +7 -0
  251. package/dist/modules/cpq/services/cpqQuotingService.js +1867 -0
  252. package/dist/modules/cpq/services/cpqQuotingService.js.map +7 -0
  253. package/dist/modules/cpq/services/cpqValidationService.js +234 -0
  254. package/dist/modules/cpq/services/cpqValidationService.js.map +7 -0
  255. package/dist/modules/cpq/services/cpqWizardService.js +137 -0
  256. package/dist/modules/cpq/services/cpqWizardService.js.map +7 -0
  257. package/dist/modules/cpq/services/types.js +114 -0
  258. package/dist/modules/cpq/services/types.js.map +7 -0
  259. package/dist/modules/cpq/setup.js +49 -0
  260. package/dist/modules/cpq/setup.js.map +7 -0
  261. package/dist/modules/cpq/subscribers/subscription-amended-log.js +18 -0
  262. package/dist/modules/cpq/subscribers/subscription-amended-log.js.map +7 -0
  263. package/dist/modules/cpq/subscribers/subscription-cancelled-log.js +19 -0
  264. package/dist/modules/cpq/subscribers/subscription-cancelled-log.js.map +7 -0
  265. package/dist/modules/cpq/subscribers/subscription-merged-log.js +20 -0
  266. package/dist/modules/cpq/subscribers/subscription-merged-log.js.map +7 -0
  267. package/dist/modules/cpq/subscribers/subscription-renewed-log.js +18 -0
  268. package/dist/modules/cpq/subscribers/subscription-renewed-log.js.map +7 -0
  269. package/dist/modules/cpq/subscribers/subscription-superseded-log.js +18 -0
  270. package/dist/modules/cpq/subscribers/subscription-superseded-log.js.map +7 -0
  271. package/dist/modules/cpq/widgets/injection/customer-inventory/widget.client.js +192 -0
  272. package/dist/modules/cpq/widgets/injection/customer-inventory/widget.client.js.map +7 -0
  273. package/dist/modules/cpq/widgets/injection/customer-inventory/widget.js +17 -0
  274. package/dist/modules/cpq/widgets/injection/customer-inventory/widget.js.map +7 -0
  275. package/dist/modules/cpq/widgets/injection/order-cpq-tab/widget.client.js +79 -0
  276. package/dist/modules/cpq/widgets/injection/order-cpq-tab/widget.client.js.map +7 -0
  277. package/dist/modules/cpq/widgets/injection/order-cpq-tab/widget.js +17 -0
  278. package/dist/modules/cpq/widgets/injection/order-cpq-tab/widget.js.map +7 -0
  279. package/dist/modules/cpq/widgets/injection/quote-configurator/widget.client.js +181 -0
  280. package/dist/modules/cpq/widgets/injection/quote-configurator/widget.client.js.map +7 -0
  281. package/dist/modules/cpq/widgets/injection/quote-configurator/widget.js +17 -0
  282. package/dist/modules/cpq/widgets/injection/quote-configurator/widget.js.map +7 -0
  283. package/dist/modules/cpq/widgets/injection-table.js +44 -0
  284. package/dist/modules/cpq/widgets/injection-table.js.map +7 -0
  285. package/dist/modules/cpq/workflows/WizardRunner.js +113 -0
  286. package/dist/modules/cpq/workflows/WizardRunner.js.map +7 -0
  287. package/dist/modules/cpq/workflows/WizardTrigger.js +116 -0
  288. package/dist/modules/cpq/workflows/WizardTrigger.js.map +7 -0
  289. package/dist/modules/cpq/workflows/engine.js +188 -0
  290. package/dist/modules/cpq/workflows/engine.js.map +7 -0
  291. package/dist/modules/cpq/workflows/registry.js +16 -0
  292. package/dist/modules/cpq/workflows/registry.js.map +7 -0
  293. package/dist/modules/cpq/workflows/steps/CustomerSelectStep.js +119 -0
  294. package/dist/modules/cpq/workflows/steps/CustomerSelectStep.js.map +7 -0
  295. package/dist/modules/cpq/workflows/steps/InventorySelectStep.js +24 -0
  296. package/dist/modules/cpq/workflows/steps/InventorySelectStep.js.map +7 -0
  297. package/dist/modules/cpq/workflows/steps/ItemListStep.js +115 -0
  298. package/dist/modules/cpq/workflows/steps/ItemListStep.js.map +7 -0
  299. package/dist/modules/cpq/workflows/steps/OfferingSelectStep.js +327 -0
  300. package/dist/modules/cpq/workflows/steps/OfferingSelectStep.js.map +7 -0
  301. package/dist/modules/cpq/workflows/steps/ProductConfigureStep.js +231 -0
  302. package/dist/modules/cpq/workflows/steps/ProductConfigureStep.js.map +7 -0
  303. package/dist/modules/cpq/workflows/steps/ReviewStep.js +152 -0
  304. package/dist/modules/cpq/workflows/steps/ReviewStep.js.map +7 -0
  305. package/dist/modules/cpq/workflows/steps/index.js +49 -0
  306. package/dist/modules/cpq/workflows/steps/index.js.map +7 -0
  307. package/dist/modules/cpq/workflows/types.js +1 -0
  308. package/dist/modules/cpq/workflows/types.js.map +7 -0
  309. package/package.json +150 -0
  310. package/src/modules/cpq/__integration__/TC-CPQ-001.spec.ts +177 -0
  311. package/src/modules/cpq/__integration__/TC-CPQ-002.spec.ts +123 -0
  312. package/src/modules/cpq/__integration__/TC-CPQ-003.spec.ts +115 -0
  313. package/src/modules/cpq/__integration__/TC-CPQ-004.spec.ts +184 -0
  314. package/src/modules/cpq/__integration__/TC-CPQ-005.spec.ts +43 -0
  315. package/src/modules/cpq/__integration__/TC-CPQ-006.spec.ts +87 -0
  316. package/src/modules/cpq/__integration__/TC-CPQ-007.spec.ts +79 -0
  317. package/src/modules/cpq/__integration__/TC-CPQ-008.spec.ts +55 -0
  318. package/src/modules/cpq/__integration__/TC-CPQ-009.spec.ts +45 -0
  319. package/src/modules/cpq/__integration__/TC-CPQ-010.spec.ts +54 -0
  320. package/src/modules/cpq/__integration__/TC-CPQ-011.spec.ts +24 -0
  321. package/src/modules/cpq/__integration__/TC-CPQ-012.spec.ts +62 -0
  322. package/src/modules/cpq/__integration__/TC-CPQ-ARC-001.spec.ts +52 -0
  323. package/src/modules/cpq/__integration__/TC-CPQ-ARC-002.spec.ts +65 -0
  324. package/src/modules/cpq/__integration__/TC-CPQ-ARC-003.spec.ts +107 -0
  325. package/src/modules/cpq/__integration__/TC-CPQ-ARC-004.spec.ts +74 -0
  326. package/src/modules/cpq/__integration__/TC-CPQ-ARC-005.spec.ts +86 -0
  327. package/src/modules/cpq/__integration__/TC-CPQ-ARC-006.spec.ts +79 -0
  328. package/src/modules/cpq/__integration__/TC-CPQ-ARC-007.spec.ts +63 -0
  329. package/src/modules/cpq/__integration__/TC-CPQ-ARC-008.spec.ts +62 -0
  330. package/src/modules/cpq/__integration__/TC-CPQ-ARC-009.spec.ts +62 -0
  331. package/src/modules/cpq/__integration__/TC-CPQ-ARC-010.spec.ts +59 -0
  332. package/src/modules/cpq/__integration__/TC-CPQ-ARC-011.spec.ts +128 -0
  333. package/src/modules/cpq/__integration__/_helpers/cpqArcFixtures.ts +208 -0
  334. package/src/modules/cpq/__tests__/package-isolation.test.ts +232 -0
  335. package/src/modules/cpq/acl.ts +26 -0
  336. package/src/modules/cpq/api/_helpers/__tests__/handleArcError.test.ts +117 -0
  337. package/src/modules/cpq/api/_helpers/handleArcError.ts +81 -0
  338. package/src/modules/cpq/api/attribute-options/route.ts +55 -0
  339. package/src/modules/cpq/api/bundle-slots/route.ts +112 -0
  340. package/src/modules/cpq/api/bundle-tree/route.ts +31 -0
  341. package/src/modules/cpq/api/context.ts +39 -0
  342. package/src/modules/cpq/api/inventory/assets/route.ts +123 -0
  343. package/src/modules/cpq/api/inventory/assets/status/route.ts +34 -0
  344. package/src/modules/cpq/api/inventory/customer/[customerId]/parent-items/route.ts +30 -0
  345. package/src/modules/cpq/api/inventory/customer/[customerId]/route.ts +31 -0
  346. package/src/modules/cpq/api/inventory/subscription-items/route.ts +107 -0
  347. package/src/modules/cpq/api/inventory/subscriptions/[subscriptionId]/change-log/route.ts +64 -0
  348. package/src/modules/cpq/api/inventory/subscriptions/expiring/route.ts +66 -0
  349. package/src/modules/cpq/api/inventory/subscriptions/route.ts +126 -0
  350. package/src/modules/cpq/api/inventory/subscriptions/status/route.ts +34 -0
  351. package/src/modules/cpq/api/offering-components/route.ts +103 -0
  352. package/src/modules/cpq/api/orders/[orderId]/activate/route.ts +48 -0
  353. package/src/modules/cpq/api/orders/[orderId]/route.ts +28 -0
  354. package/src/modules/cpq/api/orders/[orderId]/status/route.ts +38 -0
  355. package/src/modules/cpq/api/orders/route.ts +77 -0
  356. package/src/modules/cpq/api/price-rules/route.ts +210 -0
  357. package/src/modules/cpq/api/pricing-table-entries/route.ts +159 -0
  358. package/src/modules/cpq/api/pricing-tables/route.ts +202 -0
  359. package/src/modules/cpq/api/product-attributes/route.ts +175 -0
  360. package/src/modules/cpq/api/product-charges/route.ts +181 -0
  361. package/src/modules/cpq/api/product-offerings/route.ts +329 -0
  362. package/src/modules/cpq/api/product-relationships/route.ts +156 -0
  363. package/src/modules/cpq/api/product-specifications/route.ts +325 -0
  364. package/src/modules/cpq/api/quotes/[quoteId]/cancel-meta/route.ts +77 -0
  365. package/src/modules/cpq/api/quotes/[quoteId]/clone/route.ts +28 -0
  366. package/src/modules/cpq/api/quotes/[quoteId]/items/[lineId]/route.ts +55 -0
  367. package/src/modules/cpq/api/quotes/[quoteId]/items/route.ts +26 -0
  368. package/src/modules/cpq/api/quotes/[quoteId]/merge-meta/route.ts +78 -0
  369. package/src/modules/cpq/api/quotes/[quoteId]/recalculate/route.ts +34 -0
  370. package/src/modules/cpq/api/quotes/[quoteId]/route.ts +109 -0
  371. package/src/modules/cpq/api/quotes/[quoteId]/status/route.ts +26 -0
  372. package/src/modules/cpq/api/quotes/[quoteId]/target-subscriptions/[targetId]/route.ts +91 -0
  373. package/src/modules/cpq/api/quotes/[quoteId]/target-subscriptions/route.ts +107 -0
  374. package/src/modules/cpq/api/quotes/attributes/route.ts +61 -0
  375. package/src/modules/cpq/api/quotes/from-subscription/route.ts +85 -0
  376. package/src/modules/cpq/api/quotes/price/route.ts +81 -0
  377. package/src/modules/cpq/api/quotes/route.ts +114 -0
  378. package/src/modules/cpq/api/quotes/validate-relationships/route.ts +100 -0
  379. package/src/modules/cpq/api/resolveQuotingService.ts +11 -0
  380. package/src/modules/cpq/api/wizards/resolve/route.ts +39 -0
  381. package/src/modules/cpq/api/wizards/route.ts +127 -0
  382. package/src/modules/cpq/backend/cpq/inventory/AssetsTable.tsx +166 -0
  383. package/src/modules/cpq/backend/cpq/inventory/SubscriptionsTable.tsx +251 -0
  384. package/src/modules/cpq/backend/cpq/inventory/assets/[id]/page.meta.ts +9 -0
  385. package/src/modules/cpq/backend/cpq/inventory/assets/[id]/page.tsx +440 -0
  386. package/src/modules/cpq/backend/cpq/inventory/page.meta.ts +16 -0
  387. package/src/modules/cpq/backend/cpq/inventory/page.tsx +49 -0
  388. package/src/modules/cpq/backend/cpq/inventory/shared.tsx +32 -0
  389. package/src/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.meta.ts +9 -0
  390. package/src/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.tsx +1085 -0
  391. package/src/modules/cpq/backend/cpq/offerings/[id]/page.tsx +1165 -0
  392. package/src/modules/cpq/backend/cpq/offerings/page.meta.ts +16 -0
  393. package/src/modules/cpq/backend/cpq/offerings/page.tsx +468 -0
  394. package/src/modules/cpq/backend/cpq/orders/[id]/page.tsx +921 -0
  395. package/src/modules/cpq/backend/cpq/orders/page.meta.ts +16 -0
  396. package/src/modules/cpq/backend/cpq/orders/page.tsx +182 -0
  397. package/src/modules/cpq/backend/cpq/price-rules/PriceRuleForm.tsx +310 -0
  398. package/src/modules/cpq/backend/cpq/price-rules/[id]/page.meta.ts +9 -0
  399. package/src/modules/cpq/backend/cpq/price-rules/[id]/page.tsx +472 -0
  400. package/src/modules/cpq/backend/cpq/price-rules/page.meta.ts +16 -0
  401. package/src/modules/cpq/backend/cpq/price-rules/page.tsx +253 -0
  402. package/src/modules/cpq/backend/cpq/pricing/[id]/EntriesEditor.tsx +431 -0
  403. package/src/modules/cpq/backend/cpq/pricing/[id]/ImportPreview.tsx +122 -0
  404. package/src/modules/cpq/backend/cpq/pricing/[id]/page.tsx +588 -0
  405. package/src/modules/cpq/backend/cpq/pricing/[id]/xlsxExport.ts +90 -0
  406. package/src/modules/cpq/backend/cpq/pricing/[id]/xlsxImport.ts +338 -0
  407. package/src/modules/cpq/backend/cpq/pricing/page.meta.ts +16 -0
  408. package/src/modules/cpq/backend/cpq/pricing/page.tsx +111 -0
  409. package/src/modules/cpq/backend/cpq/quotes/[id]/_components/ArcQuoteConfigurator.tsx +737 -0
  410. package/src/modules/cpq/backend/cpq/quotes/[id]/page.tsx +1721 -0
  411. package/src/modules/cpq/backend/cpq/quotes/page.meta.ts +16 -0
  412. package/src/modules/cpq/backend/cpq/quotes/page.tsx +370 -0
  413. package/src/modules/cpq/backend/cpq/specifications/[id]/DependsOnRulesEditor.tsx +300 -0
  414. package/src/modules/cpq/backend/cpq/specifications/[id]/page.tsx +1722 -0
  415. package/src/modules/cpq/backend/cpq/specifications/page.meta.ts +16 -0
  416. package/src/modules/cpq/backend/cpq/specifications/page.tsx +191 -0
  417. package/src/modules/cpq/backend/cpq/wizards/[definitionCode]/detail/page.tsx +319 -0
  418. package/src/modules/cpq/backend/cpq/wizards/[definitionCode]/page.tsx +234 -0
  419. package/src/modules/cpq/backend/cpq/wizards/page.meta.ts +16 -0
  420. package/src/modules/cpq/backend/cpq/wizards/page.tsx +141 -0
  421. package/src/modules/cpq/ce.ts +150 -0
  422. package/src/modules/cpq/cli.ts +10 -0
  423. package/src/modules/cpq/components/CpqListView.tsx +431 -0
  424. package/src/modules/cpq/components/NumberInput.tsx +166 -0
  425. package/src/modules/cpq/components/StatusPath.tsx +116 -0
  426. package/src/modules/cpq/components/statusMaps.ts +148 -0
  427. package/src/modules/cpq/components/useCpqRowActions.tsx +183 -0
  428. package/src/modules/cpq/data/__tests__/validators.arc.test.ts +271 -0
  429. package/src/modules/cpq/data/__tests__/validators.test.ts +782 -0
  430. package/src/modules/cpq/data/entities.ts +1467 -0
  431. package/src/modules/cpq/data/validators.ts +663 -0
  432. package/src/modules/cpq/di.ts +70 -0
  433. package/src/modules/cpq/events.ts +62 -0
  434. package/src/modules/cpq/index.ts +15 -0
  435. package/src/modules/cpq/lib/seeds/__tests__/api.test.ts +86 -0
  436. package/src/modules/cpq/lib/seeds/__tests__/tenant-provisioning.test.ts +349 -0
  437. package/src/modules/cpq/lib/seeds/api.ts +119 -0
  438. package/src/modules/cpq/lib/seeds/tenant-provisioning.ts +239 -0
  439. package/src/modules/cpq/lib/seeds.ts +18 -0
  440. package/src/modules/cpq/migrations/.snapshot-open-mercato.json +7473 -0
  441. package/src/modules/cpq/migrations/Migration20260220220000_cpq.ts +51 -0
  442. package/src/modules/cpq/migrations/Migration20260330000000_cpq_product_domain.ts +70 -0
  443. package/src/modules/cpq/migrations/Migration20260331000000_cpq_charge_unique_per_offering.ts +15 -0
  444. package/src/modules/cpq/migrations/Migration20260401000000_cpq_quoting_v2.ts +73 -0
  445. package/src/modules/cpq/migrations/Migration20260402000000_cpq_workflows.ts +59 -0
  446. package/src/modules/cpq/migrations/Migration20260407000000_cpq_pricing_tables_v2.ts +30 -0
  447. package/src/modules/cpq/migrations/Migration20260407100000_cpq_price_rules.ts +36 -0
  448. package/src/modules/cpq/migrations/Migration20260408000000_cpq_price_rules.ts +33 -0
  449. package/src/modules/cpq/migrations/Migration20260410000000_cpq_drop_datacentres_inventory.ts +22 -0
  450. package/src/modules/cpq/migrations/Migration20260410000000_cpq_wizard_rename.ts +56 -0
  451. package/src/modules/cpq/migrations/Migration20260410100000_cpq_inventory.ts +118 -0
  452. package/src/modules/cpq/migrations/Migration20260411000000_cpq_orders.ts +62 -0
  453. package/src/modules/cpq/migrations/Migration20260412000000_cpq_bundled_offerings.ts +33 -0
  454. package/src/modules/cpq/migrations/Migration20260504064621_cpq_arc.ts +68 -0
  455. package/src/modules/cpq/migrations/Migration20260514000000_cpq_spec_merge_retired_deprecated.ts +30 -0
  456. package/src/modules/cpq/migrations/Migration20260514100000_cpq_offering_merge_retired_deprecated.ts +27 -0
  457. package/src/modules/cpq/migrations/Migration20260514110000_cpq_list_search_indexes.ts +82 -0
  458. package/src/modules/cpq/migrations/Migration20260515000000_cpq_inventory_subscriptions_search_indexes.ts +52 -0
  459. package/src/modules/cpq/services/__tests__/_helpers/mockEm.ts +59 -0
  460. package/src/modules/cpq/services/__tests__/cpqBundleService.test.ts +661 -0
  461. package/src/modules/cpq/services/__tests__/cpqInventoryService.arc.test.ts +357 -0
  462. package/src/modules/cpq/services/__tests__/cpqInventoryService.test.ts +718 -0
  463. package/src/modules/cpq/services/__tests__/cpqOrderService.test.ts +603 -0
  464. package/src/modules/cpq/services/__tests__/cpqPricingService.test.ts +1012 -0
  465. package/src/modules/cpq/services/__tests__/cpqProductService.test.ts +603 -0
  466. package/src/modules/cpq/services/__tests__/cpqQuotingService.arc.test.ts +143 -0
  467. package/src/modules/cpq/services/__tests__/cpqQuotingService.test.ts +658 -0
  468. package/src/modules/cpq/services/__tests__/cpqValidationService.test.ts +811 -0
  469. package/src/modules/cpq/services/__tests__/cpqWizardService.test.ts +389 -0
  470. package/src/modules/cpq/services/__tests__/types.test.ts +359 -0
  471. package/src/modules/cpq/services/cpqBundleService.ts +671 -0
  472. package/src/modules/cpq/services/cpqInventoryService.ts +1929 -0
  473. package/src/modules/cpq/services/cpqOrderService.ts +1230 -0
  474. package/src/modules/cpq/services/cpqPricingService.ts +412 -0
  475. package/src/modules/cpq/services/cpqProductService.ts +311 -0
  476. package/src/modules/cpq/services/cpqQuotingService.ts +2638 -0
  477. package/src/modules/cpq/services/cpqValidationService.ts +323 -0
  478. package/src/modules/cpq/services/cpqWizardService.ts +204 -0
  479. package/src/modules/cpq/services/types.ts +303 -0
  480. package/src/modules/cpq/setup.ts +63 -0
  481. package/src/modules/cpq/subscribers/subscription-amended-log.ts +20 -0
  482. package/src/modules/cpq/subscribers/subscription-cancelled-log.ts +19 -0
  483. package/src/modules/cpq/subscribers/subscription-merged-log.ts +22 -0
  484. package/src/modules/cpq/subscribers/subscription-renewed-log.ts +18 -0
  485. package/src/modules/cpq/subscribers/subscription-superseded-log.ts +19 -0
  486. package/src/modules/cpq/widgets/injection/customer-inventory/widget.client.tsx +339 -0
  487. package/src/modules/cpq/widgets/injection/customer-inventory/widget.ts +16 -0
  488. package/src/modules/cpq/widgets/injection/order-cpq-tab/widget.client.tsx +96 -0
  489. package/src/modules/cpq/widgets/injection/order-cpq-tab/widget.ts +16 -0
  490. package/src/modules/cpq/widgets/injection/quote-configurator/widget.client.tsx +265 -0
  491. package/src/modules/cpq/widgets/injection/quote-configurator/widget.ts +16 -0
  492. package/src/modules/cpq/widgets/injection-table.ts +42 -0
  493. package/src/modules/cpq/workflows/WizardRunner.tsx +158 -0
  494. package/src/modules/cpq/workflows/WizardTrigger.tsx +142 -0
  495. package/src/modules/cpq/workflows/engine.tsx +278 -0
  496. package/src/modules/cpq/workflows/registry.ts +15 -0
  497. package/src/modules/cpq/workflows/steps/CustomerSelectStep.tsx +136 -0
  498. package/src/modules/cpq/workflows/steps/InventorySelectStep.tsx +34 -0
  499. package/src/modules/cpq/workflows/steps/ItemListStep.tsx +146 -0
  500. package/src/modules/cpq/workflows/steps/OfferingSelectStep.tsx +438 -0
  501. package/src/modules/cpq/workflows/steps/ProductConfigureStep.tsx +287 -0
  502. package/src/modules/cpq/workflows/steps/ReviewStep.tsx +219 -0
  503. package/src/modules/cpq/workflows/steps/index.ts +51 -0
  504. package/src/modules/cpq/workflows/types.ts +102 -0
@@ -0,0 +1,72 @@
1
+ import { NextResponse } from "next/server";
2
+ import { resolveCpqRouteContext } from "../../context.js";
3
+ import { cpqCreateQuoteFromSubscriptionSchema } from "../../../data/validators.js";
4
+ import { resolveQuotingService } from "../../resolveQuotingService.js";
5
+ import { handleArcError } from "../../_helpers/handleArcError.js";
6
+ const metadata = {
7
+ POST: { requireAuth: true, requireFeatures: ["cpq.quotes.manage"] }
8
+ };
9
+ async function POST(req) {
10
+ try {
11
+ const ctx = await resolveCpqRouteContext(req);
12
+ if (!ctx.auth) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
13
+ const body = cpqCreateQuoteFromSubscriptionSchema.parse(await req.json());
14
+ const scope = { organizationId: ctx.organizationId, tenantId: ctx.tenantId };
15
+ const service = resolveQuotingService(ctx);
16
+ const result = await service.createQuoteFromSubscription(
17
+ {
18
+ subscriptionId: body.subscriptionId,
19
+ type: body.type,
20
+ renewTerm: body.renewTerm
21
+ },
22
+ scope
23
+ );
24
+ return NextResponse.json(result, { status: 201 });
25
+ } catch (err) {
26
+ return handleArcError(err, "cpq/quotes/from-subscription.POST");
27
+ }
28
+ }
29
+ const openApi = {
30
+ "/api/cpq/quotes/from-subscription": {
31
+ post: {
32
+ tags: ["CPQ ARC"],
33
+ summary: "Create an ARC quote pre-filled from a subscription",
34
+ requestBody: {
35
+ required: true,
36
+ content: {
37
+ "application/json": {
38
+ schema: {
39
+ type: "object",
40
+ required: ["subscriptionId", "type"],
41
+ properties: {
42
+ subscriptionId: { type: "string", format: "uuid" },
43
+ type: { type: "string", enum: ["amend", "renew", "cancel"] },
44
+ renewTerm: {
45
+ type: "object",
46
+ properties: {
47
+ newTermStart: { type: "string" },
48
+ newTermEnd: { type: "string" },
49
+ newTermMonths: { type: "integer", minimum: 1 }
50
+ }
51
+ }
52
+ }
53
+ }
54
+ }
55
+ }
56
+ },
57
+ responses: {
58
+ "201": { description: "Quote created", content: { "application/json": {} } },
59
+ "400": { description: "Validation error" },
60
+ "401": { description: "Unauthorized" },
61
+ "404": { description: "Subscription not found" },
62
+ "409": { description: "Subscription not in eligible status / concurrent ARC quote" }
63
+ }
64
+ }
65
+ }
66
+ };
67
+ export {
68
+ POST,
69
+ metadata,
70
+ openApi
71
+ };
72
+ //# sourceMappingURL=route.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/cpq/api/quotes/from-subscription/route.ts"],
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { resolveCpqRouteContext } from '../../context'\nimport { cpqCreateQuoteFromSubscriptionSchema } from '../../../data/validators'\nimport { resolveQuotingService } from '../../resolveQuotingService'\nimport { handleArcError } from '../../_helpers/handleArcError'\n\n/**\n * POST /api/cpq/quotes/from-subscription\n *\n * Create a fresh ARC quote pre-filled with one subscription's items.\n *\n * Body (validated):\n * {\n * subscriptionId: uuid,\n * type: 'amend' | 'renew' | 'cancel',\n * renewTerm?: { newTermStart, newTermEnd, newTermMonths? }\n * }\n *\n * Returns: { quoteId, cpqConfigId }\n */\nexport const metadata = {\n POST: { requireAuth: true, requireFeatures: ['cpq.quotes.manage'] },\n}\n\nexport async function POST(req: Request) {\n try {\n const ctx = await resolveCpqRouteContext(req)\n if (!ctx.auth) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n\n const body = cpqCreateQuoteFromSubscriptionSchema.parse(await req.json())\n const scope = { organizationId: ctx.organizationId, tenantId: ctx.tenantId }\n\n const service = resolveQuotingService(ctx)\n const result = await service.createQuoteFromSubscription(\n {\n subscriptionId: body.subscriptionId,\n type: body.type,\n renewTerm: body.renewTerm,\n },\n scope,\n )\n return NextResponse.json(result, { status: 201 })\n } catch (err) {\n return handleArcError(err, 'cpq/quotes/from-subscription.POST')\n }\n}\n\nexport const openApi = {\n '/api/cpq/quotes/from-subscription': {\n post: {\n tags: ['CPQ ARC'],\n summary: 'Create an ARC quote pre-filled from a subscription',\n requestBody: {\n required: true,\n content: {\n 'application/json': {\n schema: {\n type: 'object',\n required: ['subscriptionId', 'type'],\n properties: {\n subscriptionId: { type: 'string', format: 'uuid' },\n type: { type: 'string', enum: ['amend', 'renew', 'cancel'] },\n renewTerm: {\n type: 'object',\n properties: {\n newTermStart: { type: 'string' },\n newTermEnd: { type: 'string' },\n newTermMonths: { type: 'integer', minimum: 1 },\n },\n },\n },\n },\n },\n },\n },\n responses: {\n '201': { description: 'Quote created', content: { 'application/json': {} } },\n '400': { description: 'Validation error' },\n '401': { description: 'Unauthorized' },\n '404': { description: 'Subscription not found' },\n '409': { description: 'Subscription not in eligible status / concurrent ARC quote' },\n },\n },\n },\n}\n"],
5
+ "mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,8BAA8B;AACvC,SAAS,4CAA4C;AACrD,SAAS,6BAA6B;AACtC,SAAS,sBAAsB;AAgBxB,MAAM,WAAW;AAAA,EACtB,MAAM,EAAE,aAAa,MAAM,iBAAiB,CAAC,mBAAmB,EAAE;AACpE;AAEA,eAAsB,KAAK,KAAc;AACvC,MAAI;AACF,UAAM,MAAM,MAAM,uBAAuB,GAAG;AAC5C,QAAI,CAAC,IAAI,KAAM,QAAO,aAAa,KAAK,EAAE,OAAO,eAAe,GAAG,EAAE,QAAQ,IAAI,CAAC;AAElF,UAAM,OAAO,qCAAqC,MAAM,MAAM,IAAI,KAAK,CAAC;AACxE,UAAM,QAAQ,EAAE,gBAAgB,IAAI,gBAAgB,UAAU,IAAI,SAAS;AAE3E,UAAM,UAAU,sBAAsB,GAAG;AACzC,UAAM,SAAS,MAAM,QAAQ;AAAA,MAC3B;AAAA,QACE,gBAAgB,KAAK;AAAA,QACrB,MAAM,KAAK;AAAA,QACX,WAAW,KAAK;AAAA,MAClB;AAAA,MACA;AAAA,IACF;AACA,WAAO,aAAa,KAAK,QAAQ,EAAE,QAAQ,IAAI,CAAC;AAAA,EAClD,SAAS,KAAK;AACZ,WAAO,eAAe,KAAK,mCAAmC;AAAA,EAChE;AACF;AAEO,MAAM,UAAU;AAAA,EACrB,qCAAqC;AAAA,IACnC,MAAM;AAAA,MACJ,MAAM,CAAC,SAAS;AAAA,MAChB,SAAS;AAAA,MACT,aAAa;AAAA,QACX,UAAU;AAAA,QACV,SAAS;AAAA,UACP,oBAAoB;AAAA,YAClB,QAAQ;AAAA,cACN,MAAM;AAAA,cACN,UAAU,CAAC,kBAAkB,MAAM;AAAA,cACnC,YAAY;AAAA,gBACV,gBAAgB,EAAE,MAAM,UAAU,QAAQ,OAAO;AAAA,gBACjD,MAAM,EAAE,MAAM,UAAU,MAAM,CAAC,SAAS,SAAS,QAAQ,EAAE;AAAA,gBAC3D,WAAW;AAAA,kBACT,MAAM;AAAA,kBACN,YAAY;AAAA,oBACV,cAAc,EAAE,MAAM,SAAS;AAAA,oBAC/B,YAAY,EAAE,MAAM,SAAS;AAAA,oBAC7B,eAAe,EAAE,MAAM,WAAW,SAAS,EAAE;AAAA,kBAC/C;AAAA,gBACF;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,MACA,WAAW;AAAA,QACT,OAAO,EAAE,aAAa,iBAAiB,SAAS,EAAE,oBAAoB,CAAC,EAAE,EAAE;AAAA,QAC3E,OAAO,EAAE,aAAa,mBAAmB;AAAA,QACzC,OAAO,EAAE,aAAa,eAAe;AAAA,QACrC,OAAO,EAAE,aAAa,yBAAyB;AAAA,QAC/C,OAAO,EAAE,aAAa,6DAA6D;AAAA,MACrF;AAAA,IACF;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,69 @@
1
+ import { NextResponse } from "next/server";
2
+ import { z } from "zod";
3
+ import { resolveCpqRouteContext } from "../../context.js";
4
+ import { cpqPricePreviewSchema } from "../../../data/validators.js";
5
+ import { getBaseCurrencyCode } from "../../../services/types.js";
6
+ const metadata = {
7
+ POST: { requireAuth: true, requireFeatures: ["cpq.quotes.view"] }
8
+ };
9
+ async function POST(req) {
10
+ try {
11
+ const ctx = await resolveCpqRouteContext(req);
12
+ if (!ctx.auth) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
13
+ const body = cpqPricePreviewSchema.parse(await req.json());
14
+ const scope = { organizationId: ctx.organizationId, tenantId: ctx.tenantId };
15
+ const currencyCode = body.currencyCode ?? await getBaseCurrencyCode(ctx.em, scope);
16
+ const pricingService = ctx.container.resolve("cpqPricingService");
17
+ let primaryCharges = [];
18
+ if (body.primaryItem) {
19
+ primaryCharges = await pricingService.resolveProductCharges({
20
+ offeringId: body.primaryItem.offeringId ?? void 0,
21
+ productId: body.primaryItem.productId ?? void 0,
22
+ configuration: body.primaryItem.configuration,
23
+ currencyCode,
24
+ ...scope
25
+ });
26
+ }
27
+ const childItems = [];
28
+ for (const child of body.childItems) {
29
+ const charges = await pricingService.resolveProductCharges({
30
+ offeringId: child.offeringId ?? void 0,
31
+ productId: child.productId ?? void 0,
32
+ configuration: child.configuration,
33
+ currencyCode,
34
+ ...scope
35
+ });
36
+ childItems.push({
37
+ offeringId: child.offeringId ?? null,
38
+ productId: child.productId ?? null,
39
+ charges
40
+ });
41
+ }
42
+ const allCharges = [...primaryCharges, ...childItems.flatMap((c) => c.charges)];
43
+ const nrcTotal = allCharges.filter((c) => c.chargeType === "nrc" && c.totalPrice != null).reduce((s, c) => s + (c.totalPrice ?? 0), 0);
44
+ const mrcTotal = allCharges.filter((c) => c.chargeType === "mrc" && c.totalPrice != null).reduce((s, c) => s + (c.totalPrice ?? 0), 0);
45
+ const usageCharges = allCharges.filter((c) => c.chargeType === "usage").map((c) => ({
46
+ chargeCode: c.chargeCode,
47
+ chargeName: c.chargeName,
48
+ unitPrice: c.unitPrice,
49
+ note: c.note ?? "Usage-based charge \u2014 billed on actual consumption."
50
+ }));
51
+ return NextResponse.json({
52
+ primaryCharges,
53
+ childItems,
54
+ totals: { nrcTotal, mrcTotal, usageCharges },
55
+ currencyCode
56
+ });
57
+ } catch (err) {
58
+ if (err instanceof z.ZodError) {
59
+ return NextResponse.json({ error: "Validation error", details: err.issues }, { status: 400 });
60
+ }
61
+ console.error("[cpq/quotes/price.POST]", err);
62
+ return NextResponse.json({ error: "Internal error" }, { status: 500 });
63
+ }
64
+ }
65
+ export {
66
+ POST,
67
+ metadata
68
+ };
69
+ //# sourceMappingURL=route.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/cpq/api/quotes/price/route.ts"],
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport { resolveCpqRouteContext } from '../../context'\nimport { cpqPricePreviewSchema } from '../../../data/validators'\nimport type { DefaultCpqPricingService } from '../../../services/cpqPricingService'\nimport type { ResolvedCharge } from '../../../services/types'\nimport { getBaseCurrencyCode } from '../../../services/types'\n\nexport const metadata = {\n POST: { requireAuth: true, requireFeatures: ['cpq.quotes.view'] },\n}\n\nexport async function POST(req: Request) {\n try {\n const ctx = await resolveCpqRouteContext(req)\n if (!ctx.auth) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n\n const body = cpqPricePreviewSchema.parse(await req.json())\n const scope = { organizationId: ctx.organizationId, tenantId: ctx.tenantId }\n const currencyCode = body.currencyCode ?? await getBaseCurrencyCode(ctx.em, scope)\n\n const pricingService = ctx.container.resolve('cpqPricingService') as DefaultCpqPricingService\n\n let primaryCharges: ResolvedCharge[] = []\n if (body.primaryItem) {\n primaryCharges = await pricingService.resolveProductCharges({\n offeringId: body.primaryItem.offeringId ?? undefined,\n productId: body.primaryItem.productId ?? undefined,\n configuration: body.primaryItem.configuration,\n currencyCode,\n ...scope,\n })\n }\n\n const childItems: Array<{ offeringId: string | null; productId: string | null; charges: ResolvedCharge[] }> = []\n for (const child of body.childItems) {\n const charges = await pricingService.resolveProductCharges({\n offeringId: child.offeringId ?? undefined,\n productId: child.productId ?? undefined,\n configuration: child.configuration,\n currencyCode,\n ...scope,\n })\n childItems.push({\n offeringId: child.offeringId ?? null,\n productId: child.productId ?? null,\n charges,\n })\n }\n\n const allCharges = [...primaryCharges, ...childItems.flatMap((c) => c.charges)]\n\n const nrcTotal = allCharges\n .filter((c) => c.chargeType === 'nrc' && c.totalPrice != null)\n .reduce((s, c) => s + (c.totalPrice ?? 0), 0)\n const mrcTotal = allCharges\n .filter((c) => c.chargeType === 'mrc' && c.totalPrice != null)\n .reduce((s, c) => s + (c.totalPrice ?? 0), 0)\n const usageCharges = allCharges\n .filter((c) => c.chargeType === 'usage')\n .map((c) => ({\n chargeCode: c.chargeCode,\n chargeName: c.chargeName,\n unitPrice: c.unitPrice,\n note: c.note ?? 'Usage-based charge \u2014 billed on actual consumption.',\n }))\n\n return NextResponse.json({\n primaryCharges,\n childItems,\n totals: { nrcTotal, mrcTotal, usageCharges },\n currencyCode,\n })\n } catch (err) {\n if (err instanceof z.ZodError) {\n return NextResponse.json({ error: 'Validation error', details: err.issues }, { status: 400 })\n }\n console.error('[cpq/quotes/price.POST]', err)\n return NextResponse.json({ error: 'Internal error' }, { status: 500 })\n }\n}\n"],
5
+ "mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS;AAClB,SAAS,8BAA8B;AACvC,SAAS,6BAA6B;AAGtC,SAAS,2BAA2B;AAE7B,MAAM,WAAW;AAAA,EACtB,MAAM,EAAE,aAAa,MAAM,iBAAiB,CAAC,iBAAiB,EAAE;AAClE;AAEA,eAAsB,KAAK,KAAc;AACvC,MAAI;AACF,UAAM,MAAM,MAAM,uBAAuB,GAAG;AAC5C,QAAI,CAAC,IAAI,KAAM,QAAO,aAAa,KAAK,EAAE,OAAO,eAAe,GAAG,EAAE,QAAQ,IAAI,CAAC;AAElF,UAAM,OAAO,sBAAsB,MAAM,MAAM,IAAI,KAAK,CAAC;AACzD,UAAM,QAAQ,EAAE,gBAAgB,IAAI,gBAAgB,UAAU,IAAI,SAAS;AAC3E,UAAM,eAAe,KAAK,gBAAgB,MAAM,oBAAoB,IAAI,IAAI,KAAK;AAEjF,UAAM,iBAAiB,IAAI,UAAU,QAAQ,mBAAmB;AAEhE,QAAI,iBAAmC,CAAC;AACxC,QAAI,KAAK,aAAa;AACpB,uBAAiB,MAAM,eAAe,sBAAsB;AAAA,QAC1D,YAAY,KAAK,YAAY,cAAc;AAAA,QAC3C,WAAW,KAAK,YAAY,aAAa;AAAA,QACzC,eAAe,KAAK,YAAY;AAAA,QAChC;AAAA,QACA,GAAG;AAAA,MACL,CAAC;AAAA,IACH;AAEA,UAAM,aAAwG,CAAC;AAC/G,eAAW,SAAS,KAAK,YAAY;AACnC,YAAM,UAAU,MAAM,eAAe,sBAAsB;AAAA,QACzD,YAAY,MAAM,cAAc;AAAA,QAChC,WAAW,MAAM,aAAa;AAAA,QAC9B,eAAe,MAAM;AAAA,QACrB;AAAA,QACA,GAAG;AAAA,MACL,CAAC;AACD,iBAAW,KAAK;AAAA,QACd,YAAY,MAAM,cAAc;AAAA,QAChC,WAAW,MAAM,aAAa;AAAA,QAC9B;AAAA,MACF,CAAC;AAAA,IACH;AAEA,UAAM,aAAa,CAAC,GAAG,gBAAgB,GAAG,WAAW,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;AAE9E,UAAM,WAAW,WACd,OAAO,CAAC,MAAM,EAAE,eAAe,SAAS,EAAE,cAAc,IAAI,EAC5D,OAAO,CAAC,GAAG,MAAM,KAAK,EAAE,cAAc,IAAI,CAAC;AAC9C,UAAM,WAAW,WACd,OAAO,CAAC,MAAM,EAAE,eAAe,SAAS,EAAE,cAAc,IAAI,EAC5D,OAAO,CAAC,GAAG,MAAM,KAAK,EAAE,cAAc,IAAI,CAAC;AAC9C,UAAM,eAAe,WAClB,OAAO,CAAC,MAAM,EAAE,eAAe,OAAO,EACtC,IAAI,CAAC,OAAO;AAAA,MACX,YAAY,EAAE;AAAA,MACd,YAAY,EAAE;AAAA,MACd,WAAW,EAAE;AAAA,MACb,MAAM,EAAE,QAAQ;AAAA,IAClB,EAAE;AAEJ,WAAO,aAAa,KAAK;AAAA,MACvB;AAAA,MACA;AAAA,MACA,QAAQ,EAAE,UAAU,UAAU,aAAa;AAAA,MAC3C;AAAA,IACF,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,QAAI,eAAe,EAAE,UAAU;AAC7B,aAAO,aAAa,KAAK,EAAE,OAAO,oBAAoB,SAAS,IAAI,OAAO,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC9F;AACA,YAAQ,MAAM,2BAA2B,GAAG;AAC5C,WAAO,aAAa,KAAK,EAAE,OAAO,iBAAiB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACvE;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,97 @@
1
+ import { NextResponse } from "next/server";
2
+ import { z } from "zod";
3
+ import { resolveCpqRouteContext } from "../context.js";
4
+ import { cpqCreateQuoteSchema } from "../../data/validators.js";
5
+ import { QuotingError } from "../../services/cpqQuotingService.js";
6
+ import { resolveQuotingService } from "../resolveQuotingService.js";
7
+ import { CpqQuoteConfiguration } from "../../data/entities.js";
8
+ import { SalesQuote } from "@open-mercato/core/modules/sales/data/entities";
9
+ const metadata = {
10
+ POST: { requireAuth: true, requireFeatures: ["cpq.quotes.manage"] },
11
+ GET: { requireAuth: true, requireFeatures: ["cpq.quotes.view"] }
12
+ };
13
+ async function POST(req) {
14
+ try {
15
+ const ctx = await resolveCpqRouteContext(req);
16
+ if (!ctx.auth) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
17
+ const body = cpqCreateQuoteSchema.parse(await req.json());
18
+ const scope = { organizationId: ctx.organizationId, tenantId: ctx.tenantId };
19
+ const service = resolveQuotingService(ctx);
20
+ const result = await service.createQuote(body, scope);
21
+ return NextResponse.json(result, { status: 201 });
22
+ } catch (err) {
23
+ return handleError(err, "cpq/quotes.POST");
24
+ }
25
+ }
26
+ async function GET(req) {
27
+ try {
28
+ const ctx = await resolveCpqRouteContext(req);
29
+ if (!ctx.auth) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
30
+ const url = new URL(req.url);
31
+ const scope = { organizationId: ctx.organizationId, tenantId: ctx.tenantId, deletedAt: null };
32
+ const page = Math.max(1, Number(url.searchParams.get("page") ?? "1"));
33
+ const pageSize = Math.min(100, Math.max(1, Number(url.searchParams.get("pageSize") ?? "50")));
34
+ const filters = { ...scope };
35
+ const cpqStatus = url.searchParams.get("cpqStatus");
36
+ if (cpqStatus) filters.cpqStatus = cpqStatus;
37
+ const currencyCode = url.searchParams.get("currencyCode");
38
+ if (currencyCode) filters.currencyCode = currencyCode;
39
+ const customerId = url.searchParams.get("customerId");
40
+ if (customerId) filters.customerId = customerId;
41
+ const search = url.searchParams.get("search")?.trim();
42
+ if (search) {
43
+ filters.$or = [
44
+ { quoteId: { $ilike: `%${search}%` } },
45
+ { customerId: { $ilike: `%${search}%` } }
46
+ ];
47
+ }
48
+ const ALLOWED_SORT_FIELDS = ["createdAt", "updatedAt", "cpqStatus", "version", "currencyCode"];
49
+ const sortFieldParam = url.searchParams.get("sortField") ?? "";
50
+ const sortField = ALLOWED_SORT_FIELDS.includes(sortFieldParam) ? sortFieldParam : "createdAt";
51
+ const sortDir = url.searchParams.get("sortDir") === "asc" ? "asc" : "desc";
52
+ const [items, total] = await ctx.em.findAndCount(CpqQuoteConfiguration, filters, {
53
+ limit: pageSize,
54
+ offset: (page - 1) * pageSize,
55
+ orderBy: { [sortField]: sortDir }
56
+ });
57
+ const salesQuoteIds = [...new Set(items.map((i) => i.quoteId).filter(Boolean))];
58
+ const salesQuotes = salesQuoteIds.length > 0 ? await ctx.em.find(SalesQuote, {
59
+ id: { $in: salesQuoteIds },
60
+ organizationId: ctx.organizationId,
61
+ tenantId: ctx.tenantId
62
+ }) : [];
63
+ const quoteNumberById = new Map(
64
+ salesQuotes.map((q) => [q.id, q.quoteNumber ?? null])
65
+ );
66
+ return NextResponse.json({
67
+ items: items.map((item) => ({
68
+ ...item,
69
+ quoteNumber: quoteNumberById.get(item.quoteId) ?? null
70
+ })),
71
+ total,
72
+ page,
73
+ pageSize,
74
+ totalPages: Math.ceil(total / pageSize)
75
+ });
76
+ } catch (err) {
77
+ return handleError(err, "cpq/quotes.GET");
78
+ }
79
+ }
80
+ function handleError(err, context) {
81
+ if (err instanceof z.ZodError) {
82
+ return NextResponse.json({ error: "Validation error", details: err.issues }, { status: 400 });
83
+ }
84
+ if (err instanceof QuotingError) {
85
+ const body = { error: err.message };
86
+ if (err.cpqStatus) body.cpqStatus = err.cpqStatus;
87
+ return NextResponse.json(body, { status: err.status });
88
+ }
89
+ console.error(`[${context}]`, err);
90
+ return NextResponse.json({ error: "Internal error" }, { status: 500 });
91
+ }
92
+ export {
93
+ GET,
94
+ POST,
95
+ metadata
96
+ };
97
+ //# sourceMappingURL=route.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/cpq/api/quotes/route.ts"],
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport { resolveCpqRouteContext } from '../context'\nimport { cpqCreateQuoteSchema } from '../../data/validators'\nimport { QuotingError } from '../../services/cpqQuotingService'\nimport { resolveQuotingService } from '../resolveQuotingService'\nimport { CpqQuoteConfiguration } from '../../data/entities'\nimport { SalesQuote } from '@open-mercato/core/modules/sales/data/entities'\n\nexport const metadata = {\n POST: { requireAuth: true, requireFeatures: ['cpq.quotes.manage'] },\n GET: { requireAuth: true, requireFeatures: ['cpq.quotes.view'] },\n}\n\nexport async function POST(req: Request) {\n try {\n const ctx = await resolveCpqRouteContext(req)\n if (!ctx.auth) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n\n const body = cpqCreateQuoteSchema.parse(await req.json())\n const scope = { organizationId: ctx.organizationId, tenantId: ctx.tenantId }\n\n const service = resolveQuotingService(ctx)\n const result = await service.createQuote(body, scope)\n return NextResponse.json(result, { status: 201 })\n } catch (err) {\n return handleError(err, 'cpq/quotes.POST')\n }\n}\n\nexport async function GET(req: Request) {\n try {\n const ctx = await resolveCpqRouteContext(req)\n if (!ctx.auth) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n\n const url = new URL(req.url)\n const scope = { organizationId: ctx.organizationId, tenantId: ctx.tenantId, deletedAt: null }\n\n const page = Math.max(1, Number(url.searchParams.get('page') ?? '1'))\n const pageSize = Math.min(100, Math.max(1, Number(url.searchParams.get('pageSize') ?? '50')))\n\n const filters: Record<string, unknown> = { ...scope }\n\n const cpqStatus = url.searchParams.get('cpqStatus')\n if (cpqStatus) filters.cpqStatus = cpqStatus\n const currencyCode = url.searchParams.get('currencyCode')\n if (currencyCode) filters.currencyCode = currencyCode\n const customerId = url.searchParams.get('customerId')\n if (customerId) filters.customerId = customerId\n\n // Free-text search across quoteId, customerId (case-insensitive)\n const search = url.searchParams.get('search')?.trim()\n if (search) {\n filters.$or = [\n { quoteId: { $ilike: `%${search}%` } },\n { customerId: { $ilike: `%${search}%` } },\n ]\n }\n\n const ALLOWED_SORT_FIELDS = ['createdAt', 'updatedAt', 'cpqStatus', 'version', 'currencyCode'] as const\n const sortFieldParam = url.searchParams.get('sortField') ?? ''\n const sortField = (ALLOWED_SORT_FIELDS as readonly string[]).includes(sortFieldParam)\n ? (sortFieldParam as (typeof ALLOWED_SORT_FIELDS)[number])\n : 'createdAt'\n const sortDir = url.searchParams.get('sortDir') === 'asc' ? 'asc' : 'desc'\n\n const [items, total] = await ctx.em.findAndCount(CpqQuoteConfiguration, filters, {\n limit: pageSize,\n offset: (page - 1) * pageSize,\n orderBy: { [sortField]: sortDir },\n })\n\n // Enrich rows with `quoteNumber` (e.g. \"QUOTE-20260512-00005\") so the\n // list shows human-meaningful identifiers instead of truncated UUIDs.\n // Batched lookup keeps the cost flat regardless of page size.\n const salesQuoteIds = [...new Set(items.map((i) => i.quoteId).filter(Boolean))]\n const salesQuotes = salesQuoteIds.length > 0\n ? await ctx.em.find(SalesQuote, {\n id: { $in: salesQuoteIds },\n organizationId: ctx.organizationId,\n tenantId: ctx.tenantId,\n })\n : []\n const quoteNumberById = new Map<string, string | null>(\n salesQuotes.map((q) => [q.id, q.quoteNumber ?? null]),\n )\n\n return NextResponse.json({\n items: items.map((item) => ({\n ...item,\n quoteNumber: quoteNumberById.get(item.quoteId) ?? null,\n })),\n total,\n page,\n pageSize,\n totalPages: Math.ceil(total / pageSize),\n })\n } catch (err) {\n return handleError(err, 'cpq/quotes.GET')\n }\n}\n\nfunction handleError(err: unknown, context: string) {\n if (err instanceof z.ZodError) {\n return NextResponse.json({ error: 'Validation error', details: err.issues }, { status: 400 })\n }\n if (err instanceof QuotingError) {\n const body: Record<string, unknown> = { error: err.message }\n if (err.cpqStatus) body.cpqStatus = err.cpqStatus\n return NextResponse.json(body, { status: err.status })\n }\n console.error(`[${context}]`, err)\n return NextResponse.json({ error: 'Internal error' }, { status: 500 })\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,86 @@
1
+ import { NextResponse } from "next/server";
2
+ import { z } from "zod";
3
+ import { resolveCpqRouteContext } from "../../context.js";
4
+ import { cpqValidateRelationshipsSchema } from "../../../data/validators.js";
5
+ import {
6
+ CpqProductOffering,
7
+ CpqProductSpecification,
8
+ CpqProductRelationship
9
+ } from "../../../data/entities.js";
10
+ const metadata = {
11
+ POST: { requireAuth: true, requireFeatures: ["cpq.quotes.view"] }
12
+ };
13
+ async function POST(req) {
14
+ try {
15
+ const ctx = await resolveCpqRouteContext(req);
16
+ if (!ctx.auth) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
17
+ const body = cpqValidateRelationshipsSchema.parse(await req.json());
18
+ const scope = { organizationId: ctx.organizationId, tenantId: ctx.tenantId };
19
+ const dbScope = { ...scope, deletedAt: null };
20
+ const offerings = await ctx.em.find(CpqProductOffering, {
21
+ id: { $in: body.offeringIds },
22
+ ...dbScope
23
+ });
24
+ const specIds = [...new Set(offerings.map((o) => o.specId))];
25
+ const lines = offerings.map((o, i) => ({
26
+ lineId: `mock-${i}`,
27
+ specId: o.specId,
28
+ parentLineId: null
29
+ }));
30
+ if (body.parentChildPairs) {
31
+ for (const pair of body.parentChildPairs) {
32
+ const parentOffering = offerings.find((o) => o.id === pair.parentOfferingId);
33
+ const childLine = lines.find((l) => {
34
+ const off = offerings.find((o) => o.specId === l.specId && o.id === pair.childOfferingId);
35
+ return !!off;
36
+ });
37
+ const parentLine = lines.find((l) => {
38
+ const off = offerings.find((o) => o.specId === l.specId && o.id === pair.parentOfferingId);
39
+ return !!off;
40
+ });
41
+ if (childLine && parentLine) {
42
+ childLine.parentLineId = parentLine.lineId;
43
+ }
44
+ }
45
+ }
46
+ const validationService = ctx.container.resolve("cpqValidationService");
47
+ const errors = await validationService.validateRelationships({ lines, scope });
48
+ const parentChildRels = await ctx.em.find(CpqProductRelationship, {
49
+ sourceSpecId: { $in: specIds },
50
+ relationshipType: "parent_child",
51
+ isActive: true,
52
+ ...dbScope
53
+ });
54
+ const childSpecIds = [...new Set(parentChildRels.map((r) => r.targetSpecId))];
55
+ const childSpecs = childSpecIds.length > 0 ? await ctx.em.find(CpqProductSpecification, { id: { $in: childSpecIds }, ...dbScope }) : [];
56
+ const allowedChildSpecs = parentChildRels.map((rel) => {
57
+ const spec = childSpecs.find((s) => s.id === rel.targetSpecId);
58
+ const currentCount = lines.filter((l) => l.specId === rel.targetSpecId).length;
59
+ return {
60
+ specId: rel.targetSpecId,
61
+ code: spec?.code ?? "",
62
+ name: spec?.name ?? "",
63
+ productId: spec?.productId ?? "",
64
+ cardinalityMin: rel.cardinalityMin,
65
+ cardinalityMax: rel.cardinalityMax ?? null,
66
+ currentCount
67
+ };
68
+ });
69
+ return NextResponse.json({
70
+ valid: errors.length === 0,
71
+ errors,
72
+ allowedChildSpecs
73
+ });
74
+ } catch (err) {
75
+ if (err instanceof z.ZodError) {
76
+ return NextResponse.json({ error: "Validation error", details: err.issues }, { status: 400 });
77
+ }
78
+ console.error("[cpq/quotes/validate-relationships.POST]", err);
79
+ return NextResponse.json({ error: "Internal error" }, { status: 500 });
80
+ }
81
+ }
82
+ export {
83
+ POST,
84
+ metadata
85
+ };
86
+ //# sourceMappingURL=route.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/cpq/api/quotes/validate-relationships/route.ts"],
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport { resolveCpqRouteContext } from '../../context'\nimport { cpqValidateRelationshipsSchema } from '../../../data/validators'\nimport { DefaultCpqValidationService } from '../../../services/cpqValidationService'\nimport {\n CpqProductOffering,\n CpqProductSpecification,\n CpqProductRelationship,\n} from '../../../data/entities'\n\nexport const metadata = {\n POST: { requireAuth: true, requireFeatures: ['cpq.quotes.view'] },\n}\n\nexport async function POST(req: Request) {\n try {\n const ctx = await resolveCpqRouteContext(req)\n if (!ctx.auth) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n\n const body = cpqValidateRelationshipsSchema.parse(await req.json())\n const scope = { organizationId: ctx.organizationId, tenantId: ctx.tenantId }\n const dbScope = { ...scope, deletedAt: null }\n\n // Resolve offerings -> specs\n const offerings = await ctx.em.find(CpqProductOffering, {\n id: { $in: body.offeringIds },\n ...dbScope,\n })\n\n const specIds = [...new Set(offerings.map((o) => o.specId))]\n\n // Build mock lines for relationship validation\n const lines = offerings.map((o, i) => ({\n lineId: `mock-${i}`,\n specId: o.specId,\n parentLineId: null as string | null,\n }))\n\n // Apply parent-child pairs\n if (body.parentChildPairs) {\n for (const pair of body.parentChildPairs) {\n const parentOffering = offerings.find((o) => o.id === pair.parentOfferingId)\n const childLine = lines.find((l) => {\n const off = offerings.find((o) => o.specId === l.specId && o.id === pair.childOfferingId)\n return !!off\n })\n const parentLine = lines.find((l) => {\n const off = offerings.find((o) => o.specId === l.specId && o.id === pair.parentOfferingId)\n return !!off\n })\n if (childLine && parentLine) {\n childLine.parentLineId = parentLine.lineId\n }\n }\n }\n\n const validationService = ctx.container.resolve('cpqValidationService') as DefaultCpqValidationService\n const errors = await validationService.validateRelationships({ lines, scope })\n\n // Load allowed child specs\n const parentChildRels = await ctx.em.find(CpqProductRelationship, {\n sourceSpecId: { $in: specIds },\n relationshipType: 'parent_child',\n isActive: true,\n ...dbScope,\n })\n\n const childSpecIds = [...new Set(parentChildRels.map((r) => r.targetSpecId))]\n const childSpecs = childSpecIds.length > 0\n ? await ctx.em.find(CpqProductSpecification, { id: { $in: childSpecIds }, ...dbScope })\n : []\n\n const allowedChildSpecs = parentChildRels.map((rel) => {\n const spec = childSpecs.find((s) => s.id === rel.targetSpecId)\n const currentCount = lines.filter((l) => l.specId === rel.targetSpecId).length\n return {\n specId: rel.targetSpecId,\n code: spec?.code ?? '',\n name: spec?.name ?? '',\n productId: spec?.productId ?? '',\n cardinalityMin: rel.cardinalityMin,\n cardinalityMax: rel.cardinalityMax ?? null,\n currentCount,\n }\n })\n\n return NextResponse.json({\n valid: errors.length === 0,\n errors,\n allowedChildSpecs,\n })\n } catch (err) {\n if (err instanceof z.ZodError) {\n return NextResponse.json({ error: 'Validation error', details: err.issues }, { status: 400 })\n }\n console.error('[cpq/quotes/validate-relationships.POST]', err)\n return NextResponse.json({ error: 'Internal error' }, { status: 500 })\n }\n}\n"],
5
+ "mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS;AAClB,SAAS,8BAA8B;AACvC,SAAS,sCAAsC;AAE/C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEA,MAAM,WAAW;AAAA,EACtB,MAAM,EAAE,aAAa,MAAM,iBAAiB,CAAC,iBAAiB,EAAE;AAClE;AAEA,eAAsB,KAAK,KAAc;AACvC,MAAI;AACF,UAAM,MAAM,MAAM,uBAAuB,GAAG;AAC5C,QAAI,CAAC,IAAI,KAAM,QAAO,aAAa,KAAK,EAAE,OAAO,eAAe,GAAG,EAAE,QAAQ,IAAI,CAAC;AAElF,UAAM,OAAO,+BAA+B,MAAM,MAAM,IAAI,KAAK,CAAC;AAClE,UAAM,QAAQ,EAAE,gBAAgB,IAAI,gBAAgB,UAAU,IAAI,SAAS;AAC3E,UAAM,UAAU,EAAE,GAAG,OAAO,WAAW,KAAK;AAG5C,UAAM,YAAY,MAAM,IAAI,GAAG,KAAK,oBAAoB;AAAA,MACtD,IAAI,EAAE,KAAK,KAAK,YAAY;AAAA,MAC5B,GAAG;AAAA,IACL,CAAC;AAED,UAAM,UAAU,CAAC,GAAG,IAAI,IAAI,UAAU,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAG3D,UAAM,QAAQ,UAAU,IAAI,CAAC,GAAG,OAAO;AAAA,MACrC,QAAQ,QAAQ,CAAC;AAAA,MACjB,QAAQ,EAAE;AAAA,MACV,cAAc;AAAA,IAChB,EAAE;AAGF,QAAI,KAAK,kBAAkB;AACzB,iBAAW,QAAQ,KAAK,kBAAkB;AACxC,cAAM,iBAAiB,UAAU,KAAK,CAAC,MAAM,EAAE,OAAO,KAAK,gBAAgB;AAC3E,cAAM,YAAY,MAAM,KAAK,CAAC,MAAM;AAClC,gBAAM,MAAM,UAAU,KAAK,CAAC,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,OAAO,KAAK,eAAe;AACxF,iBAAO,CAAC,CAAC;AAAA,QACX,CAAC;AACD,cAAM,aAAa,MAAM,KAAK,CAAC,MAAM;AACnC,gBAAM,MAAM,UAAU,KAAK,CAAC,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,OAAO,KAAK,gBAAgB;AACzF,iBAAO,CAAC,CAAC;AAAA,QACX,CAAC;AACD,YAAI,aAAa,YAAY;AAC3B,oBAAU,eAAe,WAAW;AAAA,QACtC;AAAA,MACF;AAAA,IACF;AAEA,UAAM,oBAAoB,IAAI,UAAU,QAAQ,sBAAsB;AACtE,UAAM,SAAS,MAAM,kBAAkB,sBAAsB,EAAE,OAAO,MAAM,CAAC;AAG7E,UAAM,kBAAkB,MAAM,IAAI,GAAG,KAAK,wBAAwB;AAAA,MAChE,cAAc,EAAE,KAAK,QAAQ;AAAA,MAC7B,kBAAkB;AAAA,MAClB,UAAU;AAAA,MACV,GAAG;AAAA,IACL,CAAC;AAED,UAAM,eAAe,CAAC,GAAG,IAAI,IAAI,gBAAgB,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;AAC5E,UAAM,aAAa,aAAa,SAAS,IACrC,MAAM,IAAI,GAAG,KAAK,yBAAyB,EAAE,IAAI,EAAE,KAAK,aAAa,GAAG,GAAG,QAAQ,CAAC,IACpF,CAAC;AAEL,UAAM,oBAAoB,gBAAgB,IAAI,CAAC,QAAQ;AACrD,YAAM,OAAO,WAAW,KAAK,CAAC,MAAM,EAAE,OAAO,IAAI,YAAY;AAC7D,YAAM,eAAe,MAAM,OAAO,CAAC,MAAM,EAAE,WAAW,IAAI,YAAY,EAAE;AACxE,aAAO;AAAA,QACL,QAAQ,IAAI;AAAA,QACZ,MAAM,MAAM,QAAQ;AAAA,QACpB,MAAM,MAAM,QAAQ;AAAA,QACpB,WAAW,MAAM,aAAa;AAAA,QAC9B,gBAAgB,IAAI;AAAA,QACpB,gBAAgB,IAAI,kBAAkB;AAAA,QACtC;AAAA,MACF;AAAA,IACF,CAAC;AAED,WAAO,aAAa,KAAK;AAAA,MACvB,OAAO,OAAO,WAAW;AAAA,MACzB;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,QAAI,eAAe,EAAE,UAAU;AAC7B,aAAO,aAAa,KAAK,EAAE,OAAO,oBAAoB,SAAS,IAAI,OAAO,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC9F;AACA,YAAQ,MAAM,4CAA4C,GAAG;AAC7D,WAAO,aAAa,KAAK,EAAE,OAAO,iBAAiB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACvE;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,7 @@
1
+ function resolveQuotingService(ctx) {
2
+ return ctx.container.resolve("cpqQuotingService");
3
+ }
4
+ export {
5
+ resolveQuotingService
6
+ };
7
+ //# sourceMappingURL=resolveQuotingService.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/cpq/api/resolveQuotingService.ts"],
4
+ "sourcesContent": ["import type { CpqRouteContext } from './context'\nimport type { DefaultCpqQuotingService } from '../services/cpqQuotingService'\n\n/**\n * Resolve CpqQuotingService from the DI container.\n * All sub-services (pricing, validation, product) are registered as scoped in di.ts,\n * ensuring they share the same request-scoped EntityManager.\n */\nexport function resolveQuotingService(ctx: CpqRouteContext): DefaultCpqQuotingService {\n return ctx.container.resolve('cpqQuotingService') as DefaultCpqQuotingService\n}\n"],
5
+ "mappings": "AAQO,SAAS,sBAAsB,KAAgD;AACpF,SAAO,IAAI,UAAU,QAAQ,mBAAmB;AAClD;",
6
+ "names": []
7
+ }
@@ -0,0 +1,38 @@
1
+ import { NextResponse } from "next/server";
2
+ import { resolveCpqRouteContext } from "../../context.js";
3
+ import { DefaultCpqWizardService } from "../../../services/cpqWizardService.js";
4
+ const metadata = {
5
+ GET: { requireAuth: true, requireFeatures: ["cpq.wizards.view"] }
6
+ };
7
+ async function GET(req) {
8
+ try {
9
+ const ctx = await resolveCpqRouteContext(req);
10
+ if (!ctx.auth) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
11
+ const url = new URL(req.url);
12
+ const surface = url.searchParams.get("surface");
13
+ if (!surface || !["backend", "portal"].includes(surface)) {
14
+ return NextResponse.json({ error: "Missing or invalid surface parameter" }, { status: 400 });
15
+ }
16
+ const scope = { organizationId: ctx.organizationId, tenantId: ctx.tenantId };
17
+ const service = new DefaultCpqWizardService(ctx.em);
18
+ const result = await service.resolveWizard(
19
+ {
20
+ surface,
21
+ specCode: url.searchParams.get("specCode") ?? void 0,
22
+ offeringCode: url.searchParams.get("offeringCode") ?? void 0,
23
+ customerSegment: url.searchParams.get("customerSegment") ?? void 0
24
+ },
25
+ scope
26
+ );
27
+ if (!result) return NextResponse.json({ error: "Not found" }, { status: 404 });
28
+ return NextResponse.json(result);
29
+ } catch (err) {
30
+ console.error("[cpq/wizards/resolve.GET]", err);
31
+ return NextResponse.json({ error: "Internal error" }, { status: 500 });
32
+ }
33
+ }
34
+ export {
35
+ GET,
36
+ metadata
37
+ };
38
+ //# sourceMappingURL=route.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/cpq/api/wizards/resolve/route.ts"],
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { resolveCpqRouteContext } from '../../context'\nimport { DefaultCpqWizardService } from '../../../services/cpqWizardService'\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['cpq.wizards.view'] },\n}\n\nexport async function GET(req: Request) {\n try {\n const ctx = await resolveCpqRouteContext(req)\n if (!ctx.auth) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n\n const url = new URL(req.url)\n const surface = url.searchParams.get('surface')\n if (!surface || !['backend', 'portal'].includes(surface)) {\n return NextResponse.json({ error: 'Missing or invalid surface parameter' }, { status: 400 })\n }\n\n const scope = { organizationId: ctx.organizationId, tenantId: ctx.tenantId }\n const service = new DefaultCpqWizardService(ctx.em)\n\n const result = await service.resolveWizard(\n {\n surface: surface as 'backend' | 'portal',\n specCode: url.searchParams.get('specCode') ?? undefined,\n offeringCode: url.searchParams.get('offeringCode') ?? undefined,\n customerSegment: url.searchParams.get('customerSegment') ?? undefined,\n },\n scope,\n )\n\n if (!result) return NextResponse.json({ error: 'Not found' }, { status: 404 })\n return NextResponse.json(result)\n } catch (err) {\n console.error('[cpq/wizards/resolve.GET]', err)\n return NextResponse.json({ error: 'Internal error' }, { status: 500 })\n }\n}\n"],
5
+ "mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,8BAA8B;AACvC,SAAS,+BAA+B;AAEjC,MAAM,WAAW;AAAA,EACtB,KAAK,EAAE,aAAa,MAAM,iBAAiB,CAAC,kBAAkB,EAAE;AAClE;AAEA,eAAsB,IAAI,KAAc;AACtC,MAAI;AACF,UAAM,MAAM,MAAM,uBAAuB,GAAG;AAC5C,QAAI,CAAC,IAAI,KAAM,QAAO,aAAa,KAAK,EAAE,OAAO,eAAe,GAAG,EAAE,QAAQ,IAAI,CAAC;AAElF,UAAM,MAAM,IAAI,IAAI,IAAI,GAAG;AAC3B,UAAM,UAAU,IAAI,aAAa,IAAI,SAAS;AAC9C,QAAI,CAAC,WAAW,CAAC,CAAC,WAAW,QAAQ,EAAE,SAAS,OAAO,GAAG;AACxD,aAAO,aAAa,KAAK,EAAE,OAAO,uCAAuC,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC7F;AAEA,UAAM,QAAQ,EAAE,gBAAgB,IAAI,gBAAgB,UAAU,IAAI,SAAS;AAC3E,UAAM,UAAU,IAAI,wBAAwB,IAAI,EAAE;AAElD,UAAM,SAAS,MAAM,QAAQ;AAAA,MAC3B;AAAA,QACE;AAAA,QACA,UAAU,IAAI,aAAa,IAAI,UAAU,KAAK;AAAA,QAC9C,cAAc,IAAI,aAAa,IAAI,cAAc,KAAK;AAAA,QACtD,iBAAiB,IAAI,aAAa,IAAI,iBAAiB,KAAK;AAAA,MAC9D;AAAA,MACA;AAAA,IACF;AAEA,QAAI,CAAC,OAAQ,QAAO,aAAa,KAAK,EAAE,OAAO,YAAY,GAAG,EAAE,QAAQ,IAAI,CAAC;AAC7E,WAAO,aAAa,KAAK,MAAM;AAAA,EACjC,SAAS,KAAK;AACZ,YAAQ,MAAM,6BAA6B,GAAG;AAC9C,WAAO,aAAa,KAAK,EAAE,OAAO,iBAAiB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACvE;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,111 @@
1
+ import { NextResponse } from "next/server";
2
+ import { z } from "zod";
3
+ import { resolveCpqRouteContext } from "../context.js";
4
+ import { cpqWizardDefinitionCreateSchema, cpqWizardDefinitionUpdateSchema } from "../../data/validators.js";
5
+ import { DefaultCpqWizardService } from "../../services/cpqWizardService.js";
6
+ const metadata = {
7
+ GET: { requireAuth: true, requireFeatures: ["cpq.wizards.view"] },
8
+ POST: { requireAuth: true, requireFeatures: ["cpq.wizards.manage"] },
9
+ PUT: { requireAuth: true, requireFeatures: ["cpq.wizards.manage"] },
10
+ DELETE: { requireAuth: true, requireFeatures: ["cpq.wizards.manage"] }
11
+ };
12
+ function resolveWizardService(ctx) {
13
+ return new DefaultCpqWizardService(ctx.em);
14
+ }
15
+ async function GET(req) {
16
+ try {
17
+ const ctx = await resolveCpqRouteContext(req);
18
+ if (!ctx.auth) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
19
+ const url = new URL(req.url);
20
+ const scope = { organizationId: ctx.organizationId, tenantId: ctx.tenantId };
21
+ const service = resolveWizardService(ctx);
22
+ const id = url.searchParams.get("id");
23
+ const code = url.searchParams.get("code");
24
+ if (id || code) {
25
+ const result = await service.getDefinition(id ?? code, scope);
26
+ if (!result) return NextResponse.json({ error: "Not found" }, { status: 404 });
27
+ return NextResponse.json(result);
28
+ }
29
+ const page = Math.max(1, Number(url.searchParams.get("page") ?? "1"));
30
+ const pageSize = Math.min(100, Math.max(1, Number(url.searchParams.get("pageSize") ?? "50")));
31
+ const surface = url.searchParams.get("surface") ?? void 0;
32
+ const isActiveParam = url.searchParams.get("isActive");
33
+ const isActive = isActiveParam !== null ? isActiveParam === "true" : void 0;
34
+ const search = url.searchParams.get("search") ?? void 0;
35
+ const ALLOWED_SORT_FIELDS = ["createdAt", "updatedAt", "name", "code", "surface"];
36
+ const sortFieldParam = url.searchParams.get("sortField") ?? "";
37
+ const sortField = ALLOWED_SORT_FIELDS.includes(sortFieldParam) ? sortFieldParam : void 0;
38
+ const sortDir = url.searchParams.get("sortDir") === "asc" ? "asc" : "desc";
39
+ return NextResponse.json(
40
+ await service.listDefinitions(
41
+ { surface, isActive, search, sortField, sortDir },
42
+ scope,
43
+ page,
44
+ pageSize
45
+ )
46
+ );
47
+ } catch (err) {
48
+ console.error("[cpq/wizards.GET]", err);
49
+ return NextResponse.json({ error: "Internal error" }, { status: 500 });
50
+ }
51
+ }
52
+ async function POST(req) {
53
+ try {
54
+ const ctx = await resolveCpqRouteContext(req);
55
+ if (!ctx.auth) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
56
+ const body = cpqWizardDefinitionCreateSchema.parse(await req.json());
57
+ const scope = { organizationId: ctx.organizationId, tenantId: ctx.tenantId };
58
+ const service = resolveWizardService(ctx);
59
+ const result = await service.createDefinition(body, scope);
60
+ return NextResponse.json(result, { status: 201 });
61
+ } catch (err) {
62
+ if (err instanceof z.ZodError) {
63
+ return NextResponse.json({ error: "Validation error", details: err.issues }, { status: 400 });
64
+ }
65
+ console.error("[cpq/wizards.POST]", err);
66
+ return NextResponse.json({ error: "Internal error" }, { status: 500 });
67
+ }
68
+ }
69
+ async function PUT(req) {
70
+ try {
71
+ const ctx = await resolveCpqRouteContext(req);
72
+ if (!ctx.auth) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
73
+ const body = cpqWizardDefinitionUpdateSchema.parse(await req.json());
74
+ const { id, ...updates } = body;
75
+ const scope = { organizationId: ctx.organizationId, tenantId: ctx.tenantId };
76
+ const service = resolveWizardService(ctx);
77
+ const result = await service.updateDefinition(id, updates, scope);
78
+ if (!result) return NextResponse.json({ error: "Not found" }, { status: 404 });
79
+ return NextResponse.json(result);
80
+ } catch (err) {
81
+ if (err instanceof z.ZodError) {
82
+ return NextResponse.json({ error: "Validation error", details: err.issues }, { status: 400 });
83
+ }
84
+ console.error("[cpq/wizards.PUT]", err);
85
+ return NextResponse.json({ error: "Internal error" }, { status: 500 });
86
+ }
87
+ }
88
+ async function DELETE(req) {
89
+ try {
90
+ const ctx = await resolveCpqRouteContext(req);
91
+ if (!ctx.auth) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
92
+ const { id } = await req.json();
93
+ if (!id) return NextResponse.json({ error: "Missing id" }, { status: 400 });
94
+ const scope = { organizationId: ctx.organizationId, tenantId: ctx.tenantId };
95
+ const service = resolveWizardService(ctx);
96
+ const deleted = await service.deleteDefinition(id, scope);
97
+ if (!deleted) return NextResponse.json({ error: "Not found" }, { status: 404 });
98
+ return NextResponse.json({ success: true });
99
+ } catch (err) {
100
+ console.error("[cpq/wizards.DELETE]", err);
101
+ return NextResponse.json({ error: "Internal error" }, { status: 500 });
102
+ }
103
+ }
104
+ export {
105
+ DELETE,
106
+ GET,
107
+ POST,
108
+ PUT,
109
+ metadata
110
+ };
111
+ //# sourceMappingURL=route.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/cpq/api/wizards/route.ts"],
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport { resolveCpqRouteContext } from '../context'\nimport { cpqWizardDefinitionCreateSchema, cpqWizardDefinitionUpdateSchema } from '../../data/validators'\nimport { DefaultCpqWizardService } from '../../services/cpqWizardService'\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['cpq.wizards.view'] },\n POST: { requireAuth: true, requireFeatures: ['cpq.wizards.manage'] },\n PUT: { requireAuth: true, requireFeatures: ['cpq.wizards.manage'] },\n DELETE: { requireAuth: true, requireFeatures: ['cpq.wizards.manage'] },\n}\n\nfunction resolveWizardService(ctx: { em: import('@mikro-orm/postgresql').EntityManager }) {\n return new DefaultCpqWizardService(ctx.em)\n}\n\nexport async function GET(req: Request) {\n try {\n const ctx = await resolveCpqRouteContext(req)\n if (!ctx.auth) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n\n const url = new URL(req.url)\n const scope = { organizationId: ctx.organizationId, tenantId: ctx.tenantId }\n const service = resolveWizardService(ctx)\n\n // Detail view\n const id = url.searchParams.get('id')\n const code = url.searchParams.get('code')\n if (id || code) {\n const result = await service.getDefinition((id ?? code)!, scope)\n if (!result) return NextResponse.json({ error: 'Not found' }, { status: 404 })\n return NextResponse.json(result)\n }\n\n // List view\n const page = Math.max(1, Number(url.searchParams.get('page') ?? '1'))\n const pageSize = Math.min(100, Math.max(1, Number(url.searchParams.get('pageSize') ?? '50')))\n const surface = url.searchParams.get('surface') ?? undefined\n const isActiveParam = url.searchParams.get('isActive')\n const isActive = isActiveParam !== null ? isActiveParam === 'true' : undefined\n const search = url.searchParams.get('search') ?? undefined\n\n const ALLOWED_SORT_FIELDS = ['createdAt', 'updatedAt', 'name', 'code', 'surface'] as const\n const sortFieldParam = url.searchParams.get('sortField') ?? ''\n const sortField = (ALLOWED_SORT_FIELDS as readonly string[]).includes(sortFieldParam)\n ? (sortFieldParam as (typeof ALLOWED_SORT_FIELDS)[number])\n : undefined\n const sortDir = url.searchParams.get('sortDir') === 'asc' ? 'asc' : 'desc'\n\n return NextResponse.json(\n await service.listDefinitions(\n { surface, isActive, search, sortField, sortDir },\n scope,\n page,\n pageSize,\n ),\n )\n } catch (err) {\n console.error('[cpq/wizards.GET]', err)\n return NextResponse.json({ error: 'Internal error' }, { status: 500 })\n }\n}\n\nexport async function POST(req: Request) {\n try {\n const ctx = await resolveCpqRouteContext(req)\n if (!ctx.auth) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n\n const body = cpqWizardDefinitionCreateSchema.parse(await req.json())\n const scope = { organizationId: ctx.organizationId, tenantId: ctx.tenantId }\n const service = resolveWizardService(ctx)\n\n const result = await service.createDefinition(body, scope)\n return NextResponse.json(result, { status: 201 })\n } catch (err) {\n if (err instanceof z.ZodError) {\n return NextResponse.json({ error: 'Validation error', details: err.issues }, { status: 400 })\n }\n console.error('[cpq/wizards.POST]', err)\n return NextResponse.json({ error: 'Internal error' }, { status: 500 })\n }\n}\n\nexport async function PUT(req: Request) {\n try {\n const ctx = await resolveCpqRouteContext(req)\n if (!ctx.auth) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n\n const body = cpqWizardDefinitionUpdateSchema.parse(await req.json())\n const { id, ...updates } = body\n const scope = { organizationId: ctx.organizationId, tenantId: ctx.tenantId }\n const service = resolveWizardService(ctx)\n\n const result = await service.updateDefinition(id, updates, scope)\n if (!result) return NextResponse.json({ error: 'Not found' }, { status: 404 })\n\n return NextResponse.json(result)\n } catch (err) {\n if (err instanceof z.ZodError) {\n return NextResponse.json({ error: 'Validation error', details: err.issues }, { status: 400 })\n }\n console.error('[cpq/wizards.PUT]', err)\n return NextResponse.json({ error: 'Internal error' }, { status: 500 })\n }\n}\n\nexport async function DELETE(req: Request) {\n try {\n const ctx = await resolveCpqRouteContext(req)\n if (!ctx.auth) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n\n const { id } = (await req.json()) as { id?: string }\n if (!id) return NextResponse.json({ error: 'Missing id' }, { status: 400 })\n\n const scope = { organizationId: ctx.organizationId, tenantId: ctx.tenantId }\n const service = resolveWizardService(ctx)\n\n const deleted = await service.deleteDefinition(id, scope)\n if (!deleted) return NextResponse.json({ error: 'Not found' }, { status: 404 })\n\n return NextResponse.json({ success: true })\n } catch (err) {\n console.error('[cpq/wizards.DELETE]', err)\n return NextResponse.json({ error: 'Internal error' }, { status: 500 })\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }