@mohasinac/appkit 3.8.1 → 3.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (485) hide show
  1. package/dist/_internal/client/features/live/LiveItemDetailView.js +2 -2
  2. package/dist/_internal/client/features/lottery/LotteryAdminEditView.d.ts +4 -4
  3. package/dist/_internal/client/features/lottery/LotteryAdminEditView.js +8 -8
  4. package/dist/_internal/client/features/lottery/LotteryAdminSlotView.d.ts +1 -1
  5. package/dist/_internal/client/features/lottery/LotteryAdminSlotView.js +2 -2
  6. package/dist/_internal/server/features/bundles/actions.js +2 -2
  7. package/dist/_internal/server/features/bundles/og.d.ts +1 -1
  8. package/dist/_internal/server/features/bundles/og.js +4 -5
  9. package/dist/_internal/server/features/checkout/actions.js +57 -21
  10. package/dist/_internal/server/features/checkout/stock-restore.d.ts +19 -0
  11. package/dist/_internal/server/features/checkout/stock-restore.js +80 -0
  12. package/dist/_internal/server/features/checkout/upi-resolution.d.ts +11 -0
  13. package/dist/_internal/server/features/checkout/upi-resolution.js +28 -0
  14. package/dist/_internal/server/features/classified/og.js +1 -1
  15. package/dist/_internal/server/features/digital-code/og.js +1 -1
  16. package/dist/_internal/server/features/item-requests/og.d.ts +2 -2
  17. package/dist/_internal/server/features/item-requests/og.js +4 -5
  18. package/dist/_internal/server/features/live/og.js +1 -1
  19. package/dist/_internal/server/features/lottery/adapters.d.ts +2 -2
  20. package/dist/_internal/server/features/lottery/adapters.js +1 -1
  21. package/dist/_internal/server/features/orders/actions.d.ts +28 -0
  22. package/dist/_internal/server/features/orders/actions.js +239 -4
  23. package/dist/_internal/server/features/orders/adapters.js +3 -0
  24. package/dist/_internal/server/features/payments/data.js +3 -2
  25. package/dist/_internal/server/features/payouts/actions.d.ts +2 -2
  26. package/dist/_internal/server/features/payouts/actions.js +4 -3
  27. package/dist/_internal/server/features/pre-orders/service.d.ts +1 -1
  28. package/dist/_internal/server/features/pre-orders/service.js +3 -2
  29. package/dist/_internal/server/features/prize-draws/og.js +5 -5
  30. package/dist/_internal/server/features/products/og.js +1 -1
  31. package/dist/_internal/server/features/promotions/service.js +3 -1
  32. package/dist/_internal/server/features/refunds/actions.d.ts +2 -2
  33. package/dist/_internal/server/features/refunds/actions.js +7 -6
  34. package/dist/_internal/server/functions/firestore.js +1 -1
  35. package/dist/_internal/server/functions/scheduled.d.ts +4 -1
  36. package/dist/_internal/server/functions/scheduled.js +26 -2
  37. package/dist/_internal/server/jobs/core/emiInstallmentReminder.js +1 -1
  38. package/dist/_internal/server/jobs/core/hardBanCascade.d.ts +4 -0
  39. package/dist/_internal/server/jobs/core/hardBanCascade.js +15 -4
  40. package/dist/_internal/server/jobs/core/hardBanReinstatement.d.ts +16 -0
  41. package/dist/_internal/server/jobs/core/hardBanReinstatement.js +63 -0
  42. package/dist/_internal/server/jobs/core/jobRunners.js +3 -1
  43. package/dist/_internal/server/jobs/core/onScamReportCreate.js +1 -1
  44. package/dist/_internal/server/jobs/core/paymentReviewAutoApprove.d.ts +10 -0
  45. package/dist/_internal/server/jobs/core/paymentReviewAutoApprove.js +60 -0
  46. package/dist/_internal/server/jobs/core/paymentWindowTimeout.d.ts +15 -0
  47. package/dist/_internal/server/jobs/core/paymentWindowTimeout.js +59 -0
  48. package/dist/_internal/server/jobs/core/pendingOrderTimeout.d.ts +7 -0
  49. package/dist/_internal/server/jobs/core/pendingOrderTimeout.js +32 -6
  50. package/dist/_internal/server/jobs/handlers/hardBanReinstatement.d.ts +2 -0
  51. package/dist/_internal/server/jobs/handlers/hardBanReinstatement.js +2 -0
  52. package/dist/_internal/server/jobs/handlers/index.d.ts +3 -0
  53. package/dist/_internal/server/jobs/handlers/index.js +3 -0
  54. package/dist/_internal/server/jobs/handlers/messages.d.ts +4 -0
  55. package/dist/_internal/server/jobs/handlers/messages.js +4 -0
  56. package/dist/_internal/server/jobs/handlers/onShipmentAllocationSync.d.ts +3 -3
  57. package/dist/_internal/server/jobs/handlers/onShipmentAllocationSync.js +12 -12
  58. package/dist/_internal/server/jobs/handlers/onShipmentItemWrite.d.ts +1 -1
  59. package/dist/_internal/server/jobs/handlers/onShipmentItemWrite.js +5 -5
  60. package/dist/_internal/server/jobs/handlers/paymentReviewAutoApprove.d.ts +2 -0
  61. package/dist/_internal/server/jobs/handlers/paymentReviewAutoApprove.js +2 -0
  62. package/dist/_internal/server/jobs/handlers/paymentWindowTimeout.d.ts +2 -0
  63. package/dist/_internal/server/jobs/handlers/paymentWindowTimeout.js +2 -0
  64. package/dist/_internal/shared/actions/action-registry.js +27 -0
  65. package/dist/_internal/shared/checkout/order-math.js +3 -2
  66. package/dist/_internal/shared/checkout/rules/_defaults.js +1 -0
  67. package/dist/_internal/shared/checkout/rules/preorder.rule.js +7 -0
  68. package/dist/_internal/shared/checkout/rules/prize-draw.rule.js +7 -0
  69. package/dist/_internal/shared/checkout/rules/types.d.ts +11 -0
  70. package/dist/_internal/shared/features/auctions/errors.js +1 -1
  71. package/dist/_internal/shared/features/categories/bundle-copy.d.ts +0 -1
  72. package/dist/_internal/shared/features/categories/bundle-copy.js +0 -1
  73. package/dist/_internal/shared/features/categories/bundle-schemas.d.ts +6 -6
  74. package/dist/_internal/shared/features/categories/bundle-schemas.js +2 -2
  75. package/dist/_internal/shared/features/checkout/config.d.ts +3 -3
  76. package/dist/_internal/shared/features/checkout/config.js +3 -3
  77. package/dist/_internal/shared/features/emi/schedule.d.ts +6 -6
  78. package/dist/_internal/shared/features/emi/schedule.js +10 -9
  79. package/dist/_internal/shared/features/promotions/errors.js +1 -1
  80. package/dist/_internal/shared/fees/calculator.d.ts +5 -5
  81. package/dist/_internal/shared/fees/calculator.js +19 -19
  82. package/dist/client.d.ts +1 -1
  83. package/dist/client.js +1 -1
  84. package/dist/constants/api-endpoints.d.ts +9 -0
  85. package/dist/constants/api-endpoints.js +3 -0
  86. package/dist/constants/field-names.d.ts +4 -0
  87. package/dist/constants/field-names.js +4 -0
  88. package/dist/features/admin/components/AdminArtView.js +2 -2
  89. package/dist/features/admin/components/AdminBidsView.js +2 -2
  90. package/dist/features/admin/components/AdminBundleEditorView.d.ts +1 -1
  91. package/dist/features/admin/components/AdminBundleEditorView.js +8 -8
  92. package/dist/features/admin/components/AdminBundlesView.js +6 -6
  93. package/dist/features/admin/components/AdminClassifiedView.js +2 -2
  94. package/dist/features/admin/components/AdminDigitalCodesView.js +2 -2
  95. package/dist/features/admin/components/AdminLiveView.js +2 -2
  96. package/dist/features/admin/components/AdminOrderEditorView.d.ts +6 -1
  97. package/dist/features/admin/components/AdminOrderEditorView.js +45 -5
  98. package/dist/features/admin/components/AdminOrdersView.js +8 -3
  99. package/dist/features/admin/components/AdminPayoutsView.js +2 -2
  100. package/dist/features/admin/components/AdminPrizeDrawsView.js +2 -2
  101. package/dist/features/admin/components/AdminReturnRequestsView.js +2 -2
  102. package/dist/features/admin/components/AdminSiteSettingsView.js +11 -11
  103. package/dist/features/admin/components/AdminStickersView.js +2 -2
  104. package/dist/features/admin/components/AdminSupportTicketDetailView.js +1 -1
  105. package/dist/features/admin/hooks/useAdminListingData.d.ts +1 -1
  106. package/dist/features/admin/hooks/useAdminListingData.js +3 -2
  107. package/dist/features/admin/schemas/firestore.d.ts +9 -7
  108. package/dist/features/admin/schemas/firestore.js +4 -3
  109. package/dist/features/auctions/components/AuctionBidsTable.js +3 -3
  110. package/dist/features/auth/checkout-value-otp.d.ts +46 -0
  111. package/dist/features/auth/checkout-value-otp.js +73 -0
  112. package/dist/features/auth/repository/user.repository.d.ts +6 -0
  113. package/dist/features/auth/repository/user.repository.js +19 -0
  114. package/dist/features/auth/schemas/firestore.d.ts +10 -0
  115. package/dist/features/auth/schemas/firestore.js +2 -0
  116. package/dist/features/cart/actions/cart-actions.d.ts +1 -1
  117. package/dist/features/cart/actions/cart-actions.js +4 -4
  118. package/dist/features/cart/components/CartView.d.ts +2 -2
  119. package/dist/features/cart/components/ShippingPicker.d.ts +4 -4
  120. package/dist/features/cart/components/ShippingPicker.js +11 -11
  121. package/dist/features/cart/repository/cart.repository.d.ts +1 -1
  122. package/dist/features/cart/repository/cart.repository.js +2 -2
  123. package/dist/features/cart/schemas/firestore.d.ts +2 -2
  124. package/dist/features/catalogue/components/CatalogueItemEditorView.js +3 -3
  125. package/dist/features/catalogue/components/PublicCatalogueView.js +2 -2
  126. package/dist/features/catalogue/schemas/validation.js +1 -1
  127. package/dist/features/categories/components/BundleCollage.js +2 -2
  128. package/dist/features/categories/components/BundleDetailView.js +2 -2
  129. package/dist/features/categories/components/BundleItemsPicker.d.ts +1 -1
  130. package/dist/features/categories/components/BundleItemsPicker.js +2 -2
  131. package/dist/features/categories/components/CategoryBundlesListing.js +2 -2
  132. package/dist/features/categories/schemas/firestore.d.ts +1 -1
  133. package/dist/features/categories/schemas/index.d.ts +3 -3
  134. package/dist/features/categories/schemas/index.js +2 -2
  135. package/dist/features/checkout/actions/checkout-value-otp-actions.d.ts +16 -0
  136. package/dist/features/checkout/actions/checkout-value-otp-actions.js +83 -0
  137. package/dist/features/checkout/actions/index.d.ts +1 -0
  138. package/dist/features/checkout/actions/index.js +1 -0
  139. package/dist/features/checkout/schemas/firestore.d.ts +1 -1
  140. package/dist/features/classified/components/index.d.ts +0 -4
  141. package/dist/features/classified/components/index.js +0 -2
  142. package/dist/features/digital-codes/components/index.d.ts +0 -4
  143. package/dist/features/digital-codes/components/index.js +0 -2
  144. package/dist/features/events/schemas/index.d.ts +1 -1
  145. package/dist/features/events/schemas/index.js +1 -1
  146. package/dist/features/homepage/components/FeaturedBundlesSection.js +2 -2
  147. package/dist/features/live/components/index.d.ts +0 -4
  148. package/dist/features/live/components/index.js +0 -2
  149. package/dist/features/lottery/types/index.d.ts +3 -3
  150. package/dist/features/lottery/types/index.js +5 -5
  151. package/dist/features/orders/components/OrderPaymentSummary.js +2 -2
  152. package/dist/features/orders/components/OrderSiblingPayments.js +1 -1
  153. package/dist/features/orders/components/RefundHistoryTable.js +1 -1
  154. package/dist/features/orders/components/RefundRequestView.js +1 -1
  155. package/dist/features/orders/constants/payment-window.d.ts +10 -0
  156. package/dist/features/orders/constants/payment-window.js +10 -0
  157. package/dist/features/orders/repository/orders.repository.d.ts +25 -0
  158. package/dist/features/orders/repository/orders.repository.js +50 -1
  159. package/dist/features/orders/schemas/firestore.d.ts +50 -2
  160. package/dist/features/orders/schemas/index.d.ts +24 -24
  161. package/dist/features/orders/schemas/index.js +20 -20
  162. package/dist/features/orders/types/index.d.ts +4 -0
  163. package/dist/features/orders/utils/bundle-grouping.d.ts +1 -1
  164. package/dist/features/orders/utils/bundle-grouping.js +1 -1
  165. package/dist/features/payments/schemas/index.d.ts +10 -10
  166. package/dist/features/payments/schemas/index.js +9 -9
  167. package/dist/features/pre-orders/components/PreOrderDetailPageView.js +2 -2
  168. package/dist/features/products/components/ArtStickersListView.d.ts +7 -0
  169. package/dist/features/products/components/ArtStickersListView.js +57 -0
  170. package/dist/features/products/components/GroupSettingsPanel.js +1 -1
  171. package/dist/features/products/components/MakeOfferButton.js +3 -3
  172. package/dist/features/products/components/MarketplaceBundleCard.d.ts +1 -1
  173. package/dist/features/products/components/MarketplaceBundleCard.js +2 -2
  174. package/dist/features/products/components/PrizeDrawCollage.js +2 -2
  175. package/dist/features/products/components/PrizeDrawItemsEditor.js +2 -2
  176. package/dist/features/products/components/PrizeRevealModal.js +1 -1
  177. package/dist/features/products/components/ProductDetailPageView.js +2 -9
  178. package/dist/features/products/components/ProductForm.js +2 -2
  179. package/dist/features/products/components/ProductGrid.js +2 -2
  180. package/dist/features/products/components/ProductsIndexListing.d.ts +13 -1
  181. package/dist/features/products/components/ProductsIndexListing.js +7 -5
  182. package/dist/features/products/components/ProductsIndexPageView.js +6 -1
  183. package/dist/features/products/constants/listing-tabs.d.ts +42 -17
  184. package/dist/features/products/constants/listing-tabs.js +25 -6
  185. package/dist/features/products/schemas/catalog-product.d.ts +5 -5
  186. package/dist/features/products/schemas/catalog-product.js +1 -1
  187. package/dist/features/products/schemas/firestore.d.ts +5 -5
  188. package/dist/features/products/schemas/firestore.js +2 -2
  189. package/dist/features/products/types/index.d.ts +5 -2
  190. package/dist/features/promotions/components/CouponCard.js +2 -2
  191. package/dist/features/promotions/schemas/firestore.d.ts +2 -0
  192. package/dist/features/promotions/schemas/firestore.js +1 -0
  193. package/dist/features/promotions/schemas/index.d.ts +14 -14
  194. package/dist/features/promotions/schemas/index.js +6 -6
  195. package/dist/features/scams/components/ScamProfileView.js +3 -7
  196. package/dist/features/scams/components/ScamRegistryView.js +2 -6
  197. package/dist/features/scams/schemas/firestore.d.ts +1 -1
  198. package/dist/features/search/components/Search.d.ts +1 -1
  199. package/dist/features/seller/actions/offer-actions.js +1 -1
  200. package/dist/features/seller/components/PrintCenterView.js +2 -2
  201. package/dist/features/seller/components/QuickProductForm.js +5 -5
  202. package/dist/features/seller/components/SellerArtView.js +2 -2
  203. package/dist/features/seller/components/SellerAuctionsView.js +2 -2
  204. package/dist/features/seller/components/SellerBidsView.js +2 -2
  205. package/dist/features/seller/components/SellerBundlesView.js +6 -6
  206. package/dist/features/seller/components/SellerClassifiedView.js +2 -2
  207. package/dist/features/seller/components/SellerDigitalCodesView.js +2 -2
  208. package/dist/features/seller/components/SellerLiveView.js +2 -2
  209. package/dist/features/seller/components/SellerOffersView.js +2 -2
  210. package/dist/features/seller/components/SellerOrdersView.js +3 -3
  211. package/dist/features/seller/components/SellerPayoutRequestView.js +2 -2
  212. package/dist/features/seller/components/SellerPayoutSettingsView.js +2 -2
  213. package/dist/features/seller/components/SellerPayoutsView.js +2 -2
  214. package/dist/features/seller/components/SellerPreOrdersView.js +2 -2
  215. package/dist/features/seller/components/SellerPrizeDrawsView.js +2 -2
  216. package/dist/features/seller/components/SellerProductShell.js +8 -8
  217. package/dist/features/seller/components/SellerProductsView.js +1 -1
  218. package/dist/features/seller/components/SellerShippingView.js +6 -6
  219. package/dist/features/seller/components/SellerStickersView.js +2 -2
  220. package/dist/features/seller/hooks/useSellerListingData.d.ts +1 -1
  221. package/dist/features/seller/hooks/useSellerListingData.js +3 -2
  222. package/dist/features/shipments/components/AdminShipmentEditorView.js +10 -10
  223. package/dist/features/shipments/components/AdminShipmentLotItemsView.js +4 -4
  224. package/dist/features/shipments/components/AdminShipmentProjectionsView.js +5 -5
  225. package/dist/features/shipments/components/AdminShipmentsView.js +4 -4
  226. package/dist/features/shipments/repository/shipment-lots.repository.d.ts +2 -2
  227. package/dist/features/shipments/repository/shipment-lots.repository.js +8 -8
  228. package/dist/features/shipments/schemas/firestore.d.ts +21 -21
  229. package/dist/features/shipments/schemas/firestore.js +9 -9
  230. package/dist/features/shipments/schemas/validation.d.ts +30 -30
  231. package/dist/features/shipments/schemas/validation.js +6 -6
  232. package/dist/features/shipments/utils/cost-allocation.d.ts +5 -5
  233. package/dist/features/shipments/utils/cost-allocation.js +39 -38
  234. package/dist/features/store-extensions/schemas/firestore.d.ts +5 -5
  235. package/dist/features/stores/components/StoreDetailLayoutView.js +9 -13
  236. package/dist/features/stores/schemas/firestore.d.ts +7 -7
  237. package/dist/features/stores/schemas/index.d.ts +84 -84
  238. package/dist/features/stores/schemas/index.js +5 -5
  239. package/dist/features/tester/seed-data/categories-tester-seed-data.js +1 -1
  240. package/dist/features/tester/seed-data/products-tester-seed-data.js +6 -6
  241. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +9 -2
  242. package/dist/features/whatsapp-bot/helpers/whatsapp.d.ts +8 -1
  243. package/dist/features/whatsapp-bot/helpers/whatsapp.js +13 -2
  244. package/dist/features/whatsapp-bot/types/index.d.ts +9 -1
  245. package/dist/index.d.ts +4 -7
  246. package/dist/index.js +9 -5
  247. package/dist/next/routing/route-map.d.ts +2 -0
  248. package/dist/next/routing/route-map.js +6 -0
  249. package/dist/schemas/firestore-helpers.d.ts +2 -2
  250. package/dist/schemas/firestore-helpers.js +2 -2
  251. package/dist/schemas/registry.d.ts +73 -73
  252. package/dist/security/index.d.ts +2 -1
  253. package/dist/security/index.js +5 -1
  254. package/dist/security/pii-encrypt.d.ts +2 -53
  255. package/dist/security/pii-encrypt.js +19 -100
  256. package/dist/security/pii-mask.d.ts +67 -0
  257. package/dist/security/pii-mask.js +100 -0
  258. package/dist/seed/bids-seed-data.js +6 -6
  259. package/dist/seed/blog-posts-seed-data.js +1 -0
  260. package/dist/seed/cart-seed-data.js +13 -13
  261. package/dist/seed/catalogue-seed-data.js +6 -6
  262. package/dist/seed/categories-seed-data.js +5 -5
  263. package/dist/seed/claimed-coupons-seed-data.js +3 -3
  264. package/dist/seed/coupons-seed-data.js +20 -20
  265. package/dist/seed/events-seed-data.js +27 -27
  266. package/dist/seed/factories/bid.factory.js +1 -1
  267. package/dist/seed/faq-seed-data.js +20 -1
  268. package/dist/seed/grouped-listings-seed-data.d.ts +2 -2
  269. package/dist/seed/grouped-listings-seed-data.js +3 -3
  270. package/dist/seed/offers-seed-data.js +19 -19
  271. package/dist/seed/orders-seed-data.js +29 -29
  272. package/dist/seed/payouts-seed-data.js +7 -7
  273. package/dist/seed/products-auctions-seed-data.js +6 -6
  274. package/dist/seed/products-preorders-seed-data.d.ts +2 -2
  275. package/dist/seed/products-preorders-seed-data.js +1 -1
  276. package/dist/seed/products-standard-seed-data.js +8 -8
  277. package/dist/seed/scammers-seed-data.js +2 -2
  278. package/dist/seed/shipments-seed-data.js +29 -29
  279. package/dist/seed/site-settings-seed-data.js +3 -2
  280. package/dist/seed/store-extensions-seed-data.js +8 -8
  281. package/dist/seed/stores-seed-data.js +37 -8
  282. package/dist/seed/users-seed-data.js +38 -1
  283. package/dist/server-entry.d.ts +1 -3
  284. package/dist/server-entry.js +1 -3
  285. package/dist/server.d.ts +2 -1
  286. package/dist/server.js +3 -1
  287. package/dist/ui/components/PriceDisplay.js +3 -12
  288. package/dist/utils/number.formatter.d.ts +2 -7
  289. package/dist/utils/number.formatter.js +3 -8
  290. package/package.json +1 -1
  291. package/scripts/seed-cli.mjs +17 -3
  292. package/dist/_internal/client/scaffolds/DashboardScaffold.d.ts +0 -34
  293. package/dist/_internal/client/scaffolds/DashboardScaffold.js +0 -26
  294. package/dist/_internal/client/theme/__tests__/ThemeProvider.test.d.ts +0 -1
  295. package/dist/_internal/client/theme/__tests__/ThemeProvider.test.js +0 -109
  296. package/dist/_internal/server/features/auctions/__tests__/service.test.d.ts +0 -1
  297. package/dist/_internal/server/features/auctions/__tests__/service.test.js +0 -140
  298. package/dist/_internal/server/features/checkout/__tests__/actions.test.d.ts +0 -1
  299. package/dist/_internal/server/features/checkout/__tests__/actions.test.js +0 -600
  300. package/dist/_internal/server/features/refunds/__tests__/actions.test.d.ts +0 -1
  301. package/dist/_internal/server/features/refunds/__tests__/actions.test.js +0 -263
  302. package/dist/_internal/server/jobs/core/__tests__/auctionSettlement.test.d.ts +0 -1
  303. package/dist/_internal/server/jobs/core/__tests__/auctionSettlement.test.js +0 -249
  304. package/dist/_internal/server/jobs/core/__tests__/couponExpiry.test.d.ts +0 -1
  305. package/dist/_internal/server/jobs/core/__tests__/couponExpiry.test.js +0 -65
  306. package/dist/_internal/server/jobs/core/__tests__/listingProcessor.test.d.ts +0 -1
  307. package/dist/_internal/server/jobs/core/__tests__/listingProcessor.test.js +0 -163
  308. package/dist/_internal/server/jobs/core/__tests__/mediaTmpCleanup.test.d.ts +0 -1
  309. package/dist/_internal/server/jobs/core/__tests__/mediaTmpCleanup.test.js +0 -115
  310. package/dist/_internal/server/jobs/core/__tests__/onBidPlaced.test.d.ts +0 -1
  311. package/dist/_internal/server/jobs/core/__tests__/onBidPlaced.test.js +0 -201
  312. package/dist/_internal/server/jobs/core/__tests__/onOrderCreate.test.d.ts +0 -1
  313. package/dist/_internal/server/jobs/core/__tests__/onOrderCreate.test.js +0 -169
  314. package/dist/_internal/server/jobs/core/__tests__/onOrderStatusChange.test.d.ts +0 -1
  315. package/dist/_internal/server/jobs/core/__tests__/onOrderStatusChange.test.js +0 -148
  316. package/dist/_internal/server/jobs/core/__tests__/onProductStockChange.test.d.ts +0 -1
  317. package/dist/_internal/server/jobs/core/__tests__/onProductStockChange.test.js +0 -210
  318. package/dist/_internal/server/jobs/core/__tests__/onReviewWrite.test.d.ts +0 -1
  319. package/dist/_internal/server/jobs/core/__tests__/onReviewWrite.test.js +0 -190
  320. package/dist/_internal/server/jobs/core/__tests__/onUserBanChange.test.d.ts +0 -1
  321. package/dist/_internal/server/jobs/core/__tests__/onUserBanChange.test.js +0 -161
  322. package/dist/_internal/server/jobs/core/__tests__/payoutBatch.test.d.ts +0 -1
  323. package/dist/_internal/server/jobs/core/__tests__/payoutBatch.test.js +0 -302
  324. package/dist/_internal/server/jobs/core/__tests__/pendingOrderTimeout.test.d.ts +0 -1
  325. package/dist/_internal/server/jobs/core/__tests__/pendingOrderTimeout.test.js +0 -96
  326. package/dist/_internal/server/jobs/core/__tests__/triggerEventRaffle.test.d.ts +0 -1
  327. package/dist/_internal/server/jobs/core/__tests__/triggerEventRaffle.test.js +0 -252
  328. package/dist/_internal/server/jobs/core/__tests__/wrapJobHandler.test.d.ts +0 -1
  329. package/dist/_internal/server/jobs/core/__tests__/wrapJobHandler.test.js +0 -129
  330. package/dist/_internal/server/jobs/core/onCatalogueSubmittedForApproval.d.ts +0 -15
  331. package/dist/_internal/server/jobs/core/onCatalogueSubmittedForApproval.js +0 -38
  332. package/dist/_internal/server/providers/index.d.ts +0 -11
  333. package/dist/_internal/server/providers/index.js +0 -11
  334. package/dist/_internal/server/providers/payment/razorpay-mock.d.ts +0 -52
  335. package/dist/_internal/server/providers/payment/razorpay-mock.js +0 -118
  336. package/dist/_internal/server/providers/resolve.d.ts +0 -36
  337. package/dist/_internal/server/providers/resolve.js +0 -31
  338. package/dist/_internal/server/providers/shipping/shiprocket-mock.d.ts +0 -29
  339. package/dist/_internal/server/providers/shipping/shiprocket-mock.js +0 -152
  340. package/dist/_internal/shared/types/__tests__/action-result.test.d.ts +0 -1
  341. package/dist/_internal/shared/types/__tests__/action-result.test.js +0 -65
  342. package/dist/errors/__tests__/error-mapping.test.d.ts +0 -1
  343. package/dist/errors/__tests__/error-mapping.test.js +0 -122
  344. package/dist/errors/__tests__/safe-read.test.d.ts +0 -1
  345. package/dist/errors/__tests__/safe-read.test.js +0 -39
  346. package/dist/features/addresses/repository/__tests__/addresses.repository.test.d.ts +0 -1
  347. package/dist/features/addresses/repository/__tests__/addresses.repository.test.js +0 -386
  348. package/dist/features/admin/components/AdminListingScaffold.d.ts +0 -41
  349. package/dist/features/admin/components/AdminListingScaffold.js +0 -68
  350. package/dist/features/admin/components/QuickActionsPanel.d.ts +0 -15
  351. package/dist/features/admin/components/QuickActionsPanel.js +0 -5
  352. package/dist/features/admin/repository/__tests__/notification.repository.test.d.ts +0 -1
  353. package/dist/features/admin/repository/__tests__/notification.repository.test.js +0 -356
  354. package/dist/features/admin/repository/__tests__/site-settings.repository.test.d.ts +0 -1
  355. package/dist/features/admin/repository/__tests__/site-settings.repository.test.js +0 -298
  356. package/dist/features/auctions/repository/__tests__/bid.repository.test.d.ts +0 -1
  357. package/dist/features/auctions/repository/__tests__/bid.repository.test.js +0 -290
  358. package/dist/features/auctions/repository/auctions.repository.d.ts +0 -12
  359. package/dist/features/auctions/repository/auctions.repository.js +0 -42
  360. package/dist/features/auth/repository/__tests__/session.repository.test.d.ts +0 -1
  361. package/dist/features/auth/repository/__tests__/session.repository.test.js +0 -310
  362. package/dist/features/auth/repository/__tests__/session.test.d.ts +0 -1
  363. package/dist/features/auth/repository/__tests__/session.test.js +0 -146
  364. package/dist/features/auth/repository/__tests__/sms-counter.repository.test.d.ts +0 -1
  365. package/dist/features/auth/repository/__tests__/sms-counter.repository.test.js +0 -171
  366. package/dist/features/auth/repository/__tests__/sms-counter.test.d.ts +0 -1
  367. package/dist/features/auth/repository/__tests__/sms-counter.test.js +0 -88
  368. package/dist/features/auth/repository/__tests__/token.repository.test.d.ts +0 -1
  369. package/dist/features/auth/repository/__tests__/token.repository.test.js +0 -260
  370. package/dist/features/auth/repository/__tests__/token.test.d.ts +0 -1
  371. package/dist/features/auth/repository/__tests__/token.test.js +0 -140
  372. package/dist/features/auth/repository/__tests__/user.repository.test.d.ts +0 -1
  373. package/dist/features/auth/repository/__tests__/user.repository.test.js +0 -352
  374. package/dist/features/auth/repository/__tests__/user.test.d.ts +0 -1
  375. package/dist/features/auth/repository/__tests__/user.test.js +0 -226
  376. package/dist/features/before-after/repository/before-after.repository.d.ts +0 -13
  377. package/dist/features/before-after/repository/before-after.repository.js +0 -36
  378. package/dist/features/before-after/server.d.ts +0 -6
  379. package/dist/features/before-after/server.js +0 -6
  380. package/dist/features/cart/repository/__tests__/cart.repository.test.d.ts +0 -1
  381. package/dist/features/cart/repository/__tests__/cart.repository.test.js +0 -371
  382. package/dist/features/categories/repository/__tests__/categories.repository.test.d.ts +0 -1
  383. package/dist/features/categories/repository/__tests__/categories.repository.test.js +0 -813
  384. package/dist/features/collections/repository/collections.repository.d.ts +0 -8
  385. package/dist/features/collections/repository/collections.repository.js +0 -16
  386. package/dist/features/collections/server.d.ts +0 -6
  387. package/dist/features/collections/server.js +0 -6
  388. package/dist/features/events/repository/__tests__/event.repository.test.d.ts +0 -1
  389. package/dist/features/events/repository/__tests__/event.repository.test.js +0 -299
  390. package/dist/features/faq/repository/__tests__/faqs.repository.test.d.ts +0 -1
  391. package/dist/features/faq/repository/__tests__/faqs.repository.test.js +0 -311
  392. package/dist/features/forms/Form.d.ts +0 -25
  393. package/dist/features/forms/Form.js +0 -37
  394. package/dist/features/history/repository/__tests__/user-history.repository.test.d.ts +0 -1
  395. package/dist/features/history/repository/__tests__/user-history.repository.test.js +0 -180
  396. package/dist/features/homepage/repository/__tests__/carousel.repository.test.d.ts +0 -1
  397. package/dist/features/homepage/repository/__tests__/carousel.repository.test.js +0 -182
  398. package/dist/features/homepage/repository/__tests__/homepage-sections.repository.test.d.ts +0 -1
  399. package/dist/features/homepage/repository/__tests__/homepage-sections.repository.test.js +0 -185
  400. package/dist/features/layout/ListingLayout.d.ts +0 -34
  401. package/dist/features/layout/ListingLayout.js +0 -103
  402. package/dist/features/messages/repository/__tests__/conversations.repository.test.d.ts +0 -1
  403. package/dist/features/messages/repository/__tests__/conversations.repository.test.js +0 -257
  404. package/dist/features/orders/repository/__tests__/orders.repository.test.d.ts +0 -1
  405. package/dist/features/orders/repository/__tests__/orders.repository.test.js +0 -211
  406. package/dist/features/payments/repository/__tests__/payout.repository.test.d.ts +0 -1
  407. package/dist/features/payments/repository/__tests__/payout.repository.test.js +0 -292
  408. package/dist/features/pre-orders/repository/preorders.repository.d.ts +0 -8
  409. package/dist/features/pre-orders/repository/preorders.repository.js +0 -25
  410. package/dist/features/products/repository/__tests__/product-features.repository.test.d.ts +0 -1
  411. package/dist/features/products/repository/__tests__/product-features.repository.test.js +0 -329
  412. package/dist/features/products/repository/__tests__/products.repository.test.d.ts +0 -1
  413. package/dist/features/products/repository/__tests__/products.repository.test.js +0 -607
  414. package/dist/features/promotions/repository/__tests__/claimed-coupons.repository.test.d.ts +0 -1
  415. package/dist/features/promotions/repository/__tests__/claimed-coupons.repository.test.js +0 -219
  416. package/dist/features/promotions/repository/__tests__/coupons.repository.test.d.ts +0 -1
  417. package/dist/features/promotions/repository/__tests__/coupons.repository.test.js +0 -480
  418. package/dist/features/promotions/repository/promotions.repository.d.ts +0 -14
  419. package/dist/features/promotions/repository/promotions.repository.js +0 -43
  420. package/dist/features/reviews/repository/__tests__/reviews.repository.test.d.ts +0 -1
  421. package/dist/features/reviews/repository/__tests__/reviews.repository.test.js +0 -327
  422. package/dist/features/scams/repository/__tests__/scammer.repository.test.d.ts +0 -1
  423. package/dist/features/scams/repository/__tests__/scammer.repository.test.js +0 -385
  424. package/dist/features/search/repository/__tests__/search.repository.test.d.ts +0 -1
  425. package/dist/features/search/repository/__tests__/search.repository.test.js +0 -369
  426. package/dist/features/seller/components/SellerStatCard.d.ts +0 -14
  427. package/dist/features/seller/components/SellerStatCard.js +0 -6
  428. package/dist/features/seller/components/seller-products-styles.d.ts +0 -7
  429. package/dist/features/seller/components/seller-products-styles.js +0 -14
  430. package/dist/features/seller/repository/__tests__/offer.repository.test.d.ts +0 -1
  431. package/dist/features/seller/repository/__tests__/offer.repository.test.js +0 -458
  432. package/dist/features/seller/repository/seller.repository.d.ts +0 -22
  433. package/dist/features/seller/repository/seller.repository.js +0 -72
  434. package/dist/features/site-settings/components/__tests__/ThemeManagerView.test.d.ts +0 -1
  435. package/dist/features/site-settings/components/__tests__/ThemeManagerView.test.js +0 -37
  436. package/dist/features/stores/repository/__tests__/store.repository.test.d.ts +0 -1
  437. package/dist/features/stores/repository/__tests__/store.repository.test.js +0 -261
  438. package/dist/features/stores/repository/stores.repository.d.ts +0 -11
  439. package/dist/features/stores/repository/stores.repository.js +0 -37
  440. package/dist/features/support/repository/__tests__/support.repository.test.d.ts +0 -1
  441. package/dist/features/support/repository/__tests__/support.repository.test.js +0 -312
  442. package/dist/features/wishlist/repository/__tests__/user-wishlist.repository.test.d.ts +0 -1
  443. package/dist/features/wishlist/repository/__tests__/user-wishlist.repository.test.js +0 -139
  444. package/dist/features/wishlist/repository/wishlist.repository.d.ts +0 -13
  445. package/dist/features/wishlist/repository/wishlist.repository.js +0 -31
  446. package/dist/providers/db-firebase/__tests__/filter-aliases.test.d.ts +0 -1
  447. package/dist/providers/db-firebase/__tests__/filter-aliases.test.js +0 -93
  448. package/dist/providers/shipping-shiprocket/index.d.ts +0 -297
  449. package/dist/providers/shipping-shiprocket/index.js +0 -194
  450. package/dist/providers/shipping-shiprocket/shiprocket-provider.d.ts +0 -45
  451. package/dist/providers/shipping-shiprocket/shiprocket-provider.js +0 -168
  452. package/dist/react/contexts/ThemeContext.d.ts +0 -13
  453. package/dist/react/contexts/ThemeContext.js +0 -64
  454. package/dist/schemas/webhooks/shiprocket.d.ts +0 -30
  455. package/dist/schemas/webhooks/shiprocket.js +0 -22
  456. package/dist/seed/actions/demo-seed-actions.d.ts +0 -42
  457. package/dist/seed/actions/demo-seed-actions.js +0 -36
  458. package/dist/seed/actions/index.d.ts +0 -1
  459. package/dist/seed/actions/index.js +0 -1
  460. package/dist/seed/sub-listings-seed-data.d.ts +0 -123
  461. package/dist/seed/sub-listings-seed-data.js +0 -447
  462. package/dist/seed/tester-checklist-seed-data.d.ts +0 -2
  463. package/dist/seed/tester-checklist-seed-data.js +0 -248
  464. package/dist/ui/components/DashboardStatsCard.d.ts +0 -15
  465. package/dist/ui/components/DashboardStatsCard.js +0 -27
  466. package/dist/ui/components/DashboardStatsCard.style.css +0 -68
  467. package/dist/ui/components/DynamicSelect.d.ts +0 -23
  468. package/dist/ui/components/DynamicSelect.js +0 -77
  469. package/dist/ui/components/DynamicSelect.style.css +0 -101
  470. package/dist/ui/components/InlineCreateSelect.d.ts +0 -48
  471. package/dist/ui/components/InlineCreateSelect.js +0 -75
  472. package/dist/ui/components/ListingViewShell.d.ts +0 -37
  473. package/dist/ui/components/ListingViewShell.js +0 -9
  474. package/dist/ui/components/PaginatedMultiSelect.d.ts +0 -28
  475. package/dist/ui/components/PaginatedMultiSelect.js +0 -141
  476. package/dist/ui/components/PaginatedMultiSelect.style.css +0 -272
  477. package/dist/ui/components/SectionTabs.d.ts +0 -19
  478. package/dist/ui/components/SectionTabs.js +0 -66
  479. package/dist/ui/components/SectionTabs.style.css +0 -164
  480. package/dist/ui/components/__tests__/BulkActionBar.test.d.ts +0 -1
  481. package/dist/ui/components/__tests__/BulkActionBar.test.js +0 -96
  482. package/dist/ui/components/__tests__/ListingToolbar.test.d.ts +0 -1
  483. package/dist/ui/components/__tests__/ListingToolbar.test.js +0 -125
  484. package/dist/ui/components/__tests__/new-primitives.test.d.ts +0 -1
  485. package/dist/ui/components/__tests__/new-primitives.test.js +0 -187
