@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,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/cpq/widgets/injection/quote-configurator/widget.client.tsx"],
4
+ "sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport type { InjectionWidgetComponentProps } from '@open-mercato/shared/modules/widgets/injection'\nimport { useRouter } from 'next/navigation'\nimport { Tag } from '@open-mercato/ui/primitives/tag'\nimport {\n formatStatusLabel,\n quoteCpqStatusMap,\n type QuoteCpqStatus,\n} from '../../../components/statusMaps'\n\n// \u2500\u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ntype ResolvedCharge = {\n chargeCode: string\n chargeName: string\n chargeType: 'nrc' | 'mrc' | 'usage'\n unitPrice: number\n quantity: number | null\n totalPrice: number | null\n currencyCode: string\n note?: string | null\n}\n\ntype QuoteLine = {\n lineId: string\n offeringId: string | null\n offeringName: string\n quantity: number\n nrcTotal: number\n mrcTotal: number\n charges: ResolvedCharge[]\n isConfigured: boolean\n validationErrors: Array<{ message: string }> | null\n}\n\ntype QuoteResult = {\n id: string\n quoteId: string\n quoteNumber: string\n customerId: string\n cpqStatus: string\n version: number\n currencyCode: string\n pricingSummary: {\n nrcTotal: number\n mrcTotal: number\n usageCharges: Array<{ chargeCode: string; chargeName: string; unitPrice: number; note: string | null }>\n usageTotalEstimated: number | null\n currencyCode: string\n }\n lines: QuoteLine[]\n}\n\n// \u2500\u2500\u2500 Helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction fmt(amount: number, currency: string): string {\n return new Intl.NumberFormat('en-US', { style: 'currency', currency }).format(amount)\n}\n\n// \u2500\u2500\u2500 Main Widget (read-only) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport default function QuoteConfiguratorWidget({ data }: InjectionWidgetComponentProps) {\n const router = useRouter()\n const record = data as Record<string, unknown> | null\n const quoteId = (record?.id as string) ?? null\n\n const [cpqQuote, setCpqQuote] = React.useState<QuoteResult | null>(null)\n const [loading, setLoading] = React.useState(true)\n const [expandedLines, setExpandedLines] = React.useState<Set<string>>(new Set())\n\n React.useEffect(() => {\n if (!quoteId) { setLoading(false); return }\n let cancelled = false\n async function load() {\n try {\n const res = await fetch(`/api/cpq/quotes/${quoteId}`)\n if (res.ok && !cancelled) setCpqQuote(await res.json())\n } catch { /* no CPQ config */ }\n finally { if (!cancelled) setLoading(false) }\n }\n load()\n return () => { cancelled = true }\n }, [quoteId])\n\n if (!quoteId) return <div className=\"p-4 text-sm text-muted-foreground\">No quote context available.</div>\n\n if (loading) {\n return (\n <div className=\"flex items-center gap-2 p-6 text-sm text-muted-foreground\">\n <Spinner /> Loading CPQ configuration\u2026\n </div>\n )\n }\n\n // \u2500\u2500\u2500 No CPQ config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n if (!cpqQuote) {\n const custId = (record?.customerEntityId as string) ?? (record?.customer_entity_id as string) ?? ''\n return (\n <div className=\"flex flex-col items-center justify-center py-12 px-4\">\n <div className=\"rounded-full bg-primary/10 p-3 mb-3\">\n <svg className=\"h-6 w-6 text-primary\" fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth=\"1.5\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.325.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 011.37.49l1.296 2.247a1.125 1.125 0 01-.26 1.431l-1.003.827c-.293.241-.438.613-.43.992a7.723 7.723 0 010 .255c-.008.378.137.75.43.991l1.004.827c.424.35.534.955.26 1.43l-1.298 2.247a1.125 1.125 0 01-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.47 6.47 0 01-.22.128c-.331.183-.581.495-.644.869l-.213 1.281c-.09.543-.56.94-1.11.94h-2.594c-.55 0-1.019-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 01-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 01-1.369-.49l-1.297-2.247a1.125 1.125 0 01.26-1.431l1.004-.827c.292-.24.437-.613.43-.991a6.932 6.932 0 010-.255c.007-.38-.138-.751-.43-.992l-1.004-.827a1.125 1.125 0 01-.26-1.43l1.297-2.247a1.125 1.125 0 011.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.086.22-.128.332-.183.582-.495.644-.869l.214-1.28z\" />\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M15 12a3 3 0 11-6 0 3 3 0 016 0z\" />\n </svg>\n </div>\n <p className=\"text-sm text-muted-foreground mb-4\">This quote has no CPQ configuration yet.</p>\n <button\n onClick={() => router.push(`/backend/cpq/quotes/new?quoteId=${quoteId}&customerId=${custId}`)}\n className=\"inline-flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground shadow-sm hover:bg-primary/90 transition-colors\"\n >\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth=\"2\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M12 4.5v15m7.5-7.5h-15\" />\n </svg>\n Create CPQ Quote\n </button>\n {!custId && <p className=\"mt-2 text-xs text-status-warning-text\">Assign a customer to this quote first.</p>}\n </div>\n )\n }\n\n // \u2500\u2500\u2500 Read-only summary \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n const { pricingSummary: summary, currencyCode: currency } = cpqQuote\n const toggleLine = (id: string) => {\n setExpandedLines((prev) => {\n const next = new Set(prev)\n next.has(id) ? next.delete(id) : next.add(id)\n return next\n })\n }\n\n return (\n <div className=\"space-y-4\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-1\">\n <div className=\"flex items-center gap-3\">\n <Tag variant={quoteCpqStatusMap[cpqQuote.cpqStatus as QuoteCpqStatus] ?? 'neutral'} dot>\n {formatStatusLabel(cpqQuote.cpqStatus)}\n </Tag>\n <span className=\"text-xs text-muted-foreground\">v{cpqQuote.version}</span>\n <span className=\"text-xs text-muted-foreground\">{currency}</span>\n </div>\n <button\n onClick={() => router.push(`/backend/cpq/quotes/${cpqQuote.id}`)}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground shadow-sm hover:bg-primary/90 transition-colors\"\n >\n Open CPQ Configurator\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth=\"2\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M13.5 6H5.25A2.25 2.25 0 003 8.25v10.5A2.25 2.25 0 005.25 21h10.5A2.25 2.25 0 0018 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25\" />\n </svg>\n </button>\n </div>\n\n {/* Lines */}\n {cpqQuote.lines.length === 0 ? (\n <div className=\"rounded-lg border bg-card py-8 text-center text-sm text-muted-foreground\">\n No items configured yet.\n </div>\n ) : (\n <div className=\"rounded-lg border bg-card divide-y\">\n {cpqQuote.lines.map((line) => {\n const isExpanded = expandedLines.has(line.lineId)\n return (\n <div key={line.lineId}>\n <div\n className=\"flex items-center gap-3 px-4 py-3 hover:bg-muted/30 transition-colors cursor-pointer\"\n onClick={() => toggleLine(line.lineId)}\n >\n <button className=\"flex h-5 w-5 shrink-0 items-center justify-center rounded text-muted-foreground\">\n <svg className={`h-4 w-4 transition-transform ${isExpanded ? 'rotate-90' : ''}`} fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth=\"2\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M8.25 4.5l7.5 7.5-7.5 7.5\" />\n </svg>\n </button>\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium text-sm\">{line.offeringName}</span>\n {line.quantity > 1 && <span className=\"rounded bg-muted px-1.5 py-0.5 text-xs font-medium\">\u00D7{line.quantity}</span>}\n {line.isConfigured ? (\n <Tag variant=\"success\" className=\"px-1.5 text-xs\">configured</Tag>\n ) : (\n <Tag variant=\"warning\" className=\"px-1.5 text-xs\">incomplete</Tag>\n )}\n </div>\n {line.validationErrors && line.validationErrors.length > 0 && (\n <p className=\"text-xs text-destructive mt-0.5\">{line.validationErrors[0].message}</p>\n )}\n </div>\n <div className=\"shrink-0 text-right text-xs space-y-0.5\">\n {line.nrcTotal > 0 && <div><span className=\"text-muted-foreground\">NRC </span><span className=\"font-mono font-medium\">{fmt(line.nrcTotal, currency)}</span></div>}\n {line.mrcTotal > 0 && <div><span className=\"text-muted-foreground\">MRC </span><span className=\"font-mono font-medium\">{fmt(line.mrcTotal, currency)}</span></div>}\n </div>\n </div>\n\n {/* Charge breakdown */}\n {isExpanded && line.charges.length > 0 && (\n <div className=\"border-t bg-muted/10 px-12 py-2\">\n <table className=\"w-full text-xs\">\n <thead>\n <tr className=\"text-muted-foreground\">\n <th className=\"text-left py-1 font-medium\">Charge</th>\n <th className=\"text-left py-1 font-medium\">Type</th>\n <th className=\"text-right py-1 font-medium\">Unit Price</th>\n <th className=\"text-right py-1 font-medium\">Qty</th>\n <th className=\"text-right py-1 font-medium\">Total</th>\n </tr>\n </thead>\n <tbody>\n {line.charges.map((c, i) => (\n <tr key={i} className=\"border-t border-dashed border-border/50\">\n <td className=\"py-1\">{c.chargeName}</td>\n <td className=\"py-1 uppercase\">{c.chargeType}</td>\n <td className=\"py-1 text-right font-mono\">{fmt(c.unitPrice, currency)}</td>\n <td className=\"py-1 text-right font-mono\">{c.quantity ?? '\u2014'}</td>\n <td className=\"py-1 text-right font-mono\">{c.totalPrice != null ? fmt(c.totalPrice, currency) : c.note ?? '\u2014'}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </div>\n )\n })}\n </div>\n )}\n\n {/* Pricing Summary */}\n {cpqQuote.lines.length > 0 && (\n <div className=\"rounded-lg border bg-card p-4\">\n <div className=\"grid grid-cols-2 sm:grid-cols-3 gap-4\">\n <div>\n <p className=\"text-xs text-muted-foreground\">Non-Recurring (NRC)</p>\n <p className=\"text-lg font-semibold font-mono\">{fmt(summary.nrcTotal, currency)}</p>\n </div>\n <div>\n <p className=\"text-xs text-muted-foreground\">Monthly Recurring (MRC)</p>\n <p className=\"text-lg font-semibold font-mono\">{fmt(summary.mrcTotal, currency)}</p>\n </div>\n {summary.usageCharges.length > 0 && (\n <div>\n <p className=\"text-xs text-muted-foreground\">Usage Charges</p>\n <div className=\"mt-1 space-y-0.5\">\n {summary.usageCharges.map((uc, i) => (\n <p key={i} className=\"text-xs\">{uc.chargeName}: {fmt(uc.unitPrice, currency)}/unit</p>\n ))}\n </div>\n </div>\n )}\n </div>\n </div>\n )}\n </div>\n )\n}\n\nfunction Spinner() {\n return (\n <svg className=\"h-4 w-4 animate-spin\" viewBox=\"0 0 24 24\" fill=\"none\">\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path className=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z\" />\n </svg>\n )\n}\n"],
5
+ "mappings": ";AAqFuB,cAIjB,YAJiB;AApFvB,YAAY,WAAW;AAEvB,SAAS,iBAAiB;AAC1B,SAAS,WAAW;AACpB;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AA+CP,SAAS,IAAI,QAAgB,UAA0B;AACrD,SAAO,IAAI,KAAK,aAAa,SAAS,EAAE,OAAO,YAAY,SAAS,CAAC,EAAE,OAAO,MAAM;AACtF;AAIe,SAAR,wBAAyC,EAAE,KAAK,GAAkC;AACvF,QAAM,SAAS,UAAU;AACzB,QAAM,SAAS;AACf,QAAM,UAAW,QAAQ,MAAiB;AAE1C,QAAM,CAAC,UAAU,WAAW,IAAI,MAAM,SAA6B,IAAI;AACvE,QAAM,CAAC,SAAS,UAAU,IAAI,MAAM,SAAS,IAAI;AACjD,QAAM,CAAC,eAAe,gBAAgB,IAAI,MAAM,SAAsB,oBAAI,IAAI,CAAC;AAE/E,QAAM,UAAU,MAAM;AACpB,QAAI,CAAC,SAAS;AAAE,iBAAW,KAAK;AAAG;AAAA,IAAO;AAC1C,QAAI,YAAY;AAChB,mBAAe,OAAO;AACpB,UAAI;AACF,cAAM,MAAM,MAAM,MAAM,mBAAmB,OAAO,EAAE;AACpD,YAAI,IAAI,MAAM,CAAC,UAAW,aAAY,MAAM,IAAI,KAAK,CAAC;AAAA,MACxD,QAAQ;AAAA,MAAsB,UAC9B;AAAU,YAAI,CAAC,UAAW,YAAW,KAAK;AAAA,MAAE;AAAA,IAC9C;AACA,SAAK;AACL,WAAO,MAAM;AAAE,kBAAY;AAAA,IAAK;AAAA,EAClC,GAAG,CAAC,OAAO,CAAC;AAEZ,MAAI,CAAC,QAAS,QAAO,oBAAC,SAAI,WAAU,qCAAoC,yCAA2B;AAEnG,MAAI,SAAS;AACX,WACE,qBAAC,SAAI,WAAU,6DACb;AAAA,0BAAC,WAAQ;AAAA,MAAE;AAAA,OACb;AAAA,EAEJ;AAIA,MAAI,CAAC,UAAU;AACb,UAAM,SAAU,QAAQ,oBAAgC,QAAQ,sBAAiC;AACjG,WACE,qBAAC,SAAI,WAAU,wDACb;AAAA,0BAAC,SAAI,WAAU,uCACb,+BAAC,SAAI,WAAU,wBAAuB,MAAK,QAAO,SAAQ,aAAY,aAAY,OAAM,QAAO,gBAC7F;AAAA,4BAAC,UAAK,eAAc,SAAQ,gBAAe,SAAQ,GAAE,29BAA09B;AAAA,QAC/gC,oBAAC,UAAK,eAAc,SAAQ,gBAAe,SAAQ,GAAE,oCAAmC;AAAA,SAC1F,GACF;AAAA,MACA,oBAAC,OAAE,WAAU,sCAAqC,sDAAwC;AAAA,MAC1F;AAAA,QAAC;AAAA;AAAA,UACC,SAAS,MAAM,OAAO,KAAK,mCAAmC,OAAO,eAAe,MAAM,EAAE;AAAA,UAC5F,WAAU;AAAA,UAEV;AAAA,gCAAC,SAAI,WAAU,WAAU,MAAK,QAAO,SAAQ,aAAY,aAAY,KAAI,QAAO,gBAC9E,8BAAC,UAAK,eAAc,SAAQ,gBAAe,SAAQ,GAAE,0BAAyB,GAChF;AAAA,YAAM;AAAA;AAAA;AAAA,MAER;AAAA,MACC,CAAC,UAAU,oBAAC,OAAE,WAAU,yCAAwC,oDAAsC;AAAA,OACzG;AAAA,EAEJ;AAIA,QAAM,EAAE,gBAAgB,SAAS,cAAc,SAAS,IAAI;AAC5D,QAAM,aAAa,CAAC,OAAe;AACjC,qBAAiB,CAAC,SAAS;AACzB,YAAM,OAAO,IAAI,IAAI,IAAI;AACzB,WAAK,IAAI,EAAE,IAAI,KAAK,OAAO,EAAE,IAAI,KAAK,IAAI,EAAE;AAC5C,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAEA,SACE,qBAAC,SAAI,WAAU,aAEb;AAAA,yBAAC,SAAI,WAAU,0CACb;AAAA,2BAAC,SAAI,WAAU,2BACb;AAAA,4BAAC,OAAI,SAAS,kBAAkB,SAAS,SAA2B,KAAK,WAAW,KAAG,MACpF,4BAAkB,SAAS,SAAS,GACvC;AAAA,QACA,qBAAC,UAAK,WAAU,iCAAgC;AAAA;AAAA,UAAE,SAAS;AAAA,WAAQ;AAAA,QACnE,oBAAC,UAAK,WAAU,iCAAiC,oBAAS;AAAA,SAC5D;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,SAAS,MAAM,OAAO,KAAK,uBAAuB,SAAS,EAAE,EAAE;AAAA,UAC/D,WAAU;AAAA,UACX;AAAA;AAAA,YAEC,oBAAC,SAAI,WAAU,WAAU,MAAK,QAAO,SAAQ,aAAY,aAAY,KAAI,QAAO,gBAC9E,8BAAC,UAAK,eAAc,SAAQ,gBAAe,SAAQ,GAAE,kIAAiI,GACxL;AAAA;AAAA;AAAA,MACF;AAAA,OACF;AAAA,IAGC,SAAS,MAAM,WAAW,IACzB,oBAAC,SAAI,WAAU,4EAA2E,sCAE1F,IAEA,oBAAC,SAAI,WAAU,sCACZ,mBAAS,MAAM,IAAI,CAAC,SAAS;AAC5B,YAAM,aAAa,cAAc,IAAI,KAAK,MAAM;AAChD,aACE,qBAAC,SACC;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,SAAS,MAAM,WAAW,KAAK,MAAM;AAAA,YAErC;AAAA,kCAAC,YAAO,WAAU,mFAChB,8BAAC,SAAI,WAAW,gCAAgC,aAAa,cAAc,EAAE,IAAI,MAAK,QAAO,SAAQ,aAAY,aAAY,KAAI,QAAO,gBACtI,8BAAC,UAAK,eAAc,SAAQ,gBAAe,SAAQ,GAAE,6BAA4B,GACnF,GACF;AAAA,cACA,qBAAC,SAAI,WAAU,kBACb;AAAA,qCAAC,SAAI,WAAU,2BACb;AAAA,sCAAC,UAAK,WAAU,uBAAuB,eAAK,cAAa;AAAA,kBACxD,KAAK,WAAW,KAAK,qBAAC,UAAK,WAAU,sDAAqD;AAAA;AAAA,oBAAE,KAAK;AAAA,qBAAS;AAAA,kBAC1G,KAAK,eACJ,oBAAC,OAAI,SAAQ,WAAU,WAAU,kBAAiB,wBAAU,IAE5D,oBAAC,OAAI,SAAQ,WAAU,WAAU,kBAAiB,wBAAU;AAAA,mBAEhE;AAAA,gBACC,KAAK,oBAAoB,KAAK,iBAAiB,SAAS,KACvD,oBAAC,OAAE,WAAU,mCAAmC,eAAK,iBAAiB,CAAC,EAAE,SAAQ;AAAA,iBAErF;AAAA,cACA,qBAAC,SAAI,WAAU,2CACZ;AAAA,qBAAK,WAAW,KAAK,qBAAC,SAAI;AAAA,sCAAC,UAAK,WAAU,yBAAwB,kBAAI;AAAA,kBAAO,oBAAC,UAAK,WAAU,yBAAyB,cAAI,KAAK,UAAU,QAAQ,GAAE;AAAA,mBAAO;AAAA,gBAC1J,KAAK,WAAW,KAAK,qBAAC,SAAI;AAAA,sCAAC,UAAK,WAAU,yBAAwB,kBAAI;AAAA,kBAAO,oBAAC,UAAK,WAAU,yBAAyB,cAAI,KAAK,UAAU,QAAQ,GAAE;AAAA,mBAAO;AAAA,iBAC7J;AAAA;AAAA;AAAA,QACF;AAAA,QAGC,cAAc,KAAK,QAAQ,SAAS,KACnC,oBAAC,SAAI,WAAU,mCACb,+BAAC,WAAM,WAAU,kBACf;AAAA,8BAAC,WACC,+BAAC,QAAG,WAAU,yBACZ;AAAA,gCAAC,QAAG,WAAU,8BAA6B,oBAAM;AAAA,YACjD,oBAAC,QAAG,WAAU,8BAA6B,kBAAI;AAAA,YAC/C,oBAAC,QAAG,WAAU,+BAA8B,wBAAU;AAAA,YACtD,oBAAC,QAAG,WAAU,+BAA8B,iBAAG;AAAA,YAC/C,oBAAC,QAAG,WAAU,+BAA8B,mBAAK;AAAA,aACnD,GACF;AAAA,UACA,oBAAC,WACE,eAAK,QAAQ,IAAI,CAAC,GAAG,MACpB,qBAAC,QAAW,WAAU,2CACpB;AAAA,gCAAC,QAAG,WAAU,QAAQ,YAAE,YAAW;AAAA,YACnC,oBAAC,QAAG,WAAU,kBAAkB,YAAE,YAAW;AAAA,YAC7C,oBAAC,QAAG,WAAU,6BAA6B,cAAI,EAAE,WAAW,QAAQ,GAAE;AAAA,YACtE,oBAAC,QAAG,WAAU,6BAA6B,YAAE,YAAY,UAAI;AAAA,YAC7D,oBAAC,QAAG,WAAU,6BAA6B,YAAE,cAAc,OAAO,IAAI,EAAE,YAAY,QAAQ,IAAI,EAAE,QAAQ,UAAI;AAAA,eALvG,CAMT,CACD,GACH;AAAA,WACF,GACF;AAAA,WAvDM,KAAK,MAyDf;AAAA,IAEJ,CAAC,GACH;AAAA,IAID,SAAS,MAAM,SAAS,KACvB,oBAAC,SAAI,WAAU,iCACb,+BAAC,SAAI,WAAU,yCACb;AAAA,2BAAC,SACC;AAAA,4BAAC,OAAE,WAAU,iCAAgC,iCAAmB;AAAA,QAChE,oBAAC,OAAE,WAAU,mCAAmC,cAAI,QAAQ,UAAU,QAAQ,GAAE;AAAA,SAClF;AAAA,MACA,qBAAC,SACC;AAAA,4BAAC,OAAE,WAAU,iCAAgC,qCAAuB;AAAA,QACpE,oBAAC,OAAE,WAAU,mCAAmC,cAAI,QAAQ,UAAU,QAAQ,GAAE;AAAA,SAClF;AAAA,MACC,QAAQ,aAAa,SAAS,KAC7B,qBAAC,SACC;AAAA,4BAAC,OAAE,WAAU,iCAAgC,2BAAa;AAAA,QAC1D,oBAAC,SAAI,WAAU,oBACZ,kBAAQ,aAAa,IAAI,CAAC,IAAI,MAC7B,qBAAC,OAAU,WAAU,WAAW;AAAA,aAAG;AAAA,UAAW;AAAA,UAAG,IAAI,GAAG,WAAW,QAAQ;AAAA,UAAE;AAAA,aAArE,CAA0E,CACnF,GACH;AAAA,SACF;AAAA,OAEJ,GACF;AAAA,KAEJ;AAEJ;AAEA,SAAS,UAAU;AACjB,SACE,qBAAC,SAAI,WAAU,wBAAuB,SAAQ,aAAY,MAAK,QAC7D;AAAA,wBAAC,YAAO,WAAU,cAAa,IAAG,MAAK,IAAG,MAAK,GAAE,MAAK,QAAO,gBAAe,aAAY,KAAI;AAAA,IAC5F,oBAAC,UAAK,WAAU,cAAa,MAAK,gBAAe,GAAE,uCAAsC;AAAA,KAC3F;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,17 @@
1
+ import QuoteConfiguratorWidget from "./widget.client.js";
2
+ const widget = {
3
+ metadata: {
4
+ id: "cpq.injection.quote-configurator",
5
+ title: "CPQ Configuration",
6
+ description: "Configure, price, and manage quote offerings",
7
+ features: ["cpq.quotes.view"],
8
+ priority: 70,
9
+ enabled: true
10
+ },
11
+ Widget: QuoteConfiguratorWidget
12
+ };
13
+ var widget_default = widget;
14
+ export {
15
+ widget_default as default
16
+ };
17
+ //# sourceMappingURL=widget.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/cpq/widgets/injection/quote-configurator/widget.ts"],
4
+ "sourcesContent": ["import type { InjectionWidgetModule } from '@open-mercato/shared/modules/widgets/injection'\nimport QuoteConfiguratorWidget from './widget.client'\n\nconst widget: InjectionWidgetModule<any, any> = {\n metadata: {\n id: 'cpq.injection.quote-configurator',\n title: 'CPQ Configuration',\n description: 'Configure, price, and manage quote offerings',\n features: ['cpq.quotes.view'],\n priority: 70,\n enabled: true,\n },\n Widget: QuoteConfiguratorWidget,\n}\n\nexport default widget\n"],
5
+ "mappings": "AACA,OAAO,6BAA6B;AAEpC,MAAM,SAA0C;AAAA,EAC9C,UAAU;AAAA,IACR,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU,CAAC,iBAAiB;AAAA,IAC5B,UAAU;AAAA,IACV,SAAS;AAAA,EACX;AAAA,EACA,QAAQ;AACV;AAEA,IAAO,iBAAQ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,44 @@
1
+ const injectionTable = {
2
+ "sales.document.detail.quote:tabs": [
3
+ {
4
+ widgetId: "cpq.injection.quote-configurator",
5
+ kind: "tab",
6
+ groupLabel: "CPQ Configuration",
7
+ groupDescription: "Configure, price, and manage quote offerings",
8
+ priority: 70
9
+ }
10
+ ],
11
+ "sales.document.detail.order:tabs": [
12
+ {
13
+ widgetId: "cpq.injection.order-cpq-tab",
14
+ kind: "tab",
15
+ groupLabel: "CPQ Order",
16
+ groupDescription: "View the CPQ order associated with this sales order",
17
+ priority: 60
18
+ }
19
+ ],
20
+ "detail:customers.company:tabs": [
21
+ {
22
+ widgetId: "cpq.injection.customer-inventory",
23
+ kind: "tab",
24
+ groupLabel: "Inventory",
25
+ groupDescription: "Products and services purchased by this customer",
26
+ priority: 60
27
+ }
28
+ ],
29
+ "detail:customers.person:tabs": [
30
+ {
31
+ widgetId: "cpq.injection.customer-inventory",
32
+ kind: "tab",
33
+ groupLabel: "Inventory",
34
+ groupDescription: "Products and services purchased by this customer",
35
+ priority: 60
36
+ }
37
+ ]
38
+ };
39
+ var injection_table_default = injectionTable;
40
+ export {
41
+ injection_table_default as default,
42
+ injectionTable
43
+ };
44
+ //# sourceMappingURL=injection-table.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/cpq/widgets/injection-table.ts"],
4
+ "sourcesContent": ["import type { ModuleInjectionTable } from '@open-mercato/shared/modules/widgets/injection'\n\nexport const injectionTable: ModuleInjectionTable = {\n 'sales.document.detail.quote:tabs': [\n {\n widgetId: 'cpq.injection.quote-configurator',\n kind: 'tab',\n groupLabel: 'CPQ Configuration',\n groupDescription: 'Configure, price, and manage quote offerings',\n priority: 70,\n },\n ],\n 'sales.document.detail.order:tabs': [\n {\n widgetId: 'cpq.injection.order-cpq-tab',\n kind: 'tab',\n groupLabel: 'CPQ Order',\n groupDescription: 'View the CPQ order associated with this sales order',\n priority: 60,\n },\n ],\n 'detail:customers.company:tabs': [\n {\n widgetId: 'cpq.injection.customer-inventory',\n kind: 'tab',\n groupLabel: 'Inventory',\n groupDescription: 'Products and services purchased by this customer',\n priority: 60,\n },\n ],\n 'detail:customers.person:tabs': [\n {\n widgetId: 'cpq.injection.customer-inventory',\n kind: 'tab',\n groupLabel: 'Inventory',\n groupDescription: 'Products and services purchased by this customer',\n priority: 60,\n },\n ],\n}\n\nexport default injectionTable\n"],
5
+ "mappings": "AAEO,MAAM,iBAAuC;AAAA,EAClD,oCAAoC;AAAA,IAClC;AAAA,MACE,UAAU;AAAA,MACV,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,kBAAkB;AAAA,MAClB,UAAU;AAAA,IACZ;AAAA,EACF;AAAA,EACA,oCAAoC;AAAA,IAClC;AAAA,MACE,UAAU;AAAA,MACV,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,kBAAkB;AAAA,MAClB,UAAU;AAAA,IACZ;AAAA,EACF;AAAA,EACA,iCAAiC;AAAA,IAC/B;AAAA,MACE,UAAU;AAAA,MACV,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,kBAAkB;AAAA,MAClB,UAAU;AAAA,IACZ;AAAA,EACF;AAAA,EACA,gCAAgC;AAAA,IAC9B;AAAA,MACE,UAAU;AAAA,MACV,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,kBAAkB;AAAA,MAClB,UAAU;AAAA,IACZ;AAAA,EACF;AACF;AAEA,IAAO,0BAAQ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,113 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import React from "react";
4
+ import { WizardEngineProvider, useWizardEngine } from "./engine.js";
5
+ import { getStepType } from "./registry.js";
6
+ function StepRenderer({ scope }) {
7
+ const { state, completeStep, goBack, skipStep } = useWizardEngine();
8
+ const { currentStep, stepData, completedSteps, currentStepId, params, quoteId, customerId } = state;
9
+ const stepType = getStepType(currentStep.type);
10
+ const stepProps = {
11
+ stepData,
12
+ completedSteps,
13
+ currentStepId,
14
+ stepDefinition: currentStep,
15
+ config: currentStep.config,
16
+ params,
17
+ onComplete: completeStep,
18
+ onBack: goBack,
19
+ onSkip: skipStep,
20
+ quoteId,
21
+ customerId,
22
+ scope
23
+ };
24
+ if (!stepType) {
25
+ return /* @__PURE__ */ jsxs("div", { className: "rounded-lg border bg-card p-6 text-center space-y-3", children: [
26
+ /* @__PURE__ */ jsxs("p", { className: "text-sm text-destructive", children: [
27
+ "Unknown step type: ",
28
+ /* @__PURE__ */ jsx("strong", { children: currentStep.type })
29
+ ] }),
30
+ /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground", children: [
31
+ "This step type is not registered. Register it via ",
32
+ /* @__PURE__ */ jsx("code", { className: "font-mono text-xs bg-muted px-1 py-0.5 rounded", children: "registerStepType()" }),
33
+ "."
34
+ ] }),
35
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-2 justify-center pt-2", children: [
36
+ state.canGoBack && /* @__PURE__ */ jsx("button", { type: "button", onClick: goBack, className: "inline-flex items-center justify-center rounded-md border px-4 py-2 text-sm font-medium hover:bg-muted", children: "Back" }),
37
+ state.canSkip && /* @__PURE__ */ jsx("button", { type: "button", onClick: skipStep, className: "inline-flex items-center justify-center rounded-md border px-4 py-2 text-sm font-medium hover:bg-muted", children: "Skip" })
38
+ ] })
39
+ ] });
40
+ }
41
+ const Component = stepType.component;
42
+ return /* @__PURE__ */ jsx(Component, { ...stepProps });
43
+ }
44
+ function WizardProgress() {
45
+ const { state } = useWizardEngine();
46
+ const { definition, completedSteps, currentStepId, completionPercent } = state;
47
+ const steps = definition.steps;
48
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 py-2", children: [
49
+ steps.map((step, idx) => {
50
+ const isCompleted = completedSteps.includes(step.stepId);
51
+ const isCurrent = step.stepId === currentStepId;
52
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
53
+ /* @__PURE__ */ jsx(
54
+ "div",
55
+ {
56
+ className: `w-7 h-7 rounded-full flex items-center justify-center text-xs ${isCompleted ? "bg-primary text-primary-foreground font-medium" : isCurrent ? "bg-primary text-primary-foreground font-bold" : "bg-muted text-muted-foreground"}`,
57
+ title: step.title,
58
+ children: isCompleted ? "\u2713" : idx + 1
59
+ }
60
+ ),
61
+ idx < steps.length - 1 && /* @__PURE__ */ jsx("div", { className: `w-6 h-0.5 ${isCompleted ? "bg-primary" : "bg-muted"}` })
62
+ ] }, step.stepId);
63
+ }),
64
+ /* @__PURE__ */ jsxs("span", { className: "ml-2 text-xs text-muted-foreground", children: [
65
+ completionPercent,
66
+ "%"
67
+ ] })
68
+ ] });
69
+ }
70
+ function WizardHeader() {
71
+ const { state } = useWizardEngine();
72
+ return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ jsxs("div", { children: [
73
+ /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold", children: state.definition.name }),
74
+ /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground", children: [
75
+ "Step: ",
76
+ state.currentStep.title
77
+ ] })
78
+ ] }) });
79
+ }
80
+ function WizardRunner({
81
+ definition,
82
+ params,
83
+ initialQuoteId,
84
+ initialCustomerId,
85
+ scope,
86
+ onComplete
87
+ }) {
88
+ const handleComplete = React.useCallback(
89
+ (stepData) => {
90
+ onComplete?.(stepData);
91
+ },
92
+ [onComplete]
93
+ );
94
+ return /* @__PURE__ */ jsx(
95
+ WizardEngineProvider,
96
+ {
97
+ definition,
98
+ params,
99
+ initialQuoteId,
100
+ initialCustomerId,
101
+ onComplete: handleComplete,
102
+ children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
103
+ /* @__PURE__ */ jsx(WizardHeader, {}),
104
+ /* @__PURE__ */ jsx(WizardProgress, {}),
105
+ /* @__PURE__ */ jsx("div", { className: "min-h-[200px]", children: /* @__PURE__ */ jsx(StepRenderer, { scope }) })
106
+ ] })
107
+ }
108
+ );
109
+ }
110
+ export {
111
+ WizardRunner
112
+ };
113
+ //# sourceMappingURL=WizardRunner.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/cpq/workflows/WizardRunner.tsx"],
4
+ "sourcesContent": ["'use client'\n\nimport React from 'react'\nimport { WizardEngineProvider, useWizardEngine } from './engine'\nimport { getStepType } from './registry'\nimport type { WizardDefinitionResult, WizardStepProps } from './types'\nimport type { TenantScope } from '../services/types'\n\n// \u2500\u2500\u2500 Step renderer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction StepRenderer({ scope }: { scope: TenantScope }) {\n const { state, completeStep, goBack, skipStep } = useWizardEngine()\n const { currentStep, stepData, completedSteps, currentStepId, params, quoteId, customerId } = state\n\n const stepType = getStepType(currentStep.type)\n\n const stepProps: WizardStepProps = {\n stepData,\n completedSteps,\n currentStepId,\n stepDefinition: currentStep,\n config: currentStep.config,\n params,\n onComplete: completeStep,\n onBack: goBack,\n onSkip: skipStep,\n quoteId,\n customerId,\n scope,\n }\n\n if (!stepType) {\n return (\n <div className=\"rounded-lg border bg-card p-6 text-center space-y-3\">\n <p className=\"text-sm text-destructive\">\n Unknown step type: <strong>{currentStep.type}</strong>\n </p>\n <p className=\"text-sm text-muted-foreground\">This step type is not registered. Register it via <code className=\"font-mono text-xs bg-muted px-1 py-0.5 rounded\">registerStepType()</code>.</p>\n <div className=\"flex gap-2 justify-center pt-2\">\n {state.canGoBack && (\n <button type=\"button\" onClick={goBack} className=\"inline-flex items-center justify-center rounded-md border px-4 py-2 text-sm font-medium hover:bg-muted\">\n Back\n </button>\n )}\n {state.canSkip && (\n <button type=\"button\" onClick={skipStep} className=\"inline-flex items-center justify-center rounded-md border px-4 py-2 text-sm font-medium hover:bg-muted\">\n Skip\n </button>\n )}\n </div>\n </div>\n )\n }\n\n const Component = stepType.component\n return <Component {...stepProps} />\n}\n\n// \u2500\u2500\u2500 Progress bar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction WizardProgress() {\n const { state } = useWizardEngine()\n const { definition, completedSteps, currentStepId, completionPercent } = state\n const steps = definition.steps\n\n return (\n <div className=\"flex items-center gap-1 py-2\">\n {steps.map((step, idx) => {\n const isCompleted = completedSteps.includes(step.stepId)\n const isCurrent = step.stepId === currentStepId\n return (\n <div key={step.stepId} className=\"flex items-center gap-1\">\n <div\n className={`w-7 h-7 rounded-full flex items-center justify-center text-xs ${\n isCompleted\n ? 'bg-primary text-primary-foreground font-medium'\n : isCurrent\n ? 'bg-primary text-primary-foreground font-bold'\n : 'bg-muted text-muted-foreground'\n }`}\n title={step.title}\n >\n {isCompleted ? '\\u2713' : idx + 1}\n </div>\n {idx < steps.length - 1 && (\n <div className={`w-6 h-0.5 ${isCompleted ? 'bg-primary' : 'bg-muted'}`} />\n )}\n </div>\n )\n })}\n <span className=\"ml-2 text-xs text-muted-foreground\">\n {completionPercent}%\n </span>\n </div>\n )\n}\n\n// \u2500\u2500\u2500 Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction WizardHeader() {\n const { state } = useWizardEngine()\n\n return (\n <div className=\"flex items-center justify-between\">\n <div>\n <h2 className=\"text-lg font-semibold\">{state.definition.name}</h2>\n <p className=\"text-sm text-muted-foreground\">\n Step: {state.currentStep.title}\n </p>\n </div>\n </div>\n )\n}\n\n// \u2500\u2500\u2500 Main Runner component \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ninterface WizardRunnerProps {\n definition: WizardDefinitionResult\n params?: Record<string, unknown>\n initialQuoteId?: string | null\n initialCustomerId?: string | null\n scope: TenantScope\n onComplete?: (stepData: Record<string, Record<string, unknown>>) => void\n}\n\nexport function WizardRunner({\n definition,\n params,\n initialQuoteId,\n initialCustomerId,\n scope,\n onComplete,\n}: WizardRunnerProps) {\n const handleComplete = React.useCallback(\n (stepData: Record<string, Record<string, unknown>>) => {\n onComplete?.(stepData)\n },\n [onComplete],\n )\n\n return (\n <WizardEngineProvider\n definition={definition}\n params={params}\n initialQuoteId={initialQuoteId}\n initialCustomerId={initialCustomerId}\n onComplete={handleComplete}\n >\n <div className=\"space-y-4\">\n <WizardHeader />\n <WizardProgress />\n <div className=\"min-h-[200px]\">\n <StepRenderer scope={scope} />\n </div>\n </div>\n </WizardEngineProvider>\n )\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,116 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useCallback, useState } from "react";
4
+ import { useRouter } from "next/navigation";
5
+ async function apiJson(url) {
6
+ const res = await fetch(url);
7
+ if (!res.ok) {
8
+ const body = await res.json().catch(() => ({}));
9
+ throw new Error(body.error ?? `API error ${res.status}`);
10
+ }
11
+ return res.json();
12
+ }
13
+ function WizardTrigger({
14
+ wizardCode,
15
+ offeringCode,
16
+ params: wizardParams = {},
17
+ surface = "backend",
18
+ label = "Start Wizard",
19
+ variant = "button",
20
+ className,
21
+ basePath,
22
+ onStart
23
+ }) {
24
+ const router = useRouter();
25
+ const [loading, setLoading] = useState(false);
26
+ const [error, setError] = useState(null);
27
+ const handleClick = useCallback(async () => {
28
+ setLoading(true);
29
+ setError(null);
30
+ try {
31
+ let definition = null;
32
+ if (wizardCode) {
33
+ definition = await apiJson(
34
+ `/api/cpq/wizards?code=${encodeURIComponent(wizardCode)}`
35
+ );
36
+ } else {
37
+ const resolveParams = new URLSearchParams({ surface });
38
+ if (offeringCode) resolveParams.set("offeringCode", offeringCode);
39
+ definition = await apiJson(
40
+ `/api/cpq/wizards/resolve?${resolveParams}`
41
+ );
42
+ }
43
+ if (!definition) {
44
+ setError("No matching wizard found");
45
+ return;
46
+ }
47
+ if (onStart) {
48
+ onStart(definition, wizardParams);
49
+ } else {
50
+ const path = basePath ?? (surface === "portal" ? "/wizards" : "/backend/cpq/wizards");
51
+ const queryParams = new URLSearchParams();
52
+ if (Object.keys(wizardParams).length > 0) {
53
+ queryParams.set("params", JSON.stringify(wizardParams));
54
+ }
55
+ const qs = queryParams.toString();
56
+ router.push(`${path}/${definition.code}${qs ? `?${qs}` : ""}`);
57
+ }
58
+ } catch (err) {
59
+ setError(err instanceof Error ? err.message : "Failed to start wizard");
60
+ } finally {
61
+ setLoading(false);
62
+ }
63
+ }, [wizardCode, offeringCode, wizardParams, surface, basePath, onStart, router]);
64
+ if (variant === "link") {
65
+ return /* @__PURE__ */ jsxs(
66
+ "a",
67
+ {
68
+ href: "#",
69
+ className: className ?? "text-sm text-primary hover:underline",
70
+ onClick: (e) => {
71
+ e.preventDefault();
72
+ handleClick();
73
+ },
74
+ children: [
75
+ loading ? "Starting..." : label,
76
+ error && /* @__PURE__ */ jsx("span", { className: "ml-2 text-xs text-destructive", children: error })
77
+ ]
78
+ }
79
+ );
80
+ }
81
+ if (variant === "card") {
82
+ return /* @__PURE__ */ jsxs(
83
+ "div",
84
+ {
85
+ className: className ?? "rounded-lg border p-4 cursor-pointer hover:shadow-sm transition-shadow",
86
+ onClick: handleClick,
87
+ role: "button",
88
+ tabIndex: 0,
89
+ onKeyDown: (e) => {
90
+ if (e.key === "Enter") handleClick();
91
+ },
92
+ children: [
93
+ /* @__PURE__ */ jsx("p", { className: "font-semibold text-sm", children: label }),
94
+ error && /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-destructive", children: error })
95
+ ]
96
+ }
97
+ );
98
+ }
99
+ return /* @__PURE__ */ jsxs(
100
+ "button",
101
+ {
102
+ type: "button",
103
+ className: className ?? "inline-flex items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50",
104
+ onClick: handleClick,
105
+ disabled: loading,
106
+ children: [
107
+ loading ? "Starting..." : label,
108
+ error && /* @__PURE__ */ jsx("span", { className: "ml-2 text-xs text-destructive/70", children: error })
109
+ ]
110
+ }
111
+ );
112
+ }
113
+ export {
114
+ WizardTrigger
115
+ };
116
+ //# sourceMappingURL=WizardTrigger.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/cpq/workflows/WizardTrigger.tsx"],
4
+ "sourcesContent": ["'use client'\n\nimport React, { useCallback, useState } from 'react'\nimport { useRouter } from 'next/navigation'\nimport type { WizardDefinitionResult } from './types'\n\n// \u2500\u2500\u2500 API helper \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nasync function apiJson<T>(url: string): Promise<T> {\n const res = await fetch(url)\n if (!res.ok) {\n const body = await res.json().catch(() => ({}))\n throw new Error(body.error ?? `API error ${res.status}`)\n }\n return res.json() as Promise<T>\n}\n\n// \u2500\u2500\u2500 Props \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface WizardTriggerProps {\n /** Explicit wizard definition code. If set, uses this wizard directly. */\n wizardCode?: string\n /** Offering code for wizard resolution (when no explicit wizard). */\n offeringCode?: string\n /** Launch params passed to the wizard engine. */\n params?: Record<string, unknown>\n /** Surface context. */\n surface?: 'backend' | 'portal'\n /** Button label. */\n label?: string\n /** Render variant. */\n variant?: 'button' | 'link' | 'card'\n /** Additional CSS class. */\n className?: string\n /** Override the navigation target base path. */\n basePath?: string\n /** Called after wizard is resolved (instead of navigating). */\n onStart?: (definition: WizardDefinitionResult, params: Record<string, unknown>) => void\n}\n\nexport function WizardTrigger({\n wizardCode,\n offeringCode,\n params: wizardParams = {},\n surface = 'backend',\n label = 'Start Wizard',\n variant = 'button',\n className,\n basePath,\n onStart,\n}: WizardTriggerProps) {\n const router = useRouter()\n const [loading, setLoading] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n const handleClick = useCallback(async () => {\n setLoading(true)\n setError(null)\n\n try {\n // Resolve definition\n let definition: WizardDefinitionResult | null = null\n\n if (wizardCode) {\n definition = await apiJson<WizardDefinitionResult>(\n `/api/cpq/wizards?code=${encodeURIComponent(wizardCode)}`,\n )\n } else {\n const resolveParams = new URLSearchParams({ surface })\n if (offeringCode) resolveParams.set('offeringCode', offeringCode)\n definition = await apiJson<WizardDefinitionResult>(\n `/api/cpq/wizards/resolve?${resolveParams}`,\n )\n }\n\n if (!definition) {\n setError('No matching wizard found')\n return\n }\n\n if (onStart) {\n onStart(definition, wizardParams)\n } else {\n const path = basePath ?? (surface === 'portal' ? '/wizards' : '/backend/cpq/wizards')\n const queryParams = new URLSearchParams()\n if (Object.keys(wizardParams).length > 0) {\n queryParams.set('params', JSON.stringify(wizardParams))\n }\n const qs = queryParams.toString()\n router.push(`${path}/${definition.code}${qs ? `?${qs}` : ''}`)\n }\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to start wizard')\n } finally {\n setLoading(false)\n }\n }, [wizardCode, offeringCode, wizardParams, surface, basePath, onStart, router])\n\n if (variant === 'link') {\n return (\n <a\n href=\"#\"\n className={className ?? 'text-sm text-primary hover:underline'}\n onClick={(e) => {\n e.preventDefault()\n handleClick()\n }}\n >\n {loading ? 'Starting...' : label}\n {error && <span className=\"ml-2 text-xs text-destructive\">{error}</span>}\n </a>\n )\n }\n\n if (variant === 'card') {\n return (\n <div\n className={className ?? 'rounded-lg border p-4 cursor-pointer hover:shadow-sm transition-shadow'}\n onClick={handleClick}\n role=\"button\"\n tabIndex={0}\n onKeyDown={(e) => { if (e.key === 'Enter') handleClick() }}\n >\n <p className=\"font-semibold text-sm\">{label}</p>\n {error && <p className=\"mt-1 text-xs text-destructive\">{error}</p>}\n </div>\n )\n }\n\n // Default: button\n return (\n <button\n type=\"button\"\n className={className ?? 'inline-flex items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50'}\n onClick={handleClick}\n disabled={loading}\n >\n {loading ? 'Starting...' : label}\n {error && <span className=\"ml-2 text-xs text-destructive/70\">{error}</span>}\n </button>\n )\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,188 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { createContext, useContext, useReducer, useCallback, useMemo } from "react";
4
+ function resolveStep(definition, stepId) {
5
+ const step = definition.steps.find((s) => s.stepId === stepId);
6
+ if (!step) throw new Error(`Step '${stepId}' not found in wizard '${definition.code}'`);
7
+ return step;
8
+ }
9
+ function engineReducer(state, action) {
10
+ switch (action.type) {
11
+ case "COMPLETE_STEP": {
12
+ const newCompletedSteps = [...state.completedSteps, action.stepId];
13
+ const newStepData = {
14
+ ...state.stepData,
15
+ [action.stepId]: action.output
16
+ };
17
+ const nextStep = resolveStep(state.definition, action.nextStepId);
18
+ const newQuoteId = typeof action.output.quoteId === "string" && action.output.quoteId ? action.output.quoteId : state.quoteId;
19
+ const newCustomerId = typeof action.output.customerId === "string" && action.output.customerId ? action.output.customerId : state.customerId;
20
+ return {
21
+ ...state,
22
+ currentStepId: action.nextStepId,
23
+ completedSteps: newCompletedSteps,
24
+ stepData: newStepData,
25
+ currentStep: nextStep,
26
+ canGoBack: newCompletedSteps.length > 0,
27
+ isFirstStep: false,
28
+ isLastStep: nextStep.transitions.length === 0,
29
+ completionPercent: Math.round(newCompletedSteps.length / state.definition.steps.length * 100),
30
+ canSkip: nextStep.isOptional === true,
31
+ quoteId: newQuoteId,
32
+ customerId: newCustomerId
33
+ };
34
+ }
35
+ case "GO_BACK": {
36
+ const newCompletedSteps = state.completedSteps.filter((s) => s !== action.prevStepId);
37
+ const prevStep = resolveStep(state.definition, action.prevStepId);
38
+ return {
39
+ ...state,
40
+ currentStepId: action.prevStepId,
41
+ completedSteps: newCompletedSteps,
42
+ currentStep: prevStep,
43
+ canGoBack: newCompletedSteps.length > 0,
44
+ isFirstStep: newCompletedSteps.length === 0,
45
+ isLastStep: prevStep.transitions.length === 0,
46
+ completionPercent: Math.round(newCompletedSteps.length / state.definition.steps.length * 100),
47
+ canSkip: prevStep.isOptional === true
48
+ };
49
+ }
50
+ case "SKIP_STEP": {
51
+ const nextStep = resolveStep(state.definition, action.nextStepId);
52
+ return {
53
+ ...state,
54
+ currentStepId: action.nextStepId,
55
+ currentStep: nextStep,
56
+ isLastStep: nextStep.transitions.length === 0,
57
+ canSkip: nextStep.isOptional === true
58
+ };
59
+ }
60
+ case "SET_QUOTE_ID":
61
+ return { ...state, quoteId: action.quoteId };
62
+ case "SET_CUSTOMER_ID":
63
+ return { ...state, customerId: action.customerId };
64
+ default:
65
+ return state;
66
+ }
67
+ }
68
+ function getNestedValue(obj, path) {
69
+ const parts = path.split(".");
70
+ let current = obj;
71
+ for (const part of parts) {
72
+ if (current == null || typeof current !== "object") return void 0;
73
+ current = current[part];
74
+ }
75
+ return current;
76
+ }
77
+ function evaluateCondition(condition, stepData, params) {
78
+ const context = { stepData, params };
79
+ const actual = getNestedValue(context, condition.field);
80
+ switch (condition.operator) {
81
+ case "exists":
82
+ return actual !== void 0 && actual !== null;
83
+ case "not_exists":
84
+ return actual === void 0 || actual === null;
85
+ case "eq":
86
+ return actual === condition.value;
87
+ case "neq":
88
+ return actual !== condition.value;
89
+ case "gt":
90
+ return typeof actual === "number" && typeof condition.value === "number" && actual > condition.value;
91
+ case "lt":
92
+ return typeof actual === "number" && typeof condition.value === "number" && actual < condition.value;
93
+ case "gte":
94
+ return typeof actual === "number" && typeof condition.value === "number" && actual >= condition.value;
95
+ case "lte":
96
+ return typeof actual === "number" && typeof condition.value === "number" && actual <= condition.value;
97
+ case "in":
98
+ return Array.isArray(condition.value) && condition.value.includes(actual);
99
+ default:
100
+ return false;
101
+ }
102
+ }
103
+ function resolveNextStep(step, stepData, params) {
104
+ for (const transition of step.transitions) {
105
+ if (!transition.condition) {
106
+ if (transition.isDefault) return transition.targetStepId;
107
+ return transition.targetStepId;
108
+ }
109
+ if (evaluateCondition(transition.condition, stepData, params)) {
110
+ return transition.targetStepId;
111
+ }
112
+ }
113
+ const defaultTransition = step.transitions.find((t) => t.isDefault);
114
+ if (defaultTransition) return defaultTransition.targetStepId;
115
+ return null;
116
+ }
117
+ const WizardEngineContext = createContext(null);
118
+ function useWizardEngine() {
119
+ const ctx = useContext(WizardEngineContext);
120
+ if (!ctx) throw new Error("useWizardEngine must be used within a WizardEngineProvider");
121
+ return ctx;
122
+ }
123
+ function WizardEngineProvider({
124
+ definition,
125
+ params: launchParams = {},
126
+ initialQuoteId = null,
127
+ initialCustomerId = null,
128
+ children,
129
+ onComplete
130
+ }) {
131
+ const firstStep = definition.steps[0];
132
+ if (!firstStep) throw new Error(`Wizard '${definition.code}' has no steps`);
133
+ const initialState = {
134
+ definition,
135
+ params: launchParams,
136
+ currentStepId: firstStep.stepId,
137
+ completedSteps: [],
138
+ stepData: {},
139
+ currentStep: firstStep,
140
+ canGoBack: false,
141
+ canSkip: firstStep.isOptional === true,
142
+ isFirstStep: true,
143
+ isLastStep: firstStep.transitions.length === 0,
144
+ completionPercent: 0,
145
+ quoteId: initialQuoteId,
146
+ customerId: initialCustomerId
147
+ };
148
+ const [state, dispatch] = useReducer(engineReducer, initialState);
149
+ const completeStep = useCallback(
150
+ (stepOutput) => {
151
+ const updatedStepData = {
152
+ ...state.stepData,
153
+ [state.currentStep.stepId]: stepOutput
154
+ };
155
+ const nextStepId = resolveNextStep(state.currentStep, updatedStepData, state.params);
156
+ if (!nextStepId) {
157
+ onComplete?.(updatedStepData);
158
+ return;
159
+ }
160
+ dispatch({ type: "COMPLETE_STEP", stepId: state.currentStep.stepId, output: stepOutput, nextStepId });
161
+ },
162
+ [state, onComplete]
163
+ );
164
+ const goBack = useCallback(() => {
165
+ if (state.completedSteps.length === 0) return;
166
+ const prevStepId = state.completedSteps[state.completedSteps.length - 1];
167
+ dispatch({ type: "GO_BACK", prevStepId });
168
+ }, [state.completedSteps]);
169
+ const skipStep = useCallback(() => {
170
+ if (!state.currentStep.isOptional) return;
171
+ const nextStepId = resolveNextStep(state.currentStep, state.stepData, state.params);
172
+ if (nextStepId) {
173
+ dispatch({ type: "SKIP_STEP", nextStepId });
174
+ }
175
+ }, [state]);
176
+ const value = useMemo(
177
+ () => ({ state, completeStep, goBack, skipStep }),
178
+ [state, completeStep, goBack, skipStep]
179
+ );
180
+ return /* @__PURE__ */ jsx(WizardEngineContext.Provider, { value, children });
181
+ }
182
+ export {
183
+ WizardEngineProvider,
184
+ evaluateCondition,
185
+ resolveNextStep,
186
+ useWizardEngine
187
+ };
188
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/cpq/workflows/engine.tsx"],
4
+ "sourcesContent": ["'use client'\n\nimport React, { createContext, useContext, useReducer, useCallback, useMemo } from 'react'\nimport type {\n WizardDefinitionResult,\n WizardStepDefinition,\n TransitionCondition,\n} from './types'\n\n// \u2500\u2500\u2500 Engine state \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface WizardEngineState {\n definition: WizardDefinitionResult\n params: Record<string, unknown>\n currentStepId: string\n completedSteps: string[]\n stepData: Record<string, Record<string, unknown>>\n currentStep: WizardStepDefinition\n canGoBack: boolean\n canSkip: boolean\n isFirstStep: boolean\n isLastStep: boolean\n completionPercent: number\n quoteId: string | null\n customerId: string | null\n}\n\ntype EngineAction =\n | { type: 'COMPLETE_STEP'; stepId: string; output: Record<string, unknown>; nextStepId: string }\n | { type: 'GO_BACK'; prevStepId: string }\n | { type: 'SKIP_STEP'; nextStepId: string }\n | { type: 'SET_QUOTE_ID'; quoteId: string }\n | { type: 'SET_CUSTOMER_ID'; customerId: string }\n\nfunction resolveStep(definition: WizardDefinitionResult, stepId: string): WizardStepDefinition {\n const step = definition.steps.find((s) => s.stepId === stepId)\n if (!step) throw new Error(`Step '${stepId}' not found in wizard '${definition.code}'`)\n return step\n}\n\nfunction engineReducer(state: WizardEngineState, action: EngineAction): WizardEngineState {\n switch (action.type) {\n case 'COMPLETE_STEP': {\n const newCompletedSteps = [...state.completedSteps, action.stepId]\n const newStepData = {\n ...state.stepData,\n [action.stepId]: action.output,\n }\n const nextStep = resolveStep(state.definition, action.nextStepId)\n // Auto-propagate quoteId / customerId from step output\n const newQuoteId = (typeof action.output.quoteId === 'string' && action.output.quoteId)\n ? action.output.quoteId : state.quoteId\n const newCustomerId = (typeof action.output.customerId === 'string' && action.output.customerId)\n ? action.output.customerId : state.customerId\n return {\n ...state,\n currentStepId: action.nextStepId,\n completedSteps: newCompletedSteps,\n stepData: newStepData,\n currentStep: nextStep,\n canGoBack: newCompletedSteps.length > 0,\n isFirstStep: false,\n isLastStep: nextStep.transitions.length === 0,\n completionPercent: Math.round((newCompletedSteps.length / state.definition.steps.length) * 100),\n canSkip: nextStep.isOptional === true,\n quoteId: newQuoteId,\n customerId: newCustomerId,\n }\n }\n\n case 'GO_BACK': {\n const newCompletedSteps = state.completedSteps.filter((s) => s !== action.prevStepId)\n const prevStep = resolveStep(state.definition, action.prevStepId)\n return {\n ...state,\n currentStepId: action.prevStepId,\n completedSteps: newCompletedSteps,\n currentStep: prevStep,\n canGoBack: newCompletedSteps.length > 0,\n isFirstStep: newCompletedSteps.length === 0,\n isLastStep: prevStep.transitions.length === 0,\n completionPercent: Math.round((newCompletedSteps.length / state.definition.steps.length) * 100),\n canSkip: prevStep.isOptional === true,\n }\n }\n\n case 'SKIP_STEP': {\n const nextStep = resolveStep(state.definition, action.nextStepId)\n return {\n ...state,\n currentStepId: action.nextStepId,\n currentStep: nextStep,\n isLastStep: nextStep.transitions.length === 0,\n canSkip: nextStep.isOptional === true,\n }\n }\n\n case 'SET_QUOTE_ID':\n return { ...state, quoteId: action.quoteId }\n\n case 'SET_CUSTOMER_ID':\n return { ...state, customerId: action.customerId }\n\n default:\n return state\n }\n}\n\n// \u2500\u2500\u2500 Transition evaluation \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction getNestedValue(obj: Record<string, unknown>, path: string): unknown {\n const parts = path.split('.')\n let current: unknown = obj\n for (const part of parts) {\n if (current == null || typeof current !== 'object') return undefined\n current = (current as Record<string, unknown>)[part]\n }\n return current\n}\n\nexport function evaluateCondition(\n condition: TransitionCondition,\n stepData: Record<string, Record<string, unknown>>,\n params: Record<string, unknown>,\n): boolean {\n const context = { stepData, params }\n const actual = getNestedValue(context as unknown as Record<string, unknown>, condition.field)\n\n switch (condition.operator) {\n case 'exists':\n return actual !== undefined && actual !== null\n case 'not_exists':\n return actual === undefined || actual === null\n case 'eq':\n return actual === condition.value\n case 'neq':\n return actual !== condition.value\n case 'gt':\n return typeof actual === 'number' && typeof condition.value === 'number' && actual > condition.value\n case 'lt':\n return typeof actual === 'number' && typeof condition.value === 'number' && actual < condition.value\n case 'gte':\n return typeof actual === 'number' && typeof condition.value === 'number' && actual >= condition.value\n case 'lte':\n return typeof actual === 'number' && typeof condition.value === 'number' && actual <= condition.value\n case 'in':\n return Array.isArray(condition.value) && condition.value.includes(actual)\n default:\n return false\n }\n}\n\nexport function resolveNextStep(\n step: WizardStepDefinition,\n stepData: Record<string, Record<string, unknown>>,\n params: Record<string, unknown>,\n): string | null {\n // Evaluate transitions in order, first match wins\n for (const transition of step.transitions) {\n if (!transition.condition) {\n if (transition.isDefault) return transition.targetStepId\n // No condition and no default flag = unconditional transition (take it)\n return transition.targetStepId\n }\n if (evaluateCondition(transition.condition, stepData, params)) {\n return transition.targetStepId\n }\n }\n // Fall back to default transition\n const defaultTransition = step.transitions.find((t) => t.isDefault)\n if (defaultTransition) return defaultTransition.targetStepId\n\n // No valid transition = end of wizard\n return null\n}\n\n// \u2500\u2500\u2500 Context \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ninterface WizardEngineContextValue {\n state: WizardEngineState\n completeStep: (stepOutput: Record<string, unknown>) => void\n goBack: () => void\n skipStep: () => void\n}\n\nconst WizardEngineContext = createContext<WizardEngineContextValue | null>(null)\n\nexport function useWizardEngine(): WizardEngineContextValue {\n const ctx = useContext(WizardEngineContext)\n if (!ctx) throw new Error('useWizardEngine must be used within a WizardEngineProvider')\n return ctx\n}\n\n// \u2500\u2500\u2500 Provider \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ninterface WizardEngineProviderProps {\n definition: WizardDefinitionResult\n params?: Record<string, unknown>\n initialQuoteId?: string | null\n initialCustomerId?: string | null\n children: React.ReactNode\n onComplete?: (stepData: Record<string, Record<string, unknown>>) => void\n}\n\nexport function WizardEngineProvider({\n definition,\n params: launchParams = {},\n initialQuoteId = null,\n initialCustomerId = null,\n children,\n onComplete,\n}: WizardEngineProviderProps) {\n const firstStep = definition.steps[0]\n if (!firstStep) throw new Error(`Wizard '${definition.code}' has no steps`)\n\n const initialState: WizardEngineState = {\n definition,\n params: launchParams,\n currentStepId: firstStep.stepId,\n completedSteps: [],\n stepData: {},\n currentStep: firstStep,\n canGoBack: false,\n canSkip: firstStep.isOptional === true,\n isFirstStep: true,\n isLastStep: firstStep.transitions.length === 0,\n completionPercent: 0,\n quoteId: initialQuoteId,\n customerId: initialCustomerId,\n }\n\n const [state, dispatch] = useReducer(engineReducer, initialState)\n\n const completeStep = useCallback(\n (stepOutput: Record<string, unknown>) => {\n const updatedStepData = {\n ...state.stepData,\n [state.currentStep.stepId]: stepOutput,\n }\n\n const nextStepId = resolveNextStep(state.currentStep, updatedStepData, state.params)\n\n if (!nextStepId) {\n // Wizard complete\n onComplete?.(updatedStepData)\n return\n }\n\n dispatch({ type: 'COMPLETE_STEP', stepId: state.currentStep.stepId, output: stepOutput, nextStepId })\n },\n [state, onComplete],\n )\n\n const goBack = useCallback(() => {\n if (state.completedSteps.length === 0) return\n const prevStepId = state.completedSteps[state.completedSteps.length - 1]\n dispatch({ type: 'GO_BACK', prevStepId })\n }, [state.completedSteps])\n\n const skipStep = useCallback(() => {\n if (!state.currentStep.isOptional) return\n const nextStepId = resolveNextStep(state.currentStep, state.stepData, state.params)\n if (nextStepId) {\n dispatch({ type: 'SKIP_STEP', nextStepId })\n }\n }, [state])\n\n const value = useMemo(\n () => ({ state, completeStep, goBack, skipStep }),\n [state, completeStep, goBack, skipStep],\n )\n\n return (\n <WizardEngineContext.Provider value={value}>\n {children}\n </WizardEngineContext.Provider>\n )\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }