@mohasinac/appkit 2.6.2 → 2.6.4

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 (607) hide show
  1. package/dist/_internal/server/features/account/data.js +2 -2
  2. package/dist/_internal/server/features/bundles/data.d.ts +26 -6
  3. package/dist/_internal/server/features/bundles/data.js +41 -6
  4. package/dist/_internal/server/features/bundles/index.d.ts +3 -2
  5. package/dist/_internal/server/features/bundles/index.js +4 -2
  6. package/dist/_internal/server/features/bundles/metadata.d.ts +20 -0
  7. package/dist/_internal/server/features/bundles/metadata.js +46 -0
  8. package/dist/_internal/server/features/bundles/og.d.ts +38 -0
  9. package/dist/_internal/server/features/bundles/og.js +122 -0
  10. package/dist/_internal/server/features/checkout/actions.js +192 -133
  11. package/dist/_internal/server/features/checkout/bundle-expansion.d.ts +57 -0
  12. package/dist/_internal/server/features/checkout/bundle-expansion.js +70 -0
  13. package/dist/_internal/server/features/checkout/prize-bundle-gates.d.ts +5 -15
  14. package/dist/_internal/server/features/checkout/prize-bundle-gates.js +5 -21
  15. package/dist/_internal/server/features/media/contextGuards.js +15 -1
  16. package/dist/_internal/server/features/payouts/actions.d.ts +19 -0
  17. package/dist/_internal/server/features/payouts/actions.js +38 -0
  18. package/dist/_internal/server/features/products/data.js +1 -2
  19. package/dist/_internal/server/features/raffle/actions.d.ts +11 -0
  20. package/dist/_internal/server/features/raffle/actions.js +31 -0
  21. package/dist/_internal/server/features/refunds/actions.d.ts +31 -0
  22. package/dist/_internal/server/features/refunds/actions.js +77 -0
  23. package/dist/_internal/server/jobs/core/adminAnalytics.d.ts +28 -0
  24. package/dist/_internal/server/jobs/core/adminAnalytics.js +98 -0
  25. package/dist/_internal/server/jobs/core/assignSpinPrize.d.ts +19 -0
  26. package/dist/_internal/server/jobs/core/assignSpinPrize.js +81 -0
  27. package/dist/_internal/server/jobs/core/auctionSettlement.d.ts +2 -0
  28. package/dist/_internal/server/jobs/core/auctionSettlement.js +70 -0
  29. package/dist/_internal/server/jobs/core/autoPayoutEligibility.d.ts +2 -0
  30. package/dist/_internal/server/jobs/core/autoPayoutEligibility.js +109 -0
  31. package/dist/_internal/server/jobs/core/bundleStockSync.d.ts +10 -0
  32. package/dist/_internal/server/jobs/core/bundleStockSync.js +71 -0
  33. package/dist/_internal/server/jobs/core/cartPrune.d.ts +2 -0
  34. package/dist/_internal/server/jobs/core/cartPrune.js +13 -0
  35. package/dist/_internal/server/jobs/core/cleanupRtdbEvents.d.ts +2 -0
  36. package/dist/_internal/server/jobs/core/cleanupRtdbEvents.js +45 -0
  37. package/dist/_internal/server/jobs/core/countersReconcile.d.ts +2 -0
  38. package/dist/_internal/server/jobs/core/countersReconcile.js +107 -0
  39. package/dist/_internal/server/jobs/core/couponExpiry.d.ts +2 -0
  40. package/dist/_internal/server/jobs/core/couponExpiry.js +13 -0
  41. package/dist/_internal/server/jobs/core/dailyDataCleanup.d.ts +2 -0
  42. package/dist/_internal/server/jobs/core/dailyDataCleanup.js +20 -0
  43. package/dist/_internal/server/jobs/core/index.d.ts +44 -0
  44. package/dist/_internal/server/jobs/core/index.js +47 -0
  45. package/dist/_internal/server/jobs/core/listingProcessor.d.ts +30 -0
  46. package/dist/_internal/server/jobs/core/listingProcessor.js +138 -0
  47. package/dist/_internal/server/jobs/core/mediaTmpCleanup.d.ts +14 -0
  48. package/dist/_internal/server/jobs/core/mediaTmpCleanup.js +68 -0
  49. package/dist/_internal/server/jobs/core/notificationPrune.d.ts +2 -0
  50. package/dist/_internal/server/jobs/core/notificationPrune.js +13 -0
  51. package/dist/_internal/server/jobs/core/offerExpiry.d.ts +2 -0
  52. package/dist/_internal/server/jobs/core/offerExpiry.js +50 -0
  53. package/dist/_internal/server/jobs/core/onBidPlaced.d.ts +15 -0
  54. package/dist/_internal/server/jobs/core/onBidPlaced.js +59 -0
  55. package/dist/_internal/server/jobs/core/onCategoryWrite.d.ts +14 -0
  56. package/dist/_internal/server/jobs/core/onCategoryWrite.js +134 -0
  57. package/dist/_internal/server/jobs/core/onOrderCreate.d.ts +18 -0
  58. package/dist/_internal/server/jobs/core/onOrderCreate.js +78 -0
  59. package/dist/_internal/server/jobs/core/onOrderStatusChange.d.ts +19 -0
  60. package/dist/_internal/server/jobs/core/onOrderStatusChange.js +139 -0
  61. package/dist/_internal/server/jobs/core/onProductStockChange.d.ts +23 -0
  62. package/dist/_internal/server/jobs/core/onProductStockChange.js +130 -0
  63. package/dist/_internal/server/jobs/core/onProductWrite.d.ts +12 -0
  64. package/dist/_internal/server/jobs/core/onProductWrite.js +94 -0
  65. package/dist/_internal/server/jobs/core/onReviewWrite.d.ts +7 -0
  66. package/dist/_internal/server/jobs/core/onReviewWrite.js +49 -0
  67. package/dist/_internal/server/jobs/core/onStoreWrite.d.ts +12 -0
  68. package/dist/_internal/server/jobs/core/onStoreWrite.js +7 -0
  69. package/dist/_internal/server/jobs/core/payoutBatch.d.ts +8 -0
  70. package/dist/_internal/server/jobs/core/payoutBatch.js +102 -0
  71. package/dist/_internal/server/jobs/core/pendingOrderTimeout.d.ts +2 -0
  72. package/dist/_internal/server/jobs/core/pendingOrderTimeout.js +27 -0
  73. package/dist/_internal/server/jobs/core/positionsReconcile.d.ts +7 -0
  74. package/dist/_internal/server/jobs/core/positionsReconcile.js +87 -0
  75. package/dist/_internal/server/jobs/core/prizeRevealClose.d.ts +2 -0
  76. package/dist/_internal/server/jobs/core/prizeRevealClose.js +22 -0
  77. package/dist/_internal/server/jobs/core/prizeRevealExpiry.d.ts +2 -0
  78. package/dist/_internal/server/jobs/core/prizeRevealExpiry.js +50 -0
  79. package/dist/_internal/server/jobs/core/prizeRevealOpen.d.ts +2 -0
  80. package/dist/_internal/server/jobs/core/prizeRevealOpen.js +56 -0
  81. package/dist/_internal/server/jobs/core/prizeRevealReminder.d.ts +2 -0
  82. package/dist/_internal/server/jobs/core/prizeRevealReminder.js +38 -0
  83. package/dist/_internal/server/jobs/core/productStatsSync.d.ts +8 -0
  84. package/dist/_internal/server/jobs/core/productStatsSync.js +36 -0
  85. package/dist/_internal/server/jobs/core/promotions.d.ts +12 -0
  86. package/dist/_internal/server/jobs/core/promotions.js +43 -0
  87. package/dist/_internal/server/jobs/core/storeAnalytics.d.ts +30 -0
  88. package/dist/_internal/server/jobs/core/storeAnalytics.js +109 -0
  89. package/dist/_internal/server/jobs/core/triggerEventRaffle.d.ts +19 -0
  90. package/dist/_internal/server/jobs/core/triggerEventRaffle.js +86 -0
  91. package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.d.ts +6 -0
  92. package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.js +85 -0
  93. package/dist/_internal/server/jobs/handlers/adminAnalytics.d.ts +2 -26
  94. package/dist/_internal/server/jobs/handlers/adminAnalytics.js +2 -98
  95. package/dist/_internal/server/jobs/handlers/assignSpinPrize.d.ts +1 -22
  96. package/dist/_internal/server/jobs/handlers/assignSpinPrize.js +2 -86
  97. package/dist/_internal/server/jobs/handlers/auctionSettlement.js +2 -70
  98. package/dist/_internal/server/jobs/handlers/autoPayoutEligibility.js +2 -110
  99. package/dist/_internal/server/jobs/handlers/bundleStockSync.d.ts +0 -16
  100. package/dist/_internal/server/jobs/handlers/bundleStockSync.js +2 -80
  101. package/dist/_internal/server/jobs/handlers/cartPrune.js +2 -13
  102. package/dist/_internal/server/jobs/handlers/cleanupRtdbEvents.js +2 -45
  103. package/dist/_internal/server/jobs/handlers/countersReconcile.js +2 -109
  104. package/dist/_internal/server/jobs/handlers/couponExpiry.js +2 -13
  105. package/dist/_internal/server/jobs/handlers/dailyDataCleanup.js +2 -20
  106. package/dist/_internal/server/jobs/handlers/listingProcessor.d.ts +3 -28
  107. package/dist/_internal/server/jobs/handlers/listingProcessor.js +3 -138
  108. package/dist/_internal/server/jobs/handlers/mediaTmpCleanup.d.ts +0 -12
  109. package/dist/_internal/server/jobs/handlers/mediaTmpCleanup.js +2 -69
  110. package/dist/_internal/server/jobs/handlers/notificationPrune.js +2 -13
  111. package/dist/_internal/server/jobs/handlers/offerExpiry.js +2 -50
  112. package/dist/_internal/server/jobs/handlers/onBidPlaced.d.ts +1 -10
  113. package/dist/_internal/server/jobs/handlers/onBidPlaced.js +2 -56
  114. package/dist/_internal/server/jobs/handlers/onCategoryWrite.d.ts +1 -8
  115. package/dist/_internal/server/jobs/handlers/onCategoryWrite.js +6 -134
  116. package/dist/_internal/server/jobs/handlers/onOrderCreate.d.ts +1 -12
  117. package/dist/_internal/server/jobs/handlers/onOrderCreate.js +2 -76
  118. package/dist/_internal/server/jobs/handlers/onOrderStatusChange.d.ts +1 -12
  119. package/dist/_internal/server/jobs/handlers/onOrderStatusChange.js +2 -139
  120. package/dist/_internal/server/jobs/handlers/onProductStockChange.d.ts +0 -13
  121. package/dist/_internal/server/jobs/handlers/onProductStockChange.js +7 -134
  122. package/dist/_internal/server/jobs/handlers/onProductWrite.d.ts +1 -6
  123. package/dist/_internal/server/jobs/handlers/onProductWrite.js +6 -106
  124. package/dist/_internal/server/jobs/handlers/onReviewWrite.js +2 -49
  125. package/dist/_internal/server/jobs/handlers/onStoreWrite.d.ts +1 -8
  126. package/dist/_internal/server/jobs/handlers/onStoreWrite.js +7 -8
  127. package/dist/_internal/server/jobs/handlers/payoutBatch.d.ts +0 -9
  128. package/dist/_internal/server/jobs/handlers/payoutBatch.js +2 -104
  129. package/dist/_internal/server/jobs/handlers/pendingOrderTimeout.d.ts +0 -6
  130. package/dist/_internal/server/jobs/handlers/pendingOrderTimeout.js +2 -33
  131. package/dist/_internal/server/jobs/handlers/positionsReconcile.d.ts +0 -5
  132. package/dist/_internal/server/jobs/handlers/positionsReconcile.js +2 -87
  133. package/dist/_internal/server/jobs/handlers/prizeRevealClose.d.ts +0 -7
  134. package/dist/_internal/server/jobs/handlers/prizeRevealClose.js +2 -29
  135. package/dist/_internal/server/jobs/handlers/prizeRevealExpiry.d.ts +0 -8
  136. package/dist/_internal/server/jobs/handlers/prizeRevealExpiry.js +2 -58
  137. package/dist/_internal/server/jobs/handlers/prizeRevealOpen.d.ts +0 -8
  138. package/dist/_internal/server/jobs/handlers/prizeRevealOpen.js +2 -65
  139. package/dist/_internal/server/jobs/handlers/prizeRevealReminder.d.ts +0 -7
  140. package/dist/_internal/server/jobs/handlers/prizeRevealReminder.js +2 -45
  141. package/dist/_internal/server/jobs/handlers/productStatsSync.d.ts +0 -6
  142. package/dist/_internal/server/jobs/handlers/productStatsSync.js +2 -36
  143. package/dist/_internal/server/jobs/handlers/promotions.d.ts +2 -10
  144. package/dist/_internal/server/jobs/handlers/promotions.js +2 -43
  145. package/dist/_internal/server/jobs/handlers/storeAnalytics.d.ts +2 -28
  146. package/dist/_internal/server/jobs/handlers/storeAnalytics.js +2 -109
  147. package/dist/_internal/server/jobs/handlers/triggerEventRaffle.d.ts +1 -28
  148. package/dist/_internal/server/jobs/handlers/triggerEventRaffle.js +2 -94
  149. package/dist/_internal/server/jobs/handlers/weeklyPayoutEligibility.d.ts +0 -6
  150. package/dist/_internal/server/jobs/handlers/weeklyPayoutEligibility.js +2 -87
  151. package/dist/_internal/server/jobs/index.d.ts +1 -0
  152. package/dist/_internal/server/jobs/index.js +1 -0
  153. package/dist/_internal/server/jobs/runtime/adapters/firebase.js +21 -0
  154. package/dist/_internal/shared/actions/action-registry.d.ts +84 -0
  155. package/dist/_internal/shared/actions/action-registry.js +160 -0
  156. package/dist/_internal/shared/checkout/rules/_defaults.d.ts +3 -0
  157. package/dist/_internal/shared/checkout/rules/_defaults.js +22 -0
  158. package/dist/_internal/shared/checkout/rules/_limits.d.ts +19 -0
  159. package/dist/_internal/shared/checkout/rules/_limits.js +19 -0
  160. package/dist/_internal/shared/checkout/rules/_registry.d.ts +44 -0
  161. package/dist/_internal/shared/checkout/rules/_registry.js +87 -0
  162. package/dist/_internal/shared/checkout/rules/auction.rule.d.ts +2 -0
  163. package/dist/_internal/shared/checkout/rules/auction.rule.js +10 -0
  164. package/dist/_internal/shared/checkout/rules/bundle.rule.d.ts +11 -0
  165. package/dist/_internal/shared/checkout/rules/bundle.rule.js +6 -0
  166. package/dist/_internal/shared/checkout/rules/classified.rule.d.ts +9 -0
  167. package/dist/_internal/shared/checkout/rules/classified.rule.js +9 -0
  168. package/dist/_internal/shared/checkout/rules/digital-code.rule.d.ts +8 -0
  169. package/dist/_internal/shared/checkout/rules/digital-code.rule.js +6 -0
  170. package/dist/_internal/shared/checkout/rules/index.d.ts +12 -0
  171. package/dist/_internal/shared/checkout/rules/index.js +12 -0
  172. package/dist/_internal/shared/checkout/rules/live.rule.d.ts +10 -0
  173. package/dist/_internal/shared/checkout/rules/live.rule.js +6 -0
  174. package/dist/_internal/shared/checkout/rules/offer.rule.d.ts +2 -0
  175. package/dist/_internal/shared/checkout/rules/offer.rule.js +9 -0
  176. package/dist/_internal/shared/checkout/rules/preorder.rule.d.ts +2 -0
  177. package/dist/_internal/shared/checkout/rules/preorder.rule.js +28 -0
  178. package/dist/_internal/shared/checkout/rules/prize-draw.rule.d.ts +2 -0
  179. package/dist/_internal/shared/checkout/rules/prize-draw.rule.js +65 -0
  180. package/dist/_internal/shared/checkout/rules/standard.rule.d.ts +2 -0
  181. package/dist/_internal/shared/checkout/rules/standard.rule.js +5 -0
  182. package/dist/_internal/shared/checkout/rules/types.d.ts +125 -0
  183. package/dist/_internal/shared/checkout/rules/types.js +13 -0
  184. package/dist/_internal/shared/features/cart/schema.d.ts +6 -6
  185. package/dist/_internal/shared/features/categories/bundle-copy.d.ts +123 -0
  186. package/dist/_internal/shared/features/categories/bundle-copy.js +134 -0
  187. package/dist/_internal/shared/features/categories/bundle-schemas.d.ts +318 -0
  188. package/dist/_internal/shared/features/categories/bundle-schemas.js +55 -0
  189. package/dist/_internal/shared/features/orders/refund-copy.d.ts +36 -0
  190. package/dist/_internal/shared/features/orders/refund-copy.js +40 -0
  191. package/dist/_internal/shared/features/orders/schema.d.ts +4 -4
  192. package/dist/_internal/shared/features/products/schema.d.ts +8 -8
  193. package/dist/_internal/shared/listing-types/_registry.d.ts +27 -0
  194. package/dist/_internal/shared/listing-types/_registry.js +8 -0
  195. package/dist/_internal/shared/listing-types/action-tracker.d.ts +41 -0
  196. package/dist/_internal/shared/listing-types/action-tracker.js +70 -0
  197. package/dist/_internal/shared/listing-types/capabilities.js +25 -0
  198. package/dist/_internal/shared/listing-types/cart-shipping.d.ts +37 -0
  199. package/dist/_internal/shared/listing-types/cart-shipping.js +46 -0
  200. package/dist/_internal/shared/listing-types/classified/config.d.ts +7 -0
  201. package/dist/_internal/shared/listing-types/classified/config.js +8 -0
  202. package/dist/_internal/shared/listing-types/classified/ctas.d.ts +1 -0
  203. package/dist/_internal/shared/listing-types/classified/ctas.js +3 -0
  204. package/dist/_internal/shared/listing-types/classified/og.d.ts +1 -0
  205. package/dist/_internal/shared/listing-types/classified/og.js +1 -0
  206. package/dist/_internal/shared/listing-types/classified/schema.d.ts +1 -0
  207. package/dist/_internal/shared/listing-types/classified/schema.js +1 -0
  208. package/dist/_internal/shared/listing-types/classified/seed-factory.d.ts +1 -0
  209. package/dist/_internal/shared/listing-types/classified/seed-factory.js +1 -0
  210. package/dist/_internal/shared/listing-types/digital-code/config.d.ts +7 -0
  211. package/dist/_internal/shared/listing-types/digital-code/config.js +8 -0
  212. package/dist/_internal/shared/listing-types/digital-code/ctas.d.ts +1 -0
  213. package/dist/_internal/shared/listing-types/digital-code/ctas.js +3 -0
  214. package/dist/_internal/shared/listing-types/digital-code/og.d.ts +1 -0
  215. package/dist/_internal/shared/listing-types/digital-code/og.js +1 -0
  216. package/dist/_internal/shared/listing-types/digital-code/schema.d.ts +1 -0
  217. package/dist/_internal/shared/listing-types/digital-code/schema.js +1 -0
  218. package/dist/_internal/shared/listing-types/digital-code/seed-factory.d.ts +1 -0
  219. package/dist/_internal/shared/listing-types/digital-code/seed-factory.js +1 -0
  220. package/dist/_internal/shared/listing-types/feature-flags.d.ts +34 -0
  221. package/dist/_internal/shared/listing-types/feature-flags.js +45 -0
  222. package/dist/_internal/shared/listing-types/live/config.d.ts +7 -0
  223. package/dist/_internal/shared/listing-types/live/config.js +8 -0
  224. package/dist/_internal/shared/listing-types/live/ctas.d.ts +1 -0
  225. package/dist/_internal/shared/listing-types/live/ctas.js +3 -0
  226. package/dist/_internal/shared/listing-types/live/og.d.ts +1 -0
  227. package/dist/_internal/shared/listing-types/live/og.js +1 -0
  228. package/dist/_internal/shared/listing-types/live/schema.d.ts +1 -0
  229. package/dist/_internal/shared/listing-types/live/schema.js +1 -0
  230. package/dist/_internal/shared/listing-types/live/seed-factory.d.ts +1 -0
  231. package/dist/_internal/shared/listing-types/live/seed-factory.js +1 -0
  232. package/dist/_internal/shared/media/limits.js +8 -0
  233. package/dist/client.d.ts +6 -1
  234. package/dist/client.js +14 -1
  235. package/dist/configs/next.js +7 -0
  236. package/dist/constants/api-endpoints.d.ts +6 -0
  237. package/dist/constants/api-endpoints.js +4 -0
  238. package/dist/core/hooks/useSyncManager.js +13 -1
  239. package/dist/core/unit-of-work.d.ts +1 -1
  240. package/dist/core/unit-of-work.js +2 -2
  241. package/dist/features/account/actions/address-actions.d.ts +1 -1
  242. package/dist/features/account/actions/address-actions.js +15 -7
  243. package/dist/features/account/schemas/firestore.d.ts +8 -43
  244. package/dist/features/account/schemas/firestore.js +8 -54
  245. package/dist/features/account/schemas/index.d.ts +6 -6
  246. package/dist/features/account/server.d.ts +1 -1
  247. package/dist/features/account/server.js +3 -1
  248. package/dist/features/addresses/index.d.ts +2 -0
  249. package/dist/features/addresses/index.js +2 -0
  250. package/dist/features/addresses/repository/addresses.repository.d.ts +29 -0
  251. package/dist/features/addresses/repository/addresses.repository.js +157 -0
  252. package/dist/features/addresses/schemas/firestore.d.ts +53 -0
  253. package/dist/features/addresses/schemas/firestore.js +68 -0
  254. package/dist/features/{bundles → addresses}/schemas/index.d.ts +0 -1
  255. package/dist/features/{bundles → addresses}/schemas/index.js +0 -1
  256. package/dist/features/addresses/server.d.ts +2 -0
  257. package/dist/features/addresses/server.js +2 -0
  258. package/dist/features/admin/components/AdminAllEventEntriesView.js +4 -3
  259. package/dist/features/admin/components/AdminBidsView.js +4 -3
  260. package/dist/features/admin/components/AdminBlogView.js +8 -3
  261. package/dist/features/admin/components/AdminBundleEditorView.d.ts +9 -0
  262. package/dist/features/admin/components/AdminBundleEditorView.js +209 -0
  263. package/dist/features/admin/components/AdminBundlesView.d.ts +9 -0
  264. package/dist/features/admin/components/AdminBundlesView.js +59 -0
  265. package/dist/features/admin/components/AdminCartsView.js +13 -3
  266. package/dist/features/admin/components/AdminContactView.js +4 -3
  267. package/dist/features/admin/components/AdminCouponsView.js +32 -13
  268. package/dist/features/admin/components/AdminNewsletterView.js +4 -3
  269. package/dist/features/admin/components/AdminOrdersView.js +15 -7
  270. package/dist/features/admin/components/AdminPayoutsView.js +4 -3
  271. package/dist/features/admin/components/AdminProductsView.js +6 -5
  272. package/dist/features/admin/components/AdminReviewsView.js +5 -4
  273. package/dist/features/admin/components/AdminStoresView.js +4 -3
  274. package/dist/features/admin/components/AdminUsersView.js +15 -5
  275. package/dist/features/admin/components/AdminWishlistsView.js +10 -1
  276. package/dist/features/admin/components/DataTable.d.ts +5 -1
  277. package/dist/features/admin/components/DataTable.js +24 -20
  278. package/dist/features/admin/components/index.d.ts +4 -0
  279. package/dist/features/admin/components/index.js +3 -0
  280. package/dist/features/admin/constants/filter-tabs.d.ts +401 -0
  281. package/dist/features/admin/constants/filter-tabs.js +200 -0
  282. package/dist/features/admin/hooks/useAdminListingData.d.ts +1 -0
  283. package/dist/features/admin/hooks/useAdminListingData.js +1 -0
  284. package/dist/features/admin/schemas/firestore.d.ts +15 -0
  285. package/dist/features/admin/schemas/firestore.js +18 -0
  286. package/dist/features/admin/types/product.types.d.ts +2 -2
  287. package/dist/features/auctions/components/AuctionCard.d.ts +4 -1
  288. package/dist/features/auctions/components/AuctionCard.js +5 -3
  289. package/dist/features/auctions/components/AuctionDetailPageView.js +1 -1
  290. package/dist/features/auctions/components/MarketplaceAuctionCard.d.ts +2 -2
  291. package/dist/features/auctions/components/PlaceBidFormClient.js +12 -2
  292. package/dist/features/auctions/schemas/index.d.ts +2 -2
  293. package/dist/features/auth/index.d.ts +1 -0
  294. package/dist/features/auth/index.js +1 -0
  295. package/dist/features/auth/role-predicates.d.ts +16 -0
  296. package/dist/features/auth/role-predicates.js +15 -0
  297. package/dist/features/blog/components/BlogFeaturedCard.d.ts +4 -1
  298. package/dist/features/blog/components/BlogFeaturedCard.js +5 -3
  299. package/dist/features/cart/actions/cart-actions.d.ts +1 -0
  300. package/dist/features/cart/actions/cart-actions.js +16 -0
  301. package/dist/features/cart/components/CartView.d.ts +19 -1
  302. package/dist/features/cart/components/CartView.js +2 -2
  303. package/dist/features/cart/components/ShippingPicker.d.ts +13 -0
  304. package/dist/features/cart/components/ShippingPicker.js +48 -0
  305. package/dist/features/cart/components/index.d.ts +3 -1
  306. package/dist/features/cart/components/index.js +1 -0
  307. package/dist/features/cart/hooks/useCartCount.js +7 -1
  308. package/dist/features/cart/repository/cart.repository.d.ts +1 -0
  309. package/dist/features/cart/repository/cart.repository.js +35 -0
  310. package/dist/features/cart/schemas/firestore.d.ts +27 -2
  311. package/dist/features/categories/components/BundleAddToCartCta.d.ts +16 -0
  312. package/dist/features/categories/components/BundleAddToCartCta.js +54 -0
  313. package/dist/features/categories/components/BundleBuyNowCta.d.ts +8 -0
  314. package/dist/features/categories/components/BundleBuyNowCta.js +37 -0
  315. package/dist/features/categories/components/BundleDetailView.d.ts +22 -0
  316. package/dist/features/categories/components/BundleDetailView.js +31 -0
  317. package/dist/features/categories/components/BundleDynamicRuleEditor.d.ts +18 -0
  318. package/dist/features/categories/components/BundleDynamicRuleEditor.js +60 -0
  319. package/dist/features/categories/components/BundleItemsPicker.d.ts +26 -0
  320. package/dist/features/categories/components/BundleItemsPicker.js +135 -0
  321. package/dist/features/categories/components/BundlesListView.d.ts +13 -0
  322. package/dist/features/categories/components/BundlesListView.js +27 -0
  323. package/dist/features/categories/components/index.d.ts +12 -0
  324. package/dist/features/categories/components/index.js +9 -0
  325. package/dist/features/checkout/actions/checkout-actions.js +10 -3
  326. package/dist/features/events/components/AdminEventEditorView.js +108 -2
  327. package/dist/features/events/components/AdminEventsView.js +16 -4
  328. package/dist/features/events/components/EventCard.d.ts +4 -1
  329. package/dist/features/events/components/EventCard.js +7 -3
  330. package/dist/features/events/components/EventRaffleWinnerView.d.ts +21 -0
  331. package/dist/features/events/components/EventRaffleWinnerView.js +18 -0
  332. package/dist/features/events/components/SpinWheelView.d.ts +27 -0
  333. package/dist/features/events/components/SpinWheelView.js +64 -0
  334. package/dist/features/events/components/index.d.ts +4 -0
  335. package/dist/features/events/components/index.js +2 -0
  336. package/dist/features/events/schemas/firestore.d.ts +27 -1
  337. package/dist/features/events/schemas/firestore.js +7 -0
  338. package/dist/features/events/types/index.d.ts +27 -1
  339. package/dist/features/homepage/components/FeaturedBundlesSection.d.ts +16 -0
  340. package/dist/features/homepage/components/FeaturedBundlesSection.js +24 -0
  341. package/dist/features/homepage/components/MarketplaceHomepageView.js +4 -1
  342. package/dist/features/homepage/components/WhatsAppCommunitySection.js +2 -2
  343. package/dist/features/homepage/lib/section-renderer.d.ts +2 -0
  344. package/dist/features/homepage/lib/section-renderer.js +5 -5
  345. package/dist/features/layout/NavbarLayout.d.ts +3 -1
  346. package/dist/features/layout/NavbarLayout.js +32 -3
  347. package/dist/features/layout/TitleBarLayout.d.ts +6 -3
  348. package/dist/features/layout/TitleBarLayout.js +22 -7
  349. package/dist/features/media/upload/MediaUploadField.d.ts +15 -1
  350. package/dist/features/media/upload/MediaUploadField.js +22 -1
  351. package/dist/features/orders/components/MarketplaceOrderCard.js +4 -2
  352. package/dist/features/orders/components/OrderSiblingPayments.d.ts +8 -0
  353. package/dist/features/orders/components/OrderSiblingPayments.js +16 -0
  354. package/dist/features/orders/components/RefundHistoryTable.d.ts +6 -0
  355. package/dist/features/orders/components/RefundHistoryTable.js +23 -0
  356. package/dist/features/orders/components/RefundRequestView.d.ts +8 -0
  357. package/dist/features/orders/components/RefundRequestView.js +42 -0
  358. package/dist/features/orders/components/index.d.ts +6 -0
  359. package/dist/features/orders/components/index.js +3 -0
  360. package/dist/features/orders/index.d.ts +1 -0
  361. package/dist/features/orders/index.js +2 -0
  362. package/dist/features/orders/repository/orders.repository.d.ts +20 -1
  363. package/dist/features/orders/repository/orders.repository.js +30 -1
  364. package/dist/features/orders/schemas/firestore.d.ts +63 -13
  365. package/dist/features/orders/schemas/firestore.js +5 -5
  366. package/dist/features/orders/schemas/index.d.ts +4 -4
  367. package/dist/features/orders/types/index.d.ts +12 -2
  368. package/dist/features/orders/utils/bundle-grouping.d.ts +48 -0
  369. package/dist/features/orders/utils/bundle-grouping.js +54 -0
  370. package/dist/features/orders/utils/order-splitter.d.ts +9 -10
  371. package/dist/features/orders/utils/order-splitter.js +24 -30
  372. package/dist/features/payments/repository/payout.repository.d.ts +17 -1
  373. package/dist/features/payments/repository/payout.repository.js +47 -0
  374. package/dist/features/payments/schemas/firestore.d.ts +26 -0
  375. package/dist/features/pre-orders/components/PreorderCard.d.ts +4 -1
  376. package/dist/features/pre-orders/components/PreorderCard.js +8 -6
  377. package/dist/features/products/actions/product-actions.d.ts +1 -1
  378. package/dist/features/products/actions/product-actions.js +1 -1
  379. package/dist/features/products/components/CompareOverlay.d.ts +2 -2
  380. package/dist/features/products/components/CompareOverlay.js +4 -4
  381. package/dist/features/products/components/InteractiveProductCard.js +7 -12
  382. package/dist/features/products/components/NonRefundableConsentModal.d.ts +1 -1
  383. package/dist/features/products/components/NonRefundableConsentModal.js +0 -10
  384. package/dist/features/products/components/ProductGrid.js +28 -12
  385. package/dist/features/products/components/ShowGroupSection.js +3 -3
  386. package/dist/features/products/components/SublistingCarouselSection.js +2 -2
  387. package/dist/features/products/components/index.d.ts +0 -4
  388. package/dist/features/products/components/index.js +5 -2
  389. package/dist/features/products/index.d.ts +1 -1
  390. package/dist/features/products/index.js +3 -1
  391. package/dist/features/products/repository/products.repository.js +4 -0
  392. package/dist/features/products/schemas/catalog-product.d.ts +70 -0
  393. package/dist/features/products/schemas/catalog-product.js +50 -0
  394. package/dist/features/products/schemas/firestore.d.ts +110 -2
  395. package/dist/features/products/schemas/firestore.js +30 -0
  396. package/dist/features/products/schemas/index.d.ts +8 -8
  397. package/dist/features/products/types/index.d.ts +1 -1
  398. package/dist/features/products/utils/listing-type.d.ts +9 -0
  399. package/dist/features/products/utils/listing-type.js +4 -0
  400. package/dist/features/promotions/actions/coupon-actions.d.ts +2 -2
  401. package/dist/features/promotions/actions/coupon-actions.js +1 -1
  402. package/dist/features/promotions/components/CouponCard.d.ts +28 -10
  403. package/dist/features/promotions/components/CouponCard.js +116 -14
  404. package/dist/features/promotions/hooks/useCouponValidate.d.ts +1 -1
  405. package/dist/features/promotions/repository/coupons.repository.d.ts +1 -1
  406. package/dist/features/reviews/schemas/index.d.ts +2 -2
  407. package/dist/features/search/schemas/index.d.ts +2 -2
  408. package/dist/features/search/types/index.d.ts +2 -2
  409. package/dist/features/seller/components/SellerAuctionsView.js +4 -5
  410. package/dist/features/seller/components/SellerBidsView.js +5 -13
  411. package/dist/features/seller/components/SellerCouponsView.js +31 -67
  412. package/dist/features/seller/components/SellerOffersView.js +4 -5
  413. package/dist/features/seller/components/SellerOrdersView.js +4 -5
  414. package/dist/features/seller/components/SellerPayoutsView.js +4 -5
  415. package/dist/features/seller/components/SellerProductsView.js +4 -8
  416. package/dist/features/seller/schemas/index.d.ts +2 -2
  417. package/dist/features/stores/actions/store-address-actions.d.ts +10 -6
  418. package/dist/features/stores/actions/store-address-actions.js +8 -7
  419. package/dist/features/stores/components/InteractiveStoreCard.js +3 -10
  420. package/dist/features/stores/components/StoreDetailLayoutView.js +20 -5
  421. package/dist/features/stores/schemas/firestore.d.ts +45 -38
  422. package/dist/features/stores/schemas/firestore.js +2 -49
  423. package/dist/features/stores/server.d.ts +0 -1
  424. package/dist/features/stores/server.js +2 -1
  425. package/dist/features/wishlist/hooks/useWishlistCount.d.ts +7 -9
  426. package/dist/features/wishlist/hooks/useWishlistCount.js +67 -86
  427. package/dist/features/wishlist/types/index.d.ts +1 -1
  428. package/dist/index.d.ts +50 -9
  429. package/dist/index.js +57 -11
  430. package/dist/next/routing/route-map.d.ts +6 -0
  431. package/dist/next/routing/route-map.js +4 -0
  432. package/dist/providers/db-firebase/admin-app-lite.js +21 -0
  433. package/dist/providers/db-firebase/admin.d.ts +6 -2
  434. package/dist/providers/db-firebase/admin.js +23 -0
  435. package/dist/repositories/index.d.ts +1 -2
  436. package/dist/repositories/index.js +5 -2
  437. package/dist/security/authorization.d.ts +2 -1
  438. package/dist/security/authorization.js +3 -2
  439. package/dist/seed/actions/demo-seed-actions.d.ts +1 -1
  440. package/dist/seed/bids-seed-data.d.ts +2 -2
  441. package/dist/seed/bids-seed-data.js +77 -2
  442. package/dist/seed/cart-seed-data.d.ts +10 -10
  443. package/dist/seed/cart-seed-data.js +15 -15
  444. package/dist/seed/events-seed-data.js +77 -0
  445. package/dist/seed/manifest.js +16 -8
  446. package/dist/seed/orders-seed-data.js +41 -2
  447. package/dist/seed/payouts-seed-data.js +18 -2
  448. package/dist/seed/stores-seed-data.js +55 -0
  449. package/dist/server-entry.d.ts +1 -0
  450. package/dist/server-entry.js +2 -0
  451. package/dist/server.d.ts +4 -0
  452. package/dist/server.js +8 -0
  453. package/dist/tailwind-utilities.css +1 -1
  454. package/dist/ui/components/FilterChipGroup.d.ts +39 -0
  455. package/dist/ui/components/FilterChipGroup.js +15 -0
  456. package/dist/ui/components/HorizontalScroller.js +32 -7
  457. package/dist/ui/components/HorizontalScroller.style.css +6 -0
  458. package/dist/ui/components/SiteLogo.js +1 -1
  459. package/dist/ui/index.d.ts +2 -0
  460. package/dist/ui/index.js +2 -0
  461. package/dist/utils/id-generators.d.ts +11 -0
  462. package/dist/utils/id-generators.js +16 -0
  463. package/package.json +1 -1
  464. package/dist/_internal/shared/features/bundles/config.d.ts +0 -6
  465. package/dist/_internal/shared/features/bundles/config.js +0 -6
  466. package/dist/_internal/shared/schema-versions.d.ts +0 -76
  467. package/dist/_internal/shared/schema-versions.js +0 -82
  468. package/dist/features/account/migrations.d.ts +0 -2
  469. package/dist/features/account/migrations.js +0 -10
  470. package/dist/features/admin/migrations.d.ts +0 -2
  471. package/dist/features/admin/migrations.js +0 -10
  472. package/dist/features/auctions/migrations.d.ts +0 -2
  473. package/dist/features/auctions/migrations.js +0 -10
  474. package/dist/features/auth/migrations.d.ts +0 -2
  475. package/dist/features/auth/migrations.js +0 -10
  476. package/dist/features/blog/migrations.d.ts +0 -2
  477. package/dist/features/blog/migrations.js +0 -10
  478. package/dist/features/brands/actions/brand-actions.d.ts +0 -2
  479. package/dist/features/brands/actions/brand-actions.js +0 -5
  480. package/dist/features/brands/index.d.ts +0 -3
  481. package/dist/features/brands/index.js +0 -3
  482. package/dist/features/brands/migrations.d.ts +0 -2
  483. package/dist/features/brands/migrations.js +0 -10
  484. package/dist/features/brands/repository/brands.repository.d.ts +0 -13
  485. package/dist/features/brands/repository/brands.repository.js +0 -60
  486. package/dist/features/brands/schemas/index.d.ts +0 -33
  487. package/dist/features/brands/schemas/index.js +0 -15
  488. package/dist/features/brands/server.d.ts +0 -7
  489. package/dist/features/brands/server.js +0 -7
  490. package/dist/features/bundles/components/AdminBundleEditorView.d.ts +0 -8
  491. package/dist/features/bundles/components/AdminBundleEditorView.js +0 -7
  492. package/dist/features/bundles/components/BundleDetailPageView.d.ts +0 -9
  493. package/dist/features/bundles/components/BundleDetailPageView.js +0 -45
  494. package/dist/features/bundles/components/BundleForm.d.ts +0 -12
  495. package/dist/features/bundles/components/BundleForm.js +0 -126
  496. package/dist/features/bundles/components/BundleItemsPicker.d.ts +0 -9
  497. package/dist/features/bundles/components/BundleItemsPicker.js +0 -77
  498. package/dist/features/bundles/components/BundlesByCategoryListing.d.ts +0 -6
  499. package/dist/features/bundles/components/BundlesByCategoryListing.js +0 -50
  500. package/dist/features/bundles/components/BundlesListingView.d.ts +0 -17
  501. package/dist/features/bundles/components/BundlesListingView.js +0 -50
  502. package/dist/features/bundles/components/FeaturedBundlesSection.d.ts +0 -5
  503. package/dist/features/bundles/components/FeaturedBundlesSection.js +0 -55
  504. package/dist/features/bundles/components/SellerBundleCreateView.d.ts +0 -8
  505. package/dist/features/bundles/components/SellerBundleCreateView.js +0 -7
  506. package/dist/features/bundles/components/SellerBundleEditView.d.ts +0 -9
  507. package/dist/features/bundles/components/SellerBundleEditView.js +0 -7
  508. package/dist/features/bundles/components/index.d.ts +0 -18
  509. package/dist/features/bundles/components/index.js +0 -9
  510. package/dist/features/bundles/constants/index.d.ts +0 -32
  511. package/dist/features/bundles/constants/index.js +0 -35
  512. package/dist/features/bundles/index.d.ts +0 -2
  513. package/dist/features/bundles/index.js +0 -2
  514. package/dist/features/bundles/migrations.d.ts +0 -2
  515. package/dist/features/bundles/migrations.js +0 -10
  516. package/dist/features/bundles/repository/bundles.repository.d.ts +0 -36
  517. package/dist/features/bundles/repository/bundles.repository.js +0 -148
  518. package/dist/features/bundles/repository/index.d.ts +0 -1
  519. package/dist/features/bundles/repository/index.js +0 -1
  520. package/dist/features/bundles/schemas/firestore.d.ts +0 -88
  521. package/dist/features/bundles/schemas/firestore.js +0 -29
  522. package/dist/features/bundles/schemas/zod.d.ts +0 -377
  523. package/dist/features/bundles/schemas/zod.js +0 -71
  524. package/dist/features/cart/migrations.d.ts +0 -2
  525. package/dist/features/cart/migrations.js +0 -10
  526. package/dist/features/categories/migrations.d.ts +0 -2
  527. package/dist/features/categories/migrations.js +0 -10
  528. package/dist/features/events/migrations.d.ts +0 -2
  529. package/dist/features/events/migrations.js +0 -10
  530. package/dist/features/faq/migrations.d.ts +0 -2
  531. package/dist/features/faq/migrations.js +0 -10
  532. package/dist/features/grouped/migrations.d.ts +0 -2
  533. package/dist/features/grouped/migrations.js +0 -10
  534. package/dist/features/history/migrations.d.ts +0 -2
  535. package/dist/features/history/migrations.js +0 -10
  536. package/dist/features/messages/migrations.d.ts +0 -2
  537. package/dist/features/messages/migrations.js +0 -10
  538. package/dist/features/orders/migrations.d.ts +0 -2
  539. package/dist/features/orders/migrations.js +0 -10
  540. package/dist/features/payments/migrations.d.ts +0 -2
  541. package/dist/features/payments/migrations.js +0 -10
  542. package/dist/features/products/migrations.d.ts +0 -2
  543. package/dist/features/products/migrations.js +0 -10
  544. package/dist/features/products/repository/sublisting-categories.repository.d.ts +0 -16
  545. package/dist/features/products/repository/sublisting-categories.repository.js +0 -126
  546. package/dist/features/products/schemas/sublisting-categories.d.ts +0 -45
  547. package/dist/features/products/schemas/sublisting-categories.js +0 -16
  548. package/dist/features/promotions/migrations.d.ts +0 -2
  549. package/dist/features/promotions/migrations.js +0 -10
  550. package/dist/features/reviews/migrations.d.ts +0 -2
  551. package/dist/features/reviews/migrations.js +0 -10
  552. package/dist/features/scams/migrations.d.ts +0 -2
  553. package/dist/features/scams/migrations.js +0 -10
  554. package/dist/features/seller/migrations.d.ts +0 -2
  555. package/dist/features/seller/migrations.js +0 -10
  556. package/dist/features/stores/migrations.d.ts +0 -2
  557. package/dist/features/stores/migrations.js +0 -10
  558. package/dist/features/sublisting/migrations.d.ts +0 -2
  559. package/dist/features/sublisting/migrations.js +0 -10
  560. package/dist/features/sublisting/schemas/firestore.d.ts +0 -32
  561. package/dist/features/sublisting/schemas/firestore.js +0 -19
  562. package/dist/features/support/migrations.d.ts +0 -2
  563. package/dist/features/support/migrations.js +0 -10
  564. package/dist/features/wishlist/migrations.d.ts +0 -2
  565. package/dist/features/wishlist/migrations.js +0 -10
  566. package/dist/seed/_bundle-constants.d.ts +0 -14
  567. package/dist/seed/_bundle-constants.js +0 -14
  568. package/dist/seed/anime-figures-seed-data.d.ts +0 -8
  569. package/dist/seed/anime-figures-seed-data.js +0 -1033
  570. package/dist/seed/beyblade-seed-data.d.ts +0 -7
  571. package/dist/seed/beyblade-seed-data.js +0 -1129
  572. package/dist/seed/brands-seed-data.d.ts +0 -7
  573. package/dist/seed/brands-seed-data.js +0 -410
  574. package/dist/seed/bundles-seed-data.d.ts +0 -13
  575. package/dist/seed/bundles-seed-data.js +0 -229
  576. package/dist/seed/cosplay-accessories-seed-data.d.ts +0 -8
  577. package/dist/seed/cosplay-accessories-seed-data.js +0 -647
  578. package/dist/seed/hot-wheels-seed-data.d.ts +0 -7
  579. package/dist/seed/hot-wheels-seed-data.js +0 -1612
  580. package/dist/seed/letitrip-official-seed-data.d.ts +0 -8
  581. package/dist/seed/letitrip-official-seed-data.js +0 -399
  582. package/dist/seed/pokemon-carousel-slides-seed-data.d.ts +0 -8
  583. package/dist/seed/pokemon-carousel-slides-seed-data.js +0 -322
  584. package/dist/seed/pokemon-categories-seed-data.d.ts +0 -24
  585. package/dist/seed/pokemon-categories-seed-data.js +0 -547
  586. package/dist/seed/pokemon-coupons-seed-data.d.ts +0 -6
  587. package/dist/seed/pokemon-coupons-seed-data.js +0 -465
  588. package/dist/seed/pokemon-homepage-sections-seed-data.d.ts +0 -7
  589. package/dist/seed/pokemon-homepage-sections-seed-data.js +0 -241
  590. package/dist/seed/pokemon-products-seed-data.d.ts +0 -9
  591. package/dist/seed/pokemon-products-seed-data.js +0 -1791
  592. package/dist/seed/pokemon-seed-bundle.d.ts +0 -47
  593. package/dist/seed/pokemon-seed-bundle.js +0 -71
  594. package/dist/seed/pokemon-stores-seed-data.d.ts +0 -6
  595. package/dist/seed/pokemon-stores-seed-data.js +0 -179
  596. package/dist/seed/pokemon-users-seed-data.d.ts +0 -6
  597. package/dist/seed/pokemon-users-seed-data.js +0 -521
  598. package/dist/seed/products-seed-data.d.ts +0 -6
  599. package/dist/seed/products-seed-data.js +0 -2530
  600. package/dist/seed/retro-gaming-seed-data.d.ts +0 -8
  601. package/dist/seed/retro-gaming-seed-data.js +0 -801
  602. package/dist/seed/server.d.ts +0 -2
  603. package/dist/seed/server.js +0 -7
  604. package/dist/seed/sublisting-categories-seed-data.d.ts +0 -7
  605. package/dist/seed/sublisting-categories-seed-data.js +0 -159
  606. package/dist/seed/transformers-seed-data.d.ts +0 -7
  607. package/dist/seed/transformers-seed-data.js +0 -530
