@mohasinac/appkit 3.8.2 → 3.9.1

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 (508) 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/AdminSectionsView.js +4 -4
  103. package/dist/features/admin/components/AdminSiteSettingsView.js +11 -11
  104. package/dist/features/admin/components/AdminStickersView.js +2 -2
  105. package/dist/features/admin/components/AdminSupportTicketDetailView.js +1 -1
  106. package/dist/features/admin/components/sections/adminSectionsBuildParse.js +13 -5
  107. package/dist/features/admin/components/sections/adminSectionsTypes.d.ts +4 -0
  108. package/dist/features/admin/components/sections/adminSectionsTypes.js +9 -5
  109. package/dist/features/admin/hooks/useAdminListingData.d.ts +1 -1
  110. package/dist/features/admin/hooks/useAdminListingData.js +3 -2
  111. package/dist/features/admin/schemas/firestore.d.ts +9 -7
  112. package/dist/features/admin/schemas/firestore.js +4 -3
  113. package/dist/features/auctions/components/AuctionBidsTable.js +3 -3
  114. package/dist/features/auth/checkout-value-otp.d.ts +46 -0
  115. package/dist/features/auth/checkout-value-otp.js +73 -0
  116. package/dist/features/auth/repository/user.repository.d.ts +6 -0
  117. package/dist/features/auth/repository/user.repository.js +19 -0
  118. package/dist/features/auth/schemas/firestore.d.ts +10 -0
  119. package/dist/features/auth/schemas/firestore.js +2 -0
  120. package/dist/features/cart/actions/cart-actions.d.ts +1 -1
  121. package/dist/features/cart/actions/cart-actions.js +4 -4
  122. package/dist/features/cart/components/CartView.d.ts +2 -2
  123. package/dist/features/cart/components/ShippingPicker.d.ts +4 -4
  124. package/dist/features/cart/components/ShippingPicker.js +11 -11
  125. package/dist/features/cart/repository/cart.repository.d.ts +1 -1
  126. package/dist/features/cart/repository/cart.repository.js +2 -2
  127. package/dist/features/cart/schemas/firestore.d.ts +2 -2
  128. package/dist/features/catalogue/components/CatalogueItemEditorView.js +3 -3
  129. package/dist/features/catalogue/components/PublicCatalogueView.js +2 -2
  130. package/dist/features/catalogue/schemas/validation.js +1 -1
  131. package/dist/features/categories/components/BundleCollage.js +2 -2
  132. package/dist/features/categories/components/BundleDetailView.js +2 -2
  133. package/dist/features/categories/components/BundleItemsPicker.d.ts +1 -1
  134. package/dist/features/categories/components/BundleItemsPicker.js +2 -2
  135. package/dist/features/categories/components/CategoryBundlesListing.js +2 -2
  136. package/dist/features/categories/schemas/firestore.d.ts +1 -1
  137. package/dist/features/categories/schemas/index.d.ts +3 -3
  138. package/dist/features/categories/schemas/index.js +2 -2
  139. package/dist/features/checkout/actions/checkout-value-otp-actions.d.ts +16 -0
  140. package/dist/features/checkout/actions/checkout-value-otp-actions.js +83 -0
  141. package/dist/features/checkout/actions/index.d.ts +1 -0
  142. package/dist/features/checkout/actions/index.js +1 -0
  143. package/dist/features/checkout/schemas/firestore.d.ts +1 -1
  144. package/dist/features/classified/components/index.d.ts +0 -4
  145. package/dist/features/classified/components/index.js +0 -2
  146. package/dist/features/digital-codes/components/index.d.ts +0 -4
  147. package/dist/features/digital-codes/components/index.js +0 -2
  148. package/dist/features/events/schemas/index.d.ts +1 -1
  149. package/dist/features/events/schemas/index.js +1 -1
  150. package/dist/features/homepage/components/BrandsSection.d.ts +4 -1
  151. package/dist/features/homepage/components/BrandsSection.js +2 -2
  152. package/dist/features/homepage/components/CustomCardsSection.js +3 -3
  153. package/dist/features/homepage/components/CustomerReviewsSection.d.ts +4 -1
  154. package/dist/features/homepage/components/CustomerReviewsSection.js +2 -2
  155. package/dist/features/homepage/components/EventsSection.d.ts +4 -1
  156. package/dist/features/homepage/components/EventsSection.js +2 -2
  157. package/dist/features/homepage/components/FeaturedAuctionsSection.d.ts +2 -1
  158. package/dist/features/homepage/components/FeaturedAuctionsSection.js +2 -2
  159. package/dist/features/homepage/components/FeaturedBundlesSection.js +2 -2
  160. package/dist/features/homepage/components/FeaturedPreOrdersSection.d.ts +2 -1
  161. package/dist/features/homepage/components/FeaturedPreOrdersSection.js +2 -2
  162. package/dist/features/homepage/components/FeaturedProductsSection.d.ts +2 -1
  163. package/dist/features/homepage/components/FeaturedProductsSection.js +2 -2
  164. package/dist/features/homepage/components/FeaturedStoresSection.d.ts +4 -1
  165. package/dist/features/homepage/components/FeaturedStoresSection.js +2 -2
  166. package/dist/features/homepage/components/HomepageCustomerReviewsSection.d.ts +4 -1
  167. package/dist/features/homepage/components/HomepageCustomerReviewsSection.js +2 -2
  168. package/dist/features/homepage/components/SectionCarousel.d.ts +3 -1
  169. package/dist/features/homepage/components/SectionCarousel.js +2 -2
  170. package/dist/features/homepage/components/ShopByCategorySection.d.ts +4 -1
  171. package/dist/features/homepage/components/ShopByCategorySection.js +2 -2
  172. package/dist/features/homepage/lib/section-renderer.js +9 -9
  173. package/dist/features/homepage/schemas/firestore.d.ts +8 -0
  174. package/dist/features/live/components/index.d.ts +0 -4
  175. package/dist/features/live/components/index.js +0 -2
  176. package/dist/features/lottery/types/index.d.ts +3 -3
  177. package/dist/features/lottery/types/index.js +5 -5
  178. package/dist/features/orders/components/OrderPaymentSummary.js +2 -2
  179. package/dist/features/orders/components/OrderSiblingPayments.js +1 -1
  180. package/dist/features/orders/components/RefundHistoryTable.js +1 -1
  181. package/dist/features/orders/components/RefundRequestView.js +1 -1
  182. package/dist/features/orders/constants/payment-window.d.ts +10 -0
  183. package/dist/features/orders/constants/payment-window.js +10 -0
  184. package/dist/features/orders/repository/orders.repository.d.ts +25 -0
  185. package/dist/features/orders/repository/orders.repository.js +50 -1
  186. package/dist/features/orders/schemas/firestore.d.ts +50 -2
  187. package/dist/features/orders/schemas/index.d.ts +24 -24
  188. package/dist/features/orders/schemas/index.js +20 -20
  189. package/dist/features/orders/types/index.d.ts +4 -0
  190. package/dist/features/orders/utils/bundle-grouping.d.ts +1 -1
  191. package/dist/features/orders/utils/bundle-grouping.js +1 -1
  192. package/dist/features/payments/schemas/index.d.ts +10 -10
  193. package/dist/features/payments/schemas/index.js +9 -9
  194. package/dist/features/pre-orders/components/PreOrderDetailPageView.js +2 -2
  195. package/dist/features/products/components/ArtStickersListView.d.ts +7 -0
  196. package/dist/features/products/components/ArtStickersListView.js +57 -0
  197. package/dist/features/products/components/GroupSettingsPanel.js +1 -1
  198. package/dist/features/products/components/MakeOfferButton.js +3 -3
  199. package/dist/features/products/components/MarketplaceBundleCard.d.ts +1 -1
  200. package/dist/features/products/components/MarketplaceBundleCard.js +2 -2
  201. package/dist/features/products/components/PrizeDrawCollage.js +2 -2
  202. package/dist/features/products/components/PrizeDrawItemsEditor.js +2 -2
  203. package/dist/features/products/components/PrizeRevealModal.js +1 -1
  204. package/dist/features/products/components/ProductDetailPageView.js +2 -9
  205. package/dist/features/products/components/ProductForm.js +2 -2
  206. package/dist/features/products/components/ProductGrid.js +2 -2
  207. package/dist/features/products/components/ProductsIndexListing.d.ts +13 -1
  208. package/dist/features/products/components/ProductsIndexListing.js +7 -5
  209. package/dist/features/products/components/ProductsIndexPageView.js +6 -1
  210. package/dist/features/products/constants/listing-tabs.d.ts +42 -17
  211. package/dist/features/products/constants/listing-tabs.js +25 -6
  212. package/dist/features/products/schemas/catalog-product.d.ts +5 -5
  213. package/dist/features/products/schemas/catalog-product.js +1 -1
  214. package/dist/features/products/schemas/firestore.d.ts +5 -5
  215. package/dist/features/products/schemas/firestore.js +2 -2
  216. package/dist/features/products/types/index.d.ts +5 -2
  217. package/dist/features/promotions/components/CouponCard.js +2 -2
  218. package/dist/features/promotions/schemas/firestore.d.ts +2 -0
  219. package/dist/features/promotions/schemas/firestore.js +1 -0
  220. package/dist/features/promotions/schemas/index.d.ts +14 -14
  221. package/dist/features/promotions/schemas/index.js +6 -6
  222. package/dist/features/scams/components/ScamProfileView.js +3 -7
  223. package/dist/features/scams/components/ScamRegistryView.js +2 -6
  224. package/dist/features/scams/schemas/firestore.d.ts +1 -1
  225. package/dist/features/search/components/Search.d.ts +1 -1
  226. package/dist/features/seller/actions/offer-actions.js +1 -1
  227. package/dist/features/seller/components/PrintCenterView.js +2 -2
  228. package/dist/features/seller/components/QuickProductForm.js +5 -5
  229. package/dist/features/seller/components/SellerArtView.js +2 -2
  230. package/dist/features/seller/components/SellerAuctionsView.js +2 -2
  231. package/dist/features/seller/components/SellerBidsView.js +2 -2
  232. package/dist/features/seller/components/SellerBundlesView.js +6 -6
  233. package/dist/features/seller/components/SellerClassifiedView.js +2 -2
  234. package/dist/features/seller/components/SellerDigitalCodesView.js +2 -2
  235. package/dist/features/seller/components/SellerLiveView.js +2 -2
  236. package/dist/features/seller/components/SellerOffersView.js +2 -2
  237. package/dist/features/seller/components/SellerOrdersView.js +3 -3
  238. package/dist/features/seller/components/SellerPayoutRequestView.js +2 -2
  239. package/dist/features/seller/components/SellerPayoutSettingsView.js +2 -2
  240. package/dist/features/seller/components/SellerPayoutsView.js +2 -2
  241. package/dist/features/seller/components/SellerPreOrdersView.js +2 -2
  242. package/dist/features/seller/components/SellerPrizeDrawsView.js +2 -2
  243. package/dist/features/seller/components/SellerProductShell.js +8 -8
  244. package/dist/features/seller/components/SellerProductsView.js +1 -1
  245. package/dist/features/seller/components/SellerShippingView.js +6 -6
  246. package/dist/features/seller/components/SellerStickersView.js +2 -2
  247. package/dist/features/seller/hooks/useSellerListingData.d.ts +1 -1
  248. package/dist/features/seller/hooks/useSellerListingData.js +3 -2
  249. package/dist/features/shipments/components/AdminShipmentEditorView.js +10 -10
  250. package/dist/features/shipments/components/AdminShipmentLotItemsView.js +4 -4
  251. package/dist/features/shipments/components/AdminShipmentProjectionsView.js +5 -5
  252. package/dist/features/shipments/components/AdminShipmentsView.js +4 -4
  253. package/dist/features/shipments/repository/shipment-lots.repository.d.ts +2 -2
  254. package/dist/features/shipments/repository/shipment-lots.repository.js +8 -8
  255. package/dist/features/shipments/schemas/firestore.d.ts +21 -21
  256. package/dist/features/shipments/schemas/firestore.js +9 -9
  257. package/dist/features/shipments/schemas/validation.d.ts +30 -30
  258. package/dist/features/shipments/schemas/validation.js +6 -6
  259. package/dist/features/shipments/utils/cost-allocation.d.ts +5 -5
  260. package/dist/features/shipments/utils/cost-allocation.js +39 -38
  261. package/dist/features/store-extensions/schemas/firestore.d.ts +5 -5
  262. package/dist/features/stores/components/StoreDetailLayoutView.js +9 -13
  263. package/dist/features/stores/schemas/firestore.d.ts +7 -7
  264. package/dist/features/stores/schemas/index.d.ts +84 -84
  265. package/dist/features/stores/schemas/index.js +5 -5
  266. package/dist/features/tester/seed-data/categories-tester-seed-data.js +1 -1
  267. package/dist/features/tester/seed-data/products-tester-seed-data.js +6 -6
  268. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +9 -2
  269. package/dist/features/whatsapp-bot/helpers/whatsapp.d.ts +8 -1
  270. package/dist/features/whatsapp-bot/helpers/whatsapp.js +13 -2
  271. package/dist/features/whatsapp-bot/types/index.d.ts +9 -1
  272. package/dist/index.d.ts +3 -7
  273. package/dist/index.js +7 -5
  274. package/dist/next/routing/route-map.d.ts +2 -0
  275. package/dist/next/routing/route-map.js +6 -0
  276. package/dist/schemas/firestore-helpers.d.ts +2 -2
  277. package/dist/schemas/firestore-helpers.js +2 -2
  278. package/dist/schemas/registry.d.ts +73 -73
  279. package/dist/seed/bids-seed-data.js +6 -6
  280. package/dist/seed/blog-posts-seed-data.js +1 -0
  281. package/dist/seed/cart-seed-data.js +13 -13
  282. package/dist/seed/catalogue-seed-data.js +6 -6
  283. package/dist/seed/categories-seed-data.js +5 -5
  284. package/dist/seed/claimed-coupons-seed-data.js +3 -3
  285. package/dist/seed/coupons-seed-data.js +20 -20
  286. package/dist/seed/events-seed-data.js +27 -27
  287. package/dist/seed/factories/bid.factory.js +1 -1
  288. package/dist/seed/faq-seed-data.js +20 -1
  289. package/dist/seed/grouped-listings-seed-data.d.ts +2 -2
  290. package/dist/seed/grouped-listings-seed-data.js +3 -3
  291. package/dist/seed/homepage-sections-seed-data.js +10 -0
  292. package/dist/seed/offers-seed-data.js +19 -19
  293. package/dist/seed/orders-seed-data.js +29 -29
  294. package/dist/seed/payouts-seed-data.js +7 -7
  295. package/dist/seed/products-auctions-seed-data.js +6 -6
  296. package/dist/seed/products-preorders-seed-data.d.ts +2 -2
  297. package/dist/seed/products-preorders-seed-data.js +1 -1
  298. package/dist/seed/products-standard-seed-data.js +8 -8
  299. package/dist/seed/scammers-seed-data.js +2 -2
  300. package/dist/seed/shipments-seed-data.js +29 -29
  301. package/dist/seed/site-settings-seed-data.js +3 -2
  302. package/dist/seed/store-extensions-seed-data.js +8 -8
  303. package/dist/seed/stores-seed-data.js +37 -8
  304. package/dist/seed/users-seed-data.js +38 -1
  305. package/dist/server-entry.d.ts +1 -3
  306. package/dist/server-entry.js +1 -3
  307. package/dist/server.d.ts +2 -1
  308. package/dist/server.js +3 -1
  309. package/dist/ui/components/HorizontalScroller.js +3 -0
  310. package/dist/ui/components/PriceDisplay.js +3 -12
  311. package/dist/utils/number.formatter.d.ts +2 -7
  312. package/dist/utils/number.formatter.js +3 -8
  313. package/package.json +1 -1
  314. package/scripts/seed-cli.mjs +8 -3
  315. package/dist/_internal/client/scaffolds/DashboardScaffold.d.ts +0 -34
  316. package/dist/_internal/client/scaffolds/DashboardScaffold.js +0 -26
  317. package/dist/_internal/client/theme/__tests__/ThemeProvider.test.d.ts +0 -1
  318. package/dist/_internal/client/theme/__tests__/ThemeProvider.test.js +0 -109
  319. package/dist/_internal/server/features/auctions/__tests__/service.test.d.ts +0 -1
  320. package/dist/_internal/server/features/auctions/__tests__/service.test.js +0 -140
  321. package/dist/_internal/server/features/checkout/__tests__/actions.test.d.ts +0 -1
  322. package/dist/_internal/server/features/checkout/__tests__/actions.test.js +0 -600
  323. package/dist/_internal/server/features/refunds/__tests__/actions.test.d.ts +0 -1
  324. package/dist/_internal/server/features/refunds/__tests__/actions.test.js +0 -263
  325. package/dist/_internal/server/jobs/core/__tests__/auctionSettlement.test.d.ts +0 -1
  326. package/dist/_internal/server/jobs/core/__tests__/auctionSettlement.test.js +0 -249
  327. package/dist/_internal/server/jobs/core/__tests__/couponExpiry.test.d.ts +0 -1
  328. package/dist/_internal/server/jobs/core/__tests__/couponExpiry.test.js +0 -65
  329. package/dist/_internal/server/jobs/core/__tests__/listingProcessor.test.d.ts +0 -1
  330. package/dist/_internal/server/jobs/core/__tests__/listingProcessor.test.js +0 -163
  331. package/dist/_internal/server/jobs/core/__tests__/mediaTmpCleanup.test.d.ts +0 -1
  332. package/dist/_internal/server/jobs/core/__tests__/mediaTmpCleanup.test.js +0 -115
  333. package/dist/_internal/server/jobs/core/__tests__/onBidPlaced.test.d.ts +0 -1
  334. package/dist/_internal/server/jobs/core/__tests__/onBidPlaced.test.js +0 -201
  335. package/dist/_internal/server/jobs/core/__tests__/onOrderCreate.test.d.ts +0 -1
  336. package/dist/_internal/server/jobs/core/__tests__/onOrderCreate.test.js +0 -169
  337. package/dist/_internal/server/jobs/core/__tests__/onOrderStatusChange.test.d.ts +0 -1
  338. package/dist/_internal/server/jobs/core/__tests__/onOrderStatusChange.test.js +0 -148
  339. package/dist/_internal/server/jobs/core/__tests__/onProductStockChange.test.d.ts +0 -1
  340. package/dist/_internal/server/jobs/core/__tests__/onProductStockChange.test.js +0 -210
  341. package/dist/_internal/server/jobs/core/__tests__/onReviewWrite.test.d.ts +0 -1
  342. package/dist/_internal/server/jobs/core/__tests__/onReviewWrite.test.js +0 -190
  343. package/dist/_internal/server/jobs/core/__tests__/onUserBanChange.test.d.ts +0 -1
  344. package/dist/_internal/server/jobs/core/__tests__/onUserBanChange.test.js +0 -161
  345. package/dist/_internal/server/jobs/core/__tests__/payoutBatch.test.d.ts +0 -1
  346. package/dist/_internal/server/jobs/core/__tests__/payoutBatch.test.js +0 -302
  347. package/dist/_internal/server/jobs/core/__tests__/pendingOrderTimeout.test.d.ts +0 -1
  348. package/dist/_internal/server/jobs/core/__tests__/pendingOrderTimeout.test.js +0 -96
  349. package/dist/_internal/server/jobs/core/__tests__/triggerEventRaffle.test.d.ts +0 -1
  350. package/dist/_internal/server/jobs/core/__tests__/triggerEventRaffle.test.js +0 -252
  351. package/dist/_internal/server/jobs/core/__tests__/wrapJobHandler.test.d.ts +0 -1
  352. package/dist/_internal/server/jobs/core/__tests__/wrapJobHandler.test.js +0 -129
  353. package/dist/_internal/server/jobs/core/onCatalogueSubmittedForApproval.d.ts +0 -15
  354. package/dist/_internal/server/jobs/core/onCatalogueSubmittedForApproval.js +0 -38
  355. package/dist/_internal/server/providers/index.d.ts +0 -11
  356. package/dist/_internal/server/providers/index.js +0 -11
  357. package/dist/_internal/server/providers/payment/razorpay-mock.d.ts +0 -52
  358. package/dist/_internal/server/providers/payment/razorpay-mock.js +0 -118
  359. package/dist/_internal/server/providers/resolve.d.ts +0 -36
  360. package/dist/_internal/server/providers/resolve.js +0 -31
  361. package/dist/_internal/server/providers/shipping/shiprocket-mock.d.ts +0 -29
  362. package/dist/_internal/server/providers/shipping/shiprocket-mock.js +0 -152
  363. package/dist/_internal/shared/types/__tests__/action-result.test.d.ts +0 -1
  364. package/dist/_internal/shared/types/__tests__/action-result.test.js +0 -65
  365. package/dist/errors/__tests__/error-mapping.test.d.ts +0 -1
  366. package/dist/errors/__tests__/error-mapping.test.js +0 -122
  367. package/dist/errors/__tests__/safe-read.test.d.ts +0 -1
  368. package/dist/errors/__tests__/safe-read.test.js +0 -39
  369. package/dist/features/addresses/repository/__tests__/addresses.repository.test.d.ts +0 -1
  370. package/dist/features/addresses/repository/__tests__/addresses.repository.test.js +0 -386
  371. package/dist/features/admin/components/AdminListingScaffold.d.ts +0 -41
  372. package/dist/features/admin/components/AdminListingScaffold.js +0 -68
  373. package/dist/features/admin/components/QuickActionsPanel.d.ts +0 -15
  374. package/dist/features/admin/components/QuickActionsPanel.js +0 -5
  375. package/dist/features/admin/repository/__tests__/notification.repository.test.d.ts +0 -1
  376. package/dist/features/admin/repository/__tests__/notification.repository.test.js +0 -356
  377. package/dist/features/admin/repository/__tests__/site-settings.repository.test.d.ts +0 -1
  378. package/dist/features/admin/repository/__tests__/site-settings.repository.test.js +0 -298
  379. package/dist/features/auctions/repository/__tests__/bid.repository.test.d.ts +0 -1
  380. package/dist/features/auctions/repository/__tests__/bid.repository.test.js +0 -290
  381. package/dist/features/auctions/repository/auctions.repository.d.ts +0 -12
  382. package/dist/features/auctions/repository/auctions.repository.js +0 -42
  383. package/dist/features/auth/repository/__tests__/session.repository.test.d.ts +0 -1
  384. package/dist/features/auth/repository/__tests__/session.repository.test.js +0 -310
  385. package/dist/features/auth/repository/__tests__/session.test.d.ts +0 -1
  386. package/dist/features/auth/repository/__tests__/session.test.js +0 -146
  387. package/dist/features/auth/repository/__tests__/sms-counter.repository.test.d.ts +0 -1
  388. package/dist/features/auth/repository/__tests__/sms-counter.repository.test.js +0 -171
  389. package/dist/features/auth/repository/__tests__/sms-counter.test.d.ts +0 -1
  390. package/dist/features/auth/repository/__tests__/sms-counter.test.js +0 -88
  391. package/dist/features/auth/repository/__tests__/token.repository.test.d.ts +0 -1
  392. package/dist/features/auth/repository/__tests__/token.repository.test.js +0 -260
  393. package/dist/features/auth/repository/__tests__/token.test.d.ts +0 -1
  394. package/dist/features/auth/repository/__tests__/token.test.js +0 -140
  395. package/dist/features/auth/repository/__tests__/user.repository.test.d.ts +0 -1
  396. package/dist/features/auth/repository/__tests__/user.repository.test.js +0 -352
  397. package/dist/features/auth/repository/__tests__/user.test.d.ts +0 -1
  398. package/dist/features/auth/repository/__tests__/user.test.js +0 -226
  399. package/dist/features/before-after/repository/before-after.repository.d.ts +0 -13
  400. package/dist/features/before-after/repository/before-after.repository.js +0 -36
  401. package/dist/features/before-after/server.d.ts +0 -6
  402. package/dist/features/before-after/server.js +0 -6
  403. package/dist/features/cart/repository/__tests__/cart.repository.test.d.ts +0 -1
  404. package/dist/features/cart/repository/__tests__/cart.repository.test.js +0 -371
  405. package/dist/features/categories/repository/__tests__/categories.repository.test.d.ts +0 -1
  406. package/dist/features/categories/repository/__tests__/categories.repository.test.js +0 -813
  407. package/dist/features/collections/repository/collections.repository.d.ts +0 -8
  408. package/dist/features/collections/repository/collections.repository.js +0 -16
  409. package/dist/features/collections/server.d.ts +0 -6
  410. package/dist/features/collections/server.js +0 -6
  411. package/dist/features/events/repository/__tests__/event.repository.test.d.ts +0 -1
  412. package/dist/features/events/repository/__tests__/event.repository.test.js +0 -299
  413. package/dist/features/faq/repository/__tests__/faqs.repository.test.d.ts +0 -1
  414. package/dist/features/faq/repository/__tests__/faqs.repository.test.js +0 -311
  415. package/dist/features/forms/Form.d.ts +0 -25
  416. package/dist/features/forms/Form.js +0 -37
  417. package/dist/features/history/repository/__tests__/user-history.repository.test.d.ts +0 -1
  418. package/dist/features/history/repository/__tests__/user-history.repository.test.js +0 -180
  419. package/dist/features/homepage/repository/__tests__/carousel.repository.test.d.ts +0 -1
  420. package/dist/features/homepage/repository/__tests__/carousel.repository.test.js +0 -182
  421. package/dist/features/homepage/repository/__tests__/homepage-sections.repository.test.d.ts +0 -1
  422. package/dist/features/homepage/repository/__tests__/homepage-sections.repository.test.js +0 -185
  423. package/dist/features/layout/ListingLayout.d.ts +0 -34
  424. package/dist/features/layout/ListingLayout.js +0 -103
  425. package/dist/features/messages/repository/__tests__/conversations.repository.test.d.ts +0 -1
  426. package/dist/features/messages/repository/__tests__/conversations.repository.test.js +0 -257
  427. package/dist/features/orders/repository/__tests__/orders.repository.test.d.ts +0 -1
  428. package/dist/features/orders/repository/__tests__/orders.repository.test.js +0 -211
  429. package/dist/features/payments/repository/__tests__/payout.repository.test.d.ts +0 -1
  430. package/dist/features/payments/repository/__tests__/payout.repository.test.js +0 -292
  431. package/dist/features/pre-orders/repository/preorders.repository.d.ts +0 -8
  432. package/dist/features/pre-orders/repository/preorders.repository.js +0 -25
  433. package/dist/features/products/repository/__tests__/product-features.repository.test.d.ts +0 -1
  434. package/dist/features/products/repository/__tests__/product-features.repository.test.js +0 -329
  435. package/dist/features/products/repository/__tests__/products.repository.test.d.ts +0 -1
  436. package/dist/features/products/repository/__tests__/products.repository.test.js +0 -607
  437. package/dist/features/promotions/repository/__tests__/claimed-coupons.repository.test.d.ts +0 -1
  438. package/dist/features/promotions/repository/__tests__/claimed-coupons.repository.test.js +0 -219
  439. package/dist/features/promotions/repository/__tests__/coupons.repository.test.d.ts +0 -1
  440. package/dist/features/promotions/repository/__tests__/coupons.repository.test.js +0 -480
  441. package/dist/features/promotions/repository/promotions.repository.d.ts +0 -14
  442. package/dist/features/promotions/repository/promotions.repository.js +0 -43
  443. package/dist/features/reviews/repository/__tests__/reviews.repository.test.d.ts +0 -1
  444. package/dist/features/reviews/repository/__tests__/reviews.repository.test.js +0 -327
  445. package/dist/features/scams/repository/__tests__/scammer.repository.test.d.ts +0 -1
  446. package/dist/features/scams/repository/__tests__/scammer.repository.test.js +0 -385
  447. package/dist/features/search/repository/__tests__/search.repository.test.d.ts +0 -1
  448. package/dist/features/search/repository/__tests__/search.repository.test.js +0 -369
  449. package/dist/features/seller/components/SellerStatCard.d.ts +0 -14
  450. package/dist/features/seller/components/SellerStatCard.js +0 -6
  451. package/dist/features/seller/components/seller-products-styles.d.ts +0 -7
  452. package/dist/features/seller/components/seller-products-styles.js +0 -14
  453. package/dist/features/seller/repository/__tests__/offer.repository.test.d.ts +0 -1
  454. package/dist/features/seller/repository/__tests__/offer.repository.test.js +0 -458
  455. package/dist/features/seller/repository/seller.repository.d.ts +0 -22
  456. package/dist/features/seller/repository/seller.repository.js +0 -72
  457. package/dist/features/site-settings/components/__tests__/ThemeManagerView.test.d.ts +0 -1
  458. package/dist/features/site-settings/components/__tests__/ThemeManagerView.test.js +0 -37
  459. package/dist/features/stores/repository/__tests__/store.repository.test.d.ts +0 -1
  460. package/dist/features/stores/repository/__tests__/store.repository.test.js +0 -261
  461. package/dist/features/stores/repository/stores.repository.d.ts +0 -11
  462. package/dist/features/stores/repository/stores.repository.js +0 -37
  463. package/dist/features/support/repository/__tests__/support.repository.test.d.ts +0 -1
  464. package/dist/features/support/repository/__tests__/support.repository.test.js +0 -312
  465. package/dist/features/wishlist/repository/__tests__/user-wishlist.repository.test.d.ts +0 -1
  466. package/dist/features/wishlist/repository/__tests__/user-wishlist.repository.test.js +0 -139
  467. package/dist/features/wishlist/repository/wishlist.repository.d.ts +0 -13
  468. package/dist/features/wishlist/repository/wishlist.repository.js +0 -31
  469. package/dist/providers/db-firebase/__tests__/filter-aliases.test.d.ts +0 -1
  470. package/dist/providers/db-firebase/__tests__/filter-aliases.test.js +0 -93
  471. package/dist/providers/shipping-shiprocket/index.d.ts +0 -297
  472. package/dist/providers/shipping-shiprocket/index.js +0 -194
  473. package/dist/providers/shipping-shiprocket/shiprocket-provider.d.ts +0 -45
  474. package/dist/providers/shipping-shiprocket/shiprocket-provider.js +0 -168
  475. package/dist/react/contexts/ThemeContext.d.ts +0 -13
  476. package/dist/react/contexts/ThemeContext.js +0 -64
  477. package/dist/schemas/webhooks/shiprocket.d.ts +0 -30
  478. package/dist/schemas/webhooks/shiprocket.js +0 -22
  479. package/dist/seed/actions/demo-seed-actions.d.ts +0 -42
  480. package/dist/seed/actions/demo-seed-actions.js +0 -36
  481. package/dist/seed/actions/index.d.ts +0 -1
  482. package/dist/seed/actions/index.js +0 -1
  483. package/dist/seed/sub-listings-seed-data.d.ts +0 -123
  484. package/dist/seed/sub-listings-seed-data.js +0 -447
  485. package/dist/seed/tester-checklist-seed-data.d.ts +0 -2
  486. package/dist/seed/tester-checklist-seed-data.js +0 -248
  487. package/dist/ui/components/DashboardStatsCard.d.ts +0 -15
  488. package/dist/ui/components/DashboardStatsCard.js +0 -27
  489. package/dist/ui/components/DashboardStatsCard.style.css +0 -68
  490. package/dist/ui/components/DynamicSelect.d.ts +0 -23
  491. package/dist/ui/components/DynamicSelect.js +0 -77
  492. package/dist/ui/components/DynamicSelect.style.css +0 -101
  493. package/dist/ui/components/InlineCreateSelect.d.ts +0 -48
  494. package/dist/ui/components/InlineCreateSelect.js +0 -75
  495. package/dist/ui/components/ListingViewShell.d.ts +0 -37
  496. package/dist/ui/components/ListingViewShell.js +0 -9
  497. package/dist/ui/components/PaginatedMultiSelect.d.ts +0 -28
  498. package/dist/ui/components/PaginatedMultiSelect.js +0 -141
  499. package/dist/ui/components/PaginatedMultiSelect.style.css +0 -272
  500. package/dist/ui/components/SectionTabs.d.ts +0 -19
  501. package/dist/ui/components/SectionTabs.js +0 -66
  502. package/dist/ui/components/SectionTabs.style.css +0 -164
  503. package/dist/ui/components/__tests__/BulkActionBar.test.d.ts +0 -1
  504. package/dist/ui/components/__tests__/BulkActionBar.test.js +0 -96
  505. package/dist/ui/components/__tests__/ListingToolbar.test.d.ts +0 -1
  506. package/dist/ui/components/__tests__/ListingToolbar.test.js +0 -125
  507. package/dist/ui/components/__tests__/new-primitives.test.d.ts +0 -1
  508. 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
  };