@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.
- package/dist/_internal/client/features/live/LiveItemDetailView.js +2 -2
- package/dist/_internal/client/features/lottery/LotteryAdminEditView.d.ts +4 -4
- package/dist/_internal/client/features/lottery/LotteryAdminEditView.js +8 -8
- package/dist/_internal/client/features/lottery/LotteryAdminSlotView.d.ts +1 -1
- package/dist/_internal/client/features/lottery/LotteryAdminSlotView.js +2 -2
- package/dist/_internal/server/features/bundles/actions.js +2 -2
- package/dist/_internal/server/features/bundles/og.d.ts +1 -1
- package/dist/_internal/server/features/bundles/og.js +4 -5
- package/dist/_internal/server/features/checkout/actions.js +57 -21
- package/dist/_internal/server/features/checkout/stock-restore.d.ts +19 -0
- package/dist/_internal/server/features/checkout/stock-restore.js +80 -0
- package/dist/_internal/server/features/checkout/upi-resolution.d.ts +11 -0
- package/dist/_internal/server/features/checkout/upi-resolution.js +28 -0
- package/dist/_internal/server/features/classified/og.js +1 -1
- package/dist/_internal/server/features/digital-code/og.js +1 -1
- package/dist/_internal/server/features/item-requests/og.d.ts +2 -2
- package/dist/_internal/server/features/item-requests/og.js +4 -5
- package/dist/_internal/server/features/live/og.js +1 -1
- package/dist/_internal/server/features/lottery/adapters.d.ts +2 -2
- package/dist/_internal/server/features/lottery/adapters.js +1 -1
- package/dist/_internal/server/features/orders/actions.d.ts +28 -0
- package/dist/_internal/server/features/orders/actions.js +239 -4
- package/dist/_internal/server/features/orders/adapters.js +3 -0
- package/dist/_internal/server/features/payments/data.js +3 -2
- package/dist/_internal/server/features/payouts/actions.d.ts +2 -2
- package/dist/_internal/server/features/payouts/actions.js +4 -3
- package/dist/_internal/server/features/pre-orders/service.d.ts +1 -1
- package/dist/_internal/server/features/pre-orders/service.js +3 -2
- package/dist/_internal/server/features/prize-draws/og.js +5 -5
- package/dist/_internal/server/features/products/og.js +1 -1
- package/dist/_internal/server/features/promotions/service.js +3 -1
- package/dist/_internal/server/features/refunds/actions.d.ts +2 -2
- package/dist/_internal/server/features/refunds/actions.js +7 -6
- package/dist/_internal/server/functions/firestore.js +1 -1
- package/dist/_internal/server/functions/scheduled.d.ts +4 -1
- package/dist/_internal/server/functions/scheduled.js +26 -2
- package/dist/_internal/server/jobs/core/emiInstallmentReminder.js +1 -1
- package/dist/_internal/server/jobs/core/hardBanCascade.d.ts +4 -0
- package/dist/_internal/server/jobs/core/hardBanCascade.js +15 -4
- package/dist/_internal/server/jobs/core/hardBanReinstatement.d.ts +16 -0
- package/dist/_internal/server/jobs/core/hardBanReinstatement.js +63 -0
- package/dist/_internal/server/jobs/core/jobRunners.js +3 -1
- package/dist/_internal/server/jobs/core/onScamReportCreate.js +1 -1
- package/dist/_internal/server/jobs/core/paymentReviewAutoApprove.d.ts +10 -0
- package/dist/_internal/server/jobs/core/paymentReviewAutoApprove.js +60 -0
- package/dist/_internal/server/jobs/core/paymentWindowTimeout.d.ts +15 -0
- package/dist/_internal/server/jobs/core/paymentWindowTimeout.js +59 -0
- package/dist/_internal/server/jobs/core/pendingOrderTimeout.d.ts +7 -0
- package/dist/_internal/server/jobs/core/pendingOrderTimeout.js +32 -6
- package/dist/_internal/server/jobs/handlers/hardBanReinstatement.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/hardBanReinstatement.js +2 -0
- package/dist/_internal/server/jobs/handlers/index.d.ts +3 -0
- package/dist/_internal/server/jobs/handlers/index.js +3 -0
- package/dist/_internal/server/jobs/handlers/messages.d.ts +4 -0
- package/dist/_internal/server/jobs/handlers/messages.js +4 -0
- package/dist/_internal/server/jobs/handlers/onShipmentAllocationSync.d.ts +3 -3
- package/dist/_internal/server/jobs/handlers/onShipmentAllocationSync.js +12 -12
- package/dist/_internal/server/jobs/handlers/onShipmentItemWrite.d.ts +1 -1
- package/dist/_internal/server/jobs/handlers/onShipmentItemWrite.js +5 -5
- package/dist/_internal/server/jobs/handlers/paymentReviewAutoApprove.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/paymentReviewAutoApprove.js +2 -0
- package/dist/_internal/server/jobs/handlers/paymentWindowTimeout.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/paymentWindowTimeout.js +2 -0
- package/dist/_internal/shared/actions/action-registry.js +27 -0
- package/dist/_internal/shared/checkout/order-math.js +3 -2
- package/dist/_internal/shared/checkout/rules/_defaults.js +1 -0
- package/dist/_internal/shared/checkout/rules/preorder.rule.js +7 -0
- package/dist/_internal/shared/checkout/rules/prize-draw.rule.js +7 -0
- package/dist/_internal/shared/checkout/rules/types.d.ts +11 -0
- package/dist/_internal/shared/features/auctions/errors.js +1 -1
- package/dist/_internal/shared/features/categories/bundle-copy.d.ts +0 -1
- package/dist/_internal/shared/features/categories/bundle-copy.js +0 -1
- package/dist/_internal/shared/features/categories/bundle-schemas.d.ts +6 -6
- package/dist/_internal/shared/features/categories/bundle-schemas.js +2 -2
- package/dist/_internal/shared/features/checkout/config.d.ts +3 -3
- package/dist/_internal/shared/features/checkout/config.js +3 -3
- package/dist/_internal/shared/features/emi/schedule.d.ts +6 -6
- package/dist/_internal/shared/features/emi/schedule.js +10 -9
- package/dist/_internal/shared/features/promotions/errors.js +1 -1
- package/dist/_internal/shared/fees/calculator.d.ts +5 -5
- package/dist/_internal/shared/fees/calculator.js +19 -19
- package/dist/client.d.ts +1 -1
- package/dist/client.js +1 -1
- package/dist/constants/api-endpoints.d.ts +9 -0
- package/dist/constants/api-endpoints.js +3 -0
- package/dist/constants/field-names.d.ts +4 -0
- package/dist/constants/field-names.js +4 -0
- package/dist/features/admin/components/AdminArtView.js +2 -2
- package/dist/features/admin/components/AdminBidsView.js +2 -2
- package/dist/features/admin/components/AdminBundleEditorView.d.ts +1 -1
- package/dist/features/admin/components/AdminBundleEditorView.js +8 -8
- package/dist/features/admin/components/AdminBundlesView.js +6 -6
- package/dist/features/admin/components/AdminClassifiedView.js +2 -2
- package/dist/features/admin/components/AdminDigitalCodesView.js +2 -2
- package/dist/features/admin/components/AdminLiveView.js +2 -2
- package/dist/features/admin/components/AdminOrderEditorView.d.ts +6 -1
- package/dist/features/admin/components/AdminOrderEditorView.js +45 -5
- package/dist/features/admin/components/AdminOrdersView.js +8 -3
- package/dist/features/admin/components/AdminPayoutsView.js +2 -2
- package/dist/features/admin/components/AdminPrizeDrawsView.js +2 -2
- package/dist/features/admin/components/AdminReturnRequestsView.js +2 -2
- package/dist/features/admin/components/AdminSectionsView.js +4 -4
- package/dist/features/admin/components/AdminSiteSettingsView.js +11 -11
- package/dist/features/admin/components/AdminStickersView.js +2 -2
- package/dist/features/admin/components/AdminSupportTicketDetailView.js +1 -1
- package/dist/features/admin/components/sections/adminSectionsBuildParse.js +13 -5
- package/dist/features/admin/components/sections/adminSectionsTypes.d.ts +4 -0
- package/dist/features/admin/components/sections/adminSectionsTypes.js +9 -5
- package/dist/features/admin/hooks/useAdminListingData.d.ts +1 -1
- package/dist/features/admin/hooks/useAdminListingData.js +3 -2
- package/dist/features/admin/schemas/firestore.d.ts +9 -7
- package/dist/features/admin/schemas/firestore.js +4 -3
- package/dist/features/auctions/components/AuctionBidsTable.js +3 -3
- package/dist/features/auth/checkout-value-otp.d.ts +46 -0
- package/dist/features/auth/checkout-value-otp.js +73 -0
- package/dist/features/auth/repository/user.repository.d.ts +6 -0
- package/dist/features/auth/repository/user.repository.js +19 -0
- package/dist/features/auth/schemas/firestore.d.ts +10 -0
- package/dist/features/auth/schemas/firestore.js +2 -0
- package/dist/features/cart/actions/cart-actions.d.ts +1 -1
- package/dist/features/cart/actions/cart-actions.js +4 -4
- package/dist/features/cart/components/CartView.d.ts +2 -2
- package/dist/features/cart/components/ShippingPicker.d.ts +4 -4
- package/dist/features/cart/components/ShippingPicker.js +11 -11
- package/dist/features/cart/repository/cart.repository.d.ts +1 -1
- package/dist/features/cart/repository/cart.repository.js +2 -2
- package/dist/features/cart/schemas/firestore.d.ts +2 -2
- package/dist/features/catalogue/components/CatalogueItemEditorView.js +3 -3
- package/dist/features/catalogue/components/PublicCatalogueView.js +2 -2
- package/dist/features/catalogue/schemas/validation.js +1 -1
- package/dist/features/categories/components/BundleCollage.js +2 -2
- package/dist/features/categories/components/BundleDetailView.js +2 -2
- package/dist/features/categories/components/BundleItemsPicker.d.ts +1 -1
- package/dist/features/categories/components/BundleItemsPicker.js +2 -2
- package/dist/features/categories/components/CategoryBundlesListing.js +2 -2
- package/dist/features/categories/schemas/firestore.d.ts +1 -1
- package/dist/features/categories/schemas/index.d.ts +3 -3
- package/dist/features/categories/schemas/index.js +2 -2
- package/dist/features/checkout/actions/checkout-value-otp-actions.d.ts +16 -0
- package/dist/features/checkout/actions/checkout-value-otp-actions.js +83 -0
- package/dist/features/checkout/actions/index.d.ts +1 -0
- package/dist/features/checkout/actions/index.js +1 -0
- package/dist/features/checkout/schemas/firestore.d.ts +1 -1
- package/dist/features/classified/components/index.d.ts +0 -4
- package/dist/features/classified/components/index.js +0 -2
- package/dist/features/digital-codes/components/index.d.ts +0 -4
- package/dist/features/digital-codes/components/index.js +0 -2
- package/dist/features/events/schemas/index.d.ts +1 -1
- package/dist/features/events/schemas/index.js +1 -1
- package/dist/features/homepage/components/BrandsSection.d.ts +4 -1
- package/dist/features/homepage/components/BrandsSection.js +2 -2
- package/dist/features/homepage/components/CustomCardsSection.js +3 -3
- package/dist/features/homepage/components/CustomerReviewsSection.d.ts +4 -1
- package/dist/features/homepage/components/CustomerReviewsSection.js +2 -2
- package/dist/features/homepage/components/EventsSection.d.ts +4 -1
- package/dist/features/homepage/components/EventsSection.js +2 -2
- package/dist/features/homepage/components/FeaturedAuctionsSection.d.ts +2 -1
- package/dist/features/homepage/components/FeaturedAuctionsSection.js +2 -2
- package/dist/features/homepage/components/FeaturedBundlesSection.js +2 -2
- package/dist/features/homepage/components/FeaturedPreOrdersSection.d.ts +2 -1
- package/dist/features/homepage/components/FeaturedPreOrdersSection.js +2 -2
- package/dist/features/homepage/components/FeaturedProductsSection.d.ts +2 -1
- package/dist/features/homepage/components/FeaturedProductsSection.js +2 -2
- package/dist/features/homepage/components/FeaturedStoresSection.d.ts +4 -1
- package/dist/features/homepage/components/FeaturedStoresSection.js +2 -2
- package/dist/features/homepage/components/HomepageCustomerReviewsSection.d.ts +4 -1
- package/dist/features/homepage/components/HomepageCustomerReviewsSection.js +2 -2
- package/dist/features/homepage/components/SectionCarousel.d.ts +3 -1
- package/dist/features/homepage/components/SectionCarousel.js +2 -2
- package/dist/features/homepage/components/ShopByCategorySection.d.ts +4 -1
- package/dist/features/homepage/components/ShopByCategorySection.js +2 -2
- package/dist/features/homepage/lib/section-renderer.js +9 -9
- package/dist/features/homepage/schemas/firestore.d.ts +8 -0
- package/dist/features/live/components/index.d.ts +0 -4
- package/dist/features/live/components/index.js +0 -2
- package/dist/features/lottery/types/index.d.ts +3 -3
- package/dist/features/lottery/types/index.js +5 -5
- package/dist/features/orders/components/OrderPaymentSummary.js +2 -2
- package/dist/features/orders/components/OrderSiblingPayments.js +1 -1
- package/dist/features/orders/components/RefundHistoryTable.js +1 -1
- package/dist/features/orders/components/RefundRequestView.js +1 -1
- package/dist/features/orders/constants/payment-window.d.ts +10 -0
- package/dist/features/orders/constants/payment-window.js +10 -0
- package/dist/features/orders/repository/orders.repository.d.ts +25 -0
- package/dist/features/orders/repository/orders.repository.js +50 -1
- package/dist/features/orders/schemas/firestore.d.ts +50 -2
- package/dist/features/orders/schemas/index.d.ts +24 -24
- package/dist/features/orders/schemas/index.js +20 -20
- package/dist/features/orders/types/index.d.ts +4 -0
- package/dist/features/orders/utils/bundle-grouping.d.ts +1 -1
- package/dist/features/orders/utils/bundle-grouping.js +1 -1
- package/dist/features/payments/schemas/index.d.ts +10 -10
- package/dist/features/payments/schemas/index.js +9 -9
- package/dist/features/pre-orders/components/PreOrderDetailPageView.js +2 -2
- package/dist/features/products/components/ArtStickersListView.d.ts +7 -0
- package/dist/features/products/components/ArtStickersListView.js +57 -0
- package/dist/features/products/components/GroupSettingsPanel.js +1 -1
- package/dist/features/products/components/MakeOfferButton.js +3 -3
- package/dist/features/products/components/MarketplaceBundleCard.d.ts +1 -1
- package/dist/features/products/components/MarketplaceBundleCard.js +2 -2
- package/dist/features/products/components/PrizeDrawCollage.js +2 -2
- package/dist/features/products/components/PrizeDrawItemsEditor.js +2 -2
- package/dist/features/products/components/PrizeRevealModal.js +1 -1
- package/dist/features/products/components/ProductDetailPageView.js +2 -9
- package/dist/features/products/components/ProductForm.js +2 -2
- package/dist/features/products/components/ProductGrid.js +2 -2
- package/dist/features/products/components/ProductsIndexListing.d.ts +13 -1
- package/dist/features/products/components/ProductsIndexListing.js +7 -5
- package/dist/features/products/components/ProductsIndexPageView.js +6 -1
- package/dist/features/products/constants/listing-tabs.d.ts +42 -17
- package/dist/features/products/constants/listing-tabs.js +25 -6
- package/dist/features/products/schemas/catalog-product.d.ts +5 -5
- package/dist/features/products/schemas/catalog-product.js +1 -1
- package/dist/features/products/schemas/firestore.d.ts +5 -5
- package/dist/features/products/schemas/firestore.js +2 -2
- package/dist/features/products/types/index.d.ts +5 -2
- package/dist/features/promotions/components/CouponCard.js +2 -2
- package/dist/features/promotions/schemas/firestore.d.ts +2 -0
- package/dist/features/promotions/schemas/firestore.js +1 -0
- package/dist/features/promotions/schemas/index.d.ts +14 -14
- package/dist/features/promotions/schemas/index.js +6 -6
- package/dist/features/scams/components/ScamProfileView.js +3 -7
- package/dist/features/scams/components/ScamRegistryView.js +2 -6
- package/dist/features/scams/schemas/firestore.d.ts +1 -1
- package/dist/features/search/components/Search.d.ts +1 -1
- package/dist/features/seller/actions/offer-actions.js +1 -1
- package/dist/features/seller/components/PrintCenterView.js +2 -2
- package/dist/features/seller/components/QuickProductForm.js +5 -5
- package/dist/features/seller/components/SellerArtView.js +2 -2
- package/dist/features/seller/components/SellerAuctionsView.js +2 -2
- package/dist/features/seller/components/SellerBidsView.js +2 -2
- package/dist/features/seller/components/SellerBundlesView.js +6 -6
- package/dist/features/seller/components/SellerClassifiedView.js +2 -2
- package/dist/features/seller/components/SellerDigitalCodesView.js +2 -2
- package/dist/features/seller/components/SellerLiveView.js +2 -2
- package/dist/features/seller/components/SellerOffersView.js +2 -2
- package/dist/features/seller/components/SellerOrdersView.js +3 -3
- package/dist/features/seller/components/SellerPayoutRequestView.js +2 -2
- package/dist/features/seller/components/SellerPayoutSettingsView.js +2 -2
- package/dist/features/seller/components/SellerPayoutsView.js +2 -2
- package/dist/features/seller/components/SellerPreOrdersView.js +2 -2
- package/dist/features/seller/components/SellerPrizeDrawsView.js +2 -2
- package/dist/features/seller/components/SellerProductShell.js +8 -8
- package/dist/features/seller/components/SellerProductsView.js +1 -1
- package/dist/features/seller/components/SellerShippingView.js +6 -6
- package/dist/features/seller/components/SellerStickersView.js +2 -2
- package/dist/features/seller/hooks/useSellerListingData.d.ts +1 -1
- package/dist/features/seller/hooks/useSellerListingData.js +3 -2
- package/dist/features/shipments/components/AdminShipmentEditorView.js +10 -10
- package/dist/features/shipments/components/AdminShipmentLotItemsView.js +4 -4
- package/dist/features/shipments/components/AdminShipmentProjectionsView.js +5 -5
- package/dist/features/shipments/components/AdminShipmentsView.js +4 -4
- package/dist/features/shipments/repository/shipment-lots.repository.d.ts +2 -2
- package/dist/features/shipments/repository/shipment-lots.repository.js +8 -8
- package/dist/features/shipments/schemas/firestore.d.ts +21 -21
- package/dist/features/shipments/schemas/firestore.js +9 -9
- package/dist/features/shipments/schemas/validation.d.ts +30 -30
- package/dist/features/shipments/schemas/validation.js +6 -6
- package/dist/features/shipments/utils/cost-allocation.d.ts +5 -5
- package/dist/features/shipments/utils/cost-allocation.js +39 -38
- package/dist/features/store-extensions/schemas/firestore.d.ts +5 -5
- package/dist/features/stores/components/StoreDetailLayoutView.js +9 -13
- package/dist/features/stores/schemas/firestore.d.ts +7 -7
- package/dist/features/stores/schemas/index.d.ts +84 -84
- package/dist/features/stores/schemas/index.js +5 -5
- package/dist/features/tester/seed-data/categories-tester-seed-data.js +1 -1
- package/dist/features/tester/seed-data/products-tester-seed-data.js +6 -6
- package/dist/features/tester/seed-data/tester-checklist-seed-data.js +9 -2
- package/dist/features/whatsapp-bot/helpers/whatsapp.d.ts +8 -1
- package/dist/features/whatsapp-bot/helpers/whatsapp.js +13 -2
- package/dist/features/whatsapp-bot/types/index.d.ts +9 -1
- package/dist/index.d.ts +3 -7
- package/dist/index.js +7 -5
- package/dist/next/routing/route-map.d.ts +2 -0
- package/dist/next/routing/route-map.js +6 -0
- package/dist/schemas/firestore-helpers.d.ts +2 -2
- package/dist/schemas/firestore-helpers.js +2 -2
- package/dist/schemas/registry.d.ts +73 -73
- package/dist/seed/bids-seed-data.js +6 -6
- package/dist/seed/blog-posts-seed-data.js +1 -0
- package/dist/seed/cart-seed-data.js +13 -13
- package/dist/seed/catalogue-seed-data.js +6 -6
- package/dist/seed/categories-seed-data.js +5 -5
- package/dist/seed/claimed-coupons-seed-data.js +3 -3
- package/dist/seed/coupons-seed-data.js +20 -20
- package/dist/seed/events-seed-data.js +27 -27
- package/dist/seed/factories/bid.factory.js +1 -1
- package/dist/seed/faq-seed-data.js +20 -1
- package/dist/seed/grouped-listings-seed-data.d.ts +2 -2
- package/dist/seed/grouped-listings-seed-data.js +3 -3
- package/dist/seed/homepage-sections-seed-data.js +10 -0
- package/dist/seed/offers-seed-data.js +19 -19
- package/dist/seed/orders-seed-data.js +29 -29
- package/dist/seed/payouts-seed-data.js +7 -7
- package/dist/seed/products-auctions-seed-data.js +6 -6
- package/dist/seed/products-preorders-seed-data.d.ts +2 -2
- package/dist/seed/products-preorders-seed-data.js +1 -1
- package/dist/seed/products-standard-seed-data.js +8 -8
- package/dist/seed/scammers-seed-data.js +2 -2
- package/dist/seed/shipments-seed-data.js +29 -29
- package/dist/seed/site-settings-seed-data.js +3 -2
- package/dist/seed/store-extensions-seed-data.js +8 -8
- package/dist/seed/stores-seed-data.js +37 -8
- package/dist/seed/users-seed-data.js +38 -1
- package/dist/server-entry.d.ts +1 -3
- package/dist/server-entry.js +1 -3
- package/dist/server.d.ts +2 -1
- package/dist/server.js +3 -1
- package/dist/ui/components/HorizontalScroller.js +3 -0
- package/dist/ui/components/PriceDisplay.js +3 -12
- package/dist/utils/number.formatter.d.ts +2 -7
- package/dist/utils/number.formatter.js +3 -8
- package/package.json +1 -1
- package/scripts/seed-cli.mjs +8 -3
- package/dist/_internal/client/scaffolds/DashboardScaffold.d.ts +0 -34
- package/dist/_internal/client/scaffolds/DashboardScaffold.js +0 -26
- package/dist/_internal/client/theme/__tests__/ThemeProvider.test.d.ts +0 -1
- package/dist/_internal/client/theme/__tests__/ThemeProvider.test.js +0 -109
- package/dist/_internal/server/features/auctions/__tests__/service.test.d.ts +0 -1
- package/dist/_internal/server/features/auctions/__tests__/service.test.js +0 -140
- package/dist/_internal/server/features/checkout/__tests__/actions.test.d.ts +0 -1
- package/dist/_internal/server/features/checkout/__tests__/actions.test.js +0 -600
- package/dist/_internal/server/features/refunds/__tests__/actions.test.d.ts +0 -1
- package/dist/_internal/server/features/refunds/__tests__/actions.test.js +0 -263
- package/dist/_internal/server/jobs/core/__tests__/auctionSettlement.test.d.ts +0 -1
- package/dist/_internal/server/jobs/core/__tests__/auctionSettlement.test.js +0 -249
- package/dist/_internal/server/jobs/core/__tests__/couponExpiry.test.d.ts +0 -1
- package/dist/_internal/server/jobs/core/__tests__/couponExpiry.test.js +0 -65
- package/dist/_internal/server/jobs/core/__tests__/listingProcessor.test.d.ts +0 -1
- package/dist/_internal/server/jobs/core/__tests__/listingProcessor.test.js +0 -163
- package/dist/_internal/server/jobs/core/__tests__/mediaTmpCleanup.test.d.ts +0 -1
- package/dist/_internal/server/jobs/core/__tests__/mediaTmpCleanup.test.js +0 -115
- package/dist/_internal/server/jobs/core/__tests__/onBidPlaced.test.d.ts +0 -1
- package/dist/_internal/server/jobs/core/__tests__/onBidPlaced.test.js +0 -201
- package/dist/_internal/server/jobs/core/__tests__/onOrderCreate.test.d.ts +0 -1
- package/dist/_internal/server/jobs/core/__tests__/onOrderCreate.test.js +0 -169
- package/dist/_internal/server/jobs/core/__tests__/onOrderStatusChange.test.d.ts +0 -1
- package/dist/_internal/server/jobs/core/__tests__/onOrderStatusChange.test.js +0 -148
- package/dist/_internal/server/jobs/core/__tests__/onProductStockChange.test.d.ts +0 -1
- package/dist/_internal/server/jobs/core/__tests__/onProductStockChange.test.js +0 -210
- package/dist/_internal/server/jobs/core/__tests__/onReviewWrite.test.d.ts +0 -1
- package/dist/_internal/server/jobs/core/__tests__/onReviewWrite.test.js +0 -190
- package/dist/_internal/server/jobs/core/__tests__/onUserBanChange.test.d.ts +0 -1
- package/dist/_internal/server/jobs/core/__tests__/onUserBanChange.test.js +0 -161
- package/dist/_internal/server/jobs/core/__tests__/payoutBatch.test.d.ts +0 -1
- package/dist/_internal/server/jobs/core/__tests__/payoutBatch.test.js +0 -302
- package/dist/_internal/server/jobs/core/__tests__/pendingOrderTimeout.test.d.ts +0 -1
- package/dist/_internal/server/jobs/core/__tests__/pendingOrderTimeout.test.js +0 -96
- package/dist/_internal/server/jobs/core/__tests__/triggerEventRaffle.test.d.ts +0 -1
- package/dist/_internal/server/jobs/core/__tests__/triggerEventRaffle.test.js +0 -252
- package/dist/_internal/server/jobs/core/__tests__/wrapJobHandler.test.d.ts +0 -1
- package/dist/_internal/server/jobs/core/__tests__/wrapJobHandler.test.js +0 -129
- package/dist/_internal/server/jobs/core/onCatalogueSubmittedForApproval.d.ts +0 -15
- package/dist/_internal/server/jobs/core/onCatalogueSubmittedForApproval.js +0 -38
- package/dist/_internal/server/providers/index.d.ts +0 -11
- package/dist/_internal/server/providers/index.js +0 -11
- package/dist/_internal/server/providers/payment/razorpay-mock.d.ts +0 -52
- package/dist/_internal/server/providers/payment/razorpay-mock.js +0 -118
- package/dist/_internal/server/providers/resolve.d.ts +0 -36
- package/dist/_internal/server/providers/resolve.js +0 -31
- package/dist/_internal/server/providers/shipping/shiprocket-mock.d.ts +0 -29
- package/dist/_internal/server/providers/shipping/shiprocket-mock.js +0 -152
- package/dist/_internal/shared/types/__tests__/action-result.test.d.ts +0 -1
- package/dist/_internal/shared/types/__tests__/action-result.test.js +0 -65
- package/dist/errors/__tests__/error-mapping.test.d.ts +0 -1
- package/dist/errors/__tests__/error-mapping.test.js +0 -122
- package/dist/errors/__tests__/safe-read.test.d.ts +0 -1
- package/dist/errors/__tests__/safe-read.test.js +0 -39
- package/dist/features/addresses/repository/__tests__/addresses.repository.test.d.ts +0 -1
- package/dist/features/addresses/repository/__tests__/addresses.repository.test.js +0 -386
- package/dist/features/admin/components/AdminListingScaffold.d.ts +0 -41
- package/dist/features/admin/components/AdminListingScaffold.js +0 -68
- package/dist/features/admin/components/QuickActionsPanel.d.ts +0 -15
- package/dist/features/admin/components/QuickActionsPanel.js +0 -5
- package/dist/features/admin/repository/__tests__/notification.repository.test.d.ts +0 -1
- package/dist/features/admin/repository/__tests__/notification.repository.test.js +0 -356
- package/dist/features/admin/repository/__tests__/site-settings.repository.test.d.ts +0 -1
- package/dist/features/admin/repository/__tests__/site-settings.repository.test.js +0 -298
- package/dist/features/auctions/repository/__tests__/bid.repository.test.d.ts +0 -1
- package/dist/features/auctions/repository/__tests__/bid.repository.test.js +0 -290
- package/dist/features/auctions/repository/auctions.repository.d.ts +0 -12
- package/dist/features/auctions/repository/auctions.repository.js +0 -42
- package/dist/features/auth/repository/__tests__/session.repository.test.d.ts +0 -1
- package/dist/features/auth/repository/__tests__/session.repository.test.js +0 -310
- package/dist/features/auth/repository/__tests__/session.test.d.ts +0 -1
- package/dist/features/auth/repository/__tests__/session.test.js +0 -146
- package/dist/features/auth/repository/__tests__/sms-counter.repository.test.d.ts +0 -1
- package/dist/features/auth/repository/__tests__/sms-counter.repository.test.js +0 -171
- package/dist/features/auth/repository/__tests__/sms-counter.test.d.ts +0 -1
- package/dist/features/auth/repository/__tests__/sms-counter.test.js +0 -88
- package/dist/features/auth/repository/__tests__/token.repository.test.d.ts +0 -1
- package/dist/features/auth/repository/__tests__/token.repository.test.js +0 -260
- package/dist/features/auth/repository/__tests__/token.test.d.ts +0 -1
- package/dist/features/auth/repository/__tests__/token.test.js +0 -140
- package/dist/features/auth/repository/__tests__/user.repository.test.d.ts +0 -1
- package/dist/features/auth/repository/__tests__/user.repository.test.js +0 -352
- package/dist/features/auth/repository/__tests__/user.test.d.ts +0 -1
- package/dist/features/auth/repository/__tests__/user.test.js +0 -226
- package/dist/features/before-after/repository/before-after.repository.d.ts +0 -13
- package/dist/features/before-after/repository/before-after.repository.js +0 -36
- package/dist/features/before-after/server.d.ts +0 -6
- package/dist/features/before-after/server.js +0 -6
- package/dist/features/cart/repository/__tests__/cart.repository.test.d.ts +0 -1
- package/dist/features/cart/repository/__tests__/cart.repository.test.js +0 -371
- package/dist/features/categories/repository/__tests__/categories.repository.test.d.ts +0 -1
- package/dist/features/categories/repository/__tests__/categories.repository.test.js +0 -813
- package/dist/features/collections/repository/collections.repository.d.ts +0 -8
- package/dist/features/collections/repository/collections.repository.js +0 -16
- package/dist/features/collections/server.d.ts +0 -6
- package/dist/features/collections/server.js +0 -6
- package/dist/features/events/repository/__tests__/event.repository.test.d.ts +0 -1
- package/dist/features/events/repository/__tests__/event.repository.test.js +0 -299
- package/dist/features/faq/repository/__tests__/faqs.repository.test.d.ts +0 -1
- package/dist/features/faq/repository/__tests__/faqs.repository.test.js +0 -311
- package/dist/features/forms/Form.d.ts +0 -25
- package/dist/features/forms/Form.js +0 -37
- package/dist/features/history/repository/__tests__/user-history.repository.test.d.ts +0 -1
- package/dist/features/history/repository/__tests__/user-history.repository.test.js +0 -180
- package/dist/features/homepage/repository/__tests__/carousel.repository.test.d.ts +0 -1
- package/dist/features/homepage/repository/__tests__/carousel.repository.test.js +0 -182
- package/dist/features/homepage/repository/__tests__/homepage-sections.repository.test.d.ts +0 -1
- package/dist/features/homepage/repository/__tests__/homepage-sections.repository.test.js +0 -185
- package/dist/features/layout/ListingLayout.d.ts +0 -34
- package/dist/features/layout/ListingLayout.js +0 -103
- package/dist/features/messages/repository/__tests__/conversations.repository.test.d.ts +0 -1
- package/dist/features/messages/repository/__tests__/conversations.repository.test.js +0 -257
- package/dist/features/orders/repository/__tests__/orders.repository.test.d.ts +0 -1
- package/dist/features/orders/repository/__tests__/orders.repository.test.js +0 -211
- package/dist/features/payments/repository/__tests__/payout.repository.test.d.ts +0 -1
- package/dist/features/payments/repository/__tests__/payout.repository.test.js +0 -292
- package/dist/features/pre-orders/repository/preorders.repository.d.ts +0 -8
- package/dist/features/pre-orders/repository/preorders.repository.js +0 -25
- package/dist/features/products/repository/__tests__/product-features.repository.test.d.ts +0 -1
- package/dist/features/products/repository/__tests__/product-features.repository.test.js +0 -329
- package/dist/features/products/repository/__tests__/products.repository.test.d.ts +0 -1
- package/dist/features/products/repository/__tests__/products.repository.test.js +0 -607
- package/dist/features/promotions/repository/__tests__/claimed-coupons.repository.test.d.ts +0 -1
- package/dist/features/promotions/repository/__tests__/claimed-coupons.repository.test.js +0 -219
- package/dist/features/promotions/repository/__tests__/coupons.repository.test.d.ts +0 -1
- package/dist/features/promotions/repository/__tests__/coupons.repository.test.js +0 -480
- package/dist/features/promotions/repository/promotions.repository.d.ts +0 -14
- package/dist/features/promotions/repository/promotions.repository.js +0 -43
- package/dist/features/reviews/repository/__tests__/reviews.repository.test.d.ts +0 -1
- package/dist/features/reviews/repository/__tests__/reviews.repository.test.js +0 -327
- package/dist/features/scams/repository/__tests__/scammer.repository.test.d.ts +0 -1
- package/dist/features/scams/repository/__tests__/scammer.repository.test.js +0 -385
- package/dist/features/search/repository/__tests__/search.repository.test.d.ts +0 -1
- package/dist/features/search/repository/__tests__/search.repository.test.js +0 -369
- package/dist/features/seller/components/SellerStatCard.d.ts +0 -14
- package/dist/features/seller/components/SellerStatCard.js +0 -6
- package/dist/features/seller/components/seller-products-styles.d.ts +0 -7
- package/dist/features/seller/components/seller-products-styles.js +0 -14
- package/dist/features/seller/repository/__tests__/offer.repository.test.d.ts +0 -1
- package/dist/features/seller/repository/__tests__/offer.repository.test.js +0 -458
- package/dist/features/seller/repository/seller.repository.d.ts +0 -22
- package/dist/features/seller/repository/seller.repository.js +0 -72
- package/dist/features/site-settings/components/__tests__/ThemeManagerView.test.d.ts +0 -1
- package/dist/features/site-settings/components/__tests__/ThemeManagerView.test.js +0 -37
- package/dist/features/stores/repository/__tests__/store.repository.test.d.ts +0 -1
- package/dist/features/stores/repository/__tests__/store.repository.test.js +0 -261
- package/dist/features/stores/repository/stores.repository.d.ts +0 -11
- package/dist/features/stores/repository/stores.repository.js +0 -37
- package/dist/features/support/repository/__tests__/support.repository.test.d.ts +0 -1
- package/dist/features/support/repository/__tests__/support.repository.test.js +0 -312
- package/dist/features/wishlist/repository/__tests__/user-wishlist.repository.test.d.ts +0 -1
- package/dist/features/wishlist/repository/__tests__/user-wishlist.repository.test.js +0 -139
- package/dist/features/wishlist/repository/wishlist.repository.d.ts +0 -13
- package/dist/features/wishlist/repository/wishlist.repository.js +0 -31
- package/dist/providers/db-firebase/__tests__/filter-aliases.test.d.ts +0 -1
- package/dist/providers/db-firebase/__tests__/filter-aliases.test.js +0 -93
- package/dist/providers/shipping-shiprocket/index.d.ts +0 -297
- package/dist/providers/shipping-shiprocket/index.js +0 -194
- package/dist/providers/shipping-shiprocket/shiprocket-provider.d.ts +0 -45
- package/dist/providers/shipping-shiprocket/shiprocket-provider.js +0 -168
- package/dist/react/contexts/ThemeContext.d.ts +0 -13
- package/dist/react/contexts/ThemeContext.js +0 -64
- package/dist/schemas/webhooks/shiprocket.d.ts +0 -30
- package/dist/schemas/webhooks/shiprocket.js +0 -22
- package/dist/seed/actions/demo-seed-actions.d.ts +0 -42
- package/dist/seed/actions/demo-seed-actions.js +0 -36
- package/dist/seed/actions/index.d.ts +0 -1
- package/dist/seed/actions/index.js +0 -1
- package/dist/seed/sub-listings-seed-data.d.ts +0 -123
- package/dist/seed/sub-listings-seed-data.js +0 -447
- package/dist/seed/tester-checklist-seed-data.d.ts +0 -2
- package/dist/seed/tester-checklist-seed-data.js +0 -248
- package/dist/ui/components/DashboardStatsCard.d.ts +0 -15
- package/dist/ui/components/DashboardStatsCard.js +0 -27
- package/dist/ui/components/DashboardStatsCard.style.css +0 -68
- package/dist/ui/components/DynamicSelect.d.ts +0 -23
- package/dist/ui/components/DynamicSelect.js +0 -77
- package/dist/ui/components/DynamicSelect.style.css +0 -101
- package/dist/ui/components/InlineCreateSelect.d.ts +0 -48
- package/dist/ui/components/InlineCreateSelect.js +0 -75
- package/dist/ui/components/ListingViewShell.d.ts +0 -37
- package/dist/ui/components/ListingViewShell.js +0 -9
- package/dist/ui/components/PaginatedMultiSelect.d.ts +0 -28
- package/dist/ui/components/PaginatedMultiSelect.js +0 -141
- package/dist/ui/components/PaginatedMultiSelect.style.css +0 -272
- package/dist/ui/components/SectionTabs.d.ts +0 -19
- package/dist/ui/components/SectionTabs.js +0 -66
- package/dist/ui/components/SectionTabs.style.css +0 -164
- package/dist/ui/components/__tests__/BulkActionBar.test.d.ts +0 -1
- package/dist/ui/components/__tests__/BulkActionBar.test.js +0 -96
- package/dist/ui/components/__tests__/ListingToolbar.test.d.ts +0 -1
- package/dist/ui/components/__tests__/ListingToolbar.test.js +0 -125
- package/dist/ui/components/__tests__/new-primitives.test.d.ts +0 -1
- 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
|
|
163
|
-
message
|
|
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
|
-
|
|
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 ? ` ₹${
|
|
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
|
|
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
|
-
|
|
24
|
+
let restored = 0;
|
|
14
25
|
for (const entry of timedOut) {
|
|
15
|
-
|
|
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.
|
|
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
|
}
|
|
@@ -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
|
-
*
|
|
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
|
|
13
|
-
*
|
|
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
|
-
|
|
13
|
+
purchaseCost: lot.purchaseCost ?? 0,
|
|
14
14
|
weightGrams: lot.weightGrams ?? 0,
|
|
15
|
-
|
|
16
|
-
|
|
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
|
|
22
|
+
const laborRatePerHour = shipment.laborRatePerHour ?? 0;
|
|
23
23
|
const laborHoursSpent = shipment.laborHoursSpent ?? 0;
|
|
24
24
|
const { perLot, totals } = allocateShipmentCosts({
|
|
25
25
|
lots: allocationInputs,
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
customsTotal: shipment.customsTotal ?? 0,
|
|
27
|
+
shippingTotal: shipment.shippingTotal ?? 0,
|
|
28
28
|
laborHoursSpent,
|
|
29
|
-
|
|
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.
|
|
38
|
-
lot.
|
|
39
|
-
lot.
|
|
40
|
-
lot.
|
|
41
|
-
lot.
|
|
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,
|
|
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
|
|
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
|
-
|
|
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.
|
|
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,
|
|
25
|
-
ctx.logger.info("Recomputed lot item aggregates", { lotId, itemCount,
|
|
24
|
+
await lotRef.update({ itemCount, mainItemsProjectedRevenue, updatedAt: ctx.now });
|
|
25
|
+
ctx.logger.info("Recomputed lot item aggregates", { lotId, itemCount, mainItemsProjectedRevenue });
|
|
26
26
|
};
|
|
@@ -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
|
|
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
|
};
|