@@ -14,15 +14,18 @@ import { sendOrderConfirmationEmail } from "../../../../features/contact/server"
14
14
  import { splitCartIntoOrderGroups } from "../../../../features/orders/index";
15
15
  import { resolveDate } from "../../../../utils";
16
16
  import { getAdminDb, getAdminRealtimeDb, RTDB_PATHS, } from "../../../../providers/db-firebase";
17
- import { PRODUCT_COLLECTION, ProductStatusValues } from "../../../../features/products/schemas/firestore";
17
+ import { PRODUCT_COLLECTION } from "../../../../features/products/schemas/firestore";
18
18
  import { CART_COLLECTION } from "../../../../features/cart/schemas/index";
19
+ // S-SBUNI-RULES 2026-05-13 — bundle cart-line stock fan-out helpers.
20
+ import { getCartItemMemberIds, getExpandedDecrements, validateCartItemStock, } from "./bundle-expansion";
19
21
  import { consentOtpRef, consentOtpRateLimitRef, CONSENT_OTP_MAX_BYPASS_CREDITS, } from "../../../../features/auth/server";
20
22
  import { OrderStatusValues, PaymentStatusValues, PaymentMethodValues, } from "../../../../features/orders/schemas/index";
21
23
  import { getDefaultCurrency } from "../../../../core/index";