@@ -52,7 +52,7 @@ async function cascadePaymentClusterBan(uid, banData) {
52
52
  }
53
53
  }
54
54
  export async function runHardBanCascade(input, ctx) {
55
- const { uid, reason, bannedBy } = input;
55
+ const { uid, reason, bannedBy, expiresAt, fraudOrderId } = input;
56
56
  const target = await userRepository.findById(uid);
57
57
  if (!target) {
58
58
  return {
@@ -81,6 +81,8 @@ export async function runHardBanCascade(input, ctx) {
81
81
  hardBanReason: reason,
82
82
  hardBannedAt: new Date(),
83
83
  hardBannedBy: bannedBy,
84
+ hardBanExpiresAt: expiresAt ?? null,
85
+ ...(fraudOrderId ? { hardBanFraudOrderId: fraudOrderId } : {}),
84
86
  });
85
87
  // 3. Delete active sessions
86
88
  try {
@@ -125,7 +127,12 @@ export async function runHardBanCascade(input, ctx) {
125
127
  error: err instanceof Error ? err.message : String(err),
126
128
  });
127
129
  }
128
- // 6. Cascade address ban + cross-account cluster ban
130
+ // 6. Cascade address ban + cross-account cluster ban. Note: this bans the
131
+ // ADDRESS record for other accounts sharing a hash cluster, not those
132
+ // accounts' full status — `AddressDocument.banStatus` has no expiry
133
+ // concept, so a temporary hard-ban's cluster cascade is scoped the same
134
+ // as a permanent one's; only the primary `uid`'s account-level ban is
135
+ // ever time-bound.
129
136
  try {
130
137
  const banData = { banReason: `User hard-banned: ${reason}`, bannedBy };
131
138
  await addressesRepository.banAllForOwner("user", uid, banData);
@@ -155,12 +162,16 @@ export async function runHardBanCascade(input, ctx) {
155
162
  try {
156
163
  const siteSettings = await siteSettingsRepository.getSingleton();
157
164
  const supportEmail = siteSettings.contact?.email || "support@example.com";
165
+ const title = expiresAt ? "Account temporarily suspended" : "Account permanently suspended";
166
+ const message = expiresAt
167
+ ? `Your account has been suspended for 7 days. Reason: ${reason}. Access will be automatically restored on ${expiresAt.toDateString()}. You may appeal sooner by emailing ${supportEmail}.`
168
+ : `Your account has been permanently suspended. Reason: ${reason}. You may appeal by emailing ${supportEmail}.`;
158
169
  await sendNotification({
159
170
  userId: uid,
160
171
  type: "account_action",
161
172
  priority: "high",
162
- title: "Account permanently suspended",
163
- message: `Your account has been permanently suspended. Reason: ${reason}. You may appeal by emailing ${supportEmail}.`,
173
+ title,
174
+ message,
164
175
  relatedId: uid,
165
176
  relatedType: "user",
166
177
  });
@@ -0,0 +1,16 @@
1
+ import type { JobContext } from "../runtime/types";
2
+ /**
3
+ * Reinstatement sweep for temporary hard-bans (Tier PP — 7-day fraud-reject
4
+ * bans) whose `hardBanExpiresAt` has passed. Reversal scope is deliberately
5
+ * narrow — only what the ban itself directly controlled:
6
+ * - Re-enable Firebase Auth login.
7
+ * - Clear `isDisabled`, stamp `hardBanReinstatedAt` (keeps `hardBanReason`/
8
+ * `hardBannedAt`/`hardBannedBy`/`hardBanExpiresAt` as historical record).
9
+ * Deliberately NOT reversed — these need separate admin/appeal action:
10
+ * - The seller's store stays `suspended` (hardBanCascade stage 4).
11
+ * - Cancelled bids stay cancelled (stage 5).
12
+ * - Cross-account address/payment-method cluster bans stay banned
13
+ * (stages 6/7 — independent fraud-ring findings, not solely contingent
14
+ * on this user's temporary status).
15
+ */
16
+ export declare function runHardBanReinstatement(ctx: JobContext): Promise<void>;
@@ -0,0 +1,63 @@
1
+ import { normalizeError } from "../../../../errors/normalize";
2
+ import { userRepository } from "../../../../repositories";
3
+ import { sendNotification } from "../../../../features/admin/actions/notification-actions";
4
+ import { getAdminAuth } from "../../../../providers/db-firebase";
5
+ /**
6
+ * Reinstatement sweep for temporary hard-bans (Tier PP — 7-day fraud-reject
7
+ * bans) whose `hardBanExpiresAt` has passed. Reversal scope is deliberately
8
+ * narrow — only what the ban itself directly controlled:
9
+ * - Re-enable Firebase Auth login.
10
+ * - Clear `isDisabled`, stamp `hardBanReinstatedAt` (keeps `hardBanReason`/
11
+ * `hardBannedAt`/`hardBannedBy`/`hardBanExpiresAt` as historical record).
12
+ * Deliberately NOT reversed — these need separate admin/appeal action:
13
+ * - The seller's store stays `suspended` (hardBanCascade stage 4).
14
+ * - Cancelled bids stay cancelled (stage 5).
15
+ * - Cross-account address/payment-method cluster bans stay banned
16
+ * (stages 6/7 — independent fraud-ring findings, not solely contingent
17
+ * on this user's temporary status).
18
+ */
19
+ export async function runHardBanReinstatement(ctx) {
20
+ ctx.logger.info("Scanning temporary hard-bans past their expiry");
21
+ const expired = await userRepository.getExpiredHardBans();
22
+ if (expired.length === 0) {
23
+ ctx.logger.info("No expired hard bans found");
24
+ return;
25
+ }
26
+ let reinstated = 0;
27
+ for (const user of expired) {
28
+ try {
29
+ try {
30
+ await getAdminAuth().updateUser(user.uid, { disabled: false });
31
+ }
32
+ catch (err) {
33
+ void normalizeError(err);
34
+ ctx.logger.warn("hard-ban reinstatement: Auth re-enable failed (non-fatal)", {
35
+ uid: user.uid,
36
+ error: err instanceof Error ? err.message : String(err),
37
+ });
38
+ }
39
+ await userRepository.update(user.uid, {
40
+ isDisabled: false,
41
+ hardBanReinstatedAt: ctx.now,
42
+ });
43
+ reinstated += 1;
44
+ }
45
+ catch (err) {
46
+ void normalizeError(err);
47
+ ctx.logger.error("Failed to reinstate expired hard ban", err, { uid: user.uid });
48
+ }
49
+ }
50
+ await Promise.allSettled(expired.map((user) => sendNotification({
51
+ userId: user.uid,
52
+ type: "account_action",
53
+ priority: "normal",
54
+ title: "Account access restored",
55
+ message: "Your account access has been restored. If your seller store was suspended, contact support to reactivate it.",
56
+ relatedId: user.uid,
57
+ relatedType: "user",
58
+ })));
59
+ ctx.logger.info("Hard ban reinstatement sweep complete", {
60
+ scanned: expired.length,
61
+ reinstated,
62
+ });
63
+ }
@@ -30,7 +30,9 @@ async function runHardBanCascadeJob(payload, ctx) {
30
30
  const uid = String(payload.uid ?? "");
31
31
  const reason = String(payload.reason ?? "");
32
32
  const bannedBy = String(payload.bannedBy ?? "");
33
- return runHardBanCascade({ uid, reason, bannedBy }, ctx);
33
+ const expiresAt = typeof payload.expiresAt === "string" ? new Date(payload.expiresAt) : undefined;
34
+ const fraudOrderId = typeof payload.fraudOrderId === "string" ? payload.fraudOrderId : undefined;
35
+ return runHardBanCascade({ uid, reason, bannedBy, expiresAt, fraudOrderId }, ctx);
34
36
  }
35
37
  async function runResetOtpVerificationJob(_payload, ctx) {
36
38
  return runResetOtpVerification(ctx);
@@ -35,7 +35,7 @@ export async function handleScamReportCreate(input, ctx) {
35
35
  pageSize: 100,
36
36
  });
37
37
  const scamTypeLabel = scamType ? (SCAM_TYPE_LABELS[scamType] ?? scamType) : "Unknown";
38
- const amountStr = amountLost ? ` ₹${(amountLost / 100).toLocaleString("en-IN")}` : "";
38
+ const amountStr = amountLost ? ` ₹${amountLost.toLocaleString("en-IN")}` : "";
39
39
  const platformStr = scamPlatform ? ` via ${scamPlatform}` : "";
40
40
  await Promise.all(result.items.filter((e) => !!e.id).map((employee) => sendNotification({
41
41
  userId: employee.id,
@@ -0,0 +1,10 @@
1
+ import type { JobContext } from "../runtime/types";
2
+ /**
3
+ * 2-hour auto-approve safety net — a manual-payment proof nobody has acted
4
+ * on (no admin approve / re-upload-request / fraud-reject) within 2 hours of
5
+ * submission is auto-confirmed, exactly mirroring `adminVerifyPaymentAction`'s
6
+ * effect, plus `autoApproved`/`autoApprovedAt` so it's visibly distinguishable
7
+ * from a manually-reviewed order. Buyer/seller can raise a dispute afterward
8
+ * via `raiseOrderDisputeAction` — this sweep never reverses itself.
9
+ */
10
+ export declare function runPaymentReviewAutoApprove(ctx: JobContext): Promise<void>;
@@ -0,0 +1,60 @@
1
+ import { orderRepository } from "../../../../repositories";
2
+ import { sendNotification } from "../../../../features/admin/actions/notification-actions";
3
+ import { normalizeError } from "../../../../errors/normalize";
4
+ import { ORDER_MESSAGES } from "../handlers/messages";
5
+ const AUTO_APPROVE_HOURS = 2;
6
+ /**
7
+ * 2-hour auto-approve safety net — a manual-payment proof nobody has acted
8
+ * on (no admin approve / re-upload-request / fraud-reject) within 2 hours of
9
+ * submission is auto-confirmed, exactly mirroring `adminVerifyPaymentAction`'s
10
+ * effect, plus `autoApproved`/`autoApprovedAt` so it's visibly distinguishable
11
+ * from a manually-reviewed order. Buyer/seller can raise a dispute afterward
12
+ * via `raiseOrderDisputeAction` — this sweep never reverses itself.
13
+ */
14
+ export async function runPaymentReviewAutoApprove(ctx) {
15
+ ctx.logger.info(`Scanning unreviewed payment proofs > ${AUTO_APPROVE_HOURS}h old`);
16
+ const unreviewed = await orderRepository.getUnreviewedProofPastDeadline(AUTO_APPROVE_HOURS);
17
+ if (unreviewed.length === 0) {
18
+ ctx.logger.info("No unreviewed payment proofs past the auto-approve window");
19
+ return;
20
+ }
21
+ let approved = 0;
22
+ for (const entry of unreviewed) {
23
+ try {
24
+ await orderRepository.update(entry.id, {
25
+ paymentStatus: "paid",
26
+ paymentId: entry.data.paymentTransactionId ?? entry.data.paymentId ?? `manual-${entry.id}`,
27
+ status: "processing",
28
+ paymentRecord: {
29
+ method: "manual",
30
+ transactionId: entry.data.paymentTransactionId,
31
+ proofUrl: entry.data.paymentProofUrl,
32
+ amount: entry.data.totalPrice,
33
+ paidAt: ctx.now,
34
+ verifiedBy: "system:auto-approve",
35
+ verificationMethod: "manual_review",
36
+ },
37
+ autoApproved: true,
38
+ autoApprovedAt: ctx.now,
39
+ });
40
+ approved += 1;
41
+ }
42
+ catch (err) {
43
+ void normalizeError(err);
44
+ ctx.logger.error("Failed to auto-approve payment proof", err, { orderId: entry.id });
45
+ }
46
+ }
47
+ await Promise.allSettled(unreviewed.map((entry) => sendNotification({
48
+ userId: entry.data.userId,
49
+ type: "payment_review",
50
+ priority: "normal",
51
+ title: ORDER_MESSAGES.AUTO_APPROVED_TITLE,
52
+ message: ORDER_MESSAGES.AUTO_APPROVED_MESSAGE(entry.data.productTitle),
53
+ relatedId: entry.id,
54
+ relatedType: "order",
55
+ })));
56
+ ctx.logger.info("Payment review auto-approve sweep complete", {
57
+ scanned: unreviewed.length,
58
+ approved,
59
+ });
60
+ }
@@ -0,0 +1,15 @@
1
+ import type { JobContext } from "../runtime/types";
2
+ /**
3
+ * 15-minute payment window sweep — cancels + restocks any `upi_manual`/
4
+ * `cash`/`emi` order still `pending`/`pending` with no proof uploaded past
5
+ * its `paymentDeadline`. Runs every 5 minutes (`EVERY_5_MIN`), so an order
6
+ * can overshoot its 15-minute deadline by up to ~5 minutes before this
7
+ * catches it — acceptable, matches the existing tight-interval precedent
8
+ * (`prizeRevealOpen`/`prizeRevealClose`) rather than inventing a 1-minute
9
+ * cron that would multiply invocation cost for marginal UX gain.
10
+ *
11
+ * Orders that already have a `paymentProofUrl` are excluded by the
12
+ * repository query — those are the 2-hour auto-approve sweep's domain
13
+ * (`paymentReviewAutoApprove`), not this one's.
14
+ */
15
+ export declare function runPaymentWindowTimeout(ctx: JobContext): Promise<void>;
@@ -0,0 +1,59 @@
1
+ import { orderRepository } from "../../../../repositories";
2
+ import { normalizeError } from "../../../../errors/normalize";
3
+ import { sendNotification } from "../../../../features/admin/actions/notification-actions";
4
+ import { restoreStockForOrder } from "../../features/checkout/stock-restore";
5
+ import { OrderStatusValues } from "../../../../features/orders/schemas/firestore";
6
+ import { PAYMENT_WINDOW_EXPIRED_REASON } from "../../../../features/orders/constants/payment-window";
7
+ import { ORDER_MESSAGES } from "../handlers/messages";
8
+ /**
9
+ * 15-minute payment window sweep — cancels + restocks any `upi_manual`/
10
+ * `cash`/`emi` order still `pending`/`pending` with no proof uploaded past
11
+ * its `paymentDeadline`. Runs every 5 minutes (`EVERY_5_MIN`), so an order
12
+ * can overshoot its 15-minute deadline by up to ~5 minutes before this
13
+ * catches it — acceptable, matches the existing tight-interval precedent
14
+ * (`prizeRevealOpen`/`prizeRevealClose`) rather than inventing a 1-minute
15
+ * cron that would multiply invocation cost for marginal UX gain.
16
+ *
17
+ * Orders that already have a `paymentProofUrl` are excluded by the
18
+ * repository query — those are the 2-hour auto-approve sweep's domain
19
+ * (`paymentReviewAutoApprove`), not this one's.
20
+ */
21
+ export async function runPaymentWindowTimeout(ctx) {
22
+ ctx.logger.info("Scanning orders past their 15-minute payment deadline");
23
+ const expired = await orderRepository.getExpiredPaymentDeadlines();
24
+ if (expired.length === 0) {
25
+ ctx.logger.info("No expired payment-window orders found");
26
+ return;
27
+ }
28
+ let restored = 0;
29
+ for (const entry of expired) {
30
+ try {
31
+ await restoreStockForOrder(ctx.db, { ...entry.data, id: entry.id }, {
32
+ status: OrderStatusValues.CANCELLED,
33
+ cancellationDate: ctx.now,
34
+ cancellationReason: PAYMENT_WINDOW_EXPIRED_REASON,
35
+ updatedAt: ctx.now,
36
+ });
37
+ restored += 1;
38
+ }
39
+ catch (err) {
40
+ void normalizeError(err);
41
+ ctx.logger.error("Failed to cancel + restore stock for expired payment-window order", err, {
42
+ orderId: entry.id,
43
+ });
44
+ }
45
+ }
46
+ await Promise.allSettled(expired.map((entry) => sendNotification({
47
+ userId: entry.data.userId,
48
+ type: "order_cancelled",
49
+ priority: "normal",
50
+ title: ORDER_MESSAGES.CANCELLED_PAYMENT_WINDOW_TITLE,
51
+ message: ORDER_MESSAGES.CANCELLED_PAYMENT_WINDOW_MESSAGE(entry.data.productTitle),
52
+ relatedId: entry.id,
53
+ relatedType: "order",
54
+ })));
55
+ ctx.logger.info("Payment window timeout sweep complete", {
56
+ scanned: expired.length,
57
+ restored,
58
+ });
59
+ }
@@ -1,2 +1,9 @@
1
1
  import type { JobContext } from "../runtime/types";
2
+ /**
3
+ * COD 24h safety net. Orders with a `paymentDeadline` set (upi_manual/cash/
4
+ * emi) are excluded — those belong to the 15-minute `paymentWindowTimeout`
5
+ * sweep instead (Tier PP), which fires far sooner. Leaving them in this
6
+ * job's scope too would just be redundant double-processing against the
7
+ * same order under two different `cancellationReason`s.
8
+ */
2
9
  export declare function runPendingOrderTimeout(ctx: JobContext): Promise<void>;
@@ -1,28 +1,54 @@
1
1
  import { orderRepository } from "../../../../repositories";
2
+ import { normalizeError } from "../../../../errors/normalize";
2
3
  import { sendNotification } from "../../../../features/admin/actions/notification-actions";
4
+ import { restoreStockForOrder } from "../../features/checkout/stock-restore";
5
+ import { OrderStatusValues } from "../../../../features/orders/schemas/firestore";
3
6
  import { ORDER_MESSAGES } from "../handlers/messages";
4
7
  const DEFAULT_TIMEOUT_HOURS = 24;
8
+ /**
9
+ * COD 24h safety net. Orders with a `paymentDeadline` set (upi_manual/cash/
10
+ * emi) are excluded — those belong to the 15-minute `paymentWindowTimeout`
11
+ * sweep instead (Tier PP), which fires far sooner. Leaving them in this
12
+ * job's scope too would just be redundant double-processing against the
13
+ * same order under two different `cancellationReason`s.
14
+ */
5
15
  export async function runPendingOrderTimeout(ctx) {
6
16
  const timeoutHours = Number(ctx.env("ORDER_TIMEOUT_HOURS") ?? DEFAULT_TIMEOUT_HOURS);
7
17
  ctx.logger.info(`Scanning orders unpaid > ${timeoutHours}h`);
8
- const timedOut = await orderRepository.getTimedOutPending(timeoutHours);
18
+ const timedOutAll = await orderRepository.getTimedOutPending(timeoutHours);
19
+ const timedOut = timedOutAll.filter((entry) => !entry.data.paymentDeadline);
9
20
  if (timedOut.length === 0) {
10
21
  ctx.logger.info("No timed-out pending orders found");
11
22
  return;
12
23
  }
13
- const batch = ctx.db.batch();
24
+ let restored = 0;
14
25
  for (const entry of timedOut) {
15
- orderRepository.cancelInBatch(batch, entry.ref);
26
+ try {
27
+ // Stock decremented at checkout for every payment method (including
28
+ // COD) was never restored on timeout-cancel before this fix.
29
+ await restoreStockForOrder(ctx.db, { ...entry.data, id: entry.id }, {
30
+ status: OrderStatusValues.CANCELLED,
31
+ cancellationDate: ctx.now,
32
+ cancellationReason: "payment_timeout",
33
+ updatedAt: ctx.now,
34
+ });
35
+ restored += 1;
36
+ }
37
+ catch (err) {
38
+ void normalizeError(err);
39
+ ctx.logger.error("Failed to cancel + restore stock for timed-out order", err, {
40
+ orderId: entry.id,
41
+ });
42
+ }
16
43
  }
17
- await batch.commit();
18
44
  await Promise.allSettled(timedOut.map((entry) => sendNotification({
19
45
  userId: entry.data.userId,
20
46
  type: "order_cancelled",
21
47
  priority: "normal",
22
48
  title: ORDER_MESSAGES.CANCELLED_TITLE,
23
49
  message: ORDER_MESSAGES.CANCELLED_TIMEOUT_MESSAGE(entry.data.productTitle, timeoutHours),
24
- relatedId: entry.data.id,
50
+ relatedId: entry.id,
25
51
  relatedType: "order",
26
52
  })));
27
- ctx.logger.info("Pending order timeout complete", { cancelled: timedOut.length });
53
+ ctx.logger.info("Pending order timeout complete", { cancelled: timedOut.length, restored });
28
54
  }
@@ -0,0 +1,2 @@
1
+ import type { ScheduleHandler } from "../runtime/types";
2
+ export declare const hardBanReinstatementHandler: ScheduleHandler;
@@ -0,0 +1,2 @@
1
+ import { runHardBanReinstatement } from "../core/hardBanReinstatement";
2
+ export const hardBanReinstatementHandler = runHardBanReinstatement;
@@ -24,6 +24,9 @@ export { onReviewWriteHandler } from "./onReviewWrite";
24
24
  export { promotionsHandler, type PromotionsCallableResult } from "./promotions";
25
25
  export { mediaTmpCleanupHandler } from "./mediaTmpCleanup";
26
26
  export { pendingOrderTimeoutHandler } from "./pendingOrderTimeout";
27
+ export { paymentWindowTimeoutHandler } from "./paymentWindowTimeout";
28
+ export { hardBanReinstatementHandler } from "./hardBanReinstatement";
29
+ export { paymentReviewAutoApproveHandler } from "./paymentReviewAutoApprove";
27
30
  export { productStatsSyncHandler } from "./productStatsSync";
28
31
  export { positionsReconcileHandler } from "./positionsReconcile";
29
32
  export { payoutBatchHandler } from "./payoutBatch";
@@ -24,6 +24,9 @@ export { onReviewWriteHandler } from "./onReviewWrite";
24
24
  export { promotionsHandler } from "./promotions";
25
25
  export { mediaTmpCleanupHandler } from "./mediaTmpCleanup";
26
26
  export { pendingOrderTimeoutHandler } from "./pendingOrderTimeout";
27
+ export { paymentWindowTimeoutHandler } from "./paymentWindowTimeout";
28
+ export { hardBanReinstatementHandler } from "./hardBanReinstatement";
29
+ export { paymentReviewAutoApproveHandler } from "./paymentReviewAutoApprove";
27
30
  export { productStatsSyncHandler } from "./productStatsSync";
28
31
  export { positionsReconcileHandler } from "./positionsReconcile";
29
32
  export { payoutBatchHandler } from "./payoutBatch";
@@ -18,6 +18,10 @@ export declare const BID_MESSAGES: {
18
18
  export declare const ORDER_MESSAGES: {
19
19
  CANCELLED_TITLE: string;
20
20
  CANCELLED_TIMEOUT_MESSAGE: (productTitle: string, hours: number) => string;
21
+ CANCELLED_PAYMENT_WINDOW_TITLE: string;
22
+ CANCELLED_PAYMENT_WINDOW_MESSAGE: (productTitle: string) => string;
23
+ AUTO_APPROVED_TITLE: string;
24
+ AUTO_APPROVED_MESSAGE: (productTitle: string) => string;
21
25
  CONFIRMED_TITLE: string;
22
26
  CONFIRMED_MESSAGE: (productTitle: string) => string;
23
27
  SHIPPED_TITLE: string;
@@ -18,6 +18,10 @@ export const BID_MESSAGES = {
18
18
  export const ORDER_MESSAGES = {
19
19
  CANCELLED_TITLE: "Order cancelled",
20
20
  CANCELLED_TIMEOUT_MESSAGE: (productTitle, hours) => `Your order for "${productTitle}" was cancelled because payment was not received within ${hours} hours.`,
21
+ CANCELLED_PAYMENT_WINDOW_TITLE: "Payment window expired",
22
+ CANCELLED_PAYMENT_WINDOW_MESSAGE: (productTitle) => `Your order for "${productTitle}" was cancelled because payment wasn't completed within the 15-minute window. The item is back in stock — you're welcome to order again.`,
23
+ AUTO_APPROVED_TITLE: "Payment auto-confirmed",
24
+ AUTO_APPROVED_MESSAGE: (productTitle) => `Your payment proof for "${productTitle}" was auto-confirmed after 2 hours without manual review. If something looks wrong, you can raise a dispute from your order.`,
21
25
  CONFIRMED_TITLE: "Order confirmed ✅",
22
26
  CONFIRMED_MESSAGE: (productTitle) => `Your order for "${productTitle}" has been confirmed and is being prepared.`,
23
27
  SHIPPED_TITLE: "Your order has shipped 📦",
@@ -5,12 +5,12 @@
5
5
  * (a) any write to shipmentLots/{lotId} (itemCount/revenue changed via
6
6
  * Function #1, or the admin edited weight/cost/remainder fields)
7
7
  * (b) any write to procurementShipments/{shipmentId} (admin edited
8
- * customsTotalPaise/shippingTotalPaise/laborHoursSpent/status)
8
+ * customsTotal/shippingTotal/laborHoursSpent/status)
9
9
  *
10
10
  * Both re-run the same cross-lot allocation: read every sibling lot
11
11
  * (bounded ≤10), call the shared pure allocateShipmentCosts(), batch-write
12
- * each lot's customsAllocatedPaise/shippingAllocatedPaise/totalLandedCostPaise/
13
- * projectedRevenuePaise/projectedProfitPaise plus the shipment's persisted
12
+ * each lot's customsAllocated/shippingAllocated/totalLandedCost/
13
+ * projectedRevenue/projectedProfit plus the shipment's persisted
14
14
  * `totals` + `totalsComputedAt`. Also keeps ShipmentLot.shipmentStatus in
15
15
  * sync with its parent so the Projections list can filter on it directly.
16
16
  *
@@ -10,23 +10,23 @@ async function recomputeShipmentAllocation(shipmentId, ctx) {
10
10
  const lots = lotsSnap.docs.map((doc) => ({ id: doc.id, ...doc.data() }));
11
11
  const allocationInputs = lots.map((lot) => ({
12
12
  id: lot.id,
13
- purchaseCostPaise: lot.purchaseCostPaise ?? 0,
13
+ purchaseCost: lot.purchaseCost ?? 0,
14
14
  weightGrams: lot.weightGrams ?? 0,
15
- mainItemsProjectedRevenuePaise: lot.mainItemsProjectedRevenuePaise ?? 0,
16
- remainderEstimatedValuePaise: lot.remainderEstimatedValuePaise,
15
+ mainItemsProjectedRevenue: lot.mainItemsProjectedRevenue ?? 0,
16
+ remainderEstimatedValue: lot.remainderEstimatedValue,
17
17
  itemCount: lot.itemCount ?? 0,
18
18
  }));
19
19
  // Site-settings labor rate could be read here; falls back to the
20
20
  // shipment's own snapshot rate + a fixed max-hours-per-day default,
21
21
  // matching what the admin editor's preview also uses.
22
- const laborRatePaisePerHour = shipment.laborRatePaisePerHour ?? 0;
22
+ const laborRatePerHour = shipment.laborRatePerHour ?? 0;
23
23
  const laborHoursSpent = shipment.laborHoursSpent ?? 0;
24
24
  const { perLot, totals } = allocateShipmentCosts({
25
25
  lots: allocationInputs,
26
- customsTotalPaise: shipment.customsTotalPaise ?? 0,
27
- shippingTotalPaise: shipment.shippingTotalPaise ?? 0,
26
+ customsTotal: shipment.customsTotal ?? 0,
27
+ shippingTotal: shipment.shippingTotal ?? 0,
28
28
  laborHoursSpent,
29
- laborRatePaisePerHour,
29
+ laborRatePerHour,
30
30
  maxHoursPerDay: DEFAULT_MAX_HOURS_PER_DAY,
31
31
  });
32
32
  const batch = ctx.db.batch();
@@ -34,11 +34,11 @@ async function recomputeShipmentAllocation(shipmentId, ctx) {
34
34
  for (const lot of lots) {
35
35
  const computed = perLot[lot.id];
36
36
  const statusChanged = lot.shipmentStatus !== shipment.status;
37
- const valuesChanged = lot.customsAllocatedPaise !== computed.customsAllocatedPaise ||
38
- lot.shippingAllocatedPaise !== computed.shippingAllocatedPaise ||
39
- lot.totalLandedCostPaise !== computed.totalLandedCostPaise ||
40
- lot.projectedRevenuePaise !== computed.projectedRevenuePaise ||
41
- lot.projectedProfitPaise !== computed.projectedProfitPaise;
37
+ const valuesChanged = lot.customsAllocated !== computed.customsAllocated ||
38
+ lot.shippingAllocated !== computed.shippingAllocated ||
39
+ lot.totalLandedCost !== computed.totalLandedCost ||
40
+ lot.projectedRevenue !== computed.projectedRevenue ||
41
+ lot.projectedProfit !== computed.projectedProfit;
42
42
  if (statusChanged || valuesChanged) {
43
43
  anyLotChanged = true;
44
44
  batch.update(ctx.db.collection("shipmentLots").doc(lot.id), {
@@ -2,7 +2,7 @@
2
2
  * Function #1 of the procurement-shipments cascade.
3
3
  *
4
4
  * Fires on any write to shipmentItems/{itemId}. Recomputes the owning lot's
5
- * item-derived aggregates (itemCount, mainItemsProjectedRevenuePaise) by
5
+ * item-derived aggregates (itemCount, mainItemsProjectedRevenue) by
6
6
  * summing all of that lot's items (bounded ≤500 — Firestore's own batch cap).
7
7
  * Writing those aggregates onto shipmentLots/{lotId} is what triggers
8
8
  * Function #2 (onShipmentLotWrite) to redo the cross-lot cost allocation.
@@ -3,14 +3,14 @@ export const onShipmentItemWriteHandler = async (event, ctx) => {
3
3
  if (!lotId)
4
4
  return;
5
5
  const itemsSnap = await ctx.db.collection("shipmentItems").where("lotId", "==", lotId).get();
6
- let mainItemsProjectedRevenuePaise = 0;
6
+ let mainItemsProjectedRevenue = 0;
7
7
  itemsSnap.docs.forEach((doc) => {
8
8
  const item = doc.data();
9
9
  if (item.isForSelfUse)
10
10
  return;
11
11
  const price = item.price ?? 0;
12
12
  const quantity = item.quantity ?? 0;
13
- mainItemsProjectedRevenuePaise += price * quantity;
13
+ mainItemsProjectedRevenue += price * quantity;
14
14
  });
15
15
  const itemCount = itemsSnap.size;
16
16
  const lotRef = ctx.db.collection("shipmentLots").doc(lotId);
@@ -18,9 +18,9 @@ export const onShipmentItemWriteHandler = async (event, ctx) => {
18
18
  if (!lotSnap.exists)
19
19
  return;
20
20
  const lot = lotSnap.data() ?? {};
21
- if (lot.itemCount === itemCount && lot.mainItemsProjectedRevenuePaise === mainItemsProjectedRevenuePaise) {
21
+ if (lot.itemCount === itemCount && lot.mainItemsProjectedRevenue === mainItemsProjectedRevenue) {
22
22
  return; // no-op — breaks the write→trigger→write cycle once settled
23
23
  }
24
- await lotRef.update({ itemCount, mainItemsProjectedRevenuePaise, updatedAt: ctx.now });
25
- ctx.logger.info("Recomputed lot item aggregates", { lotId, itemCount, mainItemsProjectedRevenuePaise });
24
+ await lotRef.update({ itemCount, mainItemsProjectedRevenue, updatedAt: ctx.now });
25
+ ctx.logger.info("Recomputed lot item aggregates", { lotId, itemCount, mainItemsProjectedRevenue });
26
26
  };
@@ -0,0 +1,2 @@
1
+ import type { ScheduleHandler } from "../runtime/types";
2
+ export declare const paymentReviewAutoApproveHandler: ScheduleHandler;
@@ -0,0 +1,2 @@
1
+ import { runPaymentReviewAutoApprove } from "../core/paymentReviewAutoApprove";
2
+ export const paymentReviewAutoApproveHandler = runPaymentReviewAutoApprove;
@@ -0,0 +1,2 @@
1
+ import type { ScheduleHandler } from "../runtime/types";
2
+ export declare const paymentWindowTimeoutHandler: ScheduleHandler;
@@ -0,0 +1,2 @@
1
+ import { runPaymentWindowTimeout } from "../core/paymentWindowTimeout";
2
+ export const paymentWindowTimeoutHandler = runPaymentWindowTimeout;
@@ -1010,6 +1010,33 @@ export const ACTIONS = {
1010
1010
  confirmLabel: "Yes, verify",
1011
1011
  },
1012
1012
  },
1013
+ "request-payment-reupload": {
1014
+ id: "admin.request-payment-reupload",
1015
+ label: "Request Re-upload",
1016
+ ariaLabel: "Ask the buyer to re-upload a corrected payment proof",
1017
+ description: "Clears the current proof and gives the buyer 15 more minutes to resubmit — for honest mistakes (blurry screenshot, wrong amount), not fraud.",
1018
+ kind: "secondary",
1019
+ permissions: ["admin", "moderator"],
1020
+ confirmation: {
1021
+ title: "Request a proof re-upload?",
1022
+ body: "The buyer's current proof will be cleared and they'll get 15 more minutes to resubmit. Use this for honest mistakes, not suspected fraud.",
1023
+ confirmLabel: "Request re-upload",
1024
+ },
1025
+ },
1026
+ "reject-payment-fraud": {
1027
+ id: "admin.reject-payment-fraud",
1028
+ label: "Reject as Fraudulent",
1029
+ ariaLabel: "Reject this payment proof as fraudulent, cancel the order, and ban the account",
1030
+ description: "Cancels the order, restores stock, and triggers a temporary 7-day full-account ban. Use only for suspected deliberate fraud, not honest mistakes.",
1031
+ kind: "danger",
1032
+ permissions: ["admin", "moderator"],
1033
+ confirmation: {
1034
+ title: "Reject as fraudulent?",
1035
+ body: "This cancels the order, returns the item to stock, and suspends the buyer's account for 7 days. This is severe — use only for suspected deliberate fraud, not an honest mistake.",
1036
+ confirmLabel: "Reject and ban 7 days",
1037
+ confirmKind: "danger",
1038
+ },
1039
+ },
1013
1040
  "verify-vendor": {
1014
1041
  id: "admin.verify-vendor",
1015
1042
  label: "Verify vendor",
@@ -1,3 +1,4 @@
1
+ import { roundRupees } from "../../../utils/number.formatter";
1
2
  // SB-UNI-5 2026-05-13 — bundle cart-lines use item.price (locked bundle price
2
3
  // at add-time); regular lines use product.price (current Firestore). Prevents
3
4
  // stale cart-cached prices from being charged on COD/UPI orders.
@@ -18,7 +19,7 @@ export function computePreOrderDepositAmount(group, defaultDepositPercent) {
18
19
  const raw = group.reduce((sum, { item, product }) => {
19
20
  const lineTotal = unitPriceFor(item, product) * item.quantity;
20
21
  const pct = product.preOrderDepositPercent ?? defaultDepositPercent;
21
- return sum + lineTotal * (pct / 100);
22
+ return sum + lineTotal * (pct / 100); // audit-money-units-ok: percentage divisor, not paise
22
23
  }, 0);
23
- return Math.round(raw * 100) / 100;
24
+ return roundRupees(raw);
24
25
  }
@@ -15,6 +15,7 @@ export const DEFAULT_LISTING_RULE = {
15
15
  splitMultipleOrders: (item) => [item],
16
16
  preflightChecks: (_pairs) => { },
17
17
  stockDecrementExtras: (_product, _qty) => ({}),
18
+ stockIncrementExtras: (_product, _qty) => ({}),
18
19
  decorateOrderItem: (line, product) => ({
19
20
  ...line,
20
21
  ...(product.listingType ? { listingType: product.listingType } : {}),
@@ -25,4 +25,11 @@ export const preOrderRule = {
25
25
  preOrderCurrentCount: (product.preOrderCurrentCount ?? 0) + quantity,
26
26
  };
27
27
  },
28
+ stockIncrementExtras: (product, quantity) => {
29
+ if (product.listingType !== "pre-order")
30
+ return {};
31
+ return {
32
+ preOrderCurrentCount: Math.max(0, (product.preOrderCurrentCount ?? 0) - quantity),
33
+ };
34
+ },
28
35
  };