@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
@@ -7,5 +7,33 @@ export declare function attachPaymentProofAction(orderId: string, proof: {
7
7
  proofUrl: string;
8
8
  transactionId?: string;
9
9
  mimeType?: string;
10
+ buyerMarkedPaid: boolean;
11
+ buyerFraudAgreementAccepted: boolean;
12
+ buyerReportedUpiId?: string;
10
13
  }): Promise<ActionResult<void>>;
11
14
  export declare function adminVerifyPaymentAction(orderId: string): Promise<ActionResult<void>>;
15
+ /**
16
+ * Tier PP — "honest mistake" tier of the two-tier admin review (blurry
17
+ * screenshot, wrong amount typed). Clears the proof so the buyer can cleanly
18
+ * resubmit, and extends `paymentDeadline` by another 15 minutes from now so
19
+ * review latency doesn't eat into the buyer's time to fix it. Order stays
20
+ * `pending`/`pending` — no penalty.
21
+ */
22
+ export declare function adminRequestProofReuploadAction(orderId: string, note: string): Promise<ActionResult<void>>;
23
+ /**
24
+ * Tier PP — "fraud" tier of the two-tier admin review. Cancels the order,
25
+ * restores stock, and triggers a new temporary 7-day full-account hard ban
26
+ * (extends the existing permanent-only `hardBanCascade` job with an
27
+ * `expiresAt`, rather than forking a parallel cascade — see
28
+ * `HardBanCascadeInput.expiresAt`).
29
+ */
30
+ export declare function adminRejectPaymentAsFraudAction(orderId: string, note: string): Promise<ActionResult<void>>;
31
+ /**
32
+ * Tier PP — raises a dispute on an auto-approved order ("the automation
33
+ * might be wrong"). Only valid when `autoApproved === true` — a manually
34
+ * reviewed order already went through human judgment and disputes on it go
35
+ * through the existing return/refund flow instead. Callable by the buyer,
36
+ * the seller (store owner), or admin/moderator. Does not itself reverse
37
+ * payment/order status — surfaces to the admin queue for investigation.
38
+ */
39
+ export declare function raiseOrderDisputeAction(orderId: string, reason: string): Promise<ActionResult<void>>;
@@ -1,12 +1,19 @@
1
1
  "use server";
2
2
  import { wrapAction } from "@mohasinac/appkit/server";
3
- import { orderRepository } from "../../../../repositories";
3
+ import { orderRepository, storeRepository, userRepository } from "../../../../repositories";
4
4
  import { requireRoleUser } from "../../../../providers/auth-firebase/helpers";
5
5
  import { createOrderSchema, updateOrderStatusSchema, cancelOrderSchema, } from "../../../shared/features/orders/schema";
6
6
  import { assertOrderCancellable, assertReturnWindowOpen } from "./service";
7
7
  import { ValidationError } from "../../../shared/errors/index";
8
8
  import { OrderNotFoundError, OrderOwnershipError } from "../../../shared/features/orders/errors";
9
9
  import { isAdminUser, isModeratorUser } from "../../../../features/auth/role-predicates";