22
24
  import { verifyPaymentSignatureWithKeys, fetchRazorpayOrder, paiseToRupees, } from "../../../../providers/payment-razorpay/index";
23
25
  import { CHECKOUT_DEFAULT_COMMISSIONS } from "../../../shared/features/checkout/config";
24
26
  import { formatShippingAddress } from "./data";
25
- import { enforceMaxPerUserForCart, enforcePrizePoolCap, computePrizeRevealDeadline, } from "./prize-bundle-gates";
27
+ import { enforceMaxPerUserForCart, computePrizeRevealDeadline, } from "./prize-bundle-gates";
28
+ import { getListingRule, runSyncPreflight, } from "../../../shared/checkout/rules";
26
29
  /**
27
30
  * Fire-and-forget in-app notifications when an order is created.
28
31
  *
@@ -89,7 +92,10 @@ export async function createCheckoutOrderAction(input) {
89
92
  if (cartItems.length === 0) {
90
93
  throw new ValidationError(ERROR_MESSAGES.CHECKOUT.CART_EMPTY);
91
94
  }
92
- const address = await unitOfWork.addresses.findById(uid, addressId);
95
+ const addressDoc = await unitOfWork.addresses.findById(addressId);
96
+ const address = addressDoc && addressDoc.ownerType === "user" && addressDoc.ownerId === uid
97
+ ? addressDoc
98
+ : null;
93
99
  if (!address) {
94
100
  failedCheckoutRepository
95
101
  .logCheckout(uid, "address_not_found", "Address not found", { addressId, paymentMethod })
@@ -104,14 +110,26 @@ export async function createCheckoutOrderAction(input) {
104
110
  // product docs are re-read inside the transaction below for stock + prize
105
111
  // pool checks; this is intentional (the tx is the source of truth for the
106
112
  // counts we actually mutate).
107
- const preTxProductRefs = cartItems.map((item) => db.collection(PRODUCT_COLLECTION).doc(item.productId));
113
+ //
114
+ // SB-UNI-5 2026-05-13 — for bundle cart-lines we pair the bundle item with
115
+ // its FIRST member product (so the maxPerUser cap check uses real product
116
+ // data instead of failing the bundle's category-id lookup). The full
117
+ // bundle-member stock fan-out happens in-tx below.
118
+ const preTxLookup = getExpandedDecrements(cartItems);
119
+ const preTxProductRefs = preTxLookup.productIds.map((pid) => db.collection(PRODUCT_COLLECTION).doc(pid));
108
120
  const preTxProductSnaps = await Promise.all(preTxProductRefs.map((r) => r.get()));
121
+ const preTxProductById = new Map();
122
+ for (let i = 0; i < preTxLookup.productIds.length; i++) {
123
+ const snap = preTxProductSnaps[i];
124
+ if (snap.exists) {
125
+ preTxProductById.set(preTxLookup.productIds[i], snap.data());
126
+ }
127
+ }
109
128
  const preTxPairs = cartItems
110
- .map((item, i) => {
111
- const data = preTxProductSnaps[i].exists
112
- ? preTxProductSnaps[i].data()
113
- : undefined;
114
- return data ? { item, product: data } : null;
129
+ .map((item) => {
130
+ const [firstMember] = getCartItemMemberIds(item);
131
+ const product = preTxProductById.get(firstMember);
132
+ return product ? { item, product } : null;
115
133
  })
116
134
  .filter((pair) => pair !== null);
117
135
  await enforceMaxPerUserForCart({ userId: uid, items: preTxPairs });
@@ -130,40 +148,63 @@ export async function createCheckoutOrderAction(input) {
130
148
  throw Object.assign(new ApiError(403, "Order verification required. Please complete OTP verification before placing this order."), { _failReason: reason });
131
149
  }
132
150
  const emailOtpUsed = otpData.verifiedVia !== "sms";
133
- const productRefs = cartItems.map((item) => db.collection(PRODUCT_COLLECTION).doc(item.productId));
134
- const productDocs = await Promise.all(productRefs.map((ref) => tx.get(ref)));
151
+ // SB-UNI-5 2026-05-13 — bundle-aware stock fan-out. Build the unique
152
+ // product-id set across the whole cart (regular items + each bundle's
153
+ // members) and fetch each one ONCE. Validation walks per cart-line and
154
+ // checks every required member against the cart-cumulative decrement.
155
+ const expansion = getExpandedDecrements(cartItems);
156
+ const productRefById = new Map();
157
+ for (const pid of expansion.productIds) {
158
+ productRefById.set(pid, db.collection(PRODUCT_COLLECTION).doc(pid));
159
+ }
160
+ const productDocs = await Promise.all(expansion.productIds.map((pid) => tx.get(productRefById.get(pid))));
161
+ const productById = new Map();
162
+ for (let i = 0; i < expansion.productIds.length; i++) {
163
+ const doc = productDocs[i];
164
+ if (doc.exists) {
165
+ productById.set(expansion.productIds[i], doc.data());
166
+ }
167
+ }
135
168
  const availableItems = [];
136
169
  const unavailableItems = [];
137
- for (let i = 0; i < cartItems.length; i++) {
138
- const item = cartItems[i];
139
- const doc = productDocs[i];
140
- const productData = doc.exists ? doc.data() : null;
141
- if (!productData ||
142
- productData.status !== ProductStatusValues.PUBLISHED ||
143
- productData.availableQuantity < item.quantity) {
170
+ for (const item of cartItems) {
171
+ const shortfall = validateCartItemStock(item, productById, expansion.decrements);
172
+ if (shortfall) {
144
173
  unavailableItems.push({
145
- productId: item.productId,
174
+ productId: shortfall.productId,
146
175
  productTitle: item.productTitle,
147
176
  requestedQty: item.quantity,
148
- availableQty: productData?.availableQuantity ?? 0,
177
+ availableQty: shortfall.availableQty,
149
178
  });
179
+ continue;
150
180
  }
151
- else {
152
- // SB6-C prize-draw pool cap (in-tx, atomic with availableQuantity).
153
- enforcePrizePoolCap({
154
- productSnapshot: productData,
155
- requestedQuantity: item.quantity,
156
- });
157
- const productUpdate = {
158
- availableQuantity: productData.availableQuantity - item.quantity,
181
+ // Bundle cart-lines surface the first member as the "product" so
182
+ // downstream listingType branching (prize-draw) stays sound bundle
183
+ // pricing is always "standard" so the prize-draw cap isn't enforced.
184
+ const memberIds = getCartItemMemberIds(item);
185
+ const representative = productById.get(memberIds[0]);
186
+ // S-SBUNI-RULES 2026-05-13 — sync preflight (prize-pool cap, pre-order
187
+ // quota) via rule registry. Bundles skip — they bypass the cart path.
188
+ if (!item.bundleProductIds?.length) {
189
+ runSyncPreflight([{ item, product: representative }]);
190
+ }
191
+ availableItems.push({ item, product: representative });
192
+ }
193
+ // Apply per-product decrements ONCE per unique product (sums across the
194
+ // cart) so two cart lines sharing a product don't double-decrement.
195
+ if (availableItems.length > 0) {
196
+ for (const [pid, qtyDelta] of expansion.decrements) {
197
+ const product = productById.get(pid);
198
+ if (!product)
199
+ continue;
200
+ const lt = (product.listingType ?? "standard");
201
+ const rule = getListingRule(lt);
202
+ const update = {
203
+ availableQuantity: product.availableQuantity - qtyDelta,
159
204
  updatedAt: new Date(),
205
+ ...rule.stockDecrementExtras(product, qtyDelta),
160
206
  };
161
- if (productData.listingType === "prize-draw") {
162
- productUpdate.prizeCurrentEntries =
163
- (productData.prizeCurrentEntries ?? 0) + item.quantity;
164
- }
165
- tx.update(productRefs[i], productUpdate);
166
- availableItems.push({ item, product: productData });
207
+ tx.update(productRefById.get(pid), update);
167
208
  }
168
209
  }
169
210
  if (availableItems.length > 0) {
@@ -217,30 +258,27 @@ export async function createCheckoutOrderAction(input) {
217
258
  const firstItem = group[0].item;
218
259
  const groupTotal = group.reduce((sum, { item }) => sum + item.price * item.quantity, 0);
219
260
  total += groupTotal;
220
- // SB8-Fwhen a line is a prize-draw entry, stamp the listingType +
221
- // reveal status + deadline so the user-orders surface can render the
222
- // reveals-remaining badge immediately after order creation.
223
- const groupRevealDeadline = orderType === "prize-draw"
224
- ? computePrizeRevealDeadline(group[0].product)
225
- : undefined;
261
+ // S-SBUNI-RULES 2026-05-13 order-item decoration via rule registry.
226
262
  const orderItems = group.map(({ item, product }) => {
227
- const isPrizeDrawLine = product.listingType === "prize-draw";
228
- return {
263
+ const lt = (product.listingType ?? "standard");
264
+ const itemRule = getListingRule(lt);
265
+ // SB-UNI-5 2026-05-13 — forward bundle identifiers so the order-detail
266
+ // UI can collapse expanded lines back under a "Bundle: <name>" header.
267
+ const bundleFields = item.bundleCategorySlug && item.bundleProductIds
268
+ ? {
269
+ bundleCategorySlug: item.bundleCategorySlug,
270
+ bundleProductIds: item.bundleProductIds,
271
+ }
272
+ : {};
273
+ const baseLine = {
229
274
  productId: item.productId,
230
275
  productTitle: item.productTitle,
231
276
  quantity: item.quantity,
232
277
  unitPrice: item.price,
233
278
  totalPrice: item.price * item.quantity,
234
- ...(isPrizeDrawLine
235
- ? {
236
- listingType: "prize-draw",
237
- prizeRevealStatus: product.prizeRevealStatus === "open" ? "open" : "pending",
238
- prizeRevealDeadline: groupRevealDeadline?.toISOString(),
239
- }
240
- : product.listingType
241
- ? { listingType: product.listingType }
242
- : {}),
279
+ ...bundleFields,
243
280
  };
281
+ return itemRule.decorateOrderItem(baseLine, product);
244
282
  });
245
283
  const totalQuantity = group.reduce((sum, { item }) => sum + item.quantity, 0);
246
284
  let shippingFee = 0;
@@ -327,17 +365,15 @@ export async function createCheckoutOrderAction(input) {
327
365
  .map(({ product }) => product.mainImage)
328
366
  .filter((url) => typeof url === "string" && url.length > 0)),
329
367
  ];
330
- // SB-UNI-D"bundle" order-type removed; bundle cart lines will expand
331
- // to N product order lines at checkout (forward-looking feature, not
332
- // wired yet). Prize-draw fields only.
333
- const isPrizeDrawOrder = orderType === "prize-draw";
334
- const prizeDrawFields = isPrizeDrawOrder
335
- ? {
336
- prizeDrawProductId: group[0].product.id,
337
- isNonRefundable: true,
338
- prizeRevealDeadline: computePrizeRevealDeadline(group[0].product),
339
- }
340
- : {};
368
+ // S-SBUNI-RULES 2026-05-13 — order-doc decoration via rule registry.
369
+ const lt0 = (group[0].product.listingType ?? "standard");
370
+ const groupRule = getListingRule(lt0);
371
+ const extraOrderFields = {
372
+ ...groupRule.decorateOrderDoc(group[0].item, group[0].product),
373
+ ...(orderType === "prize-draw"
374
+ ? { prizeRevealDeadline: computePrizeRevealDeadline(group[0].product) }
375
+ : {}),
376
+ };
341
377
  const order = await unitOfWork.orders.create({
342
378
  productId: firstItem.productId,
343
379
  productTitle: firstItem.productTitle,
@@ -365,7 +401,7 @@ export async function createCheckoutOrderAction(input) {
365
401
  couponDiscount: couponDiscount > 0 ? couponDiscount : undefined,
366
402
  appliedDiscounts: appliedDiscounts.length > 0 ? appliedDiscounts : undefined,
367
403
  imageUrls: imageUrls.length > 0 ? imageUrls : undefined,
368
- ...prizeDrawFields,
404
+ ...extraOrderFields,
369
405
  });
370
406
  orderIds.push(order.id);
371
407
  for (const code of groupCouponCodes) {
@@ -473,7 +509,10 @@ export async function verifyAndPlaceRazorpayOrderAction(input) {
473
509
  if (!cart.items || cart.items.length === 0) {
474
510
  throw new ValidationError(ERROR_MESSAGES.CHECKOUT.CART_EMPTY);
475
511
  }
476
- const address = await unitOfWork.addresses.findById(uid, addressId);
512
+ const addressDoc = await unitOfWork.addresses.findById(addressId);
513
+ const address = addressDoc && addressDoc.ownerType === "user" && addressDoc.ownerId === uid
514
+ ? addressDoc
515
+ : null;
477
516
  if (!address) {
478
517
  throw new NotFoundError(ERROR_MESSAGES.CHECKOUT.ADDRESS_REQUIRED);
479
518
  }
@@ -500,10 +539,22 @@ export async function verifyAndPlaceRazorpayOrderAction(input) {
500
539
  throw new ApiError(403, "Order verification required. Please complete OTP verification and retry.");
501
540
  }
502
541
  }
503
- const productChecks = await Promise.all(cart.items.map(async (item) => {
504
- const product = await unitOfWork.products.findById(item.productId);
542
+ // SB-UNI-5 2026-05-13 bundle-aware product fetch + validation. Each
543
+ // cart line gets paired with a "representative" product (first member id
544
+ // for bundles, productId for regular items). The full bundle-member
545
+ // decrement runs against `expansionPaid.decrements` lower down.
546
+ const expansionPaid = getExpandedDecrements(cart.items);
547
+ const productByIdPaid = new Map();
548
+ for (const pid of expansionPaid.productIds) {
549
+ const product = await unitOfWork.products.findById(pid);
550
+ if (product)
551
+ productByIdPaid.set(pid, product);
552
+ }
553
+ const productChecks = cart.items.map((item) => {
554
+ const [firstMember] = getCartItemMemberIds(item);
555
+ const product = productByIdPaid.get(firstMember) ?? null;
505
556
  return { item, product };
506
- }));
557
+ });
507
558
  // SB6-C — maxPerUser cap check before we touch any state.
508
559
  await enforceMaxPerUserForCart({
509
560
  userId: uid,
@@ -511,39 +562,40 @@ export async function verifyAndPlaceRazorpayOrderAction(input) {
511
562
  .filter((p) => p.product !== null && p.product !== undefined)
512
563
  .map(({ item, product }) => ({ item, product })),
513
564
  });
514
- // SB6-C — prize-pool cap. Runs against the freshly-read product snapshots.
515
- for (const { item, product } of productChecks) {
516
- if (!product)
517
- continue;
518
- enforcePrizePoolCap({
519
- productSnapshot: product,
520
- requestedQuantity: item.quantity,
521
- });
522
- }
523
- for (const { item, product } of productChecks) {
524
- if (!product || product.status !== ProductStatusValues.PUBLISHED) {
525
- failedCheckoutRepository
526
- .logPayment(uid, "product_unavailable", `Product ${item.productId} not published`, {
527
- gatewayOrderId: razorpay_order_id,
528
- gatewayPaymentId: razorpay_payment_id,
529
- addressId,
530
- })
531
- .catch(() => { });
532
- throw new ValidationError(ERROR_MESSAGES.CHECKOUT.PRODUCT_UNAVAILABLE);
533
- }
534
- if (product.availableQuantity < item.quantity) {
565
+ // S-SBUNI-RULES 2026-05-13 sync preflight via rule registry.
566
+ // Bundle items bypass the cart flow so skip the prize-pool cap.
567
+ const preflightPairs = productChecks.filter((p) => p.product !== null && p.product !== undefined && !p.item.bundleProductIds?.length);
568
+ runSyncPreflight(preflightPairs);
569
+ // SB-UNI-5 — validate every required member product across the cart with
570
+ // cumulative decrement awareness (two bundles sharing a member must NOT
571
+ // both succeed unless the product has enough stock for the sum).
572
+ for (const item of cart.items) {
573
+ const shortfall = validateCartItemStock(item, productByIdPaid, expansionPaid.decrements);
574
+ if (shortfall) {
575
+ const exists = productByIdPaid.has(shortfall.productId);
576
+ const reason = exists ? "stock_insufficient" : "product_unavailable";
535
577
  failedCheckoutRepository
536
- .logPayment(uid, "stock_insufficient", `Product ${item.productId} has ${product.availableQuantity} left, requested ${item.quantity}`, {
578
+ .logPayment(uid, reason, exists
579
+ ? `Product ${shortfall.productId} has ${shortfall.availableQty} left, requested ${item.quantity}`
580
+ : `Product ${shortfall.productId} not published`, {
537
581
  gatewayOrderId: razorpay_order_id,
538
582
  gatewayPaymentId: razorpay_payment_id,
539
583
  addressId,
540
584
  })
541
585
  .catch(() => { });
542
- throw new ValidationError(ERROR_MESSAGES.CHECKOUT.INSUFFICIENT_STOCK);
586
+ throw new ValidationError(exists
587
+ ? ERROR_MESSAGES.CHECKOUT.INSUFFICIENT_STOCK
588
+ : ERROR_MESSAGES.CHECKOUT.PRODUCT_UNAVAILABLE);
543
589
  }
544
590
  }
545
591
  {
546
- const cartSubtotalRs = productChecks.reduce((sum, { item, product }) => sum + product.price * item.quantity, 0);
592
+ // SB-UNI-5 2026-05-13 bundle cart-lines use item.price (locked
593
+ // bundlePriceInPaise) instead of the representative member's product.price.
594
+ const cartSubtotalRs = productChecks.reduce((sum, { item, product }) => {
595
+ const isBundle = Boolean(item.bundleCategorySlug && item.bundleProductIds?.length);
596
+ const unit = isBundle ? item.price : product.price;
597
+ return sum + unit * item.quantity;
598
+ }, 0);
547
599
  const expectedPlatformFee = Math.round(cartSubtotalRs * (razorpayFeePercent / 100) * 100) / 100;
548
600
  const expectedPaymentAmountRs = cartSubtotalRs + expectedPlatformFee;
549
601
  const rzpOrderRecord = await fetchRazorpayOrder(razorpay_order_id);
@@ -566,11 +618,17 @@ export async function verifyAndPlaceRazorpayOrderAction(input) {
566
618
  const orderIds = [];
567
619
  let total = 0;
568
620
  const emailsToSend = [];
621
+ // SB-UNI-5 2026-05-13 — bundle cart-lines use item.price (locked bundle
622
+ // price); regular lines use product.price. The helper keeps the math
623
+ // local to this block.
624
+ const unitPriceFor = (item, product) => item.bundleCategorySlug && item.bundleProductIds?.length
625
+ ? item.price
626
+ : product.price;
569
627
  const cartSubtotal = orderGroups.reduce((s, { items: g }) => s +
570
- g.reduce((gs, { item, product }) => gs + product.price * item.quantity, 0), 0);
628
+ g.reduce((gs, { item, product }) => gs + unitPriceFor(item, product) * item.quantity, 0), 0);
571
629
  for (const { items: group, orderType } of orderGroups) {
572
630
  const firstItem = group[0].item;
573
- const groupTotal = group.reduce((sum, { item, product }) => sum + product.price * item.quantity, 0);
631
+ const groupTotal = group.reduce((sum, { item, product }) => sum + unitPriceFor(item, product) * item.quantity, 0);
574
632
  let shippingFee = 0;
575
633
  let storeOwnerId;
576
634
  const storeId = firstItem.storeId;
@@ -600,7 +658,7 @@ export async function verifyAndPlaceRazorpayOrderAction(input) {
600
658
  if (coupon.applicableItemIds?.length) {
601
659
  const eligibleTotal = group
602
660
  .filter(({ item }) => coupon.applicableItemIds.includes(item.itemId))
603
- .reduce((s, { item, product }) => s + product.price * item.quantity, 0);
661
+ .reduce((s, { item, product }) => s + unitPriceFor(item, product) * item.quantity, 0);
604
662
  couponGroupDiscount =
605
663
  eligibleTotal > 0
606
664
  ? Math.min(Math.round((eligibleTotal / groupTotal) * coupon.discountAmount * 100) / 100, eligibleTotal)
@@ -629,30 +687,30 @@ export async function verifyAndPlaceRazorpayOrderAction(input) {
629
687
  const platformFee = Math.round(groupTotal * (razorpayFeePercent / 100) * 100) / 100;
630
688
  const orderTotal = Math.max(0, groupTotal - couponDiscount) + shippingFee;
631
689
  total += orderTotal;
632
- // SB8-Fstamp listingType + reveal-status + deadline for prize-draw lines.
633
- const groupRevealDeadlineRzp = orderType === "prize-draw" && group[0].product
634
- ? computePrizeRevealDeadline(group[0].product)
635
- : undefined;
690
+ // S-SBUNI-RULES 2026-05-13 order-item decoration via rule registry.
636
691
  const orderItems = group.map(({ item, product }) => {
637
- const isPrizeDrawLine = product?.listingType === "prize-draw";
638
- return {
692
+ const lt = (product?.listingType ?? "standard");
693
+ const itemRule = getListingRule(lt);
694
+ // SB-UNI-5 2026-05-13 — bundle cart-lines surface the locked
695
+ // bundlePriceInPaise (item.price), not the representative member's
696
+ // product.price. Stock decrement still runs per member elsewhere.
697
+ const isBundle = Boolean(item.bundleCategorySlug && item.bundleProductIds?.length);
698
+ const unitPrice = isBundle ? item.price : product.price;
699
+ const bundleFields = isBundle
700
+ ? {
701
+ bundleCategorySlug: item.bundleCategorySlug,
702
+ bundleProductIds: item.bundleProductIds,
703
+ }
704
+ : {};
705
+ const baseLine = {
639
706
  productId: item.productId,
640
707
  productTitle: item.productTitle,
641
708
  quantity: item.quantity,
642
- unitPrice: product.price,
643
- totalPrice: product.price * item.quantity,
644
- ...(isPrizeDrawLine
645
- ? {
646
- listingType: "prize-draw",
647
- prizeRevealStatus: product?.prizeRevealStatus === "open"
648
- ? "open"
649
- : "pending",
650
- prizeRevealDeadline: groupRevealDeadlineRzp?.toISOString(),
651
- }
652
- : product?.listingType
653
- ? { listingType: product.listingType }
654
- : {}),
709
+ unitPrice,
710
+ totalPrice: unitPrice * item.quantity,
711
+ ...bundleFields,
655
712
  };
713
+ return itemRule.decorateOrderItem(baseLine, product);
656
714
  });
657
715
  const totalQuantity = group.reduce((sum, { item }) => sum + item.quantity, 0);
658
716
  const imageUrls = [
@@ -660,16 +718,15 @@ export async function verifyAndPlaceRazorpayOrderAction(input) {
660
718
  .map(({ product }) => product?.mainImage)
661
719
  .filter((url) => typeof url === "string" && url.length > 0)),
662
720
  ];
663
- // SB-UNI-D"bundle" order-type removed; bundle cart lines will expand
664
- // to N product order lines at checkout (forward-looking, not wired).
665
- const isPrizeDrawOrder = orderType === "prize-draw";
666
- const prizeDrawFields = isPrizeDrawOrder && group[0].product
667
- ? {
668
- prizeDrawProductId: group[0].product.id,
669
- isNonRefundable: true,
670
- prizeRevealDeadline: computePrizeRevealDeadline(group[0].product),
671
- }
672
- : {};
721
+ // S-SBUNI-RULES 2026-05-13 — order-doc decoration via rule registry.
722
+ const lt0Rzp = (group[0].product?.listingType ?? "standard");
723
+ const groupRuleRzp = getListingRule(lt0Rzp);
724
+ const extraOrderFields = {
725
+ ...groupRuleRzp.decorateOrderDoc(group[0].item, group[0].product),
726
+ ...(orderType === "prize-draw" && group[0].product
727
+ ? { prizeRevealDeadline: computePrizeRevealDeadline(group[0].product) }
728
+ : {}),
729
+ };
673
730
  const order = await unitOfWork.orders.create({
674
731
  productId: firstItem.productId,
675
732
  productTitle: firstItem.productTitle,
@@ -697,7 +754,7 @@ export async function verifyAndPlaceRazorpayOrderAction(input) {
697
754
  couponDiscount: couponDiscount > 0 ? couponDiscount : undefined,
698
755
  appliedDiscounts: appliedDiscounts.length > 0 ? appliedDiscounts : undefined,
699
756
  imageUrls: imageUrls.length > 0 ? imageUrls : undefined,
700
- ...prizeDrawFields,
757
+ ...extraOrderFields,
701
758
  });
702
759
  orderIds.push(order.id);
703
760
  if (userEmail) {
@@ -723,18 +780,20 @@ export async function verifyAndPlaceRazorpayOrderAction(input) {
723
780
  paid: true,
724
781
  });
725
782
  }
783
+ // SB-UNI-5 2026-05-13 — bundle-aware batch decrement. We iterate the
784
+ // cumulative `decrements` map (one entry per unique member product) so a
785
+ // bundle's members + any sibling cart line touching the same product
786
+ // collapse into ONE update per product.
726
787
  await unitOfWork.runBatch((batch) => {
727
- for (const { item, product } of productChecks) {
788
+ for (const [pid, qtyDelta] of expansionPaid.decrements) {
789
+ const product = productByIdPaid.get(pid);
728
790
  if (!product)
729
791
  continue;
730
- const prizeBump = product.listingType === "prize-draw"
731
- ? {
732
- prizeCurrentEntries: (product.prizeCurrentEntries ?? 0) + item.quantity,
733
- }
734
- : {};
735
- unitOfWork.products.updateInBatch(batch, item.productId, {
736
- availableQuantity: product.availableQuantity - item.quantity,
737
- ...prizeBump,
792
+ const lt = (product.listingType ?? "standard");
793
+ const batchRule = getListingRule(lt);
794
+ unitOfWork.products.updateInBatch(batch, pid, {
795
+ availableQuantity: product.availableQuantity - qtyDelta,
796
+ ...batchRule.stockDecrementExtras(product, qtyDelta),
738
797
  });
739
798
  }
740
799
  unitOfWork.carts.updateInBatch(batch, uid, {
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Bundle cart-item expansion helpers — S-SBUNI-5 2026-05-13.
3
+ *
4
+ * Checkout treats each cart item as one OrderItem row (bundles stay grouped
5
+ * in the order) but stock decrement has to fan out to the bundle's member
6
+ * products. These helpers do that fan-out without breaking the existing
7
+ * per-cart-item validation loops.
8
+ *
9
+ * Two-step model:
10
+ * 1. `getExpandedDecrements(cartItems)` — returns the unique product-id set
11
+ * to fetch + a per-product total-quantity map. Multiple cart items that
12
+ * touch the same product (e.g. two bundles sharing one member, or a
13
+ * bundle + a regular item) get summed.
14
+ * 2. `validateCartItemStock(item, productById)` — for one cart item, looks
15
+ * up every required product (bundle members OR the single productId) +
16
+ * returns the worst-case shortfall: `null` if all OK, or the first
17
+ * unavailable member's id + availableQty.
18
+ *
19
+ * Note: validation in-tx is still subject to product writes from a parallel
20
+ * checkout — the Firestore transaction guarantees the second checkout sees
21
+ * the first's decrement before re-running its own validation.
22
+ */
23
+ import type { CartItemDocument } from "../../../../features/cart/schemas";
24
+ import type { ProductDocument } from "../../../../features/products/schemas/firestore";
25
+ export interface BundleExpansion {
26
+ /** Unique product ids referenced by any cart item (regular or bundle member). */
27
+ productIds: string[];
28
+ /**
29
+ * Sum of requested quantities per product id. Bundle members get
30
+ * `item.quantity` per occurrence (so 2x of a bundle with member X
31
+ * decrements X by 2, not 1).
32
+ */
33
+ decrements: Map<string, number>;
34
+ }
35
+ /** Resolve the member-product ids for a cart item. Bundle items expand to
36
+ * `bundleProductIds[]`; regular items collapse to `[productId]`. */
37
+ export declare function getCartItemMemberIds(item: CartItemDocument): string[];
38
+ /** Build the unique-product-id + per-product decrement map for a cart. */
39
+ export declare function getExpandedDecrements(cartItems: CartItemDocument[]): BundleExpansion;
40
+ export interface StockShortfall {
41
+ /** The member product id that ran out (or never existed). */
42
+ productId: string;
43
+ /** Quantity Firestore still has for that product. */
44
+ availableQty: number;
45
+ }
46
+ /**
47
+ * For a single cart item: returns `null` when every required product is
48
+ * published + has enough stock, or the first shortfall encountered. The
49
+ * caller supplies a `productById` lookup populated from the in-tx fetch
50
+ * (so the same query runs once for the whole cart).
51
+ *
52
+ * `decrements` lets the caller account for OTHER cart items touching the
53
+ * same product — pass the cumulative map from `getExpandedDecrements` so
54
+ * the available quantity is compared against the WHOLE cart's demand for
55
+ * that product, not just this item's slice.
56
+ */
57
+ export declare function validateCartItemStock(item: CartItemDocument, productById: Map<string, ProductDocument>, decrements: Map<string, number>): StockShortfall | null;
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Bundle cart-item expansion helpers — S-SBUNI-5 2026-05-13.
3
+ *
4
+ * Checkout treats each cart item as one OrderItem row (bundles stay grouped
5
+ * in the order) but stock decrement has to fan out to the bundle's member
6
+ * products. These helpers do that fan-out without breaking the existing
7
+ * per-cart-item validation loops.
8
+ *
9
+ * Two-step model:
10
+ * 1. `getExpandedDecrements(cartItems)` — returns the unique product-id set
11
+ * to fetch + a per-product total-quantity map. Multiple cart items that
12
+ * touch the same product (e.g. two bundles sharing one member, or a
13
+ * bundle + a regular item) get summed.
14
+ * 2. `validateCartItemStock(item, productById)` — for one cart item, looks
15
+ * up every required product (bundle members OR the single productId) +
16
+ * returns the worst-case shortfall: `null` if all OK, or the first
17
+ * unavailable member's id + availableQty.
18
+ *
19
+ * Note: validation in-tx is still subject to product writes from a parallel
20
+ * checkout — the Firestore transaction guarantees the second checkout sees
21
+ * the first's decrement before re-running its own validation.
22
+ */
23
+ import { ProductStatusValues } from "../../../../features/products/schemas/firestore";
24
+ /** Resolve the member-product ids for a cart item. Bundle items expand to
25
+ * `bundleProductIds[]`; regular items collapse to `[productId]`. */
26
+ export function getCartItemMemberIds(item) {
27
+ if (item.bundleProductIds && item.bundleProductIds.length > 0) {
28
+ return item.bundleProductIds;
29
+ }
30
+ return [item.productId];
31
+ }
32
+ /** Build the unique-product-id + per-product decrement map for a cart. */
33
+ export function getExpandedDecrements(cartItems) {
34
+ const decrements = new Map();
35
+ for (const item of cartItems) {
36
+ const memberIds = getCartItemMemberIds(item);
37
+ for (const pid of memberIds) {
38
+ decrements.set(pid, (decrements.get(pid) ?? 0) + item.quantity);
39
+ }
40
+ }
41
+ return {
42
+ productIds: [...decrements.keys()],
43
+ decrements,
44
+ };
45
+ }
46
+ /**
47
+ * For a single cart item: returns `null` when every required product is
48
+ * published + has enough stock, or the first shortfall encountered. The
49
+ * caller supplies a `productById` lookup populated from the in-tx fetch
50
+ * (so the same query runs once for the whole cart).
51
+ *
52
+ * `decrements` lets the caller account for OTHER cart items touching the
53
+ * same product — pass the cumulative map from `getExpandedDecrements` so
54
+ * the available quantity is compared against the WHOLE cart's demand for
55
+ * that product, not just this item's slice.
56
+ */
57
+ export function validateCartItemStock(item, productById, decrements) {
58
+ const memberIds = getCartItemMemberIds(item);
59
+ for (const pid of memberIds) {
60
+ const product = productById.get(pid);
61
+ if (!product || product.status !== ProductStatusValues.PUBLISHED) {
62
+ return { productId: pid, availableQty: product?.availableQuantity ?? 0 };
63
+ }
64
+ const totalNeeded = decrements.get(pid) ?? item.quantity;
65
+ if (product.availableQuantity < totalNeeded) {
66
+ return { productId: pid, availableQty: product.availableQuantity };
67
+ }
68
+ }
69
+ return null;
70
+ }
@@ -1,9 +1,10 @@
1
1
  /**
2
- * Prize-draw + bundle + maxPerUser gates for the checkout pipeline (SB6-C, SB8-A).
2
+ * maxPerUser gate + prize reveal deadline helper for the checkout pipeline
3
+ * (SB6-C, SB8-A).
3
4
  *
4
- * Shared helper used by both `createCheckoutOrderAction` (COD/UPI-manual path)
5
- * and `verifyAndPlaceRazorpayOrderAction` (Razorpay path). Pulled out here so
6
- * the two transactional flows enforce the same rules.
5
+ * `enforcePrizePoolCap` was removed in S-SBUNI-RULES (2026-05-13) — the
6
+ * equivalent check now lives in `prizeDrawRule.preflightChecks` in the rule
7
+ * registry and is invoked via `runSyncPreflight`.
7
8
  */
8
9
  import type { ProductDocument } from "../../../../features/products/schemas/firestore";
9
10
  import type { CartItemDocument } from "../../../../features/cart/schemas/firestore";
@@ -46,14 +47,3 @@ export declare function enforceMaxPerUserForCart(args: {
46
47
  * Returns `undefined` if the product lacks the prize-draw fields.
47
48
  */
48
49
  export declare function computePrizeRevealDeadline(product: Pick<ProductDocument, "prizeRevealWindowStart" | "prizeRevealWindowEnd" | "prizeRevealDeadlineDays">, now?: Date): Date | undefined;
49
- /**
50
- * Inside the existing checkout transaction, validate the prize-pool cap for
51
- * each prize-draw line. Caller must pass the fresh product snapshot read
52
- * within the transaction (so `prizeCurrentEntries` is up-to-date).
53
- *
54
- * Throws ValidationError if any item would overflow the pool.
55
- */
56
- export declare function enforcePrizePoolCap(args: {
57
- productSnapshot: ProductDocument;
58
- requestedQuantity: number;
59
- }): void;