@mohasinac/appkit 3.4.8 → 3.5.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/classified/ClassifiedDetailView.js +1 -1
- package/dist/_internal/client/features/digital-code/CodeRevealPanel.js +1 -1
- package/dist/_internal/client/features/digital-code/DigitalCodeDetailView.js +1 -1
- package/dist/_internal/client/features/filters/filter-load-options.js +10 -9
- package/dist/_internal/client/features/layout/DashboardLayoutClient.d.ts +6 -1
- package/dist/_internal/client/features/layout/DashboardLayoutClient.js +11 -4
- package/dist/_internal/client/features/live/LiveItemDetailView.js +2 -2
- package/dist/_internal/client/features/maintenance/views/AnalysisRunnerView.js +10 -3
- package/dist/_internal/client/features/maintenance/views/ServerErrorsListView.js +2 -2
- package/dist/_internal/client/scaffolds/DashboardScaffold.js +3 -1
- package/dist/_internal/server/features/checkout/actions.d.ts +16 -0
- package/dist/_internal/server/features/checkout/actions.js +149 -35
- package/dist/_internal/server/features/checkout/bundle-expansion.d.ts +31 -0
- package/dist/_internal/server/features/checkout/bundle-expansion.js +41 -0
- package/dist/_internal/server/features/lottery/actions.js +14 -4
- package/dist/_internal/server/features/maintenance/analyze.js +4 -2
- package/dist/_internal/server/features/orders/actions.js +9 -0
- package/dist/_internal/server/features/orders/adapters.js +19 -0
- package/dist/_internal/server/features/seo/robots.js +1 -1
- package/dist/_internal/server/functions/firestore.d.ts +47 -1
- package/dist/_internal/server/functions/firestore.js +56 -1
- package/dist/_internal/server/functions/scheduled.d.ts +2 -1
- package/dist/_internal/server/functions/scheduled.js +9 -1
- package/dist/_internal/server/jobs/core/catalogueImageStalenessReminder.d.ts +10 -0
- package/dist/_internal/server/jobs/core/catalogueImageStalenessReminder.js +49 -0
- package/dist/_internal/server/jobs/core/cleanupRtdbEvents.js +32 -0
- package/dist/_internal/server/jobs/core/hardBanCascade.d.ts +26 -0
- package/dist/_internal/server/jobs/core/hardBanCascade.js +181 -0
- package/dist/_internal/server/jobs/core/index.d.ts +4 -1
- package/dist/_internal/server/jobs/core/index.js +4 -1
- package/dist/_internal/server/jobs/core/jobRunners.d.ts +28 -0
- package/dist/_internal/server/jobs/core/jobRunners.js +37 -0
- package/dist/_internal/server/jobs/core/onCatalogueSubmittedForApproval.d.ts +15 -0
- package/dist/_internal/server/jobs/core/onCatalogueSubmittedForApproval.js +38 -0
- package/dist/_internal/server/jobs/core/onJobCreated.d.ts +22 -0
- package/dist/_internal/server/jobs/core/onJobCreated.js +59 -0
- package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.d.ts +6 -1
- package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.js +5 -2
- package/dist/_internal/server/jobs/handlers/catalogueImageStalenessReminder.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/catalogueImageStalenessReminder.js +2 -0
- package/dist/_internal/server/jobs/handlers/index.d.ts +6 -0
- package/dist/_internal/server/jobs/handlers/index.js +8 -0
- package/dist/_internal/server/jobs/handlers/onCatalogueSubmittedForApproval.d.ts +12 -0
- package/dist/_internal/server/jobs/handlers/onCatalogueSubmittedForApproval.js +20 -0
- package/dist/_internal/server/jobs/handlers/onJobCreated.d.ts +3 -0
- package/dist/_internal/server/jobs/handlers/onJobCreated.js +9 -0
- package/dist/_internal/server/jobs/handlers/onShipmentAllocationSync.d.ts +25 -0
- package/dist/_internal/server/jobs/handlers/onShipmentAllocationSync.js +71 -0
- package/dist/_internal/server/jobs/handlers/onShipmentDeleted.d.ts +14 -0
- package/dist/_internal/server/jobs/handlers/onShipmentDeleted.js +23 -0
- package/dist/_internal/server/jobs/handlers/onShipmentItemWrite.d.ts +17 -0
- package/dist/_internal/server/jobs/handlers/onShipmentItemWrite.js +26 -0
- package/dist/_internal/server/jobs/handlers/weeklyPayoutEligibility.js +3 -1
- package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
- package/dist/_internal/shared/actions/action-registry.js +136 -0
- package/dist/_internal/shared/features/blog/schema.d.ts +8 -8
- package/dist/_internal/shared/features/brands/schema.d.ts +4 -4
- package/dist/_internal/shared/features/categories/bundle-schemas.d.ts +8 -8
- package/dist/_internal/shared/features/events/schema.d.ts +4 -4
- package/dist/_internal/shared/features/products/schema.d.ts +8 -8
- package/dist/_internal/shared/features/promotions/schema.d.ts +4 -4
- package/dist/_internal/shared/features/reviews/schema.d.ts +4 -4
- package/dist/client/api/useFeatureFlags.d.ts +22 -0
- package/dist/client/api/useFeatureFlags.js +27 -0
- package/dist/client/observability/reportClientError.js +3 -2
- package/dist/client.d.ts +4 -2
- package/dist/client.js +2 -1
- package/dist/configs/next.js +1 -0
- package/dist/constants/api-endpoints.d.ts +279 -3
- package/dist/constants/api-endpoints.js +130 -2
- package/dist/core/hooks/useSyncManager.js +5 -4
- package/dist/errors/conflict-error.d.ts +4 -0
- package/dist/errors/conflict-error.js +6 -0
- package/dist/errors/index.d.ts +1 -0
- package/dist/errors/index.js +1 -0
- package/dist/features/about/components/FeesView.js +2 -2
- package/dist/features/about/components/HelpPageView.js +2 -2
- package/dist/features/about/components/HowAuctionsWorkView.js +2 -2
- package/dist/features/about/components/HowCheckoutWorksView.js +2 -2
- package/dist/features/about/components/HowEmiWorksView.js +2 -2
- package/dist/features/about/components/HowOffersWorkView.js +3 -3
- package/dist/features/about/components/HowOrdersWorkView.js +3 -3
- package/dist/features/about/components/HowPayoutsWorkView.js +2 -2
- package/dist/features/about/components/HowPreOrdersWorkView.js +2 -2
- package/dist/features/about/components/HowReviewsWorkView.js +2 -2
- package/dist/features/about/components/PublicProfileView.d.ts +8 -1
- package/dist/features/about/components/PublicProfileView.js +11 -9
- package/dist/features/about/components/SecurityPrivacyView.js +2 -2
- package/dist/features/about/components/UnauthorizedView.js +2 -2
- package/dist/features/account/components/AddressBook.js +1 -1
- package/dist/features/account/components/AddressesIndexListing.js +1 -1
- package/dist/features/account/components/NotificationBell.js +5 -5
- package/dist/features/account/components/NotificationPreferencesPanel.js +5 -2
- package/dist/features/account/components/UserOffersPanel.js +5 -4
- package/dist/features/account/components/UserSidebar.js +2 -2
- package/dist/features/account/components/UserSupportView.js +3 -3
- package/dist/features/account/schemas/index.d.ts +12 -12
- package/dist/features/addresses/schemas/index.d.ts +6 -6
- package/dist/features/admin/components/AdminAdEditorView.js +3 -3
- package/dist/features/admin/components/AdminAddressEditorView.js +3 -3
- package/dist/features/admin/components/AdminAdsView.js +3 -3
- package/dist/features/admin/components/AdminBlogEditorView.js +1 -1
- package/dist/features/admin/components/AdminBlogView.js +12 -15
- package/dist/features/admin/components/AdminBrandEditorView.js +1 -1
- package/dist/features/admin/components/AdminBrandsView.js +12 -13
- package/dist/features/admin/components/AdminBundleEditorView.js +5 -4
- package/dist/features/admin/components/AdminBundlesView.js +32 -23
- package/dist/features/admin/components/AdminCarouselEditorView.js +5 -5
- package/dist/features/admin/components/AdminCarouselView.js +2 -2
- package/dist/features/admin/components/AdminCatalogGuideView.js +1 -1
- package/dist/features/admin/components/AdminCategoriesView.js +12 -13
- package/dist/features/admin/components/AdminCategoryEditorView.js +2 -2
- package/dist/features/admin/components/AdminContactEditorView.js +2 -2
- package/dist/features/admin/components/AdminCouponEditorView.d.ts +10 -1
- package/dist/features/admin/components/AdminCouponEditorView.js +7 -2
- package/dist/features/admin/components/AdminCouponsView.js +32 -27
- package/dist/features/admin/components/AdminEmployeeEditorView.js +3 -3
- package/dist/features/admin/components/AdminFaqEditorView.js +1 -1
- package/dist/features/admin/components/AdminFaqsView.js +20 -20
- package/dist/features/admin/components/AdminFeatureEditorView.js +5 -5
- package/dist/features/admin/components/AdminFeaturesView.js +9 -10
- package/dist/features/admin/components/AdminFilterBar.js +1 -1
- package/dist/features/admin/components/AdminFulfillmentView.js +4 -4
- package/dist/features/admin/components/AdminGuideHubView.js +2 -2
- package/dist/features/admin/components/AdminMediaView.js +3 -2
- package/dist/features/admin/components/AdminNavigationView.js +1 -1
- package/dist/features/admin/components/AdminOrderEditorView.js +3 -3
- package/dist/features/admin/components/AdminOrdersView.js +21 -30
- package/dist/features/admin/components/AdminPageHeader.js +3 -3
- package/dist/features/admin/components/AdminPayoutsView.js +8 -8
- package/dist/features/admin/components/AdminPrizeDrawsView.js +8 -9
- package/dist/features/admin/components/AdminProductEditorView.d.ts +9 -1
- package/dist/features/admin/components/AdminProductEditorView.js +7 -4
- package/dist/features/admin/components/AdminProductsView.js +30 -41
- package/dist/features/admin/components/AdminReviewsView.js +14 -17
- package/dist/features/admin/components/AdminScammerEditorView.js +5 -5
- package/dist/features/admin/components/AdminSectionsView.js +3 -3
- package/dist/features/admin/components/AdminSessionsView.js +8 -10
- package/dist/features/admin/components/AdminSidebar.js +2 -2
- package/dist/features/admin/components/AdminSiteSettingsView.js +10 -3
- package/dist/features/admin/components/AdminStoreEditorView.js +4 -5
- package/dist/features/admin/components/AdminStoresView.js +18 -13
- package/dist/features/admin/components/AdminSupportTicketDetailView.js +7 -7
- package/dist/features/admin/components/AdminTeamView.js +9 -5
- package/dist/features/admin/components/AdminUsersView.js +19 -15
- package/dist/features/admin/components/AdminViewCards.js +5 -5
- package/dist/features/admin/components/DashboardStats.js +1 -1
- package/dist/features/admin/components/DataListingView.js +2 -2
- package/dist/features/admin/components/DataTable.js +2 -2
- package/dist/features/admin/components/DrawerFormFooter.js +1 -1
- package/dist/features/admin/components/analytics/AdminAnalyticsCharts.js +2 -2
- package/dist/features/admin/components/analytics/AdminStatCard.js +1 -1
- package/dist/features/admin/hooks/useAdminListing.d.ts +3 -2
- package/dist/features/admin/hooks/useAdminListing.js +8 -2
- package/dist/features/admin/permission-map.js +2 -0
- package/dist/features/admin/schemas/firestore.d.ts +7 -0
- package/dist/features/admin/schemas/firestore.js +4 -0
- package/dist/features/auctions/components/AuctionBidsTable.js +1 -1
- package/dist/features/auctions/components/AuctionDetailPageView.js +7 -7
- package/dist/features/auctions/components/MarketplaceAuctionCard.js +3 -3
- package/dist/features/auctions/components/MarketplaceAuctionGrid.js +4 -4
- package/dist/features/auctions/components/PlaceBidFormClient.js +1 -1
- package/dist/features/auctions/schemas/index.d.ts +16 -16
- package/dist/features/auth/permissions/constants.d.ts +1 -1
- package/dist/features/auth/permissions/constants.js +2 -0
- package/dist/features/auth/schemas/index.d.ts +6 -6
- package/dist/features/before-after/schemas/index.d.ts +3 -3
- package/dist/features/blog/actions/blog-actions.d.ts +32 -32
- package/dist/features/blog/components/BlogFeaturedCard.js +2 -2
- package/dist/features/blog/components/BlogIndexListing.js +2 -2
- package/dist/features/blog/components/BlogListView.js +4 -4
- package/dist/features/blog/components/BlogPostView.js +4 -4
- package/dist/features/blog/schemas/index.d.ts +77 -77
- package/dist/features/cart/components/CartDrawer.js +2 -2
- package/dist/features/catalogue/actions/approve-catalogue-listing.d.ts +12 -0
- package/dist/features/catalogue/actions/approve-catalogue-listing.js +50 -0
- package/dist/features/catalogue/actions/list-from-catalogue.d.ts +17 -0
- package/dist/features/catalogue/actions/list-from-catalogue.js +50 -0
- package/dist/features/catalogue/actions/submit-for-approval.d.ts +8 -0
- package/dist/features/catalogue/actions/submit-for-approval.js +30 -0
- package/dist/features/catalogue/components/AdminCatalogueApprovalsView.d.ts +2 -0
- package/dist/features/catalogue/components/AdminCatalogueApprovalsView.js +53 -0
- package/dist/features/catalogue/components/CatalogueItemEditorView.d.ts +7 -0
- package/dist/features/catalogue/components/CatalogueItemEditorView.js +79 -0
- package/dist/features/catalogue/components/PublicCatalogueView.d.ts +5 -0
- package/dist/features/catalogue/components/PublicCatalogueView.js +22 -0
- package/dist/features/catalogue/components/UserCatalogueView.d.ts +12 -0
- package/dist/features/catalogue/components/UserCatalogueView.js +51 -0
- package/dist/features/catalogue/index.d.ts +12 -0
- package/dist/features/catalogue/index.js +9 -0
- package/dist/features/catalogue/repository/catalogue.repository.d.ts +39 -0
- package/dist/features/catalogue/repository/catalogue.repository.js +68 -0
- package/dist/features/catalogue/schemas/firestore.d.ts +47 -0
- package/dist/features/catalogue/schemas/firestore.js +22 -0
- package/dist/features/catalogue/schemas/index.d.ts +2 -0
- package/dist/features/catalogue/schemas/index.js +2 -0
- package/dist/features/catalogue/schemas/validation.d.ts +71 -0
- package/dist/features/catalogue/schemas/validation.js +25 -0
- package/dist/features/catalogue/utils/freshness.d.ts +10 -0
- package/dist/features/catalogue/utils/freshness.js +15 -0
- package/dist/features/catalogue/utils/product-from-item.d.ts +15 -0
- package/dist/features/catalogue/utils/product-from-item.js +34 -0
- package/dist/features/categories/components/BrandDetailPageView.js +1 -1
- package/dist/features/categories/components/BrandDetailTabs.js +2 -2
- package/dist/features/categories/components/BundleCollage.js +2 -2
- package/dist/features/categories/components/BundleItemsPicker.js +3 -2
- package/dist/features/categories/components/CategoriesIndexListing.js +8 -6
- package/dist/features/categories/components/CategoryBundlesListing.js +10 -4
- package/dist/features/categories/components/CategoryDetailPageView.js +1 -1
- package/dist/features/categories/components/CategoryDetailTabs.js +2 -2
- package/dist/features/categories/components/CategoryGrid.js +3 -3
- package/dist/features/categories/components/CategoryProductsListing.js +1 -1
- package/dist/features/categories/components/CategorySortSelect.js +1 -1
- package/dist/features/categories/components/CategoryStoresListing.js +1 -1
- package/dist/features/categories/components/CategoryTableColumns.js +1 -1
- package/dist/features/categories/components/CategoryTree.js +2 -2
- package/dist/features/categories/components/ConcernCard.js +1 -1
- package/dist/features/categories/hooks/useCategories.js +1 -1
- package/dist/features/categories/schemas/index.d.ts +32 -32
- package/dist/features/classified/components/ClassifiedFilters.js +2 -2
- package/dist/features/classified/components/ClassifiedIndexListing.js +9 -3
- package/dist/features/collections/schemas/index.d.ts +2 -2
- package/dist/features/consultation/components/ConsultationForm.js +1 -1
- package/dist/features/consultation/schemas/index.d.ts +10 -10
- package/dist/features/contact/components/ContactForm.js +4 -4
- package/dist/features/contact/components/ContactInfoSidebar.js +1 -1
- package/dist/features/contact/components/ContactPageView.js +2 -1
- package/dist/features/copilot/components/AdminCopilotView.js +5 -4
- package/dist/features/corporate/schemas/index.d.ts +2 -2
- package/dist/features/digital-codes/components/DigitalCodesIndexListing.js +3 -3
- package/dist/features/events/components/AdminEventEditorView.js +4 -4
- package/dist/features/events/components/AdminEventEntriesView.js +2 -2
- package/dist/features/events/components/AdminEventsView.js +8 -8
- package/dist/features/events/components/EventBanner.js +1 -1
- package/dist/features/events/components/EventCard.js +3 -3
- package/dist/features/events/components/EventLeaderboard.js +1 -1
- package/dist/features/events/components/EventOfferCard.js +1 -1
- package/dist/features/events/components/EventPollWidget.js +6 -5
- package/dist/features/events/components/EventRaffleEntryForm.js +1 -1
- package/dist/features/events/components/EventRaffleWinnerView.js +5 -5
- package/dist/features/events/components/EventRafflesSection.js +1 -1
- package/dist/features/events/components/EventSaleBanner.js +1 -1
- package/dist/features/events/components/EventsIndexListing.js +4 -2
- package/dist/features/events/components/EventsListView.js +2 -2
- package/dist/features/events/components/SpinWheelView.js +11 -5
- package/dist/features/events/schemas/index.d.ts +100 -100
- package/dist/features/faq/actions/faq-actions.d.ts +6 -6
- package/dist/features/faq/components/ContactCTA.js +3 -3
- package/dist/features/faq/components/FAQCategorySidebar.js +2 -2
- package/dist/features/faq/components/FAQHelpfulButtons.js +3 -3
- package/dist/features/faq/schemas/index.d.ts +12 -12
- package/dist/features/filters/AsyncFacetSection.js +4 -4
- package/dist/features/filters/FilterFacetSection.js +8 -8
- package/dist/features/filters/RangeFilter.js +2 -2
- package/dist/features/filters/SwitchFilter.js +1 -1
- package/dist/features/forms/Checkbox.js +2 -8
- package/dist/features/forms/Input.js +2 -1
- package/dist/features/forms/Radio.js +3 -3
- package/dist/features/forms/Select.d.ts +1 -1
- package/dist/features/forms/Select.js +3 -2
- package/dist/features/forms/Slider.js +5 -11
- package/dist/features/forms/Textarea.js +2 -1
- package/dist/features/grouped/schemas/index.d.ts +6 -6
- package/dist/features/homepage/actions/homepage-section-actions.d.ts +4 -4
- package/dist/features/homepage/components/AdvertisementBanner.js +4 -4
- package/dist/features/homepage/components/AnnouncementBar.js +3 -3
- package/dist/features/homepage/components/BeforeAfterCard.js +1 -1
- package/dist/features/homepage/components/BrandsSection.js +9 -9
- package/dist/features/homepage/components/CTABannerSection.js +1 -1
- package/dist/features/homepage/components/CharacterHotspot.js +4 -4
- package/dist/features/homepage/components/CharacterHotspotForm.js +15 -13
- package/dist/features/homepage/components/CollectionCardsSection.js +1 -1
- package/dist/features/homepage/components/CustomCardsSection.js +6 -6
- package/dist/features/homepage/components/CustomerReviewsSection.js +2 -2
- package/dist/features/homepage/components/FAQSection.js +2 -2
- package/dist/features/homepage/components/FeaturedBundlesSection.js +3 -3
- package/dist/features/homepage/components/FeaturedResultsSection.js +2 -2
- package/dist/features/homepage/components/GoogleReviewsSection.js +6 -6
- package/dist/features/homepage/components/HeroBanner.js +1 -1
- package/dist/features/homepage/components/HeroCarousel.js +5 -4
- package/dist/features/homepage/components/HeroSection.js +1 -7
- package/dist/features/homepage/components/HomepageSkeleton.js +1 -1
- package/dist/features/homepage/components/HowItWorksInfoView.js +1 -1
- package/dist/features/homepage/components/HowItWorksSection.js +2 -2
- package/dist/features/homepage/components/NewsletterBanner.js +2 -2
- package/dist/features/homepage/components/NewsletterSection.js +1 -1
- package/dist/features/homepage/components/PromoGrid.js +1 -1
- package/dist/features/homepage/components/SectionCarousel.js +6 -6
- package/dist/features/homepage/components/SecurityHighlightsSection.js +2 -2
- package/dist/features/homepage/components/ShopByCategorySection.js +10 -10
- package/dist/features/homepage/components/SiteFeaturesSection.js +2 -2
- package/dist/features/homepage/components/SocialFeedSection.js +5 -5
- package/dist/features/homepage/components/SocialPostCard.js +1 -1
- package/dist/features/homepage/components/StatsCounterSection.js +1 -1
- package/dist/features/homepage/components/TestimonialsCarousel.js +1 -1
- package/dist/features/homepage/components/TrustBadges.js +1 -1
- package/dist/features/homepage/components/TrustFeaturesSection.js +2 -2
- package/dist/features/homepage/components/TrustIndicatorsSection.js +2 -2
- package/dist/features/homepage/components/WelcomeSection.js +2 -2
- package/dist/features/homepage/components/WhatsAppCommunitySection.js +1 -1
- package/dist/features/homepage/hooks/useActiveAd.js +2 -1
- package/dist/features/homepage/schemas/firestore.d.ts +10 -0
- package/dist/features/homepage/schemas/index.d.ts +116 -116
- package/dist/features/jobs/actions/enqueue-job.d.ts +24 -0
- package/dist/features/jobs/actions/enqueue-job.js +44 -0
- package/dist/features/jobs/repository/jobs.repository.d.ts +21 -0
- package/dist/features/jobs/repository/jobs.repository.js +48 -0
- package/dist/features/jobs/schemas/firestore.d.ts +54 -0
- package/dist/features/jobs/schemas/firestore.js +24 -0
- package/dist/features/layout/AppLayoutShell.js +17 -11
- package/dist/features/layout/AutoBreadcrumbs.js +1 -1
- package/dist/features/layout/BackToTop.js +2 -2
- package/dist/features/layout/BottomActions.js +7 -7
- package/dist/features/layout/BottomNavItem.js +2 -2
- package/dist/features/layout/BottomNavLayout.js +13 -4
- package/dist/features/layout/BottomNavbar.d.ts +9 -1
- package/dist/features/layout/BottomNavbar.js +12 -5
- package/dist/features/layout/BottomSheet.js +1 -1
- package/dist/features/layout/Breadcrumbs.js +1 -1
- package/dist/features/layout/FooterLayout.js +2 -2
- package/dist/features/layout/NavItem.js +3 -3
- package/dist/features/layout/NavbarLayout.js +6 -6
- package/dist/features/layout/SidebarLayout.d.ts +3 -0
- package/dist/features/layout/SidebarLayout.js +3 -3
- package/dist/features/layout/TitleBarLayout.js +4 -4
- package/dist/features/live/components/LiveItemFilters.js +2 -2
- package/dist/features/live/components/LiveItemsIndexListing.js +3 -3
- package/dist/features/lottery/types/index.d.ts +3 -1
- package/dist/features/lottery/types/index.js +16 -3
- package/dist/features/loyalty/components/CoinsDisplay.js +2 -2
- package/dist/features/media/MediaImage.d.ts +6 -1
- package/dist/features/media/MediaImage.js +10 -4
- package/dist/features/media/MediaLightbox.js +1 -1
- package/dist/features/media/MediaPickerModal.js +4 -3
- package/dist/features/media/MediaVideo.js +1 -1
- package/dist/features/media/modals/ImageCropModal.js +1 -1
- package/dist/features/media/modals/ImageEditor.js +1 -1
- package/dist/features/media/repository/media-assets.repository.d.ts +9 -0
- package/dist/features/media/types/index.d.ts +4 -4
- package/dist/features/media/upload/MediaUploadField.js +3 -3
- package/dist/features/media/upload/MediaUploadList.js +1 -1
- package/dist/features/messages/hooks/useConversation.js +4 -3
- package/dist/features/messages/hooks/useConversations.js +2 -1
- package/dist/features/messages/schemas/index.d.ts +6 -6
- package/dist/features/orders/components/MarketplaceOrderCard.js +1 -1
- package/dist/features/orders/components/OrderPaymentSummary.d.ts +16 -0
- package/dist/features/orders/components/OrderPaymentSummary.js +32 -0
- package/dist/features/orders/components/OrderSiblingPayments.js +1 -1
- package/dist/features/orders/components/OrdersList.d.ts +7 -2
- package/dist/features/orders/components/OrdersList.js +5 -5
- package/dist/features/orders/components/RefundHistoryTable.js +1 -1
- package/dist/features/orders/components/RefundRequestView.js +1 -1
- package/dist/features/orders/components/index.d.ts +2 -0
- package/dist/features/orders/components/index.js +1 -0
- package/dist/features/orders/repository/orders.repository.d.ts +8 -0
- package/dist/features/orders/repository/orders.repository.js +24 -0
- package/dist/features/orders/schemas/firestore.d.ts +59 -0
- package/dist/features/orders/schemas/firestore.js +5 -0
- package/dist/features/orders/schemas/index.d.ts +91 -40
- package/dist/features/orders/schemas/index.js +10 -0
- package/dist/features/orders/types/index.d.ts +15 -0
- package/dist/features/payments/schemas/index.d.ts +12 -12
- package/dist/features/pre-orders/components/MarketplacePreorderCard.js +5 -5
- package/dist/features/pre-orders/components/PreOrderActionsClient.js +1 -1
- package/dist/features/pre-orders/components/PreOrderBadge.js +1 -1
- package/dist/features/pre-orders/components/PreOrderDetailPageView.js +7 -7
- package/dist/features/pre-orders/components/PreOrdersIndexListing.js +3 -3
- package/dist/features/pre-orders/schemas/index.d.ts +12 -12
- package/dist/features/products/columns/productTableColumns.js +2 -2
- package/dist/features/products/components/AuctionsIndexListing.js +3 -3
- package/dist/features/products/components/CompareOverlay.js +15 -10
- package/dist/features/products/components/CustomFieldsEditor.js +2 -2
- package/dist/features/products/components/CustomSectionsEditor.js +3 -3
- package/dist/features/products/components/FeatureBadge.js +2 -2
- package/dist/features/products/components/GroupSettingsPanel.js +5 -4
- package/dist/features/products/components/MakeOfferButton.js +4 -4
- package/dist/features/products/components/MarketplaceBundleCard.js +3 -2
- package/dist/features/products/components/MarketplacePrizeDrawCard.js +1 -1
- package/dist/features/products/components/PrizeDrawCollage.js +6 -6
- package/dist/features/products/components/PrizeDrawDetailPageView.js +5 -5
- package/dist/features/products/components/PrizeDrawEntryActions.js +1 -1
- package/dist/features/products/components/PrizeDrawItemsEditor.js +4 -4
- package/dist/features/products/components/PrizeDrawsIndexListing.js +11 -4
- package/dist/features/products/components/PrizeDrawsSection.js +1 -1
- package/dist/features/products/components/PrizeRevealModal.js +9 -4
- package/dist/features/products/components/ProductDetailActions.js +2 -1
- package/dist/features/products/components/ProductDetailPageView.js +16 -16
- package/dist/features/products/components/ProductFeaturesSelector.js +5 -5
- package/dist/features/products/components/ProductForm.js +1 -1
- package/dist/features/products/components/ProductGalleryClient.js +5 -3
- package/dist/features/products/components/ProductGrid.js +11 -11
- package/dist/features/products/components/ProductTabs.js +2 -2
- package/dist/features/products/components/ProductTabsShell.js +2 -1
- package/dist/features/products/components/ProductsIndexListing.js +6 -1
- package/dist/features/products/components/ShareButton.js +2 -1
- package/dist/features/products/components/ShowGroupSection.js +9 -5
- package/dist/features/products/components/SublistingCarouselSection.js +8 -4
- package/dist/features/products/constants/action-defs.d.ts +10 -2
- package/dist/features/products/constants/action-defs.js +20 -2
- package/dist/features/products/schemas/firestore.d.ts +5 -0
- package/dist/features/products/schemas/index.d.ts +40 -40
- package/dist/features/products/schemas/product-features.validators.d.ts +14 -14
- package/dist/features/promotions/components/CouponCard.js +13 -7
- package/dist/features/promotions/components/CouponsIndexListing.js +4 -6
- package/dist/features/promotions/components/PromotionsView.js +2 -2
- package/dist/features/promotions/schemas/index.d.ts +26 -26
- package/dist/features/reviews/components/ReviewDetailPageView.js +1 -1
- package/dist/features/reviews/components/ReviewDetailShell.js +11 -11
- package/dist/features/reviews/components/ReviewModal.js +1 -1
- package/dist/features/reviews/components/ReviewsIndexListing.js +2 -2
- package/dist/features/reviews/components/ReviewsList.js +2 -2
- package/dist/features/reviews/schemas/index.d.ts +22 -22
- package/dist/features/scams/components/ScamAwarenessModal.js +2 -2
- package/dist/features/scams/components/ScamProfileView.js +3 -3
- package/dist/features/scams/components/ScamRegistryView.js +2 -2
- package/dist/features/scams/schemas/index.d.ts +20 -20
- package/dist/features/search/components/Search.js +9 -9
- package/dist/features/search/components/SearchFiltersRow.js +1 -1
- package/dist/features/search/components/SearchResultsSection.js +3 -3
- package/dist/features/search/components/SearchView.js +1 -1
- package/dist/features/search/hooks/useNavSuggestions.js +2 -1
- package/dist/features/search/hooks/useSearch.js +2 -2
- package/dist/features/search/schemas/index.d.ts +3 -3
- package/dist/features/seller/components/BrandInlineSelect.js +2 -2
- package/dist/features/seller/components/CategoryInlineSelect.js +2 -2
- package/dist/features/seller/components/QuickProductForm.js +1 -1
- package/dist/features/seller/components/SellerAddressesView.js +4 -4
- package/dist/features/seller/components/SellerAnalyticsAlertsView.js +3 -3
- package/dist/features/seller/components/SellerAnalyticsView.js +2 -2
- package/dist/features/seller/components/SellerArtView.js +11 -11
- package/dist/features/seller/components/SellerAuctionsView.js +11 -11
- package/dist/features/seller/components/SellerBidsView.js +3 -3
- package/dist/features/seller/components/SellerBundlesView.js +12 -12
- package/dist/features/seller/components/SellerClassifiedView.js +11 -11
- package/dist/features/seller/components/SellerCouponEditorView.js +2 -2
- package/dist/features/seller/components/SellerDigitalCodesView.js +11 -11
- package/dist/features/seller/components/SellerFeaturesView.js +4 -4
- package/dist/features/seller/components/SellerLiveView.js +11 -11
- package/dist/features/seller/components/SellerOffersPanel.js +3 -2
- package/dist/features/seller/components/SellerOrdersView.js +2 -2
- package/dist/features/seller/components/SellerPayoutMethodsView.js +1 -1
- package/dist/features/seller/components/SellerPayoutRequestView.js +6 -5
- package/dist/features/seller/components/SellerPayoutSettingsView.js +5 -4
- package/dist/features/seller/components/SellerPreOrdersView.js +1 -1
- package/dist/features/seller/components/SellerPrizeDrawsView.js +1 -1
- package/dist/features/seller/components/SellerProductShell.js +20 -6
- package/dist/features/seller/components/SellerProductsCards.js +3 -3
- package/dist/features/seller/components/SellerProductsView.js +4 -4
- package/dist/features/seller/components/SellerReviewsView.js +7 -6
- package/dist/features/seller/components/SellerShippingView.js +2 -1
- package/dist/features/seller/components/SellerSidebar.js +5 -5
- package/dist/features/seller/components/SellerStickersView.js +11 -11
- package/dist/features/seller/components/SellerTemplatesView.js +1 -1
- package/dist/features/seller/schemas/index.d.ts +20 -20
- package/dist/features/server-errors/schemas/index.d.ts +6 -6
- package/dist/features/shell/CommandPalette.d.ts +27 -0
- package/dist/features/shell/CommandPalette.js +92 -0
- package/dist/features/shell/FormShell.js +4 -3
- package/dist/features/shell/QuickFormDrawer.js +3 -2
- package/dist/features/shell/StepForm.js +2 -2
- package/dist/features/shell/index.d.ts +2 -0
- package/dist/features/shell/index.js +1 -0
- package/dist/features/shipments/components/AdminShipmentEditorView.d.ts +7 -0
- package/dist/features/shipments/components/AdminShipmentEditorView.js +123 -0
- package/dist/features/shipments/components/AdminShipmentLotItemsView.d.ts +6 -0
- package/dist/features/shipments/components/AdminShipmentLotItemsView.js +96 -0
- package/dist/features/shipments/components/AdminShipmentProjectionsView.d.ts +9 -0
- package/dist/features/shipments/components/AdminShipmentProjectionsView.js +44 -0
- package/dist/features/shipments/components/AdminShipmentsView.d.ts +8 -0
- package/dist/features/shipments/components/AdminShipmentsView.js +82 -0
- package/dist/features/shipments/components/ShipmentItemLinkModal.d.ts +15 -0
- package/dist/features/shipments/components/ShipmentItemLinkModal.js +37 -0
- package/dist/features/shipments/hooks/useShipments.d.ts +69 -0
- package/dist/features/shipments/hooks/useShipments.js +96 -0
- package/dist/features/shipments/index.d.ts +10 -0
- package/dist/features/shipments/index.js +7 -0
- package/dist/features/shipments/manifest.d.ts +2 -0
- package/dist/features/shipments/manifest.js +26 -0
- package/dist/features/shipments/repository/shipment-items.repository.d.ts +56 -0
- package/dist/features/shipments/repository/shipment-items.repository.js +78 -0
- package/dist/features/shipments/repository/shipment-lots.repository.d.ts +48 -0
- package/dist/features/shipments/repository/shipment-lots.repository.js +55 -0
- package/dist/features/shipments/repository/shipments.repository.d.ts +50 -0
- package/dist/features/shipments/repository/shipments.repository.js +77 -0
- package/dist/features/shipments/schemas/firestore.d.ts +150 -0
- package/dist/features/shipments/schemas/firestore.js +76 -0
- package/dist/features/shipments/schemas/index.d.ts +2 -0
- package/dist/features/shipments/schemas/index.js +2 -0
- package/dist/features/shipments/schemas/validation.d.ts +350 -0
- package/dist/features/shipments/schemas/validation.js +96 -0
- package/dist/features/shipments/utils/cost-allocation.d.ts +25 -0
- package/dist/features/shipments/utils/cost-allocation.js +83 -0
- package/dist/features/site-settings/components/ActionPermissionsManager.js +2 -2
- package/dist/features/stores/components/InteractiveStoreCard.js +2 -2
- package/dist/features/stores/components/StoreAboutView.js +1 -1
- package/dist/features/stores/components/StoreAuctionsListing.js +3 -3
- package/dist/features/stores/components/StoreAuctionsView.js +1 -1
- package/dist/features/stores/components/StoreCapabilitiesGuideView.js +1 -1
- package/dist/features/stores/components/StoreClassifiedsListing.js +2 -2
- package/dist/features/stores/components/StoreDetailLayoutView.js +1 -1
- package/dist/features/stores/components/StoreDigitalCodesListing.js +2 -2
- package/dist/features/stores/components/StoreFinanceGuideView.js +2 -2
- package/dist/features/stores/components/StoreGuideHubView.js +2 -2
- package/dist/features/stores/components/StoreHeader.js +4 -4
- package/dist/features/stores/components/StoreLiveItemsListing.js +2 -2
- package/dist/features/stores/components/StoreNavTabs.js +2 -2
- package/dist/features/stores/components/StoreOrdersGuideView.js +1 -1
- package/dist/features/stores/components/StorePreOrdersListing.js +3 -3
- package/dist/features/stores/components/StoreProductsListing.js +1 -1
- package/dist/features/stores/components/StoreReviewsListing.js +2 -2
- package/dist/features/stores/components/StoreReviewsView.js +1 -1
- package/dist/features/stores/components/StoreSettingsGuideView.js +1 -1
- package/dist/features/stores/components/StoresIndexListing.js +9 -3
- package/dist/features/stores/schemas/index.d.ts +10 -10
- package/dist/features/support/schemas/index.d.ts +22 -22
- package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +3 -3
- package/dist/features/whatsapp-bot/components/WhatsAppChatButton.js +1 -1
- package/dist/features/wishlist/hooks/useWishlistCount.js +1 -2
- package/dist/index.d.ts +44 -1
- package/dist/index.js +37 -1
- package/dist/next/routing/route-map.d.ts +18 -0
- package/dist/next/routing/route-map.js +9 -0
- package/dist/react/hooks/useVisualViewportInset.d.ts +1 -0
- package/dist/react/hooks/useVisualViewportInset.js +59 -0
- package/dist/react/index.d.ts +1 -0
- package/dist/react/index.js +1 -0
- package/dist/repositories/index.d.ts +5 -0
- package/dist/repositories/index.js +5 -0
- package/dist/schemas/registry.d.ts +398 -364
- package/dist/schemas/sieve.d.ts +2 -2
- package/dist/schemas/webhooks/google-oauth.d.ts +2 -2
- package/dist/schemas/webhooks/razorpay.d.ts +100 -100
- package/dist/seed/_helpers/media.js +1 -0
- package/dist/seed/actions/demo-seed-actions.d.ts +1 -1
- package/dist/seed/catalogue-seed-data.d.ts +2 -0
- package/dist/seed/catalogue-seed-data.js +112 -0
- package/dist/seed/grouped-listings-seed-data.d.ts +5 -0
- package/dist/seed/homepage-sections-seed-data.js +0 -1
- package/dist/seed/index.d.ts +2 -0
- package/dist/seed/index.js +2 -0
- package/dist/seed/manifest.js +6 -0
- package/dist/seed/products-preorders-seed-data.d.ts +5 -0
- package/dist/seed/shipments-seed-data.d.ts +5 -0
- package/dist/seed/shipments-seed-data.js +185 -0
- package/dist/server.d.ts +4 -0
- package/dist/server.js +5 -0
- package/dist/styles.css +75 -19
- package/dist/tailwind-utilities.css +1 -1
- package/dist/tokens/index.d.ts +0 -2
- package/dist/tokens/index.js +0 -2
- package/dist/tokens/tokens.css +12 -2
- package/dist/ui/DataTable.js +4 -3
- package/dist/ui/components/Button.d.ts +4 -1
- package/dist/ui/components/Button.js +11 -5
- package/dist/ui/components/Checkbox.d.ts +9 -1
- package/dist/ui/components/Checkbox.js +5 -2
- package/dist/ui/components/ClaimCouponButton.js +2 -1
- package/dist/ui/components/ConfirmDeleteModal.style.css +1 -1
- package/dist/ui/components/Drawer.style.css +13 -1
- package/dist/ui/components/Dropdown.style.css +2 -2
- package/dist/ui/components/FilterDrawer.d.ts +4 -1
- package/dist/ui/components/FilterDrawer.js +8 -2
- package/dist/ui/components/Form.d.ts +1 -1
- package/dist/ui/components/Form.js +2 -2
- package/dist/ui/components/FormActionBar.style.css +6 -1
- package/dist/ui/components/IconButton.d.ts +6 -1
- package/dist/ui/components/IconButton.js +5 -2
- package/dist/ui/components/IconButton.style.css +11 -0
- package/dist/ui/components/ImageGallery.style.css +2 -0
- package/dist/ui/components/ImageLightbox.style.css +1 -0
- package/dist/ui/components/ListingFilterDrawer.d.ts +4 -1
- package/dist/ui/components/ListingFilterDrawer.js +4 -3
- package/dist/ui/components/ListingLayout.style.css +2 -2
- package/dist/ui/components/Modal.style.css +1 -1
- package/dist/ui/components/Pagination.d.ts +5 -1
- package/dist/ui/components/Pagination.js +4 -2
- package/dist/ui/components/RowActionMenu.js +1 -1
- package/dist/ui/components/RowActionMenu.style.css +1 -1
- package/dist/ui/components/Select.d.ts +6 -1
- package/dist/ui/components/Select.js +18 -13
- package/dist/ui/components/Select.style.css +1 -1
- package/dist/ui/components/Semantic.d.ts +13 -0
- package/dist/ui/components/Semantic.js +16 -3
- package/dist/ui/components/SideDrawer.style.css +16 -4
- package/dist/ui/components/SideModal.style.css +1 -1
- package/dist/ui/components/StickyToolbar.d.ts +3 -2
- package/dist/ui/components/StickyToolbar.js +1 -1
- package/dist/ui/components/Textarea.d.ts +5 -0
- package/dist/ui/components/Textarea.js +8 -4
- package/dist/ui/components/Toast.style.css +3 -0
- package/dist/ui/components/UnsavedChangesModal.style.css +1 -1
- package/dist/ui/components/surface-tokens.d.ts +121 -113
- package/dist/ui/components/surface-tokens.js +110 -104
- package/dist/ui/forms/FormShell.d.ts +8 -27
- package/dist/ui/forms/FormShell.js +1 -194
- package/dist/ui/forms/index.d.ts +2 -2
- package/dist/ui/forms/index.js +1 -1
- package/dist/ui/index.d.ts +8 -4
- package/dist/ui/index.js +4 -2
- package/dist/utils/id-generators.d.ts +27 -0
- package/dist/utils/id-generators.js +45 -0
- package/dist/utils/number.formatter.d.ts +7 -0
- package/dist/utils/number.formatter.js +9 -0
- package/dist/validation/schemas.d.ts +5 -5
- package/package.json +1 -1
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core: hard-ban cascade — disables Auth login, marks the user banned,
|
|
3
|
+
* revokes sessions, suspends any owned store + archives its products,
|
|
4
|
+
* cancels active bids, and cascades the ban across any address / payment
|
|
5
|
+
* clusters shared with other accounts (fraud-ring containment).
|
|
6
|
+
*
|
|
7
|
+
* Extracted verbatim (stage-for-stage) from the former synchronous
|
|
8
|
+
* `POST /api/admin/users/[uid]/hard-ban` route body — that route now only
|
|
9
|
+
* runs the cheap pre-flight guards (self-ban / target-exists / admin-target)
|
|
10
|
+
* and enqueues this as a `hardBanCascade` job (see `./jobRunners.ts`) so the
|
|
11
|
+
* cascade runs inside a Firebase Function instead of the Vercel 10s sync
|
|
12
|
+
* ceiling (CLAUDE.md Rule #6).
|
|
13
|
+
*
|
|
14
|
+
* Each stage keeps its original non-fatal try/catch-log-continue behavior,
|
|
15
|
+
* EXCEPT stage 2 (marking the user banned on Firestore), which is the one
|
|
16
|
+
* write that must succeed for the ban to take effect — if it throws, the job
|
|
17
|
+
* is marked failed so an admin can retry.
|
|
18
|
+
*/
|
|
19
|
+
import { normalizeError } from "../../../../errors/normalize";
|
|
20
|
+
import { userRepository, sessionRepository, storeRepository, productRepository, bidRepository, addressesRepository, savedPaymentMethodsRepository, siteSettingsRepository, } from "../../../../repositories";
|
|
21
|
+
import { sendNotification } from "../../../../features/admin/actions/notification-actions";
|
|
22
|
+
import { isSellerUser } from "../../../../features/auth/role-predicates";
|
|
23
|
+
import { getAdminAuth } from "../../../../providers/db-firebase";
|
|
24
|
+
async function cascadeAddressClusterBan(uid, banData) {
|
|
25
|
+
const userAddresses = await addressesRepository.listByOwner("user", uid);
|
|
26
|
+
const uniqueHashes = [...new Set(userAddresses.map((a) => a.addressHash).filter(Boolean))];
|
|
27
|
+
for (const hash of uniqueHashes) {
|
|
28
|
+
const cluster = await addressesRepository.listByAddressHash(hash);
|
|
29
|
+
const hasBannedAccount = cluster.some((a) => a.ownerId !== uid && a.banStatus === "banned");
|
|
30
|
+
if (!hasBannedAccount)
|
|
31
|
+
continue;
|
|
32
|
+
const otherOwners = [...new Set(cluster.filter((a) => a.ownerId !== uid).map((a) => `${a.ownerType}|${a.ownerId}`))];
|
|
33
|
+
for (const ownerKey of otherOwners) {
|
|
34
|
+
const [ownerType, ownerId] = ownerKey.split("|");
|
|
35
|
+
await addressesRepository.banAllForOwner(ownerType, ownerId, banData);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async function cascadePaymentClusterBan(uid, banData) {
|
|
40
|
+
const userMethods = await savedPaymentMethodsRepository.listByUser(uid);
|
|
41
|
+
for (const method of userMethods) {
|
|
42
|
+
if (!method.identifierHash)
|
|
43
|
+
continue;
|
|
44
|
+
const cluster = await savedPaymentMethodsRepository.listByIdentifierHash(method.identifierHash);
|
|
45
|
+
const hasBannedAccount = cluster.some((m) => m.userId !== uid && m.banStatus === "banned");
|
|
46
|
+
if (!hasBannedAccount)
|
|
47
|
+
continue;
|
|
48
|
+
const otherUserIds = [...new Set(cluster.filter((m) => m.userId !== uid).map((m) => m.userId))];
|
|
49
|
+
for (const otherId of otherUserIds) {
|
|
50
|
+
await savedPaymentMethodsRepository.banAllForUser(otherId, banData);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
export async function runHardBanCascade(input, ctx) {
|
|
55
|
+
const { uid, reason, bannedBy } = input;
|
|
56
|
+
const target = await userRepository.findById(uid);
|
|
57
|
+
if (!target) {
|
|
58
|
+
return {
|
|
59
|
+
summary: { total: 1, succeeded: 0, skipped: 1, failed: 0 },
|
|
60
|
+
succeeded: [],
|
|
61
|
+
skipped: [uid],
|
|
62
|
+
failed: [],
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
// 1. Disable Firebase Auth login
|
|
66
|
+
try {
|
|
67
|
+
await getAdminAuth().updateUser(uid, { disabled: true });
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
void normalizeError(err);
|
|
71
|
+
ctx.logger.warn("hard-ban: Auth disable failed (user may lack Auth record)", {
|
|
72
|
+
uid,
|
|
73
|
+
error: err instanceof Error ? err.message : String(err),
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
// 2. Mark banned on Firestore doc — the one write that must succeed for the
|
|
77
|
+
// ban to take effect. Left unguarded so a failure here marks the whole job
|
|
78
|
+
// failed (matches the original route's behavior of surfacing a 500).
|
|
79
|
+
await userRepository.update(uid, {
|
|
80
|
+
isDisabled: true,
|
|
81
|
+
hardBanReason: reason,
|
|
82
|
+
hardBannedAt: new Date(),
|
|
83
|
+
hardBannedBy: bannedBy,
|
|
84
|
+
});
|
|
85
|
+
// 3. Delete active sessions
|
|
86
|
+
try {
|
|
87
|
+
const sessions = await sessionRepository.findActiveByUser(uid);
|
|
88
|
+
await Promise.all(sessions.map((s) => sessionRepository.delete(s.id)));
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
void normalizeError(err);
|
|
92
|
+
ctx.logger.warn("hard-ban: session cleanup failed (non-fatal)", {
|
|
93
|
+
uid,
|
|
94
|
+
error: err instanceof Error ? err.message : String(err),
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
// 4. Cascade to store if seller
|
|
98
|
+
if (isSellerUser(target)) {
|
|
99
|
+
try {
|
|
100
|
+
const store = await storeRepository.findByOwnerId(uid);
|
|
101
|
+
if (store) {
|
|
102
|
+
await storeRepository.update(store.id, { status: "suspended" });
|
|
103
|
+
const products = await productRepository.findByStore(store.id);
|
|
104
|
+
await Promise.all(products.map((p) => productRepository.update(p.id, { status: "archived" })));
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
void normalizeError(err);
|
|
109
|
+
ctx.logger.warn("hard-ban: store/product cascade failed (non-fatal)", {
|
|
110
|
+
uid,
|
|
111
|
+
error: err instanceof Error ? err.message : String(err),
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// 5. Cancel active bids
|
|
116
|
+
try {
|
|
117
|
+
const bids = await bidRepository.findBy("bidderId", uid);
|
|
118
|
+
const activeBids = bids.filter((b) => b.status === "active");
|
|
119
|
+
await Promise.all(activeBids.map((b) => bidRepository.update(b.id, { status: "cancelled" })));
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
void normalizeError(err);
|
|
123
|
+
ctx.logger.warn("hard-ban: bid cancellation failed (non-fatal)", {
|
|
124
|
+
uid,
|
|
125
|
+
error: err instanceof Error ? err.message : String(err),
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
// 6. Cascade address ban + cross-account cluster ban
|
|
129
|
+
try {
|
|
130
|
+
const banData = { banReason: `User hard-banned: ${reason}`, bannedBy };
|
|
131
|
+
await addressesRepository.banAllForOwner("user", uid, banData);
|
|
132
|
+
await cascadeAddressClusterBan(uid, banData);
|
|
133
|
+
}
|
|
134
|
+
catch (err) {
|
|
135
|
+
void normalizeError(err);
|
|
136
|
+
ctx.logger.warn("hard-ban: address cluster ban failed (non-fatal)", {
|
|
137
|
+
uid,
|
|
138
|
+
error: err instanceof Error ? err.message : String(err),
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
// 7. Cascade payment method ban + cross-account cluster ban
|
|
142
|
+
try {
|
|
143
|
+
const banData = { banReason: `User hard-banned: ${reason}`, bannedBy };
|
|
144
|
+
await savedPaymentMethodsRepository.banAllForUser(uid, banData);
|
|
145
|
+
await cascadePaymentClusterBan(uid, banData);
|
|
146
|
+
}
|
|
147
|
+
catch (err) {
|
|
148
|
+
void normalizeError(err);
|
|
149
|
+
ctx.logger.warn("hard-ban: payment method cluster ban failed (non-fatal)", {
|
|
150
|
+
uid,
|
|
151
|
+
error: err instanceof Error ? err.message : String(err),
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
// 8. Notify user
|
|
155
|
+
try {
|
|
156
|
+
const siteSettings = await siteSettingsRepository.getSingleton();
|
|
157
|
+
const supportEmail = siteSettings.contact?.email || "support@example.com";
|
|
158
|
+
await sendNotification({
|
|
159
|
+
userId: uid,
|
|
160
|
+
type: "account_action",
|
|
161
|
+
priority: "high",
|
|
162
|
+
title: "Account permanently suspended",
|
|
163
|
+
message: `Your account has been permanently suspended. Reason: ${reason}. You may appeal by emailing ${supportEmail}.`,
|
|
164
|
+
relatedId: uid,
|
|
165
|
+
relatedType: "user",
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
catch (err) {
|
|
169
|
+
void normalizeError(err);
|
|
170
|
+
ctx.logger.warn("hard-ban: user notification failed (non-fatal)", {
|
|
171
|
+
uid,
|
|
172
|
+
error: err instanceof Error ? err.message : String(err),
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
return {
|
|
176
|
+
summary: { total: 1, succeeded: 1, skipped: 0, failed: 0 },
|
|
177
|
+
succeeded: [uid],
|
|
178
|
+
skipped: [],
|
|
179
|
+
failed: [],
|
|
180
|
+
};
|
|
181
|
+
}
|
|
@@ -22,7 +22,9 @@ export { runPayoutBatch } from "./payoutBatch";
|
|
|
22
22
|
export { runAutoPayoutEligibility } from "./autoPayoutEligibility";
|
|
23
23
|
export { runProductStatsSync } from "./productStatsSync";
|
|
24
24
|
export { runPositionsReconcile } from "./positionsReconcile";
|
|
25
|
-
export { runWeeklyPayoutEligibility } from "./weeklyPayoutEligibility";
|
|
25
|
+
export { runWeeklyPayoutEligibility, type WeeklyPayoutEligibilityResult, } from "./weeklyPayoutEligibility";
|
|
26
|
+
export { runHardBanCascade } from "./hardBanCascade";
|
|
27
|
+
export { JOB_RUNNERS, type JobRunner, type JobRunResult, } from "./jobRunners";
|
|
26
28
|
export { runAuctionSettlement } from "./auctionSettlement";
|
|
27
29
|
export { runPrizeRevealOpen } from "./prizeRevealOpen";
|
|
28
30
|
export { runPrizeRevealClose } from "./prizeRevealClose";
|
|
@@ -42,3 +44,4 @@ export { handleProductStockChange, type HandleProductStockChangeInput, syncBundl
|
|
|
42
44
|
export { handleReviewWrite, type HandleReviewWriteInput } from "./onReviewWrite";
|
|
43
45
|
export { handleCategoryWrite, type HandleCategoryWriteInput, type CategoryDoc, } from "./onCategoryWrite";
|
|
44
46
|
export { handleStoreWrite, type HandleStoreWriteInput, type StoreDoc, } from "./onStoreWrite";
|
|
47
|
+
export { handleJobCreated, type HandleJobCreatedInput } from "./onJobCreated";
|
|
@@ -23,7 +23,9 @@ export { runPayoutBatch } from "./payoutBatch";
|
|
|
23
23
|
export { runAutoPayoutEligibility } from "./autoPayoutEligibility";
|
|
24
24
|
export { runProductStatsSync } from "./productStatsSync";
|
|
25
25
|
export { runPositionsReconcile } from "./positionsReconcile";
|
|
26
|
-
export { runWeeklyPayoutEligibility } from "./weeklyPayoutEligibility";
|
|
26
|
+
export { runWeeklyPayoutEligibility, } from "./weeklyPayoutEligibility";
|
|
27
|
+
export { runHardBanCascade } from "./hardBanCascade";
|
|
28
|
+
export { JOB_RUNNERS, } from "./jobRunners";
|
|
27
29
|
export { runAuctionSettlement } from "./auctionSettlement";
|
|
28
30
|
export { runPrizeRevealOpen } from "./prizeRevealOpen";
|
|
29
31
|
export { runPrizeRevealClose } from "./prizeRevealClose";
|
|
@@ -45,3 +47,4 @@ export { handleProductStockChange, syncBundlesForProduct, syncGroupedListingsFor
|
|
|
45
47
|
export { handleReviewWrite } from "./onReviewWrite";
|
|
46
48
|
export { handleCategoryWrite, } from "./onCategoryWrite";
|
|
47
49
|
export { handleStoreWrite, } from "./onStoreWrite";
|
|
50
|
+
export { handleJobCreated } from "./onJobCreated";
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JOB_RUNNERS — registry of `jobType` → runner function for the
|
|
3
|
+
* `onJobCreated` Firestore trigger (see `./onJobCreated.ts`).
|
|
4
|
+
*
|
|
5
|
+
* Every runner takes the job's opaque `payload` + a `JobContext` and returns
|
|
6
|
+
* a `JobRunResult` shaped like the client-facing `BulkActionResult` (see
|
|
7
|
+
* `appkit/src/react/hooks/useBulkAction.ts`) so it can be written verbatim to
|
|
8
|
+
* both the `jobs/{jobId}.result` field and the `bulk_events/{jobId}` RTDB
|
|
9
|
+
* ping channel the client subscribes to via `useBulkEvent`.
|
|
10
|
+
*/
|
|
11
|
+
import type { JobContext } from "../runtime/types";
|
|
12
|
+
export interface JobRunResult {
|
|
13
|
+
summary: {
|
|
14
|
+
total: number;
|
|
15
|
+
succeeded: number;
|
|
16
|
+
skipped: number;
|
|
17
|
+
failed: number;
|
|
18
|
+
};
|
|
19
|
+
succeeded: string[];
|
|
20
|
+
skipped: string[];
|
|
21
|
+
failed: {
|
|
22
|
+
id: string;
|
|
23
|
+
reason: string;
|
|
24
|
+
}[];
|
|
25
|
+
data?: Record<string, unknown>;
|
|
26
|
+
}
|
|
27
|
+
export type JobRunner = (payload: Record<string, unknown>, ctx: JobContext) => Promise<JobRunResult>;
|
|
28
|
+
export declare const JOB_RUNNERS: Record<string, JobRunner>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JOB_RUNNERS — registry of `jobType` → runner function for the
|
|
3
|
+
* `onJobCreated` Firestore trigger (see `./onJobCreated.ts`).
|
|
4
|
+
*
|
|
5
|
+
* Every runner takes the job's opaque `payload` + a `JobContext` and returns
|
|
6
|
+
* a `JobRunResult` shaped like the client-facing `BulkActionResult` (see
|
|
7
|
+
* `appkit/src/react/hooks/useBulkAction.ts`) so it can be written verbatim to
|
|
8
|
+
* both the `jobs/{jobId}.result` field and the `bulk_events/{jobId}` RTDB
|
|
9
|
+
* ping channel the client subscribes to via `useBulkEvent`.
|
|
10
|
+
*/
|
|
11
|
+
import { runWeeklyPayoutEligibility } from "./weeklyPayoutEligibility";
|
|
12
|
+
import { runHardBanCascade } from "./hardBanCascade";
|
|
13
|
+
async function runPayoutsWeeklyJob(_payload, ctx) {
|
|
14
|
+
const { payoutsCreated, ordersProcessed, payoutIds } = await runWeeklyPayoutEligibility(ctx);
|
|
15
|
+
return {
|
|
16
|
+
summary: {
|
|
17
|
+
total: payoutsCreated,
|
|
18
|
+
succeeded: payoutsCreated,
|
|
19
|
+
skipped: 0,
|
|
20
|
+
failed: 0,
|
|
21
|
+
},
|
|
22
|
+
succeeded: payoutIds,
|
|
23
|
+
skipped: [],
|
|
24
|
+
failed: [],
|
|
25
|
+
data: { payoutsCreated, ordersProcessed },
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
async function runHardBanCascadeJob(payload, ctx) {
|
|
29
|
+
const uid = String(payload.uid ?? "");
|
|
30
|
+
const reason = String(payload.reason ?? "");
|
|
31
|
+
const bannedBy = String(payload.bannedBy ?? "");
|
|
32
|
+
return runHardBanCascade({ uid, reason, bannedBy }, ctx);
|
|
33
|
+
}
|
|
34
|
+
export const JOB_RUNNERS = {
|
|
35
|
+
payoutsWeekly: runPayoutsWeeklyJob,
|
|
36
|
+
hardBanCascade: runHardBanCascadeJob,
|
|
37
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { JobContext } from "../runtime/types";
|
|
2
|
+
import type { CatalogueItemDocument } from "../../../../features/catalogue/schemas/firestore";
|
|
3
|
+
export interface CatalogueApprovalEvent {
|
|
4
|
+
itemId: string;
|
|
5
|
+
before: CatalogueItemDocument;
|
|
6
|
+
after: CatalogueItemDocument;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Fires when a catalogue item's `listingStatus` transitions to
|
|
10
|
+
* "pending_admin_approval" (a buyer's "Request to sell"). Notifies every
|
|
11
|
+
* admin so the approvals queue doesn't go unnoticed. Kept out of the
|
|
12
|
+
* synchronous submit action per Rule #6 — the buyer-facing request stays
|
|
13
|
+
* fast regardless of how many admins there are to fan out to.
|
|
14
|
+
*/
|
|
15
|
+
export declare function handleCatalogueSubmittedForApproval(event: CatalogueApprovalEvent, ctx: JobContext): Promise<void>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { userRepository } from "../../../../features/auth/repository/user.repository";
|
|
2
|
+
import { sendNotification } from "../../../../features/admin/actions/notification-actions";
|
|
3
|
+
import { normalizeError } from "../../../../errors/normalize";
|
|
4
|
+
/**
|
|
5
|
+
* Fires when a catalogue item's `listingStatus` transitions to
|
|
6
|
+
* "pending_admin_approval" (a buyer's "Request to sell"). Notifies every
|
|
7
|
+
* admin so the approvals queue doesn't go unnoticed. Kept out of the
|
|
8
|
+
* synchronous submit action per Rule #6 — the buyer-facing request stays
|
|
9
|
+
* fast regardless of how many admins there are to fan out to.
|
|
10
|
+
*/
|
|
11
|
+
export async function handleCatalogueSubmittedForApproval(event, ctx) {
|
|
12
|
+
const becamePending = event.before.listingStatus !== "pending_admin_approval" &&
|
|
13
|
+
event.after.listingStatus === "pending_admin_approval";
|
|
14
|
+
if (!becamePending)
|
|
15
|
+
return;
|
|
16
|
+
const admins = await userRepository.findByRole("admin");
|
|
17
|
+
for (const admin of admins) {
|
|
18
|
+
try {
|
|
19
|
+
await sendNotification({
|
|
20
|
+
userId: admin.uid,
|
|
21
|
+
type: "system",
|
|
22
|
+
priority: "normal",
|
|
23
|
+
title: "New catalogue listing request",
|
|
24
|
+
message: `"${event.after.title}" was submitted for approval to list under LetItRip Official.`,
|
|
25
|
+
actionUrl: "/admin/catalogue-approvals",
|
|
26
|
+
actionLabel: "Review request",
|
|
27
|
+
relatedId: event.itemId,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
void normalizeError(err);
|
|
32
|
+
ctx.logger.error("onCatalogueSubmittedForApproval: failed to notify admin", {
|
|
33
|
+
itemId: event.itemId,
|
|
34
|
+
adminUid: admin.uid,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core: `jobs/{jobId}` document-created trigger.
|
|
3
|
+
*
|
|
4
|
+
* This is the single dispatch point for the async-job primitive
|
|
5
|
+
* (CLAUDE.md Rule #6 — Vercel routes never do heavy work; they write a
|
|
6
|
+
* `jobs` doc and return, this Function does the actual processing).
|
|
7
|
+
*
|
|
8
|
+
* Flow:
|
|
9
|
+
* 1. Mark the job "processing".
|
|
10
|
+
* 2. Look up a runner in `JOB_RUNNERS` by `job.jobType`.
|
|
11
|
+
* 3. Run it, mark the job "done"/"failed", and best-effort ping the
|
|
12
|
+
* `bulk_events/{jobId}` RTDB channel the client is subscribed to via
|
|
13
|
+
* `useBulkEvent` — every RTDB write is its own try/catch so a ping
|
|
14
|
+
* failure never masks the real Firestore result.
|
|
15
|
+
*/
|
|
16
|
+
import type { JobDocument } from "../../../../features/jobs/schemas/firestore";
|
|
17
|
+
import type { JobContext } from "../runtime/types";
|
|
18
|
+
export interface HandleJobCreatedInput {
|
|
19
|
+
jobId: string;
|
|
20
|
+
job: JobDocument;
|
|
21
|
+
}
|
|
22
|
+
export declare function handleJobCreated(input: HandleJobCreatedInput, ctx: JobContext): Promise<void>;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core: `jobs/{jobId}` document-created trigger.
|
|
3
|
+
*
|
|
4
|
+
* This is the single dispatch point for the async-job primitive
|
|
5
|
+
* (CLAUDE.md Rule #6 — Vercel routes never do heavy work; they write a
|
|
6
|
+
* `jobs` doc and return, this Function does the actual processing).
|
|
7
|
+
*
|
|
8
|
+
* Flow:
|
|
9
|
+
* 1. Mark the job "processing".
|
|
10
|
+
* 2. Look up a runner in `JOB_RUNNERS` by `job.jobType`.
|
|
11
|
+
* 3. Run it, mark the job "done"/"failed", and best-effort ping the
|
|
12
|
+
* `bulk_events/{jobId}` RTDB channel the client is subscribed to via
|
|
13
|
+
* `useBulkEvent` — every RTDB write is its own try/catch so a ping
|
|
14
|
+
* failure never masks the real Firestore result.
|
|
15
|
+
*/
|
|
16
|
+
import { normalizeError } from "../../../../errors/normalize";
|
|
17
|
+
import { jobsRepository } from "../../../../repositories";
|
|
18
|
+
import { getAdminRealtimeDb } from "../../../../providers/db-firebase";
|
|
19
|
+
import { RTDB_PATHS } from "../../../../providers/db-firebase/rtdb-paths";
|
|
20
|
+
import { JOB_RUNNERS } from "./jobRunners";
|
|
21
|
+
async function pingBulkEvent(jobId, payload, ctx) {
|
|
22
|
+
try {
|
|
23
|
+
await getAdminRealtimeDb()
|
|
24
|
+
.ref(`${RTDB_PATHS.BULK_EVENTS}/${jobId}`)
|
|
25
|
+
.set({ ...payload, updatedAt: Date.now() });
|
|
26
|
+
}
|
|
27
|
+
catch (err) {
|
|
28
|
+
void normalizeError(err);
|
|
29
|
+
ctx.logger.warn("onJobCreated: RTDB ping failed (non-fatal)", {
|
|
30
|
+
jobId,
|
|
31
|
+
error: err instanceof Error ? err.message : String(err),
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export async function handleJobCreated(input, ctx) {
|
|
36
|
+
const { jobId, job } = input;
|
|
37
|
+
await jobsRepository.markProcessing(jobId);
|
|
38
|
+
const runner = JOB_RUNNERS[job.jobType];
|
|
39
|
+
if (!runner) {
|
|
40
|
+
const error = `Unknown jobType: ${job.jobType}`;
|
|
41
|
+
await jobsRepository.markFailed(jobId, error);
|
|
42
|
+
await pingBulkEvent(jobId, { status: "failed", action: job.jobType, error }, ctx);
|
|
43
|
+
ctx.logger.error("onJobCreated: unknown jobType", null, { jobId, jobType: job.jobType });
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const result = await runner(job.payload, ctx);
|
|
48
|
+
await jobsRepository.markDone(jobId, result);
|
|
49
|
+
await pingBulkEvent(jobId, { status: "success", action: job.jobType, ...result }, ctx);
|
|
50
|
+
ctx.logger.info("onJobCreated: job complete", { jobId, jobType: job.jobType, summary: result.summary });
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
void normalizeError(err);
|
|
54
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
55
|
+
await jobsRepository.markFailed(jobId, message);
|
|
56
|
+
await pingBulkEvent(jobId, { status: "failed", action: job.jobType, error: message }, ctx);
|
|
57
|
+
ctx.logger.error("onJobCreated: job failed", err, { jobId, jobType: job.jobType });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -3,4 +3,9 @@
|
|
|
3
3
|
* `payoutStatus=eligible` into pending payout documents grouped by seller.
|
|
4
4
|
*/
|
|
5
5
|
import type { JobContext } from "../runtime/types";
|
|
6
|
-
export
|
|
6
|
+
export interface WeeklyPayoutEligibilityResult {
|
|
7
|
+
payoutsCreated: number;
|
|
8
|
+
ordersProcessed: number;
|
|
9
|
+
payoutIds: string[];
|
|
10
|
+
}
|
|
11
|
+
export declare function runWeeklyPayoutEligibility(ctx: JobContext): Promise<WeeklyPayoutEligibilityResult>;
|
|
@@ -9,7 +9,7 @@ import { computePayoutDeduction } from "../../../shared/fees/calculator";
|
|
|
9
9
|
export async function runWeeklyPayoutEligibility(ctx) {
|
|
10
10
|
if (ctx.env("FEATURE_PAYOUTS") !== "true") {
|
|
11
11
|
ctx.logger.info("FEATURE_PAYOUTS disabled — skipping weekly payout eligibility");
|
|
12
|
-
return;
|
|
12
|
+
return { payoutsCreated: 0, ordersProcessed: 0, payoutIds: [] };
|
|
13
13
|
}
|
|
14
14
|
ctx.logger.info("Starting weekly payout eligibility sweep");
|
|
15
15
|
const siteSettings = await siteSettingsRepository.getSingleton();
|
|
@@ -17,7 +17,7 @@ export async function runWeeklyPayoutEligibility(ctx) {
|
|
|
17
17
|
const eligible = await orderRepository.getEligibleForPayoutSweep();
|
|
18
18
|
if (eligible.length === 0) {
|
|
19
19
|
ctx.logger.info("No eligible delivered orders found");
|
|
20
|
-
return;
|
|
20
|
+
return { payoutsCreated: 0, ordersProcessed: 0, payoutIds: [] };
|
|
21
21
|
}
|
|
22
22
|
ctx.logger.info(`Found ${eligible.length} eligible order(s) — grouping by seller`);
|
|
23
23
|
const byStore = new Map();
|
|
@@ -33,6 +33,7 @@ export async function runWeeklyPayoutEligibility(ctx) {
|
|
|
33
33
|
}
|
|
34
34
|
let payoutsCreated = 0;
|
|
35
35
|
let ordersProcessed = 0;
|
|
36
|
+
const payoutIds = [];
|
|
36
37
|
const defaultCurrency = getDefaultCurrency();
|
|
37
38
|
for (const [storeId, orders] of byStore.entries()) {
|
|
38
39
|
const store = await storeRepository.findBySlug(storeId);
|
|
@@ -82,6 +83,7 @@ export async function runWeeklyPayoutEligibility(ctx) {
|
|
|
82
83
|
}
|
|
83
84
|
payoutsCreated++;
|
|
84
85
|
ordersProcessed += orders.length;
|
|
86
|
+
payoutIds.push(payoutId);
|
|
85
87
|
ctx.logger.info(`Payout created for store ${storeId}`, {
|
|
86
88
|
payoutId,
|
|
87
89
|
orderCount: orders.length,
|
|
@@ -91,4 +93,5 @@ export async function runWeeklyPayoutEligibility(ctx) {
|
|
|
91
93
|
});
|
|
92
94
|
}
|
|
93
95
|
ctx.logger.info("Weekly payout eligibility sweep complete", { payoutsCreated, ordersProcessed });
|
|
96
|
+
return { payoutsCreated, ordersProcessed, payoutIds };
|
|
94
97
|
}
|
|
@@ -19,6 +19,7 @@ export { countersReconcileHandler } from "./countersReconcile";
|
|
|
19
19
|
export { onOrderCreateHandler } from "./onOrderCreate";
|
|
20
20
|
export { onOrderStatusChangeHandler } from "./onOrderStatusChange";
|
|
21
21
|
export { onBidPlacedHandler } from "./onBidPlaced";
|
|
22
|
+
export { onJobCreatedHandler } from "./onJobCreated";
|
|
22
23
|
export { onReviewWriteHandler } from "./onReviewWrite";
|
|
23
24
|
export { promotionsHandler, type PromotionsCallableResult } from "./promotions";
|
|
24
25
|
export { mediaTmpCleanupHandler } from "./mediaTmpCleanup";
|
|
@@ -48,3 +49,8 @@ export { onScamReportCreateHandler } from "./onScamReportCreate";
|
|
|
48
49
|
export { onScamReportUpdateHandler } from "./onScamReportUpdate";
|
|
49
50
|
export { draftPruneHandler } from "./draftPrune";
|
|
50
51
|
export { emiInstallmentReminderHandler } from "./emiInstallmentReminder";
|
|
52
|
+
export { onShipmentItemWriteHandler } from "./onShipmentItemWrite";
|
|
53
|
+
export { onShipmentLotWriteHandler, onShipmentHeaderWriteHandler } from "./onShipmentAllocationSync";
|
|
54
|
+
export { onShipmentDeletedHandler } from "./onShipmentDeleted";
|
|
55
|
+
export { catalogueImageStalenessReminderHandler } from "./catalogueImageStalenessReminder";
|
|
56
|
+
export { onCatalogueSubmittedForApprovalHandler } from "./onCatalogueSubmittedForApproval";
|
|
@@ -19,6 +19,7 @@ export { countersReconcileHandler } from "./countersReconcile";
|
|
|
19
19
|
export { onOrderCreateHandler } from "./onOrderCreate";
|
|
20
20
|
export { onOrderStatusChangeHandler } from "./onOrderStatusChange";
|
|
21
21
|
export { onBidPlacedHandler } from "./onBidPlaced";
|
|
22
|
+
export { onJobCreatedHandler } from "./onJobCreated";
|
|
22
23
|
export { onReviewWriteHandler } from "./onReviewWrite";
|
|
23
24
|
export { promotionsHandler } from "./promotions";
|
|
24
25
|
export { mediaTmpCleanupHandler } from "./mediaTmpCleanup";
|
|
@@ -57,3 +58,10 @@ export { onScamReportUpdateHandler } from "./onScamReportUpdate";
|
|
|
57
58
|
export { draftPruneHandler } from "./draftPrune";
|
|
58
59
|
// EMI — installment reminder + overdue-flagging sweep
|
|
59
60
|
export { emiInstallmentReminderHandler } from "./emiInstallmentReminder";
|
|
61
|
+
// Procurement Shipments — 3-function recompute cascade (item→lot, lot/header→shipment allocation, cascade-delete)
|
|
62
|
+
export { onShipmentItemWriteHandler } from "./onShipmentItemWrite";
|
|
63
|
+
export { onShipmentLotWriteHandler, onShipmentHeaderWriteHandler } from "./onShipmentAllocationSync";
|
|
64
|
+
export { onShipmentDeletedHandler } from "./onShipmentDeleted";
|
|
65
|
+
// Personal Catalogue (Feature B) — freshness reminder + admin approval-request notification
|
|
66
|
+
export { catalogueImageStalenessReminderHandler } from "./catalogueImageStalenessReminder";
|
|
67
|
+
export { onCatalogueSubmittedForApprovalHandler } from "./onCatalogueSubmittedForApproval";
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fires on any write to catalogueItems/{itemId} where listingStatus
|
|
3
|
+
* transitions into "pending_admin_approval" (the buyer "Request to sell"
|
|
4
|
+
* action). Sends one admin-inbox notification — kept out of the fast
|
|
5
|
+
* user-facing action per Rule #6, so the buyer's request doesn't wait on
|
|
6
|
+
* how many admins exist.
|
|
7
|
+
*/
|
|
8
|
+
import type { FirestoreTriggerHandler } from "../runtime/types";
|
|
9
|
+
import type { JsonValue } from "@mohasinac/appkit";
|
|
10
|
+
type Doc = Record<string, JsonValue>;
|
|
11
|
+
export declare const onCatalogueSubmittedForApprovalHandler: FirestoreTriggerHandler<Doc, Doc>;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { adminNotificationsRepository } from "../../../../repositories";
|
|
2
|
+
export const onCatalogueSubmittedForApprovalHandler = async (event, ctx) => {
|
|
3
|
+
const before = event.before?.listingStatus;
|
|
4
|
+
const after = event.after?.listingStatus;
|
|
5
|
+
if (before === "pending_admin_approval" || after !== "pending_admin_approval")
|
|
6
|
+
return;
|
|
7
|
+
const itemId = event.params.itemId ?? event.after?.id;
|
|
8
|
+
const title = event.after?.title ?? "Untitled item";
|
|
9
|
+
await adminNotificationsRepository.create({
|
|
10
|
+
category: "moderation",
|
|
11
|
+
title: "Catalogue listing pending approval",
|
|
12
|
+
body: `A buyer requested "${title}" be listed on their behalf.`,
|
|
13
|
+
severity: "info",
|
|
14
|
+
isRead: false,
|
|
15
|
+
entityType: "catalogueItem",
|
|
16
|
+
entityId: itemId,
|
|
17
|
+
audienceUserIds: [],
|
|
18
|
+
createdAt: ctx.now,
|
|
19
|
+
});
|
|
20
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { handleJobCreated } from "../core/onJobCreated";
|
|
2
|
+
export const onJobCreatedHandler = async (event, ctx) => {
|
|
3
|
+
const job = event.after;
|
|
4
|
+
if (!job) {
|
|
5
|
+
ctx.logger.error("No snapshot data", null);
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
await handleJobCreated({ jobId: event.params.jobId, job }, ctx);
|
|
9
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Function #2 of the procurement-shipments cascade — the allocation engine.
|
|
3
|
+
*
|
|
4
|
+
* Fires on:
|
|
5
|
+
* (a) any write to shipmentLots/{lotId} (itemCount/revenue changed via
|
|
6
|
+
* Function #1, or the admin edited weight/cost/remainder fields)
|
|
7
|
+
* (b) any write to procurementShipments/{shipmentId} (admin edited
|
|
8
|
+
* customsTotalPaise/shippingTotalPaise/laborHoursSpent/status)
|
|
9
|
+
*
|
|
10
|
+
* Both re-run the same cross-lot allocation: read every sibling lot
|
|
11
|
+
* (bounded ≤10), call the shared pure allocateShipmentCosts(), batch-write
|
|
12
|
+
* each lot's customsAllocatedPaise/shippingAllocatedPaise/totalLandedCostPaise/
|
|
13
|
+
* projectedRevenuePaise/projectedProfitPaise plus the shipment's persisted
|
|
14
|
+
* `totals` + `totalsComputedAt`. Also keeps ShipmentLot.shipmentStatus in
|
|
15
|
+
* sync with its parent so the Projections list can filter on it directly.
|
|
16
|
+
*
|
|
17
|
+
* Skips writes that would be no-ops (value-identical) so the cascade
|
|
18
|
+
* terminates instead of re-triggering itself indefinitely.
|
|
19
|
+
*/
|
|
20
|
+
import type { FirestoreTriggerHandler } from "../runtime/types";
|
|
21
|
+
import type { JsonValue } from "@mohasinac/appkit";
|
|
22
|
+
type Doc = Record<string, JsonValue>;
|
|
23
|
+
export declare const onShipmentLotWriteHandler: FirestoreTriggerHandler<Doc, Doc>;
|
|
24
|
+
export declare const onShipmentHeaderWriteHandler: FirestoreTriggerHandler<Doc, Doc>;
|
|
25
|
+
export {};
|