@mohasinac/appkit 4.59.0 → 4.60.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/.build-stamp.json +3 -3
- package/dist/_internal/client/features/layout/DashboardLayoutClient.js +62 -5
- package/dist/_internal/client/features/maintenance/views/MaintenanceDashboardView.js +2 -2
- package/dist/_internal/server/features/brands/actions.js +78 -4
- package/dist/_internal/server/features/checkout/actions.d.ts +36 -13
- package/dist/_internal/server/features/checkout/actions.js +668 -183
- package/dist/_internal/server/features/checkout/supplier-identity.js +18 -1
- package/dist/_internal/server/features/gateway-events/index.d.ts +10 -0
- package/dist/_internal/server/features/gateway-events/index.js +10 -0
- package/dist/_internal/server/features/gateway-events/ingest.d.ts +127 -0
- package/dist/_internal/server/features/gateway-events/ingest.js +188 -0
- package/dist/_internal/server/features/gateway-events/redact.d.ts +66 -0
- package/dist/_internal/server/features/gateway-events/redact.js +151 -0
- package/dist/_internal/server/features/grievance/actions.d.ts +63 -0
- package/dist/_internal/server/features/grievance/actions.js +173 -0
- package/dist/_internal/server/features/grievance/index.d.ts +8 -0
- package/dist/_internal/server/features/grievance/index.js +8 -0
- package/dist/_internal/server/features/grouped/data.js +28 -3
- package/dist/_internal/server/features/lottery/actions.js +99 -4
- package/dist/_internal/server/features/order-completion/actions.d.ts +92 -0
- package/dist/_internal/server/features/order-completion/actions.js +336 -0
- package/dist/_internal/server/features/order-completion/index.d.ts +7 -0
- package/dist/_internal/server/features/order-completion/index.js +7 -0
- package/dist/_internal/server/features/orders/actions.d.ts +13 -0
- package/dist/_internal/server/features/orders/actions.js +56 -2
- package/dist/_internal/server/features/orders/adapters.d.ts +20 -2
- package/dist/_internal/server/features/orders/adapters.js +44 -0
- package/dist/_internal/server/features/orders/cancellation-refund.d.ts +116 -0
- package/dist/_internal/server/features/orders/cancellation-refund.js +466 -0
- package/dist/_internal/server/features/orders/index.d.ts +2 -1
- package/dist/_internal/server/features/orders/index.js +1 -1
- package/dist/_internal/server/features/orders/service.d.ts +60 -0
- package/dist/_internal/server/features/orders/service.js +74 -0
- package/dist/_internal/server/features/payment-cases/disputes.d.ts +76 -0
- package/dist/_internal/server/features/payment-cases/disputes.js +241 -0
- package/dist/_internal/server/features/payment-cases/index.d.ts +9 -0
- package/dist/_internal/server/features/payment-cases/index.js +9 -0
- package/dist/_internal/server/features/payouts/actions.d.ts +28 -3
- package/dist/_internal/server/features/payouts/actions.js +84 -10
- package/dist/_internal/server/features/points/adjust.d.ts +61 -0
- package/dist/_internal/server/features/points/adjust.js +121 -0
- package/dist/_internal/server/features/points/award.d.ts +65 -0
- package/dist/_internal/server/features/points/award.js +145 -0
- package/dist/_internal/server/features/price-index/market.d.ts +33 -0
- package/dist/_internal/server/features/price-index/market.js +54 -1
- package/dist/_internal/server/features/products/data.js +40 -22
- package/dist/_internal/server/features/protection-claims/actions.d.ts +72 -0
- package/dist/_internal/server/features/protection-claims/actions.js +228 -0
- package/dist/_internal/server/features/protection-claims/index.d.ts +8 -0
- package/dist/_internal/server/features/protection-claims/index.js +8 -0
- package/dist/_internal/server/features/refunds/actions.d.ts +20 -0
- package/dist/_internal/server/features/refunds/actions.js +259 -17
- package/dist/_internal/server/features/refunds/capacity.d.ts +29 -0
- package/dist/_internal/server/features/refunds/capacity.js +37 -0
- package/dist/_internal/server/features/reviews/actions.js +3 -2
- package/dist/_internal/server/features/search/index-build/sources.js +20 -1
- package/dist/_internal/server/features/shipping/reconcile.d.ts +10 -1
- package/dist/_internal/server/features/shipping/reconcile.js +34 -3
- package/dist/_internal/server/features/shipping/reimbursement.d.ts +117 -0
- package/dist/_internal/server/features/shipping/reimbursement.js +223 -0
- package/dist/_internal/server/features/stores/tabs.d.ts +19 -4
- package/dist/_internal/server/features/stores/tabs.js +24 -4
- package/dist/_internal/server/functions/https.d.ts +31 -1
- package/dist/_internal/server/functions/https.js +52 -1
- package/dist/_internal/server/functions/scheduled.d.ts +72 -1
- package/dist/_internal/server/functions/scheduled.js +124 -1
- package/dist/_internal/server/jobs/core/autoPayoutEligibility.js +62 -16
- package/dist/_internal/server/jobs/core/boxRollupReconcile.d.ts +46 -0
- package/dist/_internal/server/jobs/core/boxRollupReconcile.js +142 -0
- package/dist/_internal/server/jobs/core/dailyDataCleanup.js +149 -1
- package/dist/_internal/server/jobs/core/dailyStatusDigest.d.ts +14 -0
- package/dist/_internal/server/jobs/core/dailyStatusDigest.js +79 -1
- package/dist/_internal/server/jobs/core/index.d.ts +2 -0
- package/dist/_internal/server/jobs/core/index.js +2 -0
- package/dist/_internal/server/jobs/core/marketPriceRollup.d.ts +64 -0
- package/dist/_internal/server/jobs/core/marketPriceRollup.js +153 -0
- package/dist/_internal/server/jobs/core/obligationSweep.d.ts +36 -0
- package/dist/_internal/server/jobs/core/obligationSweep.js +503 -0
- package/dist/_internal/server/jobs/core/paymentReconcile.d.ts +79 -0
- package/dist/_internal/server/jobs/core/paymentReconcile.js +614 -0
- package/dist/_internal/server/jobs/core/paymentWindowTimeout.js +34 -0
- package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.js +35 -4
- package/dist/_internal/server/jobs/handlers/boxRollupReconcile.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/boxRollupReconcile.js +15 -0
- package/dist/_internal/server/jobs/handlers/countersReconcileNow.d.ts +65 -0
- package/dist/_internal/server/jobs/handlers/countersReconcileNow.js +89 -0
- package/dist/_internal/server/jobs/handlers/index.d.ts +5 -0
- package/dist/_internal/server/jobs/handlers/index.js +5 -0
- package/dist/_internal/server/jobs/handlers/marketPriceRollup.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/marketPriceRollup.js +2 -0
- package/dist/_internal/server/jobs/handlers/obligationSweep.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/obligationSweep.js +15 -0
- package/dist/_internal/server/jobs/handlers/onShipmentAllocationSync.js +30 -1
- package/dist/_internal/server/jobs/handlers/paymentReconcile.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/paymentReconcile.js +6 -0
- package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
- package/dist/_internal/shared/actions/action-registry.js +71 -0
- package/dist/_internal/shared/checkout/coupon-discount.d.ts +73 -0
- package/dist/_internal/shared/checkout/coupon-discount.js +103 -0
- package/dist/_internal/shared/checkout/lanes.d.ts +42 -0
- package/dist/_internal/shared/checkout/lanes.js +46 -0
- package/dist/_internal/shared/checkout/order-math.d.ts +149 -1
- package/dist/_internal/shared/checkout/order-math.js +251 -3
- package/dist/_internal/shared/checkout/refundable-base.d.ts +116 -0
- package/dist/_internal/shared/checkout/refundable-base.js +122 -0
- package/dist/_internal/shared/features/auctions/config.d.ts +14 -1
- package/dist/_internal/shared/features/auctions/config.js +30 -1
- package/dist/_internal/shared/features/brands/schema.d.ts +42 -0
- package/dist/_internal/shared/features/brands/schema.js +18 -0
- package/dist/_internal/shared/features/orders/refund-copy.d.ts +22 -0
- package/dist/_internal/shared/features/orders/refund-copy.js +34 -0
- package/dist/_internal/shared/features/print/label-profiles.d.ts +198 -0
- package/dist/_internal/shared/features/print/label-profiles.js +350 -0
- package/dist/_internal/shared/features/products/to-product-item.js +33 -5
- package/dist/_internal/shared/fees/calculator.d.ts +31 -2
- package/dist/_internal/shared/fees/calculator.js +103 -5
- package/dist/_internal/shared/fees/india-states.d.ts +195 -0
- package/dist/_internal/shared/fees/india-states.js +190 -0
- package/dist/_internal/shared/fees/payout-hold.d.ts +80 -0
- package/dist/_internal/shared/fees/payout-hold.js +74 -0
- package/dist/_internal/shared/obligations/deadlines.d.ts +94 -0
- package/dist/_internal/shared/obligations/deadlines.js +155 -0
- package/dist/_internal/shared/shipping/quote.d.ts +96 -0
- package/dist/_internal/shared/shipping/quote.js +67 -0
- package/dist/_internal/shared/time/business-days.d.ts +91 -0
- package/dist/_internal/shared/time/business-days.js +185 -0
- package/dist/cli/index.js +0 -2
- package/dist/client.d.ts +10 -4
- package/dist/client.js +29 -3
- package/dist/configs/tailwind.d.ts +0 -12
- package/dist/configs/tailwind.js +28 -15
- package/dist/constants/api-endpoints.d.ts +51 -9
- package/dist/constants/api-endpoints.js +23 -7
- package/dist/constants/index.d.ts +1 -1
- package/dist/constants/index.js +1 -1
- package/dist/contracts/index.d.ts +1 -1
- package/dist/contracts/payment.d.ts +131 -0
- package/dist/features/about/components/AboutView.js +1 -1
- package/dist/features/about/components/DeveloperView.js +5 -2
- package/dist/features/about/components/FAQPageView.js +2 -1
- package/dist/features/about/components/FeesView.js +2 -1
- package/dist/features/about/components/HelpPageView.js +2 -1
- package/dist/features/about/components/HowAuctionsWorkView.js +2 -1
- package/dist/features/about/components/HowCheckoutWorksView.js +2 -1
- package/dist/features/about/components/HowEmiWorksView.js +2 -1
- package/dist/features/about/components/HowOffersWorkView.js +2 -1
- package/dist/features/about/components/HowOrdersWorkView.js +2 -1
- package/dist/features/about/components/HowPayoutsWorkView.js +2 -1
- package/dist/features/about/components/HowPreOrdersWorkView.js +2 -1
- package/dist/features/about/components/HowReviewsWorkView.js +2 -1
- package/dist/features/about/components/PolicyPageView.js +2 -1
- package/dist/features/about/components/ProseHero.d.ts +73 -0
- package/dist/features/about/components/ProseHero.js +18 -0
- package/dist/features/about/components/SecurityPrivacyView.js +2 -1
- package/dist/features/about/components/ShippingPolicyView.js +2 -1
- package/dist/features/about/components/TrackOrderView.js +2 -1
- package/dist/features/about/components/UnauthorizedView.js +1 -1
- package/dist/features/about/index.d.ts +2 -0
- package/dist/features/about/index.js +5 -0
- package/dist/features/account/actions/address-actions.d.ts +26 -2
- package/dist/features/account/actions/address-actions.js +25 -1
- package/dist/features/account/components/BuyerShoppingGuideView.js +1 -1
- package/dist/features/account/components/NotificationPreferencesPanel.js +1 -1
- package/dist/features/account/components/UserOrdersView.js +17 -0
- package/dist/features/account/components/UserSidebar.js +1 -1
- package/dist/features/account/hooks/useNotifications.js +29 -0
- package/dist/features/admin/actions/admin-coupon-actions.js +36 -0
- package/dist/features/admin/components/AdminBeysView.js +2 -2
- package/dist/features/admin/components/AdminBlogEditorView.js +2 -2
- package/dist/features/admin/components/AdminBrandEditorView.js +32 -2
- package/dist/features/admin/components/AdminBundleEditorView.js +1 -1
- package/dist/features/admin/components/AdminCarouselEditorView.js +1 -1
- package/dist/features/admin/components/AdminCategoriesView.js +1 -1
- package/dist/features/admin/components/AdminCategoryEditorView.js +73 -17
- package/dist/features/admin/components/AdminContactEditorView.js +1 -1
- package/dist/features/admin/components/AdminCouponEditorView.js +26 -1
- package/dist/features/admin/components/AdminFaqEditorView.js +1 -1
- package/dist/features/admin/components/AdminFaqsView.js +2 -2
- package/dist/features/admin/components/AdminGatewayEventsView.d.ts +54 -0
- package/dist/features/admin/components/AdminGatewayEventsView.js +209 -0
- package/dist/features/admin/components/AdminGuideHubView.js +1 -1
- package/dist/features/admin/components/AdminMoneyCasesView.d.ts +60 -0
- package/dist/features/admin/components/AdminMoneyCasesView.js +287 -0
- package/dist/features/admin/components/AdminPartsView.js +2 -2
- package/dist/features/admin/components/AdminProductsView.js +75 -4
- package/dist/features/admin/components/AdminSidebar.js +2 -2
- package/dist/features/admin/components/AdminSiteSettingsView.js +65 -7
- package/dist/features/admin/components/AdminSublistingCategoriesView.js +2 -0
- package/dist/features/admin/components/AdminSupportTicketDetailView.js +1 -1
- package/dist/features/admin/components/AdminSupportTicketsView.js +2 -2
- package/dist/features/admin/components/AdminTesterChecklistView.js +2 -2
- package/dist/features/admin/components/AdminUsersView.js +72 -1
- package/dist/features/admin/components/AdminViewCards.d.ts +3 -1
- package/dist/features/admin/components/AdminViewCards.js +4 -4
- package/dist/features/admin/components/DataListingView.d.ts +28 -0
- package/dist/features/admin/components/DataListingView.js +175 -14
- package/dist/features/admin/components/DataTable.d.ts +12 -1
- package/dist/features/admin/components/DataTable.js +3 -3
- package/dist/features/admin/components/OwnerQuickActions.d.ts +1 -1
- package/dist/features/admin/components/OwnerQuickActions.js +60 -2
- package/dist/features/admin/components/RecordOwnerQuickActions.d.ts +1 -1
- package/dist/features/admin/components/RecordOwnerQuickActions.js +61 -14
- package/dist/features/admin/components/analytics/AdminStatCard.d.ts +35 -1
- package/dist/features/admin/components/analytics/AdminStatCard.js +77 -2
- package/dist/features/admin/components/index.d.ts +4 -0
- package/dist/features/admin/components/index.js +6 -0
- package/dist/features/admin/constants/filter-tabs.d.ts +156 -0
- package/dist/features/admin/constants/filter-tabs.js +106 -0
- package/dist/features/admin/repository/site-settings.repository.d.ts +22 -0
- package/dist/features/admin/repository/site-settings.repository.js +82 -1
- package/dist/features/admin/schemas/admin-editor-forms.d.ts +21 -0
- package/dist/features/admin/schemas/admin-editor-forms.js +44 -0
- package/dist/features/admin/schemas/firestore.js +5 -1
- package/dist/features/admin/schemas/site-settings-form.js +30 -1
- package/dist/features/auctions/actions/bid-actions.js +13 -1
- package/dist/features/auctions/components/AuctionBottomActions.js +2 -2
- package/dist/features/auctions/components/AuctionDetailPageView.js +3 -1
- package/dist/features/auctions/components/MarketplaceAuctionCard.d.ts +11 -0
- package/dist/features/auctions/components/MarketplaceAuctionCard.js +5 -3
- package/dist/features/auctions/components/PlaceBidFormClient.d.ts +8 -1
- package/dist/features/auctions/components/PlaceBidFormClient.js +2 -2
- package/dist/features/audit-log/schemas/firestore.d.ts +28 -0
- package/dist/features/audit-log/schemas/firestore.js +14 -0
- package/dist/features/auth/permissions/constants.d.ts +17 -1
- package/dist/features/auth/permissions/constants.js +18 -0
- package/dist/features/blog/components/BlogPostView.js +1 -1
- package/dist/features/catalogue/components/AdminCatalogueApprovalsView.js +1 -1
- package/dist/features/categories/api/[id]/description-template/route.js +107 -1
- package/dist/features/categories/components/BrandDetailPageView.js +2 -2
- package/dist/features/categories/components/BreadcrumbTrail.js +7 -1
- package/dist/features/categories/components/BundleDetailView.js +1 -1
- package/dist/features/categories/components/CategoryDetailPageView.js +2 -2
- package/dist/features/categories/components/CategoryForm.js +12 -1
- package/dist/features/categories/components/CategoryTemplatePicker.js +38 -5
- package/dist/features/categories/repository/market-price-index.repository.d.ts +123 -0
- package/dist/features/categories/repository/market-price-index.repository.js +105 -0
- package/dist/features/categories/repository/price-observation.repository.d.ts +166 -0
- package/dist/features/categories/repository/price-observation.repository.js +132 -0
- package/dist/features/events/components/EventSaleBanner.js +1 -1
- package/dist/features/events/components/EventStatusBadge.js +1 -1
- package/dist/features/faq/components/FAQAccordion.js +2 -1
- package/dist/features/faq/components/FAQCategorySidebar.js +2 -2
- package/dist/features/faq/components/FAQHelpfulButtons.js +4 -4
- package/dist/features/faq/components/RelatedFAQs.js +1 -1
- package/dist/features/filters/FilterFacetSection.js +1 -1
- package/dist/features/filters/SwitchFilter.js +1 -1
- package/dist/features/gateway-events/repository/gateway-events.repository.d.ts +117 -0
- package/dist/features/gateway-events/repository/gateway-events.repository.js +274 -0
- package/dist/features/gateway-events/schemas/firestore.d.ts +217 -0
- package/dist/features/gateway-events/schemas/firestore.js +125 -0
- package/dist/features/gateway-events/schemas/index.d.ts +81 -0
- package/dist/features/gateway-events/schemas/index.js +79 -0
- package/dist/features/grouped/components/GroupedListingDetailView.js +1 -1
- package/dist/features/homepage/components/AnnouncementBar.js +37 -1
- package/dist/features/homepage/components/AnnouncementBar.style.css +30 -0
- package/dist/features/homepage/components/BrandsSection.js +1 -1
- package/dist/features/homepage/components/CTABannerSection.js +1 -1
- package/dist/features/homepage/components/FeaturedBundlesSection.js +14 -24
- package/dist/features/homepage/components/HeroCarousel.js +2 -2
- package/dist/features/homepage/components/SocialPostCard.js +1 -1
- package/dist/features/inventory/components/AdminMoveLedgerView.d.ts +7 -0
- package/dist/features/inventory/components/AdminMoveLedgerView.js +157 -0
- package/dist/features/inventory/components/AdminStorageBoxesView.d.ts +11 -0
- package/dist/features/inventory/components/AdminStorageBoxesView.js +168 -0
- package/dist/features/inventory/components/ReceiveStationView.d.ts +39 -0
- package/dist/features/inventory/components/ReceiveStationView.js +413 -0
- package/dist/features/inventory/components/operator-message.d.ts +29 -0
- package/dist/features/inventory/components/operator-message.js +41 -0
- package/dist/features/inventory/index.d.ts +13 -0
- package/dist/features/inventory/index.js +28 -0
- package/dist/features/inventory/repository/inventory-movements.repository.d.ts +97 -0
- package/dist/features/inventory/repository/inventory-movements.repository.js +186 -0
- package/dist/features/inventory/repository/inventory-placements.repository.d.ts +179 -0
- package/dist/features/inventory/repository/inventory-placements.repository.js +345 -0
- package/dist/features/inventory/repository/storage-boxes.repository.d.ts +83 -0
- package/dist/features/inventory/repository/storage-boxes.repository.js +127 -0
- package/dist/features/inventory/schemas/firestore.d.ts +197 -0
- package/dist/features/inventory/schemas/firestore.js +159 -0
- package/dist/features/layout/AppLayoutShell.d.ts +12 -1
- package/dist/features/layout/AppLayoutShell.js +25 -12
- package/dist/features/layout/AutoBreadcrumbs.js +162 -3
- package/dist/features/layout/AutoBreadcrumbs.style.css +45 -0
- package/dist/features/layout/BottomNavbar.d.ts +1 -1
- package/dist/features/layout/BottomNavbar.js +2 -2
- package/dist/features/media/MediaAvatar.js +1 -1
- package/dist/features/media/MediaImage.d.ts +24 -4
- package/dist/features/media/MediaImage.js +44 -4
- package/dist/features/media/MediaLightbox.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/upload/MediaUploadField.js +91 -3
- package/dist/features/obligations/constants/policies.d.ts +92 -0
- package/dist/features/obligations/constants/policies.js +378 -0
- package/dist/features/obligations/repository/obligations.repository.d.ts +68 -0
- package/dist/features/obligations/repository/obligations.repository.js +158 -0
- package/dist/features/obligations/schemas/firestore.d.ts +160 -0
- package/dist/features/obligations/schemas/firestore.js +87 -0
- package/dist/features/orders/actions/order-actions.d.ts +43 -4
- package/dist/features/orders/actions/order-actions.js +60 -3
- package/dist/features/orders/actions/refund-actions.js +70 -10
- package/dist/features/orders/components/OrderCompletionPanel.d.ts +27 -0
- package/dist/features/orders/components/OrderCompletionPanel.js +192 -0
- package/dist/features/orders/components/OrdersList.js +2 -2
- package/dist/features/orders/components/RefundHistoryTable.js +3 -1
- package/dist/features/orders/components/index.d.ts +2 -0
- package/dist/features/orders/components/index.js +6 -0
- package/dist/features/orders/constants/transitions.d.ts +59 -0
- package/dist/features/orders/constants/transitions.js +104 -0
- package/dist/features/orders/repository/orders.repository.d.ts +109 -6
- package/dist/features/orders/repository/orders.repository.js +464 -21
- package/dist/features/orders/schemas/firestore.d.ts +270 -0
- package/dist/features/orders/schemas/firestore.js +24 -0
- package/dist/features/orders/schemas/index.d.ts +61 -0
- package/dist/features/orders/schemas/index.js +22 -0
- package/dist/features/orders/types/index.d.ts +79 -0
- package/dist/features/parts/components/PartsIndexPageView.js +8 -1
- package/dist/features/payment-cases/repository/payment-cases.repository.d.ts +170 -0
- package/dist/features/payment-cases/repository/payment-cases.repository.js +342 -0
- package/dist/features/payment-cases/schemas/firestore.d.ts +229 -0
- package/dist/features/payment-cases/schemas/firestore.js +105 -0
- package/dist/features/payment-cases/schemas/resolve-form.d.ts +97 -0
- package/dist/features/payment-cases/schemas/resolve-form.js +114 -0
- package/dist/features/payments/repository/payout.repository.d.ts +0 -1
- package/dist/features/payments/repository/payout.repository.js +0 -1
- package/dist/features/points/repository/points.repository.d.ts +122 -0
- package/dist/features/points/repository/points.repository.js +304 -1
- package/dist/features/points/schemas/adjust-form.d.ts +58 -0
- package/dist/features/points/schemas/adjust-form.js +63 -0
- package/dist/features/points/schemas/firestore.d.ts +108 -1
- package/dist/features/points/schemas/firestore.js +84 -0
- package/dist/features/pre-orders/components/MarketplacePreorderCard.js +3 -3
- package/dist/features/pre-orders/components/PreOrderBadge.js +1 -1
- package/dist/features/pre-orders/components/PreOrderDetailPageView.js +1 -1
- package/dist/features/price-index/components/PriceIndexToolView.d.ts +23 -4
- package/dist/features/price-index/components/PriceIndexToolView.js +71 -6
- package/dist/features/price-index/market-stats.d.ts +82 -0
- package/dist/features/price-index/market-stats.js +230 -0
- package/dist/features/print/components/BoxLabelPrintView.d.ts +25 -0
- package/dist/features/print/components/BoxLabelPrintView.js +66 -0
- package/dist/features/print/components/LabelProfilePicker.d.ts +13 -0
- package/dist/features/print/components/LabelProfilePicker.js +38 -0
- package/dist/features/print/components/labels.d.ts +117 -0
- package/dist/features/print/components/labels.js +258 -0
- package/dist/features/print/components/labels.style.css +46 -0
- package/dist/features/print/index.d.ts +6 -0
- package/dist/features/print/index.js +16 -0
- package/dist/features/products/columns/productTableColumns.js +5 -4
- package/dist/features/products/components/MarketplaceBundleCard.js +2 -2
- package/dist/features/products/components/MarketplacePrizeDrawCard.js +6 -6
- package/dist/features/products/components/PrizeDrawCollage.js +1 -1
- package/dist/features/products/components/PrizeDrawItemsEditor.js +1 -1
- package/dist/features/products/components/PrizeRevealModal.js +2 -2
- package/dist/features/products/components/ProductDetailPageView.js +18 -4
- package/dist/features/products/components/ProductForm.js +34 -23
- package/dist/features/products/components/ProductGrid.js +86 -62
- package/dist/features/products/constants/card-badges.d.ts +97 -0
- package/dist/features/products/constants/card-badges.js +100 -0
- package/dist/features/products/repository/products.repository.js +34 -1
- package/dist/features/products/schemas/firestore.d.ts +46 -3
- package/dist/features/products/schemas/firestore.js +21 -0
- package/dist/features/promotions/components/PromotionsView.js +1 -1
- package/dist/features/promotions/repository/claimed-coupons.repository.d.ts +32 -0
- package/dist/features/promotions/repository/claimed-coupons.repository.js +58 -0
- package/dist/features/promotions/schemas/firestore.js +30 -3
- package/dist/features/promotions/schemas/index.d.ts +6 -6
- package/dist/features/protection-claims/repository/protection-claims.repository.d.ts +54 -0
- package/dist/features/protection-claims/repository/protection-claims.repository.js +174 -0
- package/dist/features/protection-claims/schemas/firestore.d.ts +168 -0
- package/dist/features/protection-claims/schemas/firestore.js +130 -0
- package/dist/features/reviews/actions/review-actions.js +3 -2
- package/dist/features/reviews/components/ReviewModal.js +1 -1
- package/dist/features/reviews/components/ReviewsList.js +1 -1
- package/dist/features/reviews/schemas/firestore.d.ts +20 -1
- package/dist/features/scams/constants/scam-types.d.ts +2 -0
- package/dist/features/scams/constants/scam-types.js +18 -0
- package/dist/features/scams/schemas/report-form.d.ts +3 -3
- package/dist/features/scams/schemas/report-form.js +26 -1
- package/dist/features/search/components/Search.js +9 -9
- package/dist/features/search/components/SearchResultsClient.js +18 -3
- package/dist/features/search/components/SearchResultsPageView.d.ts +1 -6
- package/dist/features/search/components/SearchResultsPageView.js +2 -2
- package/dist/features/seller/actions/offer-actions.js +16 -1
- package/dist/features/seller/actions/seller-actions.js +14 -3
- package/dist/features/seller/components/CategoryInlineSelect.js +75 -11
- package/dist/features/seller/components/PrintCenterView.d.ts +5 -0
- package/dist/features/seller/components/PrintCenterView.js +41 -30
- package/dist/features/seller/components/SellerOrdersView.js +1 -1
- package/dist/features/seller/components/SellerPayoutRequestView.js +16 -5
- package/dist/features/seller/components/SellerPayoutSettingsView.js +1 -1
- package/dist/features/seller/components/SellerProductShell.d.ts +16 -0
- package/dist/features/seller/components/SellerProductShell.js +123 -13
- package/dist/features/seller/components/SellerReviewsView.js +4 -2
- package/dist/features/seller/components/SellerSidebar.js +1 -1
- package/dist/features/seller/schemas/coupon-form.d.ts +26 -0
- package/dist/features/seller/schemas/coupon-form.js +27 -0
- package/dist/features/seller/schemas/product-form.d.ts +3 -0
- package/dist/features/seller/schemas/product-form.js +5 -0
- package/dist/features/shell/FormShell.js +2 -2
- package/dist/features/shell/QuickFormDrawer.js +14 -0
- package/dist/features/shell/SectionForm.d.ts +19 -0
- package/dist/features/shell/SectionForm.js +133 -9
- package/dist/features/shell/SectionForm.style.css +54 -0
- package/dist/features/shipments/components/AdminShipmentsView.js +16 -1
- package/dist/features/shipments/repository/shipment-items.repository.d.ts +9 -0
- package/dist/features/shipments/repository/shipment-items.repository.js +14 -0
- package/dist/features/site-settings/components/ActionPermissionsManager.js +1 -1
- package/dist/features/sticker-trace/components/StickerCommitPanel.js +1 -1
- package/dist/features/store-extensions/schemas/report-review-form.d.ts +8 -8
- package/dist/features/stores/components/StoreGuideHubView.js +1 -1
- package/dist/features/stores/components/StoreHeader.js +1 -1
- package/dist/features/support/schemas/firestore.d.ts +73 -2
- package/dist/features/support/schemas/firestore.js +59 -0
- package/dist/index.d.ts +16 -24
- package/dist/index.js +38 -47
- package/dist/next/ErrorBoundary.js +1 -1
- package/dist/next/routing/route-map.d.ts +24 -0
- package/dist/next/routing/route-map.js +40 -0
- package/dist/providers/payment-manual/index.d.ts +15 -1
- package/dist/providers/payment-manual/index.js +37 -0
- package/dist/providers/payment-phonepe/index.d.ts +14 -1
- package/dist/providers/payment-phonepe/index.js +36 -0
- package/dist/providers/payment-razorpay/index.d.ts +44 -1
- package/dist/providers/payment-razorpay/index.js +99 -0
- package/dist/providers/shipping-shiprocket/index.d.ts +18 -0
- package/dist/providers/shipping-shiprocket/index.js +18 -0
- package/dist/schemas/registry.d.ts +44 -11
- package/dist/server-entry.d.ts +2 -0
- package/dist/server-entry.js +27 -0
- package/dist/server.d.ts +43 -0
- package/dist/server.js +98 -0
- package/dist/styles.css +418 -149
- package/dist/tailwind-utilities.css +1 -1
- package/dist/tokens/themes/default-dark.js +15 -12
- package/dist/tokens/themes/default-light.js +14 -11
- package/dist/tokens/tokens.css +106 -23
- package/dist/ui/DataTable.style.css +4 -4
- package/dist/ui/columns/cell-renderers.d.ts +20 -0
- package/dist/ui/columns/cell-renderers.js +26 -1
- package/dist/ui/columns/index.d.ts +1 -1
- package/dist/ui/columns/index.js +4 -1
- package/dist/ui/components/Badge.style.css +1 -1
- package/dist/ui/components/Breadcrumb.js +19 -1
- package/dist/ui/components/BulkActionBar.style.css +4 -4
- package/dist/ui/components/Button.style.css +1 -1
- package/dist/ui/components/Checkbox.style.css +1 -1
- package/dist/ui/components/FallbackShell.js +1 -1
- package/dist/ui/components/Form.d.ts +14 -1
- package/dist/ui/components/Form.js +2 -2
- package/dist/ui/components/FormField.js +18 -4
- package/dist/ui/components/FormField.style.css +43 -3
- package/dist/ui/components/GatedPrice.style.css +1 -1
- package/dist/ui/components/IconButton.style.css +1 -1
- package/dist/ui/components/Input.js +22 -1
- package/dist/ui/components/Input.style.css +38 -22
- package/dist/ui/components/ListingFilterDrawer.js +1 -1
- package/dist/ui/components/ListingToolbar.js +1 -1
- package/dist/ui/components/PaginatedSelect.js +0 -0
- package/dist/ui/components/Radio.style.css +1 -1
- package/dist/ui/components/Repeater.d.ts +53 -0
- package/dist/ui/components/Repeater.js +7 -0
- package/dist/ui/components/RichTextEditor.d.ts +20 -1
- package/dist/ui/components/RichTextEditor.js +23 -2
- package/dist/ui/components/Select.style.css +7 -21
- package/dist/ui/components/Semantic.js +27 -3
- package/dist/ui/components/TagInput.style.css +4 -9
- package/dist/ui/components/Textarea.style.css +4 -18
- package/dist/ui/components/Toggle.style.css +1 -1
- package/dist/ui/components/Typography.d.ts +3 -3
- package/dist/ui/components/Typography.js +15 -15
- package/dist/ui/components/ViewToggle.style.css +4 -4
- package/dist/ui/forms/AddAnotherToggle.d.ts +16 -0
- package/dist/ui/forms/AddAnotherToggle.js +56 -0
- package/dist/ui/forms/ColorPickerField.js +15 -2
- package/dist/ui/forms/FieldCheckbox.js +15 -2
- package/dist/ui/forms/FieldInput.d.ts +22 -1
- package/dist/ui/forms/FieldInput.js +19 -5
- package/dist/ui/forms/FieldLabel.d.ts +35 -0
- package/dist/ui/forms/FieldLabel.js +70 -0
- package/dist/ui/forms/FieldSelect.d.ts +4 -1
- package/dist/ui/forms/FieldSelect.js +27 -5
- package/dist/ui/forms/FieldTextarea.d.ts +4 -1
- package/dist/ui/forms/FieldTextarea.js +22 -5
- package/dist/ui/forms/FormShell.d.ts +17 -1
- package/dist/ui/forms/FormShell.js +36 -2
- package/dist/ui/forms/FormShell.style.css +41 -33
- package/dist/ui/forms/index.d.ts +5 -1
- package/dist/ui/forms/index.js +2 -0
- package/dist/ui/icons/icon-registry.d.ts +1 -0
- package/dist/ui/icons/icon-registry.js +17 -1
- package/dist/utils/id-generators.d.ts +80 -0
- package/dist/utils/id-generators.js +93 -0
- package/dist/utils/search-txt-builders.d.ts +12 -0
- package/dist/utils/search-txt-builders.js +17 -0
- package/package.json +1 -1
- package/scripts/seed-cli.mjs +106 -5
- package/dist/features/loyalty/api/admin/loyalty/grant/route.d.ts +0 -12
- package/dist/features/loyalty/api/admin/loyalty/grant/route.js +0 -38
- package/dist/features/loyalty/api/balance/route.d.ts +0 -12
- package/dist/features/loyalty/api/balance/route.js +0 -41
- package/dist/features/loyalty/api/earn/route.d.ts +0 -12
- package/dist/features/loyalty/api/earn/route.js +0 -38
- package/dist/features/loyalty/api/history/route.d.ts +0 -12
- package/dist/features/loyalty/api/history/route.js +0 -58
- package/dist/features/loyalty/api/redeem/route.d.ts +0 -12
- package/dist/features/loyalty/api/redeem/route.js +0 -38
- package/dist/features/loyalty/columns/index.d.ts +0 -17
- package/dist/features/loyalty/columns/index.js +0 -40
- package/dist/features/loyalty/components/CoinsDisplay.d.ts +0 -12
- package/dist/features/loyalty/components/CoinsDisplay.js +0 -10
- package/dist/features/loyalty/components/index.d.ts +0 -1
- package/dist/features/loyalty/components/index.js +0 -1
- package/dist/features/loyalty/hooks/useLoyaltyBalance.d.ts +0 -4
- package/dist/features/loyalty/hooks/useLoyaltyBalance.js +0 -25
- package/dist/features/loyalty/index.d.ts +0 -6
- package/dist/features/loyalty/index.js +0 -6
- package/dist/features/loyalty/manifest.d.ts +0 -2
- package/dist/features/loyalty/manifest.js +0 -16
- package/dist/features/loyalty/messages/en.json +0 -19
- package/dist/features/loyalty/repository/loyalty.repository.d.ts +0 -8
- package/dist/features/loyalty/repository/loyalty.repository.js +0 -22
- package/dist/features/loyalty/schemas/index.d.ts +0 -85
- package/dist/features/loyalty/schemas/index.js +0 -40
- package/dist/features/loyalty/server.d.ts +0 -6
- package/dist/features/loyalty/server.js +0 -6
- package/dist/features/loyalty/types/index.d.ts +0 -31
- package/dist/features/loyalty/types/index.js +0 -1
- package/dist/features/loyalty/types/loyalty-config.d.ts +0 -7
- package/dist/features/loyalty/types/loyalty-config.js +0 -1
- package/dist/features/loyalty/types/loyalty-math.d.ts +0 -9
- package/dist/features/loyalty/types/loyalty-math.js +0 -27
- package/dist/features/products/components/ProductOwnerQuickActions.d.ts +0 -11
- package/dist/features/products/components/ProductOwnerQuickActions.js +0 -120
|
@@ -98,6 +98,48 @@ export declare function isLaneCheckoutable(items: readonly LaneAssignable[], lan
|
|
|
98
98
|
* selection" means "the lane on screen" and can mean nothing else.
|
|
99
99
|
*/
|
|
100
100
|
export declare function defaultCheckoutItems<T extends LaneAssignable>(items: readonly T[]): T[];
|
|
101
|
+
/**
|
|
102
|
+
* THE item set a checkout charges for and settles. One definition, both paths.
|
|
103
|
+
*
|
|
104
|
+
* ## 🛑 D40: the captured item set was not the settled item set, in TWO ways
|
|
105
|
+
*
|
|
106
|
+
* Measured, because the plan recorded only the first half:
|
|
107
|
+
*
|
|
108
|
+
* | | capture (`/api/payment/create-order`) | settle (gateway path) |
|
|
109
|
+
* |---|---|---|
|
|
110
|
+
* | with a selection | the selected items, **any lane** | **the active lane**, selection IGNORED |
|
|
111
|
+
* | with no selection | **the whole cart, every lane** | the active lane only |
|
|
112
|
+
*
|
|
113
|
+
* The first row is the one the plan describes: deselect half the cart, pay for
|
|
114
|
+
* half, receive orders for the whole lane — the buyer gets goods they did not
|
|
115
|
+
* pay for and the seller's stock leaves without payment.
|
|
116
|
+
*
|
|
117
|
+
* 🛑 **The second row is worse and was not recorded anywhere: the buyer is
|
|
118
|
+
* OVERCHARGED.** With no explicit selection the capture route billed
|
|
119
|
+
* `cart.items` — every lane — while settle created orders for the active lane
|
|
120
|
+
* only. And multi-lane carts are not an edge case: `defaultCheckoutItems`' own
|
|
121
|
+
* docstring above says they "are what the lane model produces", because
|
|
122
|
+
* `auctionSettlement` pushes a won auction into whatever is already in the
|
|
123
|
+
* cart. So a buyer with a won auction and ordinary items in the cart was
|
|
124
|
+
* charged for both and received orders for one.
|
|
125
|
+
*
|
|
126
|
+
* ## The rule
|
|
127
|
+
*
|
|
128
|
+
* **Active lane first, then the selection as a filter within it.** Not the
|
|
129
|
+
* other way round, and not selection-instead-of-lane:
|
|
130
|
+
*
|
|
131
|
+
* - The lane invariant is non-negotiable — `assertCheckoutLane` refuses any
|
|
132
|
+
* settle whose items are not the active lane, so a selection spanning lanes
|
|
133
|
+
* could be charged and then never settled. That is the D64 class (money
|
|
134
|
+
* taken, no order).
|
|
135
|
+
* - An empty intersection is a REFUSAL, not a silent widening. A selection
|
|
136
|
+
* naming only off-lane items means the buyer is looking at something the
|
|
137
|
+
* server will not sell them, and falling back to the whole lane would charge
|
|
138
|
+
* them for items they deliberately unticked.
|
|
139
|
+
*/
|
|
140
|
+
export declare function resolveCheckoutItems<T extends LaneAssignable & {
|
|
141
|
+
itemId: string;
|
|
142
|
+
}>(items: readonly T[], selectedItemIds?: readonly string[] | null): T[];
|
|
101
143
|
/**
|
|
102
144
|
* Why `lane` can't be checked out right now — null when it can.
|
|
103
145
|
* Phrased for the buyer, naming the lane that's blocking and what to do.
|
|
@@ -156,6 +156,52 @@ export function defaultCheckoutItems(items) {
|
|
|
156
156
|
const active = activeLane(items);
|
|
157
157
|
return active ? laneItems(items, active) : [...items];
|
|
158
158
|
}
|
|
159
|
+
/**
|
|
160
|
+
* THE item set a checkout charges for and settles. One definition, both paths.
|
|
161
|
+
*
|
|
162
|
+
* ## 🛑 D40: the captured item set was not the settled item set, in TWO ways
|
|
163
|
+
*
|
|
164
|
+
* Measured, because the plan recorded only the first half:
|
|
165
|
+
*
|
|
166
|
+
* | | capture (`/api/payment/create-order`) | settle (gateway path) |
|
|
167
|
+
* |---|---|---|
|
|
168
|
+
* | with a selection | the selected items, **any lane** | **the active lane**, selection IGNORED |
|
|
169
|
+
* | with no selection | **the whole cart, every lane** | the active lane only |
|
|
170
|
+
*
|
|
171
|
+
* The first row is the one the plan describes: deselect half the cart, pay for
|
|
172
|
+
* half, receive orders for the whole lane — the buyer gets goods they did not
|
|
173
|
+
* pay for and the seller's stock leaves without payment.
|
|
174
|
+
*
|
|
175
|
+
* 🛑 **The second row is worse and was not recorded anywhere: the buyer is
|
|
176
|
+
* OVERCHARGED.** With no explicit selection the capture route billed
|
|
177
|
+
* `cart.items` — every lane — while settle created orders for the active lane
|
|
178
|
+
* only. And multi-lane carts are not an edge case: `defaultCheckoutItems`' own
|
|
179
|
+
* docstring above says they "are what the lane model produces", because
|
|
180
|
+
* `auctionSettlement` pushes a won auction into whatever is already in the
|
|
181
|
+
* cart. So a buyer with a won auction and ordinary items in the cart was
|
|
182
|
+
* charged for both and received orders for one.
|
|
183
|
+
*
|
|
184
|
+
* ## The rule
|
|
185
|
+
*
|
|
186
|
+
* **Active lane first, then the selection as a filter within it.** Not the
|
|
187
|
+
* other way round, and not selection-instead-of-lane:
|
|
188
|
+
*
|
|
189
|
+
* - The lane invariant is non-negotiable — `assertCheckoutLane` refuses any
|
|
190
|
+
* settle whose items are not the active lane, so a selection spanning lanes
|
|
191
|
+
* could be charged and then never settled. That is the D64 class (money
|
|
192
|
+
* taken, no order).
|
|
193
|
+
* - An empty intersection is a REFUSAL, not a silent widening. A selection
|
|
194
|
+
* naming only off-lane items means the buyer is looking at something the
|
|
195
|
+
* server will not sell them, and falling back to the whole lane would charge
|
|
196
|
+
* them for items they deliberately unticked.
|
|
197
|
+
*/
|
|
198
|
+
export function resolveCheckoutItems(items, selectedItemIds) {
|
|
199
|
+
const inLane = defaultCheckoutItems(items);
|
|
200
|
+
if (!selectedItemIds?.length)
|
|
201
|
+
return inLane;
|
|
202
|
+
const selected = new Set(selectedItemIds);
|
|
203
|
+
return inLane.filter((item) => selected.has(item.itemId));
|
|
204
|
+
}
|
|
159
205
|
/**
|
|
160
206
|
* Why `lane` can't be checked out right now — null when it can.
|
|
161
207
|
* Phrased for the buyer, naming the lane that's blocking and what to do.
|
|
@@ -111,7 +111,64 @@ export declare function lineTaxComponentsFor(item: CartItemDocument, productById
|
|
|
111
111
|
* one and not the other — here that would mean quoting one tax figure and
|
|
112
112
|
* charging another.
|
|
113
113
|
*/
|
|
114
|
-
export declare function sumGroupGst(items: readonly CartItemDocument[], productById: Map<string, ProductDocument | null>, intraState: boolean
|
|
114
|
+
export declare function sumGroupGst(items: readonly CartItemDocument[], productById: Map<string, ProductDocument | null>, intraState: boolean,
|
|
115
|
+
/**
|
|
116
|
+
* G1 — the group's coupon discount, in decimal rupees. **Reduces the taxable
|
|
117
|
+
* value**, prorated across the group's tax slices.
|
|
118
|
+
*
|
|
119
|
+
* 🛑 WHY THIS PARAMETER EXISTS. Without it the tax was backed out of the
|
|
120
|
+
* UNDISCOUNTED gross, so on a ₹1,000 item @18% with a ₹200 coupon the order
|
|
121
|
+
* recorded taxable ₹847.46 + GST ₹152.54 = ₹1,000 while the buyer paid ₹800
|
|
122
|
+
* for the goods. **₹30.51 of tax recorded on money that was never
|
|
123
|
+
* collected** — remitted by us, on every discounted order.
|
|
124
|
+
*
|
|
125
|
+
* A discount shown on the invoice generally reduces the value of supply
|
|
126
|
+
* under s.15(3)(a) CGST Act, so the post-discount base is both the honest
|
|
127
|
+
* figure and the lower liability. 🛑 This changes what we remit and is a CA
|
|
128
|
+
* question, not a code preference; it is implemented because it was decided,
|
|
129
|
+
* and it is flagged in the plan's standing-risk section for review.
|
|
130
|
+
*
|
|
131
|
+
* Optional, defaulting to 0, so the behaviour is unchanged for any caller
|
|
132
|
+
* that does not pass it — a REQUIRED parameter would have been better at
|
|
133
|
+
* forcing every call site to answer, but three of the four callers compute
|
|
134
|
+
* the discount after the tax today and the reorder is riskier than the
|
|
135
|
+
* default. `audit-checkout-total-parity` is what will catch an omission.
|
|
136
|
+
*/
|
|
137
|
+
couponDiscount?: number,
|
|
138
|
+
/**
|
|
139
|
+
* G5 — the group's TAXABLE ancillary charges, in decimal rupees: shipping,
|
|
140
|
+
* COD handling, gift wrap, shipment protection, sale protection.
|
|
141
|
+
*
|
|
142
|
+
* 🛑 These used to enter the order total as BARE ADDENDS carrying no tax at
|
|
143
|
+
* all. Delivery and handling are generally part of a composite supply and
|
|
144
|
+
* taxable at the rate of the principal supply, so a ₹100 shipping line on an
|
|
145
|
+
* 18% order was collected with ~₹15.25 of embedded tax that we declared
|
|
146
|
+
* nowhere.
|
|
147
|
+
*
|
|
148
|
+
* ── THE MECHANISM DIVERGES FROM THE PLAN, DELIBERATELY ──────────────────
|
|
149
|
+
*
|
|
150
|
+
* The plan recorded G5 as "raises buyer totals slightly", i.e. tax ADDED on
|
|
151
|
+
* top of each fee. That is the right reading for a tax-exclusive system and
|
|
152
|
+
* this one is not: `calculateGstInclusive`'s own header states "**Every
|
|
153
|
+
* price in this system is tax-inclusive**", and the product JSON-LD
|
|
154
|
+
* publicly asserts `valueAddedTaxIncluded: true`.
|
|
155
|
+
*
|
|
156
|
+
* So the fees are treated INCLUSIVE, exactly like goods:
|
|
157
|
+
*
|
|
158
|
+
* · the buyer pays the configured ₹100 — **no total changes, no silent
|
|
159
|
+
* re-pricing of every order**
|
|
160
|
+
* · ₹15.25 of it is recognised as GST and remitted
|
|
161
|
+
* · `taxableAmount` and `gstAmount` rise; the amount collected does not
|
|
162
|
+
*
|
|
163
|
+
* Adding tax on top instead would mix two conventions inside one total —
|
|
164
|
+
* which is the shape of the five-disagreeing-totals problem this phase
|
|
165
|
+
* exists to remove — and would make the published JSON-LD false. Flagged
|
|
166
|
+
* rather than silently chosen; it is still part of the CA conversation.
|
|
167
|
+
*
|
|
168
|
+
* Taxed at the PRINCIPAL rate, derived from the group's own goods (see
|
|
169
|
+
* below), because an ancillary charge follows the supply it is ancillary to.
|
|
170
|
+
*/
|
|
171
|
+
taxableFees?: number): GroupGstSummary;
|
|
115
172
|
/** One rate's rollup within an order group — what Rule 46 asks an invoice to show. */
|
|
116
173
|
export interface GstRateSlice {
|
|
117
174
|
gstRate: number;
|
|
@@ -235,6 +292,97 @@ export declare function ordersGoodsValue(orders: readonly PayableOrderLike[]): n
|
|
|
235
292
|
export declare function orderTaxableValue(order: PayableOrderLike): number;
|
|
236
293
|
/** Sum of `orderTaxableValue` across orders — the payout base for a batch. */
|
|
237
294
|
export declare function ordersTaxableValue(orders: readonly PayableOrderLike[]): number;
|
|
295
|
+
/** The subset `orderShippingReimbursement` reads. */
|
|
296
|
+
export interface ReimbursableOrderLike {
|
|
297
|
+
platformBookedShipment?: boolean;
|
|
298
|
+
shippingReimbursement?: {
|
|
299
|
+
approvedAmount?: number;
|
|
300
|
+
};
|
|
301
|
+
shippingReconciliation?: {
|
|
302
|
+
reimbursable?: number;
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Postage the seller is owed back on one order — **D45, and it is NOT revenue.**
|
|
307
|
+
*
|
|
308
|
+
* ## Why this is a separate term from the taxable value
|
|
309
|
+
*
|
|
310
|
+
* `orderTaxableValue` above is deliberately goods-only, and that stays true:
|
|
311
|
+
* shipping is not a sale and must never be grossed into the figure GST is
|
|
312
|
+
* backed out of. A reimbursement is a **cost being refunded**, so it is added
|
|
313
|
+
* AFTER the taxable value rather than folded into it — which also means it
|
|
314
|
+
* carries no commission, because commissioning a seller's postage would be
|
|
315
|
+
* charging them for the privilege of posting a parcel.
|
|
316
|
+
*
|
|
317
|
+
* ## 🛑 It reads `approvedAmount`, and absence means NOT YET DECIDED
|
|
318
|
+
*
|
|
319
|
+
* The self-shipped branch pays what an admin approved, never what the seller
|
|
320
|
+
* declared: *"the only approved amount will be given to them."* An absent
|
|
321
|
+
* `approvedAmount` therefore returns 0 — and that is "nothing is payable yet",
|
|
322
|
+
* not "nothing is owed". The distinction matters because a payout batch built
|
|
323
|
+
* before approval must not silently settle the order at zero postage and leave
|
|
324
|
+
* the seller with no later claim; the quiet-period invariant is what holds the
|
|
325
|
+
* order back until the reimbursement is decided.
|
|
326
|
+
*
|
|
327
|
+
* ## 🛑 Shiprocket-booked parcels get NOTHING, gated on the booking
|
|
328
|
+
*
|
|
329
|
+
* We paid that courier. The gate is `platformBookedShipment`, a fact about how
|
|
330
|
+
* the shipment was created — never "does a receipt exist", which a seller
|
|
331
|
+
* supplies and could therefore supply for a parcel they did not pay for.
|
|
332
|
+
*
|
|
333
|
+
* ## The quoted branch pays `reimbursable` from the reconciliation
|
|
334
|
+
*
|
|
335
|
+
* On an order that went through the courier picker, `reconcileOrderShipping`
|
|
336
|
+
* has already computed `min(spent, charged)` at dispatch and stored it. No
|
|
337
|
+
* approval step there: the seller declared a spend against a quote the buyer
|
|
338
|
+
* chose, which is its own evidence, and the cap does the rest.
|
|
339
|
+
*
|
|
340
|
+
* Either way **the platform nets exactly zero on shipping** — the seller is
|
|
341
|
+
* made whole up to what the buyer paid, and any saving goes to the buyer as
|
|
342
|
+
* points.
|
|
343
|
+
*/
|
|
344
|
+
export declare function orderShippingReimbursement(order: ReimbursableOrderLike): number;
|
|
345
|
+
/**
|
|
346
|
+
* Points this order issued, which the STORE funds.
|
|
347
|
+
*
|
|
348
|
+
* ## 🛑 A DEDUCTION, and never a clawback
|
|
349
|
+
*
|
|
350
|
+
* Owner, 2026-10-21: *"so stores bear it"*, framed as *"like a sale discount
|
|
351
|
+
* for getting a repeat customer — you get to pay few loss."* So the earn is a
|
|
352
|
+
* discount expense the seller absorbs, and it comes off their payout.
|
|
353
|
+
*
|
|
354
|
+
* That works as a simple deduction — with no ledger, no clawback and no
|
|
355
|
+
* negative balance — only because of an ordering guarantee worth stating
|
|
356
|
+
* explicitly, since I had it backwards in the plan for a while:
|
|
357
|
+
*
|
|
358
|
+
* ```
|
|
359
|
+
* delivered → completion (points issued) → order-complete closes
|
|
360
|
+
* → payout-release unblocks → payout computed → payout settled
|
|
361
|
+
* ```
|
|
362
|
+
*
|
|
363
|
+
* `payout-release` is `blockedBy: ["order-complete", …]`, so the payout gate
|
|
364
|
+
* opens BECAUSE the order completed — and completion is the same event that
|
|
365
|
+
* issues the points. The award is therefore **always strictly before** the
|
|
366
|
+
* payout is computed, by construction rather than by timing luck. I had
|
|
367
|
+
* recorded this as "the buyer's fast path RELEASES the payout early, so the
|
|
368
|
+
* absorption may happen after the money has left", which would have required
|
|
369
|
+
* a `sellerLedger` debit against a future payout. The fast path *unblocks*;
|
|
370
|
+
* it does not release. One planned mechanism deleted rather than built.
|
|
371
|
+
*
|
|
372
|
+
* Reads `pointsAwarded` off the order rather than recomputing a percentage:
|
|
373
|
+
* the figure must be what was actually credited, and the goods value may have
|
|
374
|
+
* changed since (a partial cancellation) — recomputing would deduct an amount
|
|
375
|
+
* the buyer never received.
|
|
376
|
+
*/
|
|
377
|
+
export declare function orderPointsFunded(order: {
|
|
378
|
+
pointsAwarded?: number;
|
|
379
|
+
}): number;
|
|
380
|
+
/** Sum of `orderPointsFunded` across a batch. */
|
|
381
|
+
export declare function ordersPointsFunded(orders: readonly {
|
|
382
|
+
pointsAwarded?: number;
|
|
383
|
+
}[]): number;
|
|
384
|
+
/** Sum of `orderShippingReimbursement` across a batch. */
|
|
385
|
+
export declare function ordersShippingReimbursement(orders: readonly ReimbursableOrderLike[]): number;
|
|
238
386
|
/**
|
|
239
387
|
* P-6 — pre-order groups charge each product's own `preOrderDepositPercent`
|
|
240
388
|
* (falling back to the generic COD deposit % when a product doesn't have one
|
|
@@ -146,7 +146,64 @@ productById) {
|
|
|
146
146
|
export function sumGroupGst(items,
|
|
147
147
|
/* `| null` to match `lineTaxComponentsFor` and `lineTotalFor` — see the note
|
|
148
148
|
* there. The consumer's create-order route holds an honestly-nullable map. */
|
|
149
|
-
productById, intraState
|
|
149
|
+
productById, intraState,
|
|
150
|
+
/**
|
|
151
|
+
* G1 — the group's coupon discount, in decimal rupees. **Reduces the taxable
|
|
152
|
+
* value**, prorated across the group's tax slices.
|
|
153
|
+
*
|
|
154
|
+
* 🛑 WHY THIS PARAMETER EXISTS. Without it the tax was backed out of the
|
|
155
|
+
* UNDISCOUNTED gross, so on a ₹1,000 item @18% with a ₹200 coupon the order
|
|
156
|
+
* recorded taxable ₹847.46 + GST ₹152.54 = ₹1,000 while the buyer paid ₹800
|
|
157
|
+
* for the goods. **₹30.51 of tax recorded on money that was never
|
|
158
|
+
* collected** — remitted by us, on every discounted order.
|
|
159
|
+
*
|
|
160
|
+
* A discount shown on the invoice generally reduces the value of supply
|
|
161
|
+
* under s.15(3)(a) CGST Act, so the post-discount base is both the honest
|
|
162
|
+
* figure and the lower liability. 🛑 This changes what we remit and is a CA
|
|
163
|
+
* question, not a code preference; it is implemented because it was decided,
|
|
164
|
+
* and it is flagged in the plan's standing-risk section for review.
|
|
165
|
+
*
|
|
166
|
+
* Optional, defaulting to 0, so the behaviour is unchanged for any caller
|
|
167
|
+
* that does not pass it — a REQUIRED parameter would have been better at
|
|
168
|
+
* forcing every call site to answer, but three of the four callers compute
|
|
169
|
+
* the discount after the tax today and the reorder is riskier than the
|
|
170
|
+
* default. `audit-checkout-total-parity` is what will catch an omission.
|
|
171
|
+
*/
|
|
172
|
+
couponDiscount = 0,
|
|
173
|
+
/**
|
|
174
|
+
* G5 — the group's TAXABLE ancillary charges, in decimal rupees: shipping,
|
|
175
|
+
* COD handling, gift wrap, shipment protection, sale protection.
|
|
176
|
+
*
|
|
177
|
+
* 🛑 These used to enter the order total as BARE ADDENDS carrying no tax at
|
|
178
|
+
* all. Delivery and handling are generally part of a composite supply and
|
|
179
|
+
* taxable at the rate of the principal supply, so a ₹100 shipping line on an
|
|
180
|
+
* 18% order was collected with ~₹15.25 of embedded tax that we declared
|
|
181
|
+
* nowhere.
|
|
182
|
+
*
|
|
183
|
+
* ── THE MECHANISM DIVERGES FROM THE PLAN, DELIBERATELY ──────────────────
|
|
184
|
+
*
|
|
185
|
+
* The plan recorded G5 as "raises buyer totals slightly", i.e. tax ADDED on
|
|
186
|
+
* top of each fee. That is the right reading for a tax-exclusive system and
|
|
187
|
+
* this one is not: `calculateGstInclusive`'s own header states "**Every
|
|
188
|
+
* price in this system is tax-inclusive**", and the product JSON-LD
|
|
189
|
+
* publicly asserts `valueAddedTaxIncluded: true`.
|
|
190
|
+
*
|
|
191
|
+
* So the fees are treated INCLUSIVE, exactly like goods:
|
|
192
|
+
*
|
|
193
|
+
* · the buyer pays the configured ₹100 — **no total changes, no silent
|
|
194
|
+
* re-pricing of every order**
|
|
195
|
+
* · ₹15.25 of it is recognised as GST and remitted
|
|
196
|
+
* · `taxableAmount` and `gstAmount` rise; the amount collected does not
|
|
197
|
+
*
|
|
198
|
+
* Adding tax on top instead would mix two conventions inside one total —
|
|
199
|
+
* which is the shape of the five-disagreeing-totals problem this phase
|
|
200
|
+
* exists to remove — and would make the published JSON-LD false. Flagged
|
|
201
|
+
* rather than silently chosen; it is still part of the CA conversation.
|
|
202
|
+
*
|
|
203
|
+
* Taxed at the PRINCIPAL rate, derived from the group's own goods (see
|
|
204
|
+
* below), because an ancillary charge follows the supply it is ancillary to.
|
|
205
|
+
*/
|
|
206
|
+
taxableFees = 0) {
|
|
150
207
|
let taxableAmount = 0;
|
|
151
208
|
let exemptAmount = 0;
|
|
152
209
|
let cgst = 0;
|
|
@@ -154,8 +211,35 @@ productById, intraState) {
|
|
|
154
211
|
let igst = 0;
|
|
155
212
|
let gstAmount = 0;
|
|
156
213
|
const byRate = new Map();
|
|
157
|
-
|
|
158
|
-
|
|
214
|
+
/*
|
|
215
|
+
* ── G1: apply the discount to the slice GROSSES before backing tax out ───
|
|
216
|
+
*
|
|
217
|
+
* Collected up front rather than taxed inline, because a discount is a
|
|
218
|
+
* property of the GROUP and has to be spread across its slices before any
|
|
219
|
+
* one of them can be taxed. Three properties matter:
|
|
220
|
+
*
|
|
221
|
+
* 1. **Prorated by gross share**, including exempt slices. A coupon on a
|
|
222
|
+
* mixed 0%/18% group reduces both proportionally; excluding the exempt
|
|
223
|
+
* slice would concentrate the whole discount on the taxed one and
|
|
224
|
+
* under-report the tax.
|
|
225
|
+
* 2. **`allocateAcrossMembers` for the split**, not per-slice
|
|
226
|
+
* multiplication. It pushes the rounding remainder onto the last slice
|
|
227
|
+
* so the parts sum to EXACTLY the discounted gross — which is the
|
|
228
|
+
* invariant that keeps the invoice reconciling against the amount
|
|
229
|
+
* charged. Independent `× (1 − d/total)` roundings do not.
|
|
230
|
+
* 3. **Clamped at zero.** A discount exceeding the group total (possible
|
|
231
|
+
* on a free-item promotion) must not produce negative taxable values.
|
|
232
|
+
*/
|
|
233
|
+
const rawSlices = items.flatMap((item) => lineTaxComponentsFor(item, productById));
|
|
234
|
+
const grossTotal = rawSlices.reduce((s, sl) => s + sl.taxable, 0);
|
|
235
|
+
const discount = Math.min(Math.max(0, couponDiscount), grossTotal);
|
|
236
|
+
const discountedGross = grossTotal - discount;
|
|
237
|
+
const sliceGross = discount > 0 && grossTotal > 0
|
|
238
|
+
? allocateAcrossMembers(discountedGross, rawSlices.map((sl) => sl.taxable))
|
|
239
|
+
: rawSlices.map((sl) => sl.taxable);
|
|
240
|
+
for (const [i, raw] of rawSlices.entries()) {
|
|
241
|
+
const slice = { ...raw, taxable: sliceGross[i] ?? raw.taxable };
|
|
242
|
+
{
|
|
159
243
|
/*
|
|
160
244
|
* 🛑 A 0%-rated slice is EXEMPT, not absent. It was `continue`d
|
|
161
245
|
* entirely, so `order.taxableAmount` excluded exempt goods while
|
|
@@ -222,6 +306,62 @@ productById, intraState) {
|
|
|
222
306
|
}
|
|
223
307
|
}
|
|
224
308
|
}
|
|
309
|
+
/*
|
|
310
|
+
* ── G5: the ancillary charges, taxed at the PRINCIPAL rate ──────────────
|
|
311
|
+
*
|
|
312
|
+
* A composite supply is taxed at the rate of its principal supply, and the
|
|
313
|
+
* principal supply here is the goods — shipping, handling, gift wrap and the
|
|
314
|
+
* protections exist only because the goods are being supplied.
|
|
315
|
+
*
|
|
316
|
+
* 🛑 "Principal rate" is the rate of the HIGHEST-VALUE taxable component,
|
|
317
|
+
* not the highest rate and not an average. On a mixed 5% + 18% group the
|
|
318
|
+
* principal supply is whichever dominates by value, so a cart of mostly-5%
|
|
319
|
+
* goods carries its shipping at 5%. Taking the highest RATE would
|
|
320
|
+
* over-collect on exactly the carts where the 18% item is a minor add-on;
|
|
321
|
+
* averaging would invent a rate that exists in no schedule and cannot appear
|
|
322
|
+
* on a Rule 46 invoice.
|
|
323
|
+
*
|
|
324
|
+
* 🛑 A group whose goods are entirely EXEMPT (0%) taxes its fees at 0% too —
|
|
325
|
+
* `principalRate` stays null, so the fee lands in `exemptAmount`. Ancillary
|
|
326
|
+
* to an exempt supply is exempt; defaulting to 18% there would tax delivery
|
|
327
|
+
* on a zero-rated order.
|
|
328
|
+
*/
|
|
329
|
+
if (taxableFees > 0) {
|
|
330
|
+
let principalRate = null;
|
|
331
|
+
let principalValue = 0;
|
|
332
|
+
for (const slice of byRate.values()) {
|
|
333
|
+
if (slice.taxableAmount > principalValue) {
|
|
334
|
+
principalValue = slice.taxableAmount;
|
|
335
|
+
principalRate = slice.gstRate;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
if (principalRate === null) {
|
|
339
|
+
// No taxed goods in this group — the fee follows them and is exempt.
|
|
340
|
+
exemptAmount += taxableFees;
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
343
|
+
// INCLUSIVE, like every other price in this system: the configured fee
|
|
344
|
+
// is what the buyer pays and the tax is backed out of it.
|
|
345
|
+
const f = calculateGstInclusive(principalRate, intraState, taxableFees);
|
|
346
|
+
taxableAmount += f.taxableAmount;
|
|
347
|
+
cgst += f.cgst;
|
|
348
|
+
sgst += f.sgst;
|
|
349
|
+
igst += f.igst;
|
|
350
|
+
gstAmount += f.gstAmount;
|
|
351
|
+
// Folded into the principal rate's existing bucket rather than given its
|
|
352
|
+
// own: on the invoice these are part of one taxable supply at one rate,
|
|
353
|
+
// and a separate line at the same rate would not reconcile against the
|
|
354
|
+
// Rule 46 per-rate summary.
|
|
355
|
+
const prev = byRate.get(principalRate);
|
|
356
|
+
if (prev) {
|
|
357
|
+
prev.taxableAmount = roundRupees(prev.taxableAmount + f.taxableAmount);
|
|
358
|
+
prev.cgst = roundRupees(prev.cgst + f.cgst);
|
|
359
|
+
prev.sgst = roundRupees(prev.sgst + f.sgst);
|
|
360
|
+
prev.igst = roundRupees(prev.igst + f.igst);
|
|
361
|
+
prev.gstAmount = roundRupees(prev.gstAmount + f.gstAmount);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
225
365
|
return {
|
|
226
366
|
taxableAmount: roundRupees(taxableAmount),
|
|
227
367
|
exemptAmount: roundRupees(exemptAmount),
|
|
@@ -353,6 +493,114 @@ export function orderTaxableValue(order) {
|
|
|
353
493
|
export function ordersTaxableValue(orders) {
|
|
354
494
|
return roundRupees(orders.reduce((sum, o) => sum + orderTaxableValue(o), 0));
|
|
355
495
|
}
|
|
496
|
+
/**
|
|
497
|
+
* Postage the seller is owed back on one order — **D45, and it is NOT revenue.**
|
|
498
|
+
*
|
|
499
|
+
* ## Why this is a separate term from the taxable value
|
|
500
|
+
*
|
|
501
|
+
* `orderTaxableValue` above is deliberately goods-only, and that stays true:
|
|
502
|
+
* shipping is not a sale and must never be grossed into the figure GST is
|
|
503
|
+
* backed out of. A reimbursement is a **cost being refunded**, so it is added
|
|
504
|
+
* AFTER the taxable value rather than folded into it — which also means it
|
|
505
|
+
* carries no commission, because commissioning a seller's postage would be
|
|
506
|
+
* charging them for the privilege of posting a parcel.
|
|
507
|
+
*
|
|
508
|
+
* ## 🛑 It reads `approvedAmount`, and absence means NOT YET DECIDED
|
|
509
|
+
*
|
|
510
|
+
* The self-shipped branch pays what an admin approved, never what the seller
|
|
511
|
+
* declared: *"the only approved amount will be given to them."* An absent
|
|
512
|
+
* `approvedAmount` therefore returns 0 — and that is "nothing is payable yet",
|
|
513
|
+
* not "nothing is owed". The distinction matters because a payout batch built
|
|
514
|
+
* before approval must not silently settle the order at zero postage and leave
|
|
515
|
+
* the seller with no later claim; the quiet-period invariant is what holds the
|
|
516
|
+
* order back until the reimbursement is decided.
|
|
517
|
+
*
|
|
518
|
+
* ## 🛑 Shiprocket-booked parcels get NOTHING, gated on the booking
|
|
519
|
+
*
|
|
520
|
+
* We paid that courier. The gate is `platformBookedShipment`, a fact about how
|
|
521
|
+
* the shipment was created — never "does a receipt exist", which a seller
|
|
522
|
+
* supplies and could therefore supply for a parcel they did not pay for.
|
|
523
|
+
*
|
|
524
|
+
* ## The quoted branch pays `reimbursable` from the reconciliation
|
|
525
|
+
*
|
|
526
|
+
* On an order that went through the courier picker, `reconcileOrderShipping`
|
|
527
|
+
* has already computed `min(spent, charged)` at dispatch and stored it. No
|
|
528
|
+
* approval step there: the seller declared a spend against a quote the buyer
|
|
529
|
+
* chose, which is its own evidence, and the cap does the rest.
|
|
530
|
+
*
|
|
531
|
+
* Either way **the platform nets exactly zero on shipping** — the seller is
|
|
532
|
+
* made whole up to what the buyer paid, and any saving goes to the buyer as
|
|
533
|
+
* points.
|
|
534
|
+
*/
|
|
535
|
+
export function orderShippingReimbursement(order) {
|
|
536
|
+
if (order.platformBookedShipment === true)
|
|
537
|
+
return 0;
|
|
538
|
+
/*
|
|
539
|
+
* The self-shipped branch first: an approved amount is an explicit human
|
|
540
|
+
* decision and outranks the dispatch-time computation, which on this branch
|
|
541
|
+
* would not exist anyway.
|
|
542
|
+
*/
|
|
543
|
+
const approved = order.shippingReimbursement?.approvedAmount;
|
|
544
|
+
if (typeof approved === "number" && Number.isFinite(approved)) {
|
|
545
|
+
return roundRupees(Math.max(0, approved));
|
|
546
|
+
}
|
|
547
|
+
const reimbursable = order.shippingReconciliation?.reimbursable;
|
|
548
|
+
if (typeof reimbursable === "number" && Number.isFinite(reimbursable)) {
|
|
549
|
+
return roundRupees(Math.max(0, reimbursable));
|
|
550
|
+
}
|
|
551
|
+
/*
|
|
552
|
+
* No reconciliation and no approval. Zero, and deliberately silent: an order
|
|
553
|
+
* dispatched before this feature existed has neither field, and warning on
|
|
554
|
+
* every one of those would make the log useless for the cases that matter.
|
|
555
|
+
*/
|
|
556
|
+
return 0;
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* Points this order issued, which the STORE funds.
|
|
560
|
+
*
|
|
561
|
+
* ## 🛑 A DEDUCTION, and never a clawback
|
|
562
|
+
*
|
|
563
|
+
* Owner, 2026-10-21: *"so stores bear it"*, framed as *"like a sale discount
|
|
564
|
+
* for getting a repeat customer — you get to pay few loss."* So the earn is a
|
|
565
|
+
* discount expense the seller absorbs, and it comes off their payout.
|
|
566
|
+
*
|
|
567
|
+
* That works as a simple deduction — with no ledger, no clawback and no
|
|
568
|
+
* negative balance — only because of an ordering guarantee worth stating
|
|
569
|
+
* explicitly, since I had it backwards in the plan for a while:
|
|
570
|
+
*
|
|
571
|
+
* ```
|
|
572
|
+
* delivered → completion (points issued) → order-complete closes
|
|
573
|
+
* → payout-release unblocks → payout computed → payout settled
|
|
574
|
+
* ```
|
|
575
|
+
*
|
|
576
|
+
* `payout-release` is `blockedBy: ["order-complete", …]`, so the payout gate
|
|
577
|
+
* opens BECAUSE the order completed — and completion is the same event that
|
|
578
|
+
* issues the points. The award is therefore **always strictly before** the
|
|
579
|
+
* payout is computed, by construction rather than by timing luck. I had
|
|
580
|
+
* recorded this as "the buyer's fast path RELEASES the payout early, so the
|
|
581
|
+
* absorption may happen after the money has left", which would have required
|
|
582
|
+
* a `sellerLedger` debit against a future payout. The fast path *unblocks*;
|
|
583
|
+
* it does not release. One planned mechanism deleted rather than built.
|
|
584
|
+
*
|
|
585
|
+
* Reads `pointsAwarded` off the order rather than recomputing a percentage:
|
|
586
|
+
* the figure must be what was actually credited, and the goods value may have
|
|
587
|
+
* changed since (a partial cancellation) — recomputing would deduct an amount
|
|
588
|
+
* the buyer never received.
|
|
589
|
+
*/
|
|
590
|
+
export function orderPointsFunded(order) {
|
|
591
|
+
const awarded = order.pointsAwarded;
|
|
592
|
+
return typeof awarded === "number" && Number.isFinite(awarded)
|
|
593
|
+
? roundRupees(Math.max(0, awarded))
|
|
594
|
+
: 0;
|
|
595
|
+
}
|
|
596
|
+
/** Sum of `orderPointsFunded` across a batch. */
|
|
597
|
+
export function ordersPointsFunded(orders) {
|
|
598
|
+
return roundRupees(orders.reduce((sum, o) => sum + orderPointsFunded(o), 0));
|
|
599
|
+
}
|
|
600
|
+
/** Sum of `orderShippingReimbursement` across a batch. */
|
|
601
|
+
export function ordersShippingReimbursement(orders) {
|
|
602
|
+
return roundRupees(orders.reduce((sum, o) => sum + orderShippingReimbursement(o), 0));
|
|
603
|
+
}
|
|
356
604
|
/**
|
|
357
605
|
* P-6 — pre-order groups charge each product's own `preOrderDepositPercent`
|
|
358
606
|
* (falling back to the generic COD deposit % when a product doesn't have one
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How much of an order can still be refunded, and what is withheld.
|
|
3
|
+
*
|
|
4
|
+
* ONE owner for two numbers that were previously computed four different ways
|
|
5
|
+
* and disagreed with each other and with the money actually moved.
|
|
6
|
+
*
|
|
7
|
+
* WHY:
|
|
8
|
+
*
|
|
9
|
+
* · **D1** — the over-refund guard compared `amount > order.totalPrice`, i.e.
|
|
10
|
+
* against the ORDER TOTAL rather than the remaining balance, while its own
|
|
11
|
+
* docstring promised "≤ remaining refundable amount". So ₹500 and then
|
|
12
|
+
* another ₹500 both passed on a ₹600 order: **₹1,000 refunded, two real
|
|
13
|
+
* gateway calls, both successful.**
|
|
14
|
+
*
|
|
15
|
+
* · **D3** — `isFull` was `amount >= order.totalPrice`, so a split refund
|
|
16
|
+
* (₹300 + ₹200 of ₹500) never reached `status: "refunded"` and the order
|
|
17
|
+
* stayed fully refundable forever.
|
|
18
|
+
*
|
|
19
|
+
* · **D32** — the platform fee is non-refundable by policy, and the only code
|
|
20
|
+
* implementing that withheld ~10x too much (see `platformFeeWithheld`).
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* Half a paisa. The tolerance exists because these are IEEE-754 sums of 2dp
|
|
24
|
+
* components: `0.1 + 0.2 > 0.3` is TRUE in floating point, so an exact
|
|
25
|
+
* comparison would reject a legitimate final refund that exactly exhausts the
|
|
26
|
+
* balance. Half a paisa is below the smallest representable money unit, so it
|
|
27
|
+
* cannot admit a real over-refund.
|
|
28
|
+
*/
|
|
29
|
+
export declare const MONEY_EPSILON = 0.005;
|
|
30
|
+
/** The subset of an order this module needs. Keeps it testable and pure. */
|
|
31
|
+
export interface RefundableOrderLike {
|
|
32
|
+
totalPrice: number;
|
|
33
|
+
platformFee?: number;
|
|
34
|
+
platformFeeGst?: number;
|
|
35
|
+
refunds?: ReadonlyArray<{
|
|
36
|
+
amount: number;
|
|
37
|
+
status?: string;
|
|
38
|
+
}>;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The platform fee actually withheld on a refund: the amount CHARGED, never a
|
|
42
|
+
* recomputed percentage.
|
|
43
|
+
*
|
|
44
|
+
* 🛑 This replaces the single worst money defect found in the audit (D32).
|
|
45
|
+
* `previewCancellationRefund` did:
|
|
46
|
+
*
|
|
47
|
+
* const effectiveRate = platformFeePercent * (1 + gstPercent / 100);
|
|
48
|
+
* const feeDeducted = (grossRefund * effectiveRate) / 100;
|
|
49
|
+
*
|
|
50
|
+
* — a PERCENTAGE OF THE REFUND, which ignores `commissions.platformFeeMax`
|
|
51
|
+
* (default **₹10**) entirely and ignores `order.platformFee`, the amount that
|
|
52
|
+
* was actually collected and is stored on the order. On a ₹5,000 order at 2% +
|
|
53
|
+
* 18% GST it deducted **₹118** from a buyer who had paid **₹11.80** — keeping
|
|
54
|
+
* roughly ₹106 of their goods money and labelling it a platform fee. The
|
|
55
|
+
* overcharge grows with order value, so it is largest exactly where it is most
|
|
56
|
+
* noticeable.
|
|
57
|
+
*
|
|
58
|
+
* `platformFeeGst` is read from the order and only DERIVED for rows written
|
|
59
|
+
* before that field existed (2026-10-21). The derivation takes `gstPercent`
|
|
60
|
+
* from the caller rather than reading settings itself, so this stays pure and
|
|
61
|
+
* so a caller cannot accidentally reach for today's rate when the order is
|
|
62
|
+
* from last year — which is the mistake the whole function exists to undo.
|
|
63
|
+
*/
|
|
64
|
+
export declare function platformFeeWithheld(order: Pick<RefundableOrderLike, "platformFee" | "platformFeeGst">,
|
|
65
|
+
/** Only consulted for legacy orders with no stored `platformFeeGst`. */
|
|
66
|
+
legacyGstPercent?: number): number;
|
|
67
|
+
/**
|
|
68
|
+
* The ceiling every refund is measured against.
|
|
69
|
+
*
|
|
70
|
+
* 🛑 `totalPrice − platformFeeWithheld`, NOT `totalPrice`. The platform fee is
|
|
71
|
+
* non-refundable in every scenario — a decided policy, and one the product
|
|
72
|
+
* already states: `REFUND_COPY.request.acknowledgments[2]` tells the buyer
|
|
73
|
+
* "platform fees may be non-recoverable".
|
|
74
|
+
*
|
|
75
|
+
* This correction matters twice over. Phase 1's cumulative cap has to compare
|
|
76
|
+
* against THIS, or a refund can exceed what the buyer is owed; and `isFull`
|
|
77
|
+
* has to compare against THIS, or the largest possible refund is strictly less
|
|
78
|
+
* than `totalPrice` and **an order can never reach `status: "refunded"`** —
|
|
79
|
+
* which is what the old `amount >= totalPrice` test guaranteed.
|
|
80
|
+
*/
|
|
81
|
+
export declare function refundableBase(order: RefundableOrderLike, legacyGstPercent?: number): number;
|
|
82
|
+
/**
|
|
83
|
+
* Sum of refunds that have COMMITTED money, i.e. everything not `failed`.
|
|
84
|
+
*
|
|
85
|
+
* 🛑 A `reserved` entry counts. The two-phase write reserves before calling the
|
|
86
|
+
* provider and settles after, so between those two points the money may well
|
|
87
|
+
* have left — excluding reserved entries would let a concurrent request refund
|
|
88
|
+
* against a balance that is already spoken for, which is the TOCTOU the
|
|
89
|
+
* reservation exists to close. A `failed` entry releases its reservation by
|
|
90
|
+
* being skipped here, which is why no explicit release step is needed.
|
|
91
|
+
*
|
|
92
|
+
* `status` is optional on `OrderRefundEvent`: rows written before the
|
|
93
|
+
* two-phase scheme have none, and those are all committed refunds, so a
|
|
94
|
+
* missing status must count.
|
|
95
|
+
*/
|
|
96
|
+
export declare function committedRefundTotal(order: RefundableOrderLike): number;
|
|
97
|
+
export interface RefundCapacity {
|
|
98
|
+
/** `totalPrice` less the non-refundable platform fee. */
|
|
99
|
+
base: number;
|
|
100
|
+
/** Already committed (processed or reserved). */
|
|
101
|
+
committed: number;
|
|
102
|
+
/** `base − committed`, floored at zero. */
|
|
103
|
+
remaining: number;
|
|
104
|
+
/** The non-refundable amount, for disclosure to the buyer. */
|
|
105
|
+
withheld: number;
|
|
106
|
+
}
|
|
107
|
+
/** Everything a caller needs to decide and to EXPLAIN a refund decision. */
|
|
108
|
+
export declare function refundCapacity(order: RefundableOrderLike, legacyGstPercent?: number): RefundCapacity;
|
|
109
|
+
/**
|
|
110
|
+
* Would this refund exhaust the refundable base?
|
|
111
|
+
*
|
|
112
|
+
* Measured against `base`, not `totalPrice` — see `refundableBase`. The
|
|
113
|
+
* epsilon makes an exactly-exhausting refund count as full rather than
|
|
114
|
+
* leaving a sub-paisa residue that keeps the order refundable forever.
|
|
115
|
+
*/
|
|
116
|
+
export declare function wouldBeFullRefund(order: RefundableOrderLike, amount: number, legacyGstPercent?: number): boolean;
|