10
+ import { sendNotification } from "../../../../features/admin/actions/notification-actions";
11
+ import { restoreStockForOrder } from "../checkout/stock-restore";
12
+ import { getAdminDb } from "../../../../providers/db-firebase";
13
+ import { enqueueJob } from "../../../../features/jobs/actions/enqueue-job";
14
+ import { PAYMENT_WINDOW_MS, PAYMENT_FRAUD_REJECTED_REASON } from "../../../../features/orders/constants/payment-window";
15
+ import { normalizeError } from "../../../../errors/normalize";
16
+ import { serverLogger } from "../../../../monitoring";
10
17
  export async function createOrderAction(input) {
11
18
  return wrapAction(async () => {
12
19
  const user = await requireRoleUser(["buyer", "seller", "admin"]);
@@ -59,6 +66,63 @@ export async function updateOrderStatusAction(input) {
59
66
  });
60
67
  }
61
68
  // ── P-1 Manual payment proof ─────────────────────────────────────────────────
69
+ /** Loose UPI VPA comparison — case/whitespace differences shouldn't register as a mismatch. */
70
+ function normalizeUpi(vpa) {
71
+ return (vpa ?? "").trim().toLowerCase();
72
+ }
73
+ const REASON_REQUIRED_MSG = "A reason is required";
74
+ /**
75
+ * Fast-review WhatsApp push — fans out to every configured admin number so
76
+ * a payment proof can be acted on within the 2-hour auto-approve window
77
+ * without hunting through the orders list. Fire-and-forget, non-fatal on
78
+ * failure (mirrors the existing `onOrderCreate.ts` purchase-announcement
79
+ * pattern) — skips silently if the WhatsApp Cloud API isn't configured.
80
+ */
81
+ function notifyAdminsOfPaymentProof(order) {
82
+ void (async () => {
83
+ try {
84
+ const [{ resolveKeys }, { sendWhatsAppBusinessMessage, buildPaymentProofReviewMessage }] = await Promise.all([
85
+ import("../../../../core/integration-keys"),
86
+ import("../../../../features/whatsapp-bot/server"),
87
+ ]);
88
+ const keys = await resolveKeys();
89
+ if (!keys.whatsappPhoneNumberId || !keys.whatsappCloudApiToken)
90
+ return;
91
+ const adminNumbers = keys.whatsappAdminNotifyNumbers
92
+ .split(",")
93
+ .map((n) => n.trim().replace(/\D/g, ""))
94
+ .filter(Boolean);
95
+ if (adminNumbers.length === 0)
96
+ return;
97
+ // No hardcoded domain fallback here (audit-ssr-in-appkit) — every
98
+ // consumer sets NEXT_PUBLIC_SITE_URL; skip the review link rather than
99
+ // guessing a brand-specific domain from inside appkit/_internal/.
100
+ const baseUrl = process.env.NEXT_PUBLIC_SITE_URL ?? "";
101
+ const message = buildPaymentProofReviewMessage({
102
+ orderId: order.id,
103
+ buyerName: order.userName,
104
+ productTitle: order.productTitle,
105
+ totalAmount: order.totalPrice,
106
+ reviewUrl: `${baseUrl}/admin/orders`,
107
+ });
108
+ await Promise.allSettled(adminNumbers.map((toPhone) => sendWhatsAppBusinessMessage({
109
+ toPhone,
110
+ message,
111
+ phoneNumberId: keys.whatsappPhoneNumberId,
112
+ accessToken: keys.whatsappCloudApiToken,
113
+ })));
114
+ }
115
+ catch (err) {
116
+ void normalizeError(err);
117
+ // Non-fatal — the order itself already saved successfully; a WhatsApp
118
+ // Cloud API hiccup here must never surface as a proof-upload failure.
119
+ serverLogger.warn("Payment-proof admin WhatsApp push failed (non-fatal)", {
120
+ orderId: order.id,
121
+ error: err instanceof Error ? err.message : String(err),
122
+ });
123
+ }
124
+ })();
125
+ }
62
126
  export async function attachPaymentProofAction(orderId, proof) {
63
127
  return wrapAction(async () => {
64
128
  const user = await requireRoleUser(["buyer", "seller", "admin"]);
@@ -68,17 +132,41 @@ export async function attachPaymentProofAction(orderId, proof) {
68
132
  if (!isAdminUser(user) && order.userId !== user.uid)
69
133
  throw new OrderOwnershipError(orderId);
70
134
  const pm = order.paymentMethod ?? "";
71
- if (pm !== "cash" && pm !== "upi_manual") {
72
- throw new ValidationError("Payment proof can only be attached to cash or UPI orders");
135
+ if (pm !== "cash" && pm !== "upi_manual" && pm !== "emi") {
136
+ throw new ValidationError("Payment proof can only be attached to cash, UPI, or EMI orders");
73
137
  }
74
138
  if (order.paymentProofUrl) {
75
139
  throw new ValidationError("PROOF_ALREADY_ATTACHED");
76
140
  }
141
+ // The 15-min sweep cancels+restocks the order once its window passes with
142
+ // no proof attached — a late submission must surface a clear "window
143
+ // expired" error rather than silently attaching proof to a dead order.
144
+ if (order.paymentDeadline && new Date(order.paymentDeadline) < new Date() && order.status !== "pending") {
145
+ throw new ValidationError("PAYMENT_WINDOW_EXPIRED");
146
+ }
147
+ if (!proof.buyerFraudAgreementAccepted) {
148
+ throw new ValidationError("You must confirm this payment is genuine before submitting proof.");
149
+ }
150
+ const paymentUpiMismatch = order.displayedUpiId
151
+ ? normalizeUpi(proof.buyerReportedUpiId) !== normalizeUpi(order.displayedUpiId)
152
+ : false;
77
153
  await orderRepository.update(orderId, {
78
154
  paymentProofUrl: proof.proofUrl,
79
155
  paymentTransactionId: proof.transactionId,
80
156
  paymentProofMimeType: proof.mimeType,
81
157
  paymentProofUploadedAt: new Date(),
158
+ buyerMarkedPaid: proof.buyerMarkedPaid,
159
+ buyerMarkedPaidAt: proof.buyerMarkedPaid ? new Date() : undefined,
160
+ buyerFraudAgreementAccepted: proof.buyerFraudAgreementAccepted,
161
+ buyerFraudAgreementAcceptedAt: new Date(),
162
+ buyerReportedUpiId: proof.buyerReportedUpiId,
163
+ paymentUpiMismatch,
164
+ });
165
+ notifyAdminsOfPaymentProof({
166
+ id: orderId,
167
+ userName: order.userName,
168
+ productTitle: order.productTitle,
169
+ totalPrice: order.totalPrice,
82
170
  });
83
171
  });
84
172
  }
@@ -101,11 +189,158 @@ export async function adminVerifyPaymentAction(orderId) {
101
189
  method: "manual",
102
190
  transactionId: order.paymentTransactionId,
103
191
  proofUrl: order.paymentProofUrl,
104
- amountPaise: order.totalPrice,
192
+ amount: order.totalPrice,
105
193
  paidAt: new Date(),
106
194
  verifiedBy: user.uid,
107
195
  verificationMethod: "manual_review",
108
196
  },
197
+ paymentReviewOutcome: "approved",
198
+ paymentReviewedBy: user.uid,
199
+ paymentReviewedAt: new Date(),
200
+ });
201
+ });
202
+ }
203
+ /**
204
+ * Tier PP — "honest mistake" tier of the two-tier admin review (blurry
205
+ * screenshot, wrong amount typed). Clears the proof so the buyer can cleanly
206
+ * resubmit, and extends `paymentDeadline` by another 15 minutes from now so
207
+ * review latency doesn't eat into the buyer's time to fix it. Order stays
208
+ * `pending`/`pending` — no penalty.
209
+ */
210
+ export async function adminRequestProofReuploadAction(orderId, note) {
211
+ return wrapAction(async () => {
212
+ const user = await requireRoleUser(["admin", "moderator"]);
213
+ if (!isAdminUser(user) && !isModeratorUser(user)) {
214
+ throw new ValidationError("Only admin or moderator can request a proof re-upload");
215
+ }
216
+ if (!note.trim())
217
+ throw new ValidationError(REASON_REQUIRED_MSG);
218
+ const order = await orderRepository.findById(orderId).catch(() => null);
219
+ if (!order)
220
+ throw new OrderNotFoundError(orderId);
221
+ if (order.paymentStatus === "paid") {
222
+ throw new ValidationError("This order's payment is already verified");
223
+ }
224
+ await orderRepository.update(orderId, {
225
+ paymentProofUrl: null,
226
+ paymentTransactionId: null,
227
+ paymentProofMimeType: null,
228
+ paymentProofUploadedAt: null,
229
+ buyerMarkedPaid: null,
230
+ buyerMarkedPaidAt: null,
231
+ buyerFraudAgreementAccepted: null,
232
+ buyerFraudAgreementAcceptedAt: null,
233
+ buyerReportedUpiId: null,
234
+ paymentUpiMismatch: null,
235
+ paymentDeadline: new Date(Date.now() + PAYMENT_WINDOW_MS),
236
+ paymentReviewOutcome: "reupload_requested",
237
+ paymentReviewNote: note,
238
+ paymentReviewedBy: user.uid,
239
+ paymentReviewedAt: new Date(),
240
+ });
241
+ await sendNotification({
242
+ userId: order.userId,
243
+ type: "payment_review",
244
+ priority: "high",
245
+ title: "Payment proof needs correction",
246
+ message: `Your payment proof for "${order.productTitle}" needs correction: ${note}. Please re-upload within 15 minutes.`,
247
+ relatedId: orderId,
248
+ relatedType: "order",
249
+ });
250
+ });
251
+ }
252
+ /**
253
+ * Tier PP — "fraud" tier of the two-tier admin review. Cancels the order,
254
+ * restores stock, and triggers a new temporary 7-day full-account hard ban
255
+ * (extends the existing permanent-only `hardBanCascade` job with an
256
+ * `expiresAt`, rather than forking a parallel cascade — see
257
+ * `HardBanCascadeInput.expiresAt`).
258
+ */
259
+ export async function adminRejectPaymentAsFraudAction(orderId, note) {
260
+ return wrapAction(async () => {
261
+ const user = await requireRoleUser(["admin", "moderator"]);
262
+ if (!isAdminUser(user) && !isModeratorUser(user)) {
263
+ throw new ValidationError("Only admin or moderator can reject a payment as fraudulent");
264
+ }
265
+ if (!note.trim())
266
+ throw new ValidationError(REASON_REQUIRED_MSG);
267
+ const order = await orderRepository.findById(orderId).catch(() => null);
268
+ if (!order)
269
+ throw new OrderNotFoundError(orderId);
270
+ if (order.paymentStatus === "paid") {
271
+ throw new ValidationError("This order's payment is already verified");
272
+ }
273
+ await restoreStockForOrder(getAdminDb(), { ...order, id: orderId }, {
274
+ status: "cancelled",
275
+ cancellationDate: new Date(),
276
+ cancellationReason: PAYMENT_FRAUD_REJECTED_REASON,
277
+ paymentReviewOutcome: "rejected_fraud",
278
+ paymentReviewNote: note,
279
+ paymentReviewedBy: user.uid,
280
+ paymentReviewedAt: new Date(),
281
+ });
282
+ const expiresAt = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000);
283
+ await enqueueJob({
284
+ jobType: "hardBanCascade",
285
+ payload: {
286
+ uid: order.userId,
287
+ reason: `Fraudulent payment proof on order ${orderId}: ${note}`,
288
+ bannedBy: user.uid,
289
+ expiresAt: expiresAt.toISOString(),
290
+ fraudOrderId: orderId,
291
+ },
292
+ requestedBy: user.uid,
293
+ });
294
+ });
295
+ }
296
+ /**
297
+ * Tier PP — raises a dispute on an auto-approved order ("the automation
298
+ * might be wrong"). Only valid when `autoApproved === true` — a manually
299
+ * reviewed order already went through human judgment and disputes on it go
300
+ * through the existing return/refund flow instead. Callable by the buyer,
301
+ * the seller (store owner), or admin/moderator. Does not itself reverse
302
+ * payment/order status — surfaces to the admin queue for investigation.
303
+ */
304
+ export async function raiseOrderDisputeAction(orderId, reason) {
305
+ return wrapAction(async () => {
306
+ const user = await requireRoleUser(["buyer", "seller", "admin"]);
307
+ if (!reason.trim())
308
+ throw new ValidationError(REASON_REQUIRED_MSG);
309
+ const order = await orderRepository.findById(orderId).catch(() => null);
310
+ if (!order)
311
+ throw new OrderNotFoundError(orderId);
312
+ const isBuyer = order.userId === user.uid;
313
+ let isSeller = false;
314
+ if (!isBuyer && !isAdminUser(user) && !isModeratorUser(user) && order.storeId) {
315
+ const store = await storeRepository.findById(order.storeId).catch(() => null);
316
+ isSeller = store?.ownerId === user.uid;
317
+ }
318
+ if (!isBuyer && !isSeller && !isAdminUser(user) && !isModeratorUser(user)) {
319
+ throw new OrderOwnershipError(orderId);
320
+ }
321
+ if (!order.autoApproved) {
322
+ throw new ValidationError("Disputes can only be raised on auto-approved orders. Use the return/refund flow for manually-reviewed orders.");
323
+ }
324
+ if (order.disputeStatus === "open")
325
+ return; // idempotent
326
+ await orderRepository.update(orderId, {
327
+ disputeRaised: true,
328
+ disputeRaisedBy: user.uid,
329
+ disputeRaisedAt: new Date(),
330
+ disputeReason: reason,
331
+ disputeStatus: "open",
109
332
  });
333
+ // Notify every admin for manual investigation — a dispute on an
334
+ // auto-approved order means nobody has looked at it yet.
335
+ const admins = await userRepository.findByRole("admin");
336
+ await Promise.allSettled(admins.map((admin) => sendNotification({
337
+ userId: admin.uid,
338
+ type: "payment_review",
339
+ priority: "high",
340
+ title: "Dispute raised on auto-approved order",
341
+ message: `A dispute was raised on order "${order.productTitle}" (auto-approved payment). Reason: ${reason}.`,
342
+ relatedId: orderId,
343
+ relatedType: "order",
344
+ })));
110
345
  });
111
346
  }
