@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/backend/cpq/offerings/%5Bid%5D/page.tsx"],
4
+ "sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useParams, useRouter } from 'next/navigation'\nimport { Alert } from '@open-mercato/ui/primitives/alert'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Tag } from '@open-mercato/ui/primitives/tag'\nimport { NumberInput } from '../../../../components/NumberInput'\nimport {\n chargeTypeMap,\n formatStatusLabel,\n lifecycleStatusMap,\n type ChargeType,\n type LifecycleStatus,\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\n\ntype OfferingComponent = {\n id: string\n slotId: string\n slot: { id: string; componentGroup: string; name: string; cardinalityMin: number; cardinalityMax: number | null } | null\n childOfferingId: string\n childOffering: { id: string; code: string; name: string; offeringType: string; specId: string } | null\n isDefault: boolean\n sortOrder: number\n isActive: boolean\n}\n\ntype BundleSlot = {\n id: string\n componentGroup: string\n name: string\n targetSpecId: string\n targetSpec: { id: string; code: string; name: string; specType: string } | null\n cardinalityMin: number\n cardinalityMax: number | null\n sortOrder: number\n}\n\ntype Offering = {\n id: string\n specId: string\n catalogOfferId: string | null\n code: string\n name: string\n description: string | null\n offeringType: string\n designTimeValues: Record<string, unknown>\n lifecycleStatus: string\n effectiveFrom: string | null\n effectiveTo: string | null\n metadata: Record<string, unknown> | null\n isActive: boolean\n specification: { id: string; code: string; name: string; productId: string; specType?: string } | null\n charges: Charge[]\n components?: OfferingComponent[]\n}\n\ntype Charge = {\n id: string\n code: string\n name: string\n description: string | null\n chargeType: string\n pricingMethod: string\n pricingTableId: string | null\n priceColumnKey: string | null\n fixedPrice: string | null\n currencyCode: string | null\n quantityAttributeCode: string | null\n applicabilityCondition: Record<string, unknown> | null\n sortOrder: number\n isActive: boolean\n}\n\ntype Attribute = {\n id: string\n code: string\n name: string\n attributeType: string\n resolutionTime: string\n options: Array<{ value: string; label: string }> | null\n constraints: Record<string, unknown> | null\n defaultValue: unknown | null\n helpText: string | null\n sortOrder: number\n isRequired: boolean\n isActive: boolean\n}\n\ntype Specification = {\n id: string\n code: string\n name: string\n productId: string\n}\n\ntype PricingTableRef = { id: string; code: string; name: string; dimensions: Array<{ key: string; label: string }>; priceColumns: Array<{ key: string; label: string }> }\n\ntype EditingCharge = Omit<Charge, 'id'> & { id?: string }\n\n// \u2500\u2500\u2500 Defaults \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\nconst EMPTY_FORM = {\n code: '',\n name: '',\n description: '',\n offeringType: 'simple' as string,\n lifecycleStatus: 'draft',\n effectiveFrom: null as string | null,\n effectiveTo: null as string | null,\n isActive: true,\n specId: '',\n}\n\nconst EMPTY_CHARGE: EditingCharge = {\n code: '',\n name: '',\n description: null,\n chargeType: 'mrc',\n pricingMethod: 'flat',\n pricingTableId: null,\n priceColumnKey: null,\n fixedPrice: null,\n currencyCode: 'USD',\n quantityAttributeCode: null,\n applicabilityCondition: null,\n sortOrder: 0,\n isActive: true,\n}\n\n\nconst PRICING_METHOD_LABELS: Record<string, string> = {\n flat: 'flat price',\n fixed: 'flat price', // legacy alias \u2014 see validators.ts\n per_unit: 'per unit',\n tiered: 'tiered',\n}\n\n// V-CHG-1 in `validators.ts`: per_unit/tiered need table + column + qty\n// attribute; flat needs fixedPrice + currencyCode. Mirror it in the UI so\n// users see what's missing without round-tripping to the server.\ntype ChargeShape = {\n pricingMethod: string\n pricingTableId: string | null\n priceColumnKey: string | null\n fixedPrice: string | null\n currencyCode: string | null\n quantityAttributeCode: string | null\n}\n\nfunction isChargeComplete(charge: ChargeShape): boolean {\n return chargeMissingFields(charge).length === 0\n}\n\nfunction chargeMissingFields(charge: ChargeShape): string[] {\n const method = charge.pricingMethod === 'fixed' ? 'flat' : charge.pricingMethod\n const missing: string[] = []\n if (method === 'flat') {\n if (!charge.fixedPrice) missing.push('Fixed Price')\n if (!charge.currencyCode) missing.push('Currency')\n } else if (method === 'per_unit' || method === 'tiered') {\n if (!charge.pricingTableId) missing.push('Pricing Table')\n if (!charge.priceColumnKey) missing.push('Price Column')\n if (!charge.quantityAttributeCode) missing.push('Quantity Attribute')\n }\n return missing\n}\n\n// \u2500\u2500\u2500 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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport default function OfferingDetailPage(props: { params?: { id?: string } }) {\n const t = useT()\n const router = useRouter()\n const urlParams = useParams()\n const offeringId = (props.params?.id ?? urlParams?.id) as string\n const isNew = offeringId === 'new'\n\n // \u2500\u2500\u2500 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\u2500\u2500\u2500\n\n const [tab, setTab] = React.useState<'general' | 'charges' | 'components'>('general')\n const [form, setForm] = React.useState(EMPTY_FORM)\n const [designTimeValues, setDesignTimeValues] = React.useState<Record<string, unknown>>({})\n const [charges, setCharges] = React.useState<Charge[]>([])\n const [attributes, setAttributes] = React.useState<Attribute[]>([])\n const [specs, setSpecs] = React.useState<Specification[]>([])\n const [specDetail, setSpecDetail] = React.useState<{ id: string; code: string; name: string; specType?: string } | null>(null)\n const [pricingTables, setPricingTables] = React.useState<PricingTableRef[]>([])\n const [components, setComponents] = React.useState<OfferingComponent[]>([])\n const [bundleSlots, setBundleSlots] = React.useState<BundleSlot[]>([])\n const [addingComponent, setAddingComponent] = React.useState<{ slotId: string; childOfferingId: string; isDefault: boolean } | null>(null)\n const [slotOfferings, setSlotOfferings] = React.useState<Record<string, Array<{ id: string; code: string; name: string; offeringType: string }>>>({})\n\n const [loading, setLoading] = React.useState(!isNew)\n const [saving, setSaving] = React.useState(false)\n const [error, setError] = React.useState<string | null>(null)\n\n const [editingCharge, setEditingCharge] = React.useState<EditingCharge | null>(null)\n\n // OM-standard detail page: existing offerings open read-only and require\n // an explicit Edit click to allow changes. New offerings skip view mode.\n const [generalMode, setGeneralMode] = React.useState<'view' | 'edit'>(isNew ? 'edit' : 'view')\n const [formSnapshot, setFormSnapshot] = React.useState<typeof EMPTY_FORM | null>(null)\n const [designTimeSnapshot, setDesignTimeSnapshot] = React.useState<Record<string, unknown> | null>(null)\n\n // \u2500\u2500\u2500 Load data \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 React.useEffect(() => {\n let cancelled = false\n\n async function load() {\n try {\n // Load specs for dropdown (needed for new + showing spec name)\n const specsRes = await fetch('/api/cpq/product-specifications?pageSize=200')\n if (specsRes.ok) {\n const d = await specsRes.json()\n if (!cancelled) setSpecs(d.items ?? [])\n }\n\n if (isNew) return\n\n // Load offering detail\n const res = await fetch(`/api/cpq/product-offerings?id=${encodeURIComponent(offeringId)}`)\n if (!res.ok) {\n if (!cancelled) setError('Failed to load offering')\n return\n }\n\n const data: Offering = await res.json()\n if (!cancelled) {\n setForm({\n code: data.code,\n name: data.name,\n description: data.description ?? '',\n offeringType: data.offeringType ?? 'simple',\n lifecycleStatus: data.lifecycleStatus,\n effectiveFrom: data.effectiveFrom,\n effectiveTo: data.effectiveTo,\n isActive: data.isActive,\n specId: data.specId,\n })\n setDesignTimeValues(data.designTimeValues ?? {})\n setCharges(data.charges ?? [])\n setSpecDetail(data.specification ?? null)\n setComponents(data.components ?? [])\n\n // Load attributes for the spec\n if (data.specId) {\n const attrRes = await fetch(`/api/cpq/product-attributes?specId=${encodeURIComponent(data.specId)}&pageSize=200`)\n if (attrRes.ok) {\n const attrData = await attrRes.json()\n if (!cancelled) setAttributes(attrData.items ?? [])\n }\n }\n\n // Load bundle slots if this is a bundle offering\n if (data.offeringType === 'bundle' && data.specId) {\n const slotsRes = await fetch(`/api/cpq/bundle-slots?specId=${encodeURIComponent(data.specId)}`)\n if (slotsRes.ok) {\n const slotsData = await slotsRes.json()\n if (!cancelled) setBundleSlots(slotsData.items ?? [])\n }\n }\n }\n } catch (err) {\n console.error('Failed to load', err)\n if (!cancelled) setError('Failed to load')\n } finally {\n if (!cancelled) setLoading(false)\n }\n }\n\n load()\n return () => { cancelled = true }\n }, [offeringId, isNew])\n\n // Load attributes when spec changes (for new offering)\n const loadSpecAttributes = async (specId: string) => {\n if (!specId) { setAttributes([]); return }\n try {\n const res = await fetch(`/api/cpq/product-attributes?specId=${encodeURIComponent(specId)}&pageSize=200`)\n if (res.ok) {\n const data = await res.json()\n setAttributes(data.items ?? [])\n }\n } catch {\n console.error('Failed to load spec attributes')\n }\n }\n\n // \u2500\u2500\u2500 Save offering \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 saveOffering = async () => {\n setSaving(true)\n setError(null)\n try {\n const payload = isNew\n ? { ...form, description: form.description || null, designTimeValues, specId: form.specId }\n : { id: offeringId, ...form, description: form.description || null, designTimeValues }\n\n const res = await fetch('/api/cpq/product-offerings', {\n method: isNew ? 'POST' : 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n })\n\n if (!res.ok) {\n const d = await res.json()\n setError(d.error ?? 'Failed to save')\n return\n }\n\n const saved = await res.json()\n if (isNew) {\n router.push(`/backend/cpq/offerings/${saved.id}`)\n } else {\n setForm({\n code: saved.code,\n name: saved.name,\n description: saved.description ?? '',\n offeringType: saved.offeringType ?? form.offeringType,\n lifecycleStatus: saved.lifecycleStatus,\n effectiveFrom: saved.effectiveFrom,\n effectiveTo: saved.effectiveTo,\n isActive: saved.isActive,\n specId: saved.specId,\n })\n setDesignTimeValues(saved.designTimeValues ?? {})\n // Save succeeded \u2014 drop snapshots and flip back to read-only.\n setFormSnapshot(null)\n setDesignTimeSnapshot(null)\n setGeneralMode('view')\n }\n } catch {\n setError('Failed to save')\n } finally {\n setSaving(false)\n }\n }\n\n const deleteOffering = async () => {\n if (!confirm(t('cpq.offerings.confirmDelete', 'Delete this offering and all its charges?'))) return\n try {\n const res = await fetch('/api/cpq/product-offerings', {\n method: 'DELETE',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ id: offeringId }),\n })\n if (res.ok) {\n router.push('/backend/cpq/offerings')\n } else {\n const d = await res.json()\n setError(d.error ?? 'Failed to delete')\n }\n } catch {\n setError('Failed to delete')\n }\n }\n\n // \u2500\u2500\u2500 Charge CRUD \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 loadPricingTables = async () => {\n if (pricingTables.length > 0) return\n const res = await fetch('/api/cpq/pricing-tables?pageSize=200')\n if (res.ok) {\n const data = await res.json()\n setPricingTables(data.items ?? [])\n }\n }\n\n const startEditCharge = (charge?: Charge) => {\n const editing = charge ? { ...charge } : { ...EMPTY_CHARGE }\n setEditingCharge(editing)\n loadPricingTables()\n }\n\n const saveCharge = async () => {\n if (!editingCharge) return\n setSaving(true)\n setError(null)\n try {\n const isEdit = !!editingCharge.id\n const payload = {\n ...editingCharge,\n offeringId,\n }\n const res = await fetch('/api/cpq/product-charges', {\n method: isEdit ? 'PUT' : 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n })\n if (!res.ok) {\n const d = await res.json()\n setError(d.error ?? 'Failed to save charge')\n return\n }\n // Reload offering to get updated charges\n const offeringRes = await fetch(`/api/cpq/product-offerings?id=${encodeURIComponent(offeringId)}`)\n if (offeringRes.ok) {\n const data = await offeringRes.json()\n setCharges(data.charges ?? [])\n }\n setEditingCharge(null)\n } catch {\n setError('Failed to save charge')\n } finally {\n setSaving(false)\n }\n }\n\n const deleteCharge = async (chargeId: string) => {\n if (!confirm('Delete this charge?')) return\n try {\n const res = await fetch('/api/cpq/product-charges', {\n method: 'DELETE',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ id: chargeId }),\n })\n if (res.ok) setCharges((prev) => prev.filter((c) => c.id !== chargeId))\n } catch {\n setError('Failed to delete charge')\n }\n }\n\n const selectedPricingTable = editingCharge?.pricingTableId\n ? pricingTables.find((pt) => pt.id === editingCharge.pricingTableId)\n : null\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\n\n const designTimeAttrs = attributes.filter((a) => a.resolutionTime === 'design_time')\n\n // \u2500\u2500\u2500 Render \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 (loading) {\n return <div className=\"text-sm text-muted-foreground\">{t('common.loading', 'Loading...')}</div>\n }\n\n return (\n <div className=\"space-y-6\">\n {/* Header */}\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <button\n onClick={() => router.push('/backend/cpq/offerings')}\n className=\"text-sm text-muted-foreground hover:text-foreground\"\n >\n \u2190 {t('common.back', 'Back')}\n </button>\n <h1 className=\"text-2xl font-bold\">\n {isNew ? t('cpq.offerings.new', 'New Offering') : form.name}\n </h1>\n {!isNew && (\n <Tag variant={lifecycleStatusMap[form.lifecycleStatus as LifecycleStatus] ?? 'neutral'} dot>\n {formatStatusLabel(form.lifecycleStatus)}\n </Tag>\n )}\n {specDetail && (\n <span className=\"text-sm text-muted-foreground\">\n Spec: <button onClick={() => router.push(`/backend/cpq/specifications/${specDetail.id}`)} className=\"text-primary hover:underline\">{specDetail.name}</button>\n </span>\n )}\n </div>\n {!isNew && (\n <div className=\"flex items-center gap-2\">\n {generalMode === 'view' && tab === 'general' && (\n <Button\n type=\"button\"\n onClick={() => {\n setFormSnapshot(form)\n setDesignTimeSnapshot(designTimeValues)\n setGeneralMode('edit')\n }}\n >\n {t('common.edit', 'Edit')}\n </Button>\n )}\n <Button type=\"button\" variant=\"destructive\" onClick={deleteOffering}>\n {t('common.delete', 'Delete')}\n </Button>\n </div>\n )}\n </div>\n\n {error && (\n <Alert variant=\"destructive\">{error}</Alert>\n )}\n\n {/* Tabs */}\n {!isNew && (\n <div className=\"flex gap-1 border-b\">\n {([\n 'general',\n 'charges',\n ...(form.offeringType === 'bundle' ? ['components' as const] : []),\n ] as const).map((t_) => (\n <button\n key={t_}\n onClick={() => setTab(t_ as typeof tab)}\n className={`px-4 py-2 text-sm font-medium border-b-2 transition-colors ${\n tab === t_ ? 'border-primary text-primary' : 'border-transparent text-muted-foreground hover:text-foreground'\n }`}\n >\n {t_ === 'general' && 'General'}\n {t_ === 'charges' && `Charges (${charges.length})`}\n {t_ === 'components' && `Components (${components.length})`}\n </button>\n ))}\n </div>\n )}\n\n {/* \u2500\u2500\u2500 General Tab / New Form \u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 {(isNew || tab === 'general') && (\n <div className=\"rounded-lg border bg-card p-6 space-y-4\">\n {isNew && (\n <div>\n <label className=\"block text-sm font-medium mb-1\">Specification</label>\n <select\n value={form.specId}\n onChange={(e) => {\n setForm({ ...form, specId: e.target.value })\n loadSpecAttributes(e.target.value)\n setDesignTimeValues({})\n }}\n className=\"w-full rounded-md border px-3 py-2 text-sm\"\n >\n <option value=\"\">Select a specification...</option>\n {specs.map((s) => (\n <option key={s.id} value={s.id}>{s.name} ({s.code})</option>\n ))}\n </select>\n </div>\n )}\n\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <label className=\"block text-sm font-medium mb-1\">{t('cpq.offerings.code', 'Code')}</label>\n {generalMode === 'view' && !isNew ? (\n <p className=\"text-sm font-mono py-2\">{form.code || '\u2014'}</p>\n ) : (\n <input\n type=\"text\"\n value={form.code}\n onChange={(e) => setForm({ ...form, code: e.target.value })}\n placeholder=\"e.g. gix-cloud-connect-aws\"\n className=\"w-full rounded-md border px-3 py-2 text-sm\"\n />\n )}\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">{t('cpq.offerings.name', 'Name')}</label>\n {generalMode === 'view' && !isNew ? (\n <p className=\"text-sm py-2\">{form.name || '\u2014'}</p>\n ) : (\n <input\n type=\"text\"\n value={form.name}\n onChange={(e) => setForm({ ...form, name: e.target.value })}\n className=\"w-full rounded-md border px-3 py-2 text-sm\"\n />\n )}\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">{t('cpq.offerings.lifecycleStatus', 'Lifecycle Status')}</label>\n {generalMode === 'view' && !isNew ? (\n <div className=\"py-2\">\n <Tag variant={lifecycleStatusMap[form.lifecycleStatus as LifecycleStatus] ?? 'neutral'} dot>\n {formatStatusLabel(form.lifecycleStatus)}\n </Tag>\n </div>\n ) : (\n <select\n value={form.lifecycleStatus}\n onChange={(e) => setForm({ ...form, lifecycleStatus: e.target.value })}\n className=\"w-full rounded-md border px-3 py-2 text-sm\"\n >\n <option value=\"draft\">Draft</option>\n <option value=\"active\">Active</option>\n <option value=\"deprecated\">Deprecated</option>\n </select>\n )}\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">{t('cpq.offerings.isActive', 'Is Active?')}</label>\n <div className=\"flex items-center h-[38px]\">\n {generalMode === 'view' && !isNew ? (\n <Tag variant={form.isActive ? 'success' : 'neutral'} dot>\n {form.isActive ? t('common.yes', 'Yes') : t('common.no', 'No')}\n </Tag>\n ) : (\n <input\n type=\"checkbox\"\n checked={form.isActive}\n onChange={(e) => setForm({ ...form, isActive: e.target.checked })}\n className=\"rounded border\"\n />\n )}\n </div>\n </div>\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">{t('cpq.offerings.description', 'Description')}</label>\n {generalMode === 'view' && !isNew ? (\n <p className=\"text-sm text-muted-foreground py-2 whitespace-pre-wrap\">{form.description || '\u2014'}</p>\n ) : (\n <textarea\n value={form.description ?? ''}\n onChange={(e) => setForm({ ...form, description: e.target.value })}\n rows={3}\n className=\"w-full rounded-md border px-3 py-2 text-sm\"\n />\n )}\n </div>\n\n {/* Design-time values */}\n {designTimeAttrs.length > 0 && (\n <div className=\"space-y-3\">\n <label className=\"block text-sm font-medium\">Design-Time Values</label>\n <div className=\"grid grid-cols-2 gap-3\">\n {designTimeAttrs.map((attr) => {\n const value = designTimeValues[attr.code]\n const isViewing = generalMode === 'view' && !isNew\n // Lookup the human label for select-type values so the\n // read-only view doesn't show raw codes.\n const optionLabel =\n (attr.attributeType === 'select' || attr.attributeType === 'enum') && attr.options\n ? attr.options.find((o) => o.value === value)?.label\n : undefined\n return (\n <div key={attr.code}>\n <label className=\"block text-xs font-medium mb-1\">\n {attr.name}\n {attr.isRequired && <span className=\"text-destructive ml-0.5\">*</span>}\n </label>\n {isViewing ? (\n <p className=\"text-sm py-2\">\n {value == null || value === '' ? (\n <span className=\"text-muted-foreground\">\u2014</span>\n ) : attr.attributeType === 'boolean' ? (\n <Tag variant={value ? 'success' : 'neutral'} dot>\n {value ? t('common.yes', 'Yes') : t('common.no', 'No')}\n </Tag>\n ) : (\n optionLabel ?? String(value)\n )}\n </p>\n ) : (attr.attributeType === 'select' || attr.attributeType === 'enum') && attr.options ? (\n <select\n value={String(value ?? '')}\n onChange={(e) => setDesignTimeValues({ ...designTimeValues, [attr.code]: e.target.value || null })}\n className=\"w-full rounded-md border px-2 py-1.5 text-sm\"\n >\n <option value=\"\">Select {attr.name}...</option>\n {attr.options.map((opt) => (\n <option key={opt.value} value={opt.value}>{opt.label}</option>\n ))}\n </select>\n ) : attr.attributeType === 'number' ? (\n <NumberInput\n value={typeof value === 'number' ? (value as number) : null}\n onChange={(n) => setDesignTimeValues({ ...designTimeValues, [attr.code]: n })}\n />\n ) : attr.attributeType === 'boolean' ? (\n <div className=\"pt-1\">\n <label className=\"flex items-center gap-1.5 text-sm\">\n <input\n type=\"checkbox\"\n checked={!!value}\n onChange={(e) => setDesignTimeValues({ ...designTimeValues, [attr.code]: e.target.checked })}\n className=\"rounded border\"\n />\n {attr.name}\n </label>\n </div>\n ) : (\n <input\n type=\"text\"\n value={String(value ?? '')}\n onChange={(e) => setDesignTimeValues({ ...designTimeValues, [attr.code]: e.target.value || null })}\n className=\"w-full rounded-md border px-2 py-1.5 text-sm\"\n placeholder={attr.helpText ?? undefined}\n />\n )}\n {attr.helpText && <p className=\"text-xs text-muted-foreground mt-0.5\">{attr.helpText}</p>}\n </div>\n )\n })}\n </div>\n </div>\n )}\n\n {/* In view mode the Edit button lives in the page header next to\n Delete (OM standard). Here we only render the Save/Cancel\n pair when actually editing. */}\n {!(generalMode === 'view' && !isNew) && (\n <div className=\"flex gap-3\">\n <Button\n type=\"button\"\n onClick={saveOffering}\n disabled={saving || !form.code || !form.name || (isNew && !form.specId)}\n >\n {saving ? t('common.saving', 'Saving...') : t('common.save', 'Save')}\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => {\n if (isNew) {\n router.push('/backend/cpq/offerings')\n return\n }\n if (formSnapshot) setForm(formSnapshot)\n if (designTimeSnapshot) setDesignTimeValues(designTimeSnapshot)\n setFormSnapshot(null)\n setDesignTimeSnapshot(null)\n setGeneralMode('view')\n }}\n >\n {t('common.cancel', 'Cancel')}\n </Button>\n </div>\n )}\n </div>\n )}\n\n {/* \u2500\u2500\u2500 Charges Tab \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 {tab === 'charges' && !isNew && (\n <div className=\"space-y-4\">\n <div className=\"flex justify-end\">\n <button\n onClick={() => startEditCharge()}\n 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\"\n >\n {t('cpq.offerings.addCharge', 'Add Charge')}\n </button>\n </div>\n\n {/* Charge edit form */}\n {editingCharge && (\n <div className=\"rounded-lg border bg-card p-4 space-y-3\">\n <h3 className=\"font-medium text-sm\">\n {editingCharge.id ? 'Edit Charge' : 'New Charge'}\n </h3>\n <div className=\"grid grid-cols-3 gap-3\">\n <div>\n <label className=\"block text-xs font-medium mb-1\">Code</label>\n <input type=\"text\" value={editingCharge.code} onChange={(e) => setEditingCharge({ ...editingCharge, code: e.target.value })} placeholder=\"e.g. mrc-monthly\" className=\"w-full rounded-md border px-2 py-1.5 text-sm\" />\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Name</label>\n <input type=\"text\" value={editingCharge.name} onChange={(e) => setEditingCharge({ ...editingCharge, name: e.target.value })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\" />\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Charge Type</label>\n <select value={editingCharge.chargeType} onChange={(e) => setEditingCharge({ ...editingCharge, chargeType: e.target.value })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\">\n <option value=\"mrc\">MRC (Monthly Recurring)</option>\n <option value=\"nrc\">NRC (Non-Recurring)</option>\n <option value=\"usage\">Usage</option>\n </select>\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Pricing Method</label>\n <select value={editingCharge.pricingMethod} onChange={(e) => {\n const method = e.target.value\n if (method === 'flat') {\n setEditingCharge({ ...editingCharge, pricingMethod: method, pricingTableId: null, priceColumnKey: null, quantityAttributeCode: null })\n } else {\n setEditingCharge({ ...editingCharge, pricingMethod: method, fixedPrice: null })\n }\n }} className=\"w-full rounded-md border px-2 py-1.5 text-sm\">\n <option value=\"flat\">Flat Price</option>\n <option value=\"per_unit\">Per Unit (table lookup)</option>\n <option value=\"tiered\">Tiered (table lookup)</option>\n </select>\n </div>\n {(editingCharge.pricingMethod === 'flat' || editingCharge.pricingMethod === 'fixed') ? (\n <>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Fixed Price <span className=\"text-destructive\">*</span></label>\n <input type=\"text\" value={editingCharge.fixedPrice ?? ''} onChange={(e) => setEditingCharge({ ...editingCharge, fixedPrice: e.target.value || null })} placeholder=\"0.00\" className=\"w-full rounded-md border px-2 py-1.5 text-sm\" />\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Currency <span className=\"text-destructive\">*</span></label>\n <input type=\"text\" value={editingCharge.currencyCode ?? 'USD'} onChange={(e) => setEditingCharge({ ...editingCharge, currencyCode: e.target.value || null })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\" />\n </div>\n </>\n ) : (\n <>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Pricing Table <span className=\"text-destructive\">*</span></label>\n <select value={editingCharge.pricingTableId ?? ''} onChange={(e) => setEditingCharge({ ...editingCharge, pricingTableId: e.target.value || null, priceColumnKey: null })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\">\n <option value=\"\">Select table...</option>\n {pricingTables.map((pt) => (\n <option key={pt.id} value={pt.id}>{pt.name} ({pt.code})</option>\n ))}\n </select>\n {pricingTables.length === 0 && (\n <p className=\"text-xs text-warning mt-0.5\">\n No pricing tables yet \u2014{' '}\n <a href=\"/backend/cpq/pricing-tables\" className=\"text-primary hover:underline\">create one</a>{' '}\n before using {editingCharge.pricingMethod} pricing.\n </p>\n )}\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Price Column <span className=\"text-destructive\">*</span></label>\n <select value={editingCharge.priceColumnKey ?? ''} onChange={(e) => setEditingCharge({ ...editingCharge, priceColumnKey: e.target.value || null })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\" disabled={!selectedPricingTable}>\n <option value=\"\">Select column...</option>\n {selectedPricingTable?.priceColumns.map((col) => (\n <option key={col.key} value={col.key}>{col.label}</option>\n ))}\n </select>\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Quantity Attribute <span className=\"text-destructive\">*</span></label>\n <select value={editingCharge.quantityAttributeCode ?? ''} onChange={(e) => setEditingCharge({ ...editingCharge, quantityAttributeCode: e.target.value || null })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\">\n <option value=\"\">Select attribute...</option>\n {attributes.filter((a) => a.attributeType === 'number').map((a) => (\n <option key={a.code} value={a.code}>{a.name} ({a.code})</option>\n ))}\n </select>\n <p className=\"text-xs text-muted-foreground mt-0.5\">Attribute whose value drives the quantity for pricing</p>\n {attributes.filter((a) => a.attributeType === 'number').length === 0 && form.specId && (\n <p className=\"text-xs text-warning mt-0.5\">\n Spec has no number attributes \u2014{' '}\n <a href={`/backend/cpq/specifications/${form.specId}`} className=\"text-primary hover:underline\">\n add one to the spec\n </a>{' '}\n first.\n </p>\n )}\n </div>\n </>\n )}\n <div>\n <label className=\"block text-xs font-medium mb-1\">Sort Order</label>\n <NumberInput\n integer\n value={editingCharge.sortOrder}\n onChange={(n) => setEditingCharge({ ...editingCharge, sortOrder: n ?? 0 })}\n />\n </div>\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Description</label>\n <input type=\"text\" value={editingCharge.description ?? ''} onChange={(e) => setEditingCharge({ ...editingCharge, description: e.target.value || null })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\" />\n </div>\n <div className=\"flex items-end gap-4\">\n <label className=\"flex items-center gap-1.5 text-sm\">\n <input type=\"checkbox\" checked={editingCharge.isActive} onChange={(e) => setEditingCharge({ ...editingCharge, isActive: e.target.checked })} className=\"rounded border\" />\n Active\n </label>\n </div>\n {(() => {\n const missing = chargeMissingFields(editingCharge)\n const blocked = saving || !editingCharge.code || !editingCharge.name || missing.length > 0\n return (\n <>\n {missing.length > 0 && (\n <Alert variant=\"destructive\">\n Missing required field{missing.length > 1 ? 's' : ''} for {editingCharge.pricingMethod} pricing: {missing.join(', ')}\n </Alert>\n )}\n <div className=\"flex gap-2\">\n <button onClick={saveCharge} disabled={blocked} className=\"inline-flex items-center rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed\">\n {saving ? 'Saving...' : 'Save'}\n </button>\n <button onClick={() => setEditingCharge(null)} className=\"inline-flex items-center rounded-md border px-3 py-1.5 text-sm font-medium hover:bg-muted\">Cancel</button>\n </div>\n </>\n )\n })()}\n </div>\n )}\n\n {/* Charges table */}\n {charges.length === 0 ? (\n <div className=\"rounded-lg border bg-card p-6 text-center text-sm text-muted-foreground\">\n No charges defined. Add recurring, non-recurring, or usage charges to this offering.\n </div>\n ) : (\n <div className=\"rounded-lg border\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b bg-muted/50\">\n <th className=\"px-4 py-3 text-left font-medium\">Code</th>\n <th className=\"px-4 py-3 text-left font-medium\">Name</th>\n <th className=\"px-4 py-3 text-left font-medium\">Type</th>\n <th className=\"px-4 py-3 text-left font-medium\">Pricing</th>\n <th className=\"px-4 py-3 text-left font-medium\">Price</th>\n <th className=\"px-4 py-3 text-left font-medium\">Active</th>\n <th className=\"px-4 py-3 text-right font-medium\">Actions</th>\n </tr>\n </thead>\n <tbody>\n {charges.map((charge) => {\n const incomplete = !isChargeComplete(charge)\n const tableRef = charge.pricingTableId\n ? pricingTables.find((pt) => pt.id === charge.pricingTableId)\n : null\n const qtyAttr = charge.quantityAttributeCode\n ? attributes.find((a) => a.code === charge.quantityAttributeCode)\n : null\n const isFlat = charge.pricingMethod === 'flat' || charge.pricingMethod === 'fixed'\n return (\n <tr key={charge.id} className=\"border-b\">\n <td className=\"px-4 py-3 font-mono text-xs\">{charge.code}</td>\n <td className=\"px-4 py-3\">\n {charge.name}\n {incomplete && (\n <Tag variant=\"error\" className=\"ml-2 px-2 text-[10px]\" dot>Incomplete</Tag>\n )}\n </td>\n <td className=\"px-4 py-3\">\n <Tag variant={chargeTypeMap[charge.chargeType as ChargeType] ?? 'neutral'} className=\"px-2 text-xs\">\n {charge.chargeType.toUpperCase()}\n </Tag>\n </td>\n <td className=\"px-4 py-3 text-xs\">{PRICING_METHOD_LABELS[charge.pricingMethod] ?? charge.pricingMethod}</td>\n <td className=\"px-4 py-3 text-xs\">\n {isFlat ? (\n charge.fixedPrice != null\n ? `${charge.currencyCode ?? 'USD'} ${charge.fixedPrice}`\n : <span className=\"text-muted-foreground\">\u2014</span>\n ) : (\n <div className=\"flex flex-col gap-0.5\">\n <span>\n <span className=\"text-muted-foreground\">Table:</span>{' '}\n {tableRef ? `${tableRef.name} \u2192 ${charge.priceColumnKey ?? '?'}` : <span className=\"text-destructive\">missing</span>}\n </span>\n <span>\n <span className=\"text-muted-foreground\">\u00D7 Qty:</span>{' '}\n {qtyAttr ? `${qtyAttr.name} (${qtyAttr.code})` : <span className=\"text-destructive\">missing</span>}\n </span>\n </div>\n )}\n </td>\n <td className=\"px-4 py-3\">{charge.isActive ? 'Yes' : 'No'}</td>\n <td className=\"px-4 py-3 text-right\">\n <button onClick={() => startEditCharge(charge)} className=\"text-xs text-primary hover:underline mr-2\">Edit</button>\n <button onClick={() => deleteCharge(charge.id)} className=\"text-xs text-destructive hover:underline\">Delete</button>\n </td>\n </tr>\n )\n })}\n </tbody>\n </table>\n </div>\n )}\n </div>\n )}\n\n {/* \u2500\u2500\u2500 Components Tab (bundle offerings) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */}\n {tab === 'components' && !isNew && form.offeringType === 'bundle' && (\n <div className=\"space-y-4\">\n {bundleSlots.length === 0 ? (\n <div className=\"rounded-lg border bg-card p-6 text-center text-sm text-muted-foreground\">\n No bundle slots defined on this specification. Add slots on the specification first.\n </div>\n ) : (\n <>\n {/* Group components by slot */}\n {bundleSlots.map((slot) => {\n const slotComponents = components.filter((c) => c.slotId === slot.id)\n return (\n <div key={slot.id} className=\"rounded-lg border bg-card overflow-hidden\">\n <div className=\"bg-muted/50 px-4 py-3 border-b flex items-center justify-between\">\n <div>\n <span className=\"font-medium text-sm\">{slot.name}</span>\n <Tag variant=\"info\" className=\"ml-2 px-2 text-[10px]\">\n {slot.componentGroup}\n </Tag>\n <span className=\"ml-2 text-xs text-muted-foreground\">\n {slot.cardinalityMin}..{slot.cardinalityMax ?? '\u221E'}\n </span>\n {slot.targetSpec && (\n <span className=\"ml-2 text-xs text-muted-foreground\">\u2192 {slot.targetSpec.name}</span>\n )}\n </div>\n <button\n onClick={async () => {\n setAddingComponent({ slotId: slot.id, childOfferingId: '', isDefault: false })\n if (!slotOfferings[slot.targetSpecId]) {\n const res = await fetch(`/api/cpq/product-offerings?specId=${encodeURIComponent(slot.targetSpecId)}&pageSize=100`)\n if (res.ok) {\n const d = await res.json()\n setSlotOfferings((prev) => ({ ...prev, [slot.targetSpecId]: d.items ?? [] }))\n }\n }\n }}\n className=\"inline-flex items-center justify-center rounded-md bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground hover:bg-primary/90\"\n >\n + Add Component\n </button>\n </div>\n\n {addingComponent?.slotId === slot.id && (\n <div className=\"p-4 border-b bg-muted/20 space-y-3\">\n <div className=\"grid grid-cols-3 gap-3\">\n <div className=\"col-span-2\">\n <label className=\"block text-xs font-medium mb-1\">Component Offering</label>\n <select\n value={addingComponent.childOfferingId}\n onChange={(e) => setAddingComponent({ ...addingComponent, childOfferingId: e.target.value })}\n className=\"w-full rounded-md border px-3 py-2 text-sm\"\n >\n <option value=\"\">\u2014 Select offering \u2014</option>\n {(slotOfferings[slot.targetSpecId] ?? []).map((o) => (\n <option key={o.id} value={o.id}>{o.name} ({o.code}){o.offeringType === 'bundle' ? ' [bundle]' : ''}</option>\n ))}\n </select>\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Default?</label>\n <div className=\"flex items-center h-[38px]\">\n <input\n type=\"checkbox\"\n checked={addingComponent.isDefault}\n onChange={(e) => setAddingComponent({ ...addingComponent, isDefault: e.target.checked })}\n className=\"rounded border\"\n />\n <span className=\"ml-2 text-xs text-muted-foreground\">Pre-selected in quote</span>\n </div>\n </div>\n </div>\n <div className=\"flex gap-2\">\n <button\n disabled={saving || !addingComponent.childOfferingId}\n onClick={async () => {\n setSaving(true)\n setError(null)\n try {\n const res = await fetch('/api/cpq/offering-components', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n offeringId,\n slotId: addingComponent.slotId,\n childOfferingId: addingComponent.childOfferingId,\n isDefault: addingComponent.isDefault,\n }),\n })\n if (!res.ok) {\n const d = await res.json()\n setError(d.error ?? 'Failed to add component')\n return\n }\n setAddingComponent(null)\n const compRes = await fetch(`/api/cpq/offering-components?offeringId=${offeringId}`)\n if (compRes.ok) {\n const d = await compRes.json()\n setComponents(d.items ?? [])\n }\n } catch {\n setError('Failed to add component')\n } finally {\n setSaving(false)\n }\n }}\n className=\"inline-flex items-center justify-center rounded-md bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50\"\n >\n {saving ? 'Adding...' : 'Add'}\n </button>\n <button\n onClick={() => setAddingComponent(null)}\n className=\"inline-flex items-center justify-center rounded-md border px-3 py-1.5 text-xs font-medium hover:bg-muted\"\n >\n Cancel\n </button>\n </div>\n </div>\n )}\n\n {slotComponents.length === 0 ? (\n <div className=\"p-4 text-center text-xs text-muted-foreground\">\n No components assigned to this slot\n {slot.cardinalityMin > 0 && (\n <span className=\"ml-1 text-status-warning-text font-medium\">(required: min {slot.cardinalityMin})</span>\n )}\n </div>\n ) : (\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b bg-muted/30\">\n <th className=\"px-4 py-2 text-left text-xs font-medium\">Offering</th>\n <th className=\"px-4 py-2 text-left text-xs font-medium\">Code</th>\n <th className=\"px-4 py-2 text-left text-xs font-medium\">Type</th>\n <th className=\"px-4 py-2 text-left text-xs font-medium\">Default</th>\n <th className=\"px-4 py-2 text-right text-xs font-medium\">Actions</th>\n </tr>\n </thead>\n <tbody>\n {slotComponents.map((comp) => (\n <tr key={comp.id} className=\"border-b last:border-0\">\n <td className=\"px-4 py-2.5 font-medium\">{comp.childOffering?.name ?? 'Unknown'}</td>\n <td className=\"px-4 py-2.5 text-muted-foreground text-xs\">{comp.childOffering?.code ?? '\u2014'}</td>\n <td className=\"px-4 py-2.5\">\n {comp.childOffering?.offeringType === 'bundle' ? (\n <Tag variant=\"brand\" className=\"px-2 text-[10px]\">bundle</Tag>\n ) : (\n <Tag variant=\"neutral\" className=\"px-2 text-[10px]\">simple</Tag>\n )}\n </td>\n <td className=\"px-4 py-2.5\">\n <button\n onClick={async () => {\n try {\n const res = await fetch('/api/cpq/offering-components', {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ id: comp.id, isDefault: !comp.isDefault }),\n })\n if (res.ok) {\n setComponents((prev) => prev.map((c) => c.id === comp.id ? { ...c, isDefault: !c.isDefault } : c))\n }\n } catch { /* ignore */ }\n }}\n className=\"cursor-pointer\"\n >\n <Tag variant={comp.isDefault ? 'success' : 'neutral'} className=\"px-2 text-[10px]\">\n {comp.isDefault ? 'Yes' : 'No'}\n </Tag>\n </button>\n </td>\n <td className=\"px-4 py-2.5 text-right\">\n <button\n onClick={async () => {\n if (!confirm('Remove this component from the bundle?')) return\n try {\n const res = await fetch('/api/cpq/offering-components', {\n method: 'DELETE',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ id: comp.id }),\n })\n if (res.ok) {\n setComponents((prev) => prev.filter((c) => c.id !== comp.id))\n } else {\n const d = await res.json()\n setError(d.error ?? 'Failed to remove')\n }\n } catch {\n setError('Failed to remove component')\n }\n }}\n className=\"text-xs text-destructive hover:underline\"\n >\n Remove\n </button>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n )}\n </div>\n )\n })}\n </>\n )}\n </div>\n )}\n </div>\n )\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,405 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { useT } from "@open-mercato/shared/lib/i18n/context";
5
+ import { useRouter } from "next/navigation";
6
+ import { Button } from "@open-mercato/ui/primitives/button";
7
+ import { Checkbox } from "@open-mercato/ui/primitives/checkbox";
8
+ import { Input } from "@open-mercato/ui/primitives/input";
9
+ import {
10
+ Select,
11
+ SelectContent,
12
+ SelectItem,
13
+ SelectTrigger,
14
+ SelectValue
15
+ } from "@open-mercato/ui/primitives/select";
16
+ import { flash } from "@open-mercato/ui/backend/FlashMessages";
17
+ import { Alert } from "@open-mercato/ui/primitives/alert";
18
+ import { Tag } from "@open-mercato/ui/primitives/tag";
19
+ import { CpqListView, useCpqListData } from "../../../components/CpqListView.js";
20
+ import { NumberInput } from "../../../components/NumberInput.js";
21
+ import {
22
+ chargeTypeMap,
23
+ formatStatusLabel,
24
+ lifecycleStatusMap
25
+ } from "../../../components/statusMaps.js";
26
+ const PAGE_SIZE = 50;
27
+ function ChargePopover({ charge }) {
28
+ const [open, setOpen] = React.useState(false);
29
+ const variant = chargeTypeMap[charge.chargeType] ?? "neutral";
30
+ return /* @__PURE__ */ jsxs(
31
+ "span",
32
+ {
33
+ className: "relative inline-flex",
34
+ onMouseEnter: () => setOpen(true),
35
+ onMouseLeave: () => setOpen(false),
36
+ children: [
37
+ /* @__PURE__ */ jsx(Tag, { variant, className: "cursor-default px-2 text-[10px]", children: charge.chargeType.toUpperCase() }),
38
+ open && /* @__PURE__ */ jsxs("div", { className: "absolute bottom-full left-1/2 -translate-x-1/2 mb-2 z-50 w-56 rounded-lg border bg-popover p-3 shadow-md text-popover-foreground text-xs space-y-1.5", children: [
39
+ /* @__PURE__ */ jsx("div", { className: "font-medium text-sm", children: charge.name }),
40
+ /* @__PURE__ */ jsx("div", { className: "text-muted-foreground font-mono", children: charge.code }),
41
+ charge.description && /* @__PURE__ */ jsx("div", { className: "text-muted-foreground", children: charge.description }),
42
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between pt-1 border-t", children: [
43
+ /* @__PURE__ */ jsxs("span", { children: [
44
+ "Pricing: ",
45
+ charge.pricingMethod
46
+ ] }),
47
+ charge.fixedPrice != null && /* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
48
+ charge.currencyCode ?? "USD",
49
+ " ",
50
+ charge.fixedPrice
51
+ ] })
52
+ ] }),
53
+ !charge.isActive && /* @__PURE__ */ jsx(Tag, { variant: "warning", dot: true, children: "Inactive" }),
54
+ /* @__PURE__ */ jsx("div", { className: "absolute left-1/2 -translate-x-1/2 top-full w-2 h-2 bg-popover border-b border-r rotate-45 -mt-1" })
55
+ ] })
56
+ ]
57
+ }
58
+ );
59
+ }
60
+ function buildFilterParams(values, params) {
61
+ if (typeof values.lifecycleStatus === "string" && values.lifecycleStatus) {
62
+ params.set("lifecycleStatus", values.lifecycleStatus);
63
+ }
64
+ if (typeof values.offeringType === "string" && values.offeringType) {
65
+ params.set("offeringType", values.offeringType);
66
+ }
67
+ if (values.isActive === true) params.set("isActive", "true");
68
+ if (values.isActive === false) params.set("isActive", "false");
69
+ }
70
+ function OfferingsListPage() {
71
+ const t = useT();
72
+ const router = useRouter();
73
+ const data = useCpqListData({
74
+ endpoint: "/api/cpq/product-offerings",
75
+ pageSize: PAGE_SIZE,
76
+ buildFilterParams,
77
+ loadErrorMessage: t("cpq.offerings.list.error.load", "Failed to load offerings")
78
+ });
79
+ const [bulkChargeOpen, setBulkChargeOpen] = React.useState(false);
80
+ const [bulkChargeTargets, setBulkChargeTargets] = React.useState([]);
81
+ const [chargeForm, setChargeForm] = React.useState({
82
+ code: "",
83
+ name: "",
84
+ description: "",
85
+ chargeType: "mrc"
86
+ });
87
+ const [chargePrices, setChargePrices] = React.useState({});
88
+ const [chargeCurrency, setChargeCurrency] = React.useState("USD");
89
+ const [saving, setSaving] = React.useState(false);
90
+ const [error, setError] = React.useState(null);
91
+ const lifecycleOptions = React.useMemo(
92
+ () => [
93
+ { value: "draft", label: t("cpq.offerings.lifecycle.draft", "Draft") },
94
+ { value: "active", label: t("cpq.offerings.lifecycle.active", "Active") },
95
+ { value: "deprecated", label: t("cpq.offerings.lifecycle.deprecated", "Deprecated") }
96
+ ],
97
+ [t]
98
+ );
99
+ const offeringTypeOptions = React.useMemo(
100
+ () => [
101
+ { value: "simple", label: t("cpq.offerings.type.simple", "Simple") },
102
+ { value: "bundle", label: t("cpq.offerings.type.bundle", "Bundle") }
103
+ ],
104
+ [t]
105
+ );
106
+ const filters = React.useMemo(
107
+ () => [
108
+ {
109
+ id: "lifecycleStatus",
110
+ label: t("cpq.offerings.filters.lifecycleStatus", "Lifecycle Status"),
111
+ type: "select",
112
+ options: lifecycleOptions
113
+ },
114
+ {
115
+ id: "offeringType",
116
+ label: t("cpq.offerings.filters.offeringType", "Type"),
117
+ type: "select",
118
+ options: offeringTypeOptions
119
+ },
120
+ {
121
+ id: "isActive",
122
+ label: t("cpq.offerings.filters.isActive", "Active"),
123
+ type: "checkbox"
124
+ }
125
+ ],
126
+ [lifecycleOptions, offeringTypeOptions, t]
127
+ );
128
+ const openBulkChargeForm = React.useCallback(
129
+ (targets) => {
130
+ setBulkChargeTargets(targets);
131
+ setChargeForm({ code: "", name: "", description: "", chargeType: "mrc" });
132
+ setChargePrices({});
133
+ setChargeCurrency("USD");
134
+ setError(null);
135
+ setBulkChargeOpen(true);
136
+ },
137
+ []
138
+ );
139
+ const saveChargesForSelected = React.useCallback(async () => {
140
+ const targets = bulkChargeTargets;
141
+ if (!targets.length || !chargeForm.code || !chargeForm.name) return;
142
+ setSaving(true);
143
+ setError(null);
144
+ try {
145
+ for (const offering of targets) {
146
+ const chargeCode = targets.length > 1 ? `${offering.code}--${chargeForm.code}` : chargeForm.code;
147
+ const payload = {
148
+ offeringId: offering.id,
149
+ code: chargeCode,
150
+ name: chargeForm.name,
151
+ description: chargeForm.description || null,
152
+ chargeType: chargeForm.chargeType,
153
+ pricingMethod: "flat",
154
+ fixedPrice: chargePrices[offering.id] || null,
155
+ currencyCode: chargeCurrency,
156
+ isActive: true,
157
+ sortOrder: 0
158
+ };
159
+ const res = await fetch("/api/cpq/product-charges", {
160
+ method: "POST",
161
+ headers: { "Content-Type": "application/json" },
162
+ body: JSON.stringify(payload)
163
+ });
164
+ if (!res.ok) {
165
+ const body = await res.json().catch(() => ({}));
166
+ setError(body.error ?? `Failed to save charge for ${offering.name}`);
167
+ setSaving(false);
168
+ return;
169
+ }
170
+ }
171
+ flash(t("cpq.offerings.flash.chargesCreated", "Charges created"), "success");
172
+ setBulkChargeOpen(false);
173
+ setBulkChargeTargets([]);
174
+ data.reload();
175
+ } catch {
176
+ setError("Failed to save charges");
177
+ } finally {
178
+ setSaving(false);
179
+ }
180
+ }, [
181
+ bulkChargeTargets,
182
+ chargeCurrency,
183
+ chargeForm,
184
+ chargePrices,
185
+ data,
186
+ t
187
+ ]);
188
+ const columns = React.useMemo(
189
+ () => [
190
+ {
191
+ accessorKey: "code",
192
+ header: t("cpq.offerings.code", "Code"),
193
+ cell: ({ row }) => /* @__PURE__ */ jsx("span", { className: "font-mono text-xs", children: row.original.code })
194
+ },
195
+ {
196
+ accessorKey: "name",
197
+ header: t("cpq.offerings.name", "Name"),
198
+ cell: ({ row }) => /* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
199
+ row.original.name,
200
+ row.original.offeringType === "bundle" && /* @__PURE__ */ jsx(Tag, { variant: "brand", className: "ml-2 px-2 text-[10px]", children: "bundle" })
201
+ ] })
202
+ },
203
+ {
204
+ accessorKey: "isActive",
205
+ header: t("cpq.offerings.isActive", "Is Active?"),
206
+ cell: ({ row }) => /* @__PURE__ */ jsx(Checkbox, { checked: row.original.isActive, disabled: true })
207
+ },
208
+ {
209
+ accessorKey: "lifecycleStatus",
210
+ header: t("cpq.offerings.lifecycleStatus", "Lifecycle Status"),
211
+ cell: ({ row }) => /* @__PURE__ */ jsx(Tag, { variant: lifecycleStatusMap[row.original.lifecycleStatus] ?? "neutral", dot: true, children: formatStatusLabel(row.original.lifecycleStatus) })
212
+ },
213
+ {
214
+ id: "charges",
215
+ header: t("cpq.offerings.charges", "Charges"),
216
+ cell: ({ row }) => {
217
+ const charges = row.original.charges ?? [];
218
+ if (charges.length === 0) return /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: "\u2014" });
219
+ return /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1", onClick: (e) => e.stopPropagation(), children: charges.map((ch) => /* @__PURE__ */ jsx(ChargePopover, { charge: ch }, ch.id)) });
220
+ }
221
+ },
222
+ {
223
+ accessorKey: "description",
224
+ header: t("cpq.offerings.description", "Description"),
225
+ cell: ({ row }) => /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: row.original.description ?? "\u2014" }),
226
+ meta: { truncate: true, maxWidth: 320 }
227
+ }
228
+ ],
229
+ [t]
230
+ );
231
+ const bulkActions = React.useMemo(
232
+ () => [
233
+ {
234
+ id: "add-charge",
235
+ label: t("cpq.offerings.bulk.addCharge", "Add Charge"),
236
+ onExecute: (selectedRows) => {
237
+ if (!selectedRows.length) return { ok: false };
238
+ openBulkChargeForm(selectedRows);
239
+ return { ok: true };
240
+ }
241
+ }
242
+ ],
243
+ [openBulkChargeForm, t]
244
+ );
245
+ const bulkChargeForm = bulkChargeOpen && bulkChargeTargets.length > 0 && /* @__PURE__ */ jsxs("div", { className: "rounded-lg border bg-card p-5 space-y-4", children: [
246
+ /* @__PURE__ */ jsxs("h4", { className: "font-medium text-sm", children: [
247
+ t("cpq.offerings.bulk.formTitle", "New Flat-Price Charge for"),
248
+ " ",
249
+ bulkChargeTargets.length,
250
+ " ",
251
+ bulkChargeTargets.length > 1 ? t("cpq.offerings.bulk.offeringsPlural", "offerings") : t("cpq.offerings.bulk.offeringsSingular", "offering")
252
+ ] }),
253
+ /* @__PURE__ */ jsxs(Alert, { children: [
254
+ "Bulk creation supports ",
255
+ /* @__PURE__ */ jsx("strong", { children: "flat pricing only" }),
256
+ ". For ",
257
+ /* @__PURE__ */ jsx("em", { children: "per unit" }),
258
+ " or ",
259
+ /* @__PURE__ */ jsx("em", { children: "tiered" }),
260
+ " pricing, open each offering individually \u2014 those methods need a pricing table and a numeric attribute that lives on the offering's spec, which usually differs between offerings."
261
+ ] }),
262
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-3", children: [
263
+ /* @__PURE__ */ jsxs("div", { children: [
264
+ /* @__PURE__ */ jsx("label", { className: "block text-xs font-medium mb-1", children: "Code" }),
265
+ /* @__PURE__ */ jsx(
266
+ Input,
267
+ {
268
+ value: chargeForm.code,
269
+ onChange: (e) => setChargeForm({ ...chargeForm, code: e.target.value }),
270
+ placeholder: "e.g. mrc-monthly"
271
+ }
272
+ )
273
+ ] }),
274
+ /* @__PURE__ */ jsxs("div", { children: [
275
+ /* @__PURE__ */ jsx("label", { className: "block text-xs font-medium mb-1", children: "Name" }),
276
+ /* @__PURE__ */ jsx(
277
+ Input,
278
+ {
279
+ value: chargeForm.name,
280
+ onChange: (e) => setChargeForm({ ...chargeForm, name: e.target.value }),
281
+ placeholder: "e.g. Monthly Recurring"
282
+ }
283
+ )
284
+ ] }),
285
+ /* @__PURE__ */ jsxs("div", { children: [
286
+ /* @__PURE__ */ jsx("label", { className: "block text-xs font-medium mb-1", children: "Type" }),
287
+ /* @__PURE__ */ jsxs(
288
+ Select,
289
+ {
290
+ value: chargeForm.chargeType,
291
+ onValueChange: (value) => setChargeForm({ ...chargeForm, chargeType: value }),
292
+ children: [
293
+ /* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, {}) }),
294
+ /* @__PURE__ */ jsxs(SelectContent, { children: [
295
+ /* @__PURE__ */ jsx(SelectItem, { value: "nrc", children: "NRC (Non-Recurring)" }),
296
+ /* @__PURE__ */ jsx(SelectItem, { value: "mrc", children: "MRC (Monthly Recurring)" }),
297
+ /* @__PURE__ */ jsx(SelectItem, { value: "usage", children: "Usage" })
298
+ ] })
299
+ ]
300
+ }
301
+ )
302
+ ] })
303
+ ] }),
304
+ /* @__PURE__ */ jsxs("div", { children: [
305
+ /* @__PURE__ */ jsx("label", { className: "block text-xs font-medium mb-1", children: "Description" }),
306
+ /* @__PURE__ */ jsx(
307
+ Input,
308
+ {
309
+ value: chargeForm.description,
310
+ onChange: (e) => setChargeForm({ ...chargeForm, description: e.target.value }),
311
+ placeholder: "User-facing charge description"
312
+ }
313
+ )
314
+ ] }),
315
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
316
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
317
+ /* @__PURE__ */ jsx("label", { className: "text-xs font-medium", children: "Currency" }),
318
+ /* @__PURE__ */ jsx(
319
+ Input,
320
+ {
321
+ value: chargeCurrency,
322
+ onChange: (e) => setChargeCurrency(e.target.value.toUpperCase()),
323
+ maxLength: 3,
324
+ className: "w-20"
325
+ }
326
+ )
327
+ ] }),
328
+ /* @__PURE__ */ jsx("div", { className: "rounded border", children: /* @__PURE__ */ jsxs("table", { className: "w-full text-sm", children: [
329
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { className: "border-b bg-muted/30", children: [
330
+ /* @__PURE__ */ jsx("th", { className: "px-3 py-2 text-left font-medium text-xs", children: "Offering" }),
331
+ /* @__PURE__ */ jsxs("th", { className: "px-3 py-2 text-left font-medium text-xs", children: [
332
+ "Price (",
333
+ chargeCurrency,
334
+ ")"
335
+ ] })
336
+ ] }) }),
337
+ /* @__PURE__ */ jsx("tbody", { children: bulkChargeTargets.map((o) => /* @__PURE__ */ jsxs("tr", { className: "border-b last:border-0", children: [
338
+ /* @__PURE__ */ jsxs("td", { className: "px-3 py-2 font-medium text-xs", children: [
339
+ o.name,
340
+ " ",
341
+ /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground font-mono", children: [
342
+ "(",
343
+ o.code,
344
+ ")"
345
+ ] })
346
+ ] }),
347
+ /* @__PURE__ */ jsx("td", { className: "px-3 py-2", children: /* @__PURE__ */ jsx(
348
+ NumberInput,
349
+ {
350
+ value: chargePrices[o.id] === void 0 || chargePrices[o.id] === "" ? null : Number(chargePrices[o.id]),
351
+ onChange: (n) => setChargePrices({ ...chargePrices, [o.id]: n == null ? "" : String(n) }),
352
+ placeholder: "0.00",
353
+ className: "w-32"
354
+ }
355
+ ) })
356
+ ] }, o.id)) })
357
+ ] }) })
358
+ ] }),
359
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-2 pt-1", children: [
360
+ /* @__PURE__ */ jsx(
361
+ Button,
362
+ {
363
+ type: "button",
364
+ onClick: saveChargesForSelected,
365
+ disabled: saving || !chargeForm.code || !chargeForm.name,
366
+ children: saving ? "Saving..." : `Create Charge for ${bulkChargeTargets.length} Offering${bulkChargeTargets.length > 1 ? "s" : ""}`
367
+ }
368
+ ),
369
+ /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", onClick: () => setBulkChargeOpen(false), children: "Cancel" })
370
+ ] })
371
+ ] });
372
+ const toolbarContent = /* @__PURE__ */ jsxs(Fragment, { children: [
373
+ error && /* @__PURE__ */ jsx(Alert, { variant: "destructive", children: error }),
374
+ bulkChargeForm
375
+ ] });
376
+ return /* @__PURE__ */ jsx(
377
+ CpqListView,
378
+ {
379
+ title: t("cpq.offerings.list.title", "Product Offerings"),
380
+ tableId: "cpq.offerings.list",
381
+ data,
382
+ columns,
383
+ filters,
384
+ pageSize: PAGE_SIZE,
385
+ searchPlaceholder: t("cpq.offerings.search.placeholder", "Search offerings..."),
386
+ actions: /* @__PURE__ */ jsx(Button, { asChild: true, children: /* @__PURE__ */ jsx("a", { href: "/backend/cpq/offerings/new", children: t("cpq.offerings.add", "New Offering") }) }),
387
+ bulkActions,
388
+ crud: {
389
+ endpoint: "/api/cpq/product-offerings",
390
+ entityName: t("cpq.offerings.entityName", "offering"),
391
+ editHref: (row) => `/backend/cpq/offerings/${row.id}`
392
+ },
393
+ onRowClick: (row) => router.push(`/backend/cpq/offerings/${row.id}`),
394
+ toolbarContent,
395
+ emptyState: /* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-card p-6 text-center text-sm text-muted-foreground", children: t(
396
+ "cpq.offerings.empty",
397
+ "No product offerings found. Create one to define a sellable variant of a product specification."
398
+ ) })
399
+ }
400
+ );
401
+ }
402
+ export {
403
+ OfferingsListPage as default
404
+ };
405
+ //# sourceMappingURL=page.js.map