@@ -61,6 +61,9 @@ export function orderDocumentToOrder(doc) {
61
61
  trackingNumber: doc.trackingNumber,
62
62
  shippingCarrier: doc.shippingCarrier,
63
63
  notes: doc.notes,
64
+ autoApproved: doc.autoApproved,
65
+ disputeRaised: doc.disputeRaised,
66
+ disputeStatus: doc.disputeStatus,
64
67
  createdAt: doc.createdAt instanceof Date
65
68
  ? doc.createdAt.toISOString()
66
69
  : String(doc.createdAt),
@@ -1,4 +1,5 @@
1
1
  import { siteSettingsRepository } from "../../../../repositories";
2
+ import { roundRupees } from "../../../../utils/number.formatter";
2
3
  import { PAYMENTS_DEFAULT_PLATFORM_FEE_PERCENT, PAYMENTS_DEFAULT_GST_PERCENT, } from "../../../shared/features/payments/config";
3
4
  /**
4
5
  * Inflates the cart total by our platform fee + GST on that fee.
@@ -11,8 +12,8 @@ export async function resolvePaymentFee(baseAmount) {
11
12
  const platformFeePercent = siteSettings?.commissions?.platformFeePercent ?? PAYMENTS_DEFAULT_PLATFORM_FEE_PERCENT;
12
13
  const gstPercent = siteSettings?.commissions?.gstPercent ?? PAYMENTS_DEFAULT_GST_PERCENT;
13
14
  const minimumTransactionFee = Math.max(0, siteSettings?.commissions?.minimumTransactionFee ?? 0);
14
- const platformFee = Math.round(baseAmount * (platformFeePercent / 100) * 100) / 100;
15
- const gstOnFee = Math.round(platformFee * (gstPercent / 100) * 100) / 100;
15
+ const platformFee = roundRupees(baseAmount * (platformFeePercent / 100));
16
+ const gstOnFee = roundRupees(platformFee * (gstPercent / 100));
16
17
  const rawTotal = baseAmount + platformFee + gstOnFee;
17
18
  const totalAmount = Math.max(rawTotal, baseAmount + minimumTransactionFee);
18
19
  return { baseAmount, platformFee, gstOnFee, totalAmount };
@@ -3,8 +3,8 @@ export type ApplyRefundDeductionInput = {
3
3
  storeId: string;
4
4
  orderId: string;
5
5
  refundId: string;
6
- /** Gross refund amount in paise. */
7
- refundedAmountInPaise: number;
6
+ /** Gross refund amount, decimal rupees. */
7
+ refundedAmount: number;
8
8
  /** Platform fee rate (0–1). Defaults to DEFAULT_PLATFORM_FEE_RATE (0.05). */
9
9
  platformFeeRate?: number;
10
10
  reason: string;
@@ -15,13 +15,14 @@ import { wrapAction } from "@mohasinac/appkit/server";
15
15
  */
16
16
  import { payoutRepository } from "../../../../repositories";
17
17
  import { ValidationError } from "../../../../errors";
18
+ import { roundRupees } from "../../../../utils/number.formatter";
18
19
  export async function applyRefundDeductionAction(input) {
19
20
  return wrapAction(async () => {
20
- if (input.refundedAmountInPaise <= 0) {
21
+ if (input.refundedAmount <= 0) {
21
22
  throw new ValidationError("Refund amount must be positive");
22
23
  }
23
24
  const feeRate = input.platformFeeRate ?? 0.05;
24
- const deductedAmount = Math.round(input.refundedAmountInPaise * (1 - feeRate));
25
+ const deductedAmount = roundRupees(input.refundedAmount * (1 - feeRate));
25
26
  const pending = await payoutRepository.findPendingByStore(input.storeId);
26
27
  if (!pending) {
27
28
  return { applied: false, reason: "no_pending_payout" };
@@ -32,7 +33,7 @@ export async function applyRefundDeductionAction(input) {
32
33
  const updated = await payoutRepository.applyRefundDeduction(pending.id, {
33
34
  orderId: input.orderId,
34
35
  refundId: input.refundId,
35
- refundedAmount: input.refundedAmountInPaise,
36
+ refundedAmount: input.refundedAmount,
36
37
  deductedAmount,
37
38
  reason: input.reason,
38
39
  });
@@ -1,7 +1,7 @@
1
1
  import type { ProductDocument } from "../../../shared/features/products/types";
2
2
  /** Assert a pre-order exists, is published, and has remaining capacity. */
3
3
  export declare function assertPreOrderAvailable(preOrderId: string, requestedQty?: number): Promise<ProductDocument>;
4
- /** Compute deposit amount in paise. */
4
+ /** Compute deposit amount, decimal rupees. */
5
5
  export declare function computeDeposit(product: ProductDocument): number;
6
6
  /** Determine if the pre-order is still open for new reservations. */
7
7
  export declare function isPreOrderOpen(product: ProductDocument): boolean;
@@ -1,5 +1,6 @@
1
1
  import { productRepository } from "../../../../repositories";
2
2
  import { isPreOrderListing } from "../../../../features/products/utils/listing-type";
3
+ import { roundRupees } from "../../../../utils/number.formatter";
3
4
  import { PreOrderNotFoundError, PreOrderSoldOutError, PreOrderNotOpenError, } from "../../../shared/features/pre-orders/errors";
4
5
  /** Assert a pre-order exists, is published, and has remaining capacity. */
5
6
  export async function assertPreOrderAvailable(preOrderId, requestedQty = 1) {
@@ -14,12 +15,12 @@ export async function assertPreOrderAvailable(preOrderId, requestedQty = 1) {
14
15
  throw new PreOrderSoldOutError(preOrderId);
15
16
  return product;
16
17
  }
17
- /** Compute deposit amount in paise. */
18
+ /** Compute deposit amount, decimal rupees. */
18
19
  export function computeDeposit(product) {
19
20
  if (product.preOrderDepositAmount)
20
21
  return product.preOrderDepositAmount;
21
22
  const percent = product.preOrderDepositPercent ?? 20;
22
- return Math.round((product.price * percent) / 100);
23
+ return roundRupees((product.price * percent) / 100);
23
24
  }
24
25
  /** Determine if the pre-order is still open for new reservations. */
25
26
  export function isPreOrderOpen(product) {
@@ -4,17 +4,17 @@
4
4
  */
5
5
  import { renderOgLayout } from "../seo/og-layout";
6
6
  import { resolveOgImageUrl } from "../seo/og";
7
- function formatPriceInr(paise, currency) {
7
+ function formatPriceInr(amount, currency) {
8
8
  return new Intl.NumberFormat("en-IN", {
9
9
  style: "currency",
10
10
  currency,
11
11
  maximumFractionDigits: 0,
12
- }).format(paise / 100);
12
+ }).format(amount);
13
13
  }
14
14
  export function renderPrizeDrawOg(doc, opts) {
15
- const entryPaise = doc?.pricePerEntry ?? doc?.price ?? null;
16
- const pricePerEntryLabel = typeof entryPaise === "number" && entryPaise > 0
17
- ? `${formatPriceInr(entryPaise, doc?.currency ?? "INR")} / entry`
15
+ const entryPrice = doc?.pricePerEntry ?? doc?.price ?? null;
16
+ const pricePerEntryLabel = typeof entryPrice === "number" && entryPrice > 0
17
+ ? `${formatPriceInr(entryPrice, doc?.currency ?? "INR")} / entry`
18
18
  : "Free entry";
19
19
  const max = doc?.prizeMaxEntries ?? null;
20
20
  const current = doc?.prizeCurrentEntries ?? 0;
@@ -9,7 +9,7 @@ export function renderProductOg(doc, opts) {
9
9
  }, opts.siteName);
10
10
  }
11
11
  export function renderProductOgImage(data, siteName) {
12
- const priceLabel = data.price ? `₹${(data.price / 100).toLocaleString("en-IN")}` : null;
12
+ const priceLabel = data.price ? `₹${data.price.toLocaleString("en-IN")}` : null;
13
13
  return renderOgLayout({
14
14
  title: data.title,
15
15
  imageUrl: data.imageUrl,
@@ -1,4 +1,5 @@
1
1
  import { couponsRepository } from "../../../../repositories";
2
+ import { roundRupees } from "../../../../utils/number.formatter";
2
3
  import { CouponNotFoundError, CouponExpiredError, CouponUsageLimitError, CouponPerUserLimitError, CouponMinPurchaseError, CouponScopeError, } from "../../../shared/features/promotions/errors";
3
4
  export async function validateCoupon(input, userId) {
4
5
  const coupon = await couponsRepository.getCouponByCode(input.code).catch(() => null);
@@ -33,7 +34,8 @@ export function computeDiscount(coupon, cartTotal) {
33
34
  const maxDiscount = coupon.discount?.maxDiscount;
34
35
  let discount = 0;
35
36
  if (type === "percentage") {
36
- discount = Math.round((cartTotal * value) / 100);
37
+ // audit-money-units-ok: percentage divisor (value is 0-100), not paise
38
+ discount = roundRupees((cartTotal * value) / 100);
37
39
  if (maxDiscount)
38
40
  discount = Math.min(discount, maxDiscount);
39
41
  }
@@ -3,8 +3,8 @@ import type { RefundType } from "../../../../features/orders/schemas";
3
3
  export type ProcessRefundInput = {
4
4
  orderId: string;
5
5
  type: RefundType;
6
- /** Amount in paise. Must be > 0 and ≤ remaining refundable amount on the order. */
7
- amountInPaise: number;
6
+ /** Decimal rupees. Must be > 0 and ≤ remaining refundable amount on the order. */
7
+ amount: number;
8
8
  reason: string;
9
9
  /** Product/item ids affected (for partial refunds). */
10
10
  itemIds?: string[];
@@ -16,6 +16,7 @@ import { wrapAction } from "@mohasinac/appkit/server";
16
16
  */
17
17
  import { randomUUID } from "crypto";
18
18
  import { getProviders } from "../../../../contracts/registry";
19
+ import { rupeesToPaise } from "../../../../providers/payment-razorpay/index";
19
20
  import { orderRepository } from "../../../..";
20
21
  import { ORDER_FIELDS } from "../../../../constants/field-names";
21
22
  import { NotFoundError, ValidationError } from "../../../../errors";
@@ -79,9 +80,9 @@ export async function processRefundAction(input) {
79
80
  const order = await orderRepository.findById(input.orderId);
80
81
  if (!order)
81
82
  throw new NotFoundError(`Order ${input.orderId} not found`);
82
- if (input.amountInPaise <= 0)
83
+ if (input.amount <= 0)
83
84
  throw new ValidationError("Refund amount must be positive");
84
- if (input.amountInPaise > order.totalPrice) {
85
+ if (input.amount > order.totalPrice) {
85
86
  throw new ValidationError("Refund amount exceeds order total");
86
87
  }
87
88
  // Guard: non-refundable orders (prize draws, bundles).
@@ -98,14 +99,14 @@ export async function processRefundAction(input) {
98
99
  const payment = getProviders().payment;
99
100
  if (!payment)
100
101
  throw new ValidationError("Payment provider not configured");
101
- const result = await payment.refund(input.razorpayPaymentId, input.amountInPaise);
102
+ const result = await payment.refund(input.razorpayPaymentId, rupeesToPaise(input.amount));
102
103
  razorpayRefundId = result.id;
103
104
  }
104
- const isFull = input.amountInPaise >= order.totalPrice;
105
+ const isFull = input.amount >= order.totalPrice;
105
106
  const event = {
106
107
  refundId,
107
108
  type: input.type,
108
- amount: input.amountInPaise,
109
+ amount: input.amount,
109
110
  ...(input.itemIds?.length ? { itemIds: input.itemIds } : {}),
110
111
  reason: input.reason,
111
112
  refundedAt: now,
@@ -131,7 +132,7 @@ export async function processRefundAction(input) {
131
132
  storeId: order.storeId,
132
133
  orderId: input.orderId,
133
134
  refundId,
134
- refundedAmountInPaise: input.amountInPaise,
135
+ refundedAmount: input.amount,
135
136
  reason: input.reason,
136
137
  }).catch(() => { });
137
138
  }
@@ -105,7 +105,7 @@ export const onScamReportUpdate = defineFunction({
105
105
  // files for the full data-flow explanation.
106
106
  export const onShipmentItemWrite = defineFunction({
107
107
  name: "onShipmentItemWrite",
108
- description: "Recompute a shipment lot's itemCount + mainItemsProjectedRevenuePaise on any item write.",
108
+ description: "Recompute a shipment lot's itemCount + mainItemsProjectedRevenue on any item write.",
109
109
  trigger: { kind: "documentWritten", pathPattern: "shipmentItems/{itemId}" },
110
110
  handler: onShipmentItemWriteHandler,
111
111
  options: { region: REGION },
@@ -1,5 +1,8 @@
1
1
  export declare const auctionSettlement: import("./types").ScheduledFunctionDefinition;
2
2
  export declare const pendingOrderTimeout: import("./types").ScheduledFunctionDefinition;
3
+ export declare const paymentWindowTimeout: import("./types").ScheduledFunctionDefinition;
4
+ export declare const hardBanReinstatement: import("./types").ScheduledFunctionDefinition;
5
+ export declare const paymentReviewAutoApprove: import("./types").ScheduledFunctionDefinition;
3
6
  export declare const couponExpiry: import("./types").ScheduledFunctionDefinition;
4
7
  export declare const offerExpiry: import("./types").ScheduledFunctionDefinition;
5
8
  export declare const productStatsSync: import("./types").ScheduledFunctionDefinition;
@@ -22,4 +25,4 @@ export declare const prizeRevealReminder: import("./types").ScheduledFunctionDef
22
25
  export declare const bundleStockSync: import("./types").ScheduledFunctionDefinition;
23
26
  export declare const emiInstallmentReminder: import("./types").ScheduledFunctionDefinition;
24
27
  export declare const catalogueImageStalenessReminder: import("./types").ScheduledFunctionDefinition;
25
- export declare const SCHEDULED_FUNCTIONS: readonly [import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition];
28
+ export declare const SCHEDULED_FUNCTIONS: readonly [import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition];
@@ -1,6 +1,6 @@
1
1
  // Scheduled function definitions (Cloud Scheduler triggers).
2
2
  // Cron syntax accepts both Firebase shorthand and standard cron expressions.
3
- import { auctionSettlementHandler, autoPayoutEligibilityHandler, bundleStockSyncHandler, cartPruneHandler, cleanupRtdbEventsHandler, countersReconcileHandler, couponExpiryHandler, dailyDataCleanupHandler, draftPruneHandler, emiInstallmentReminderHandler, catalogueImageStalenessReminderHandler, mediaTmpCleanupHandler, notificationPruneHandler, offerExpiryHandler, payoutBatchHandler, pendingOrderTimeoutHandler, positionsReconcileHandler, prizeRevealCloseHandler, prizeRevealExpiryHandler, prizeRevealOpenHandler, prizeRevealReminderHandler, productStatsSyncHandler, weeklyPayoutEligibilityHandler, testerSandboxCleanupHandler, } from "../jobs/handlers";
3
+ import { auctionSettlementHandler, autoPayoutEligibilityHandler, bundleStockSyncHandler, cartPruneHandler, cleanupRtdbEventsHandler, countersReconcileHandler, couponExpiryHandler, dailyDataCleanupHandler, draftPruneHandler, emiInstallmentReminderHandler, catalogueImageStalenessReminderHandler, mediaTmpCleanupHandler, notificationPruneHandler, offerExpiryHandler, payoutBatchHandler, paymentWindowTimeoutHandler, hardBanReinstatementHandler, paymentReviewAutoApproveHandler, pendingOrderTimeoutHandler, positionsReconcileHandler, prizeRevealCloseHandler, prizeRevealExpiryHandler, prizeRevealOpenHandler, prizeRevealReminderHandler, productStatsSyncHandler, weeklyPayoutEligibilityHandler, testerSandboxCleanupHandler, } from "../jobs/handlers";
4
4
  import { defineFunction } from "./define";
5
5
  const REGION = "asia-south1";
6
6
  const EVERY_5_MIN = "every 5 minutes";
@@ -13,11 +13,32 @@ export const auctionSettlement = defineFunction({
13
13
  });
14
14
  export const pendingOrderTimeout = defineFunction({
15
15
  name: "pendingOrderTimeout",
16
- description: "Cancel pending orders that exceeded their timeout window.",
16
+ description: "Cancel pending COD orders that exceeded the 24h timeout window (orders with a paymentDeadline are paymentWindowTimeout's domain instead).",
17
17
  trigger: { kind: "schedule", cron: "0 */2 * * *" },
18
18
  handler: pendingOrderTimeoutHandler,
19
19
  options: { region: REGION, timeoutSeconds: 120, memory: "256MiB", maxInstances: 1 },
20
20
  });
21
+ export const paymentWindowTimeout = defineFunction({
22
+ name: "paymentWindowTimeout",
23
+ description: "Cancel + restock orders whose 15-minute manual-payment window expired without proof.",
24
+ trigger: { kind: "schedule", cron: EVERY_5_MIN },
25
+ handler: paymentWindowTimeoutHandler,
26
+ options: { region: REGION, timeoutSeconds: 120, memory: "256MiB", maxInstances: 1 },
27
+ });
28
+ export const hardBanReinstatement = defineFunction({
29
+ name: "hardBanReinstatement",
30
+ description: "Re-enable Auth login for temporary hard-bans past their expiry.",
31
+ trigger: { kind: "schedule", cron: "*/15 * * * *" },
32
+ handler: hardBanReinstatementHandler,
33
+ options: { region: REGION, timeoutSeconds: 120, memory: "256MiB", maxInstances: 1 },
34
+ });
35
+ export const paymentReviewAutoApprove = defineFunction({
36
+ name: "paymentReviewAutoApprove",
37
+ description: "Auto-approve manual payment proofs unreviewed after 2 hours.",
38
+ trigger: { kind: "schedule", cron: "*/15 * * * *" },
39
+ handler: paymentReviewAutoApproveHandler,
40
+ options: { region: REGION, timeoutSeconds: 120, memory: "256MiB", maxInstances: 1 },
41
+ });
21
42
  export const couponExpiry = defineFunction({
22
43
  name: "couponExpiry",
23
44
  description: "Mark coupons inactive past their endDate (daily 00:05 UTC).",
@@ -175,6 +196,9 @@ export const catalogueImageStalenessReminder = defineFunction({
175
196
  export const SCHEDULED_FUNCTIONS = [
176
197
  auctionSettlement,
177
198
  pendingOrderTimeout,
199
+ paymentWindowTimeout,
200
+ hardBanReinstatement,
201
+ paymentReviewAutoApprove,
178
202
  couponExpiry,
179
203
  offerExpiry,
180
204
  productStatsSync,
@@ -46,7 +46,7 @@ export async function runEmiInstallmentReminder(ctx) {
46
46
  title: isOverdue ? "EMI installment overdue" : "EMI installment due soon",
47
47
  message: isOverdue
48
48
  ? `Installment ${inst.index} for order ${id} is overdue. Pay now to avoid delaying your shipment.`
49
- : `Installment ${inst.index} for order ${id} (₹${(inst.amount / 100).toFixed(2)}) is due on ${dueDate.toDateString()}.`,
49
+ : `Installment ${inst.index} for order ${id} (₹${inst.amount.toFixed(2)}) is due on ${dueDate.toDateString()}.`,
50
50
  relatedId: id,
51
51
  relatedType: "order",
52
52
  actionUrl: `/user/orders/view/${id}`,
@@ -22,5 +22,9 @@ export interface HardBanCascadeInput {
22
22
  uid: string;
23
23
  reason: string;
24
24
  bannedBy: string;
25
+ /** Tier PP — omitted/undefined = permanent (today's only caller, the manual admin hard-ban route). A Date makes this a temporary ban, auto-reinstated by `hardBanReinstatement` — set by `adminRejectPaymentAsFraudAction`. */
26
+ expiresAt?: Date;
27
+ /** Tier PP — the order whose payment proof was rejected as fraudulent, for traceability. Only set alongside `expiresAt`. */
28
+ fraudOrderId?: string;
25
29
  }
26
30
  export declare function runHardBanCascade(input: HardBanCascadeInput, ctx: JobContext): Promise<JobRunResult>;