@mohasinac/appkit 4.62.0 → 4.63.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.build-stamp.json +3 -3
- package/dist/_internal/client/features/layout/DashboardLayoutClient.js +8 -29
- package/dist/_internal/client/features/layout/filterNavItems.d.ts +28 -0
- package/dist/_internal/client/features/layout/filterNavItems.js +35 -0
- package/dist/_internal/server/features/ads/booking.d.ts +118 -0
- package/dist/_internal/server/features/ads/booking.js +326 -0
- package/dist/_internal/server/features/checkout/actions.d.ts +129 -9
- package/dist/_internal/server/features/checkout/actions.js +850 -79
- package/dist/_internal/server/features/checkout/expand-order-items.d.ts +1 -2
- package/dist/_internal/server/features/checkout/expand-order-items.js +32 -0
- package/dist/_internal/server/features/checkout/freeze-parts.d.ts +50 -0
- package/dist/_internal/server/features/checkout/freeze-parts.js +94 -0
- package/dist/_internal/server/features/checkout/value-otp-gate.d.ts +55 -0
- package/dist/_internal/server/features/checkout/value-otp-gate.js +60 -0
- package/dist/_internal/server/features/dashboard/attention.d.ts +128 -0
- package/dist/_internal/server/features/dashboard/attention.js +183 -0
- package/dist/_internal/server/features/dashboard/data.d.ts +47 -0
- package/dist/_internal/server/features/dashboard/data.js +82 -0
- package/dist/_internal/server/features/inventory/reservations.d.ts +99 -0
- package/dist/_internal/server/features/inventory/reservations.js +273 -0
- package/dist/_internal/server/features/invoicing/allocate.d.ts +63 -0
- package/dist/_internal/server/features/invoicing/allocate.js +162 -0
- package/dist/_internal/server/features/invoicing/credit-note.d.ts +57 -0
- package/dist/_internal/server/features/invoicing/credit-note.js +126 -0
- package/dist/_internal/server/features/invoicing/gstr1.d.ts +74 -0
- package/dist/_internal/server/features/invoicing/gstr1.js +251 -0
- package/dist/_internal/server/features/invoicing/issue.d.ts +96 -0
- package/dist/_internal/server/features/invoicing/issue.js +202 -0
- package/dist/_internal/server/features/offers/destinations.d.ts +40 -0
- package/dist/_internal/server/features/offers/destinations.js +65 -0
- package/dist/_internal/server/features/orders/actions.d.ts +8 -1
- package/dist/_internal/server/features/orders/actions.js +81 -8
- package/dist/_internal/server/features/orders/adapters.js +54 -0
- package/dist/_internal/server/features/orders/amend-delivery.d.ts +56 -0
- package/dist/_internal/server/features/orders/amend-delivery.js +124 -0
- package/dist/_internal/server/features/orders/balance.d.ts +89 -0
- package/dist/_internal/server/features/orders/balance.js +256 -0
- package/dist/_internal/server/features/orders/cancellation-refund.d.ts +15 -9
- package/dist/_internal/server/features/orders/cancellation-refund.js +15 -9
- package/dist/_internal/server/features/points/award.js +46 -4
- package/dist/_internal/server/features/pricing/actions.d.ts +58 -0
- package/dist/_internal/server/features/pricing/actions.js +144 -0
- package/dist/_internal/server/features/refunds/actions.js +26 -0
- package/dist/_internal/server/features/shipping/book-split.d.ts +86 -0
- package/dist/_internal/server/features/shipping/book-split.js +130 -0
- package/dist/_internal/server/features/shipping/book.d.ts +61 -0
- package/dist/_internal/server/features/shipping/book.js +176 -0
- package/dist/_internal/server/features/shipping/courier-block.d.ts +69 -0
- package/dist/_internal/server/features/shipping/courier-block.js +264 -0
- package/dist/_internal/server/features/site-settings/adapters.d.ts +2 -2
- package/dist/_internal/server/features/site-settings/adapters.js +29 -0
- package/dist/_internal/server/features/stores/adapters.d.ts +2 -2
- package/dist/_internal/server/features/stores/adapters.js +65 -0
- package/dist/_internal/server/functions/scheduled.d.ts +2 -1
- package/dist/_internal/server/functions/scheduled.js +95 -2
- package/dist/_internal/server/jobs/core/autoPayoutEligibility.js +11 -2
- package/dist/_internal/server/jobs/core/dailyStatusDigest.d.ts +4 -0
- package/dist/_internal/server/jobs/core/dailyStatusDigest.js +19 -2
- package/dist/_internal/server/jobs/core/index.d.ts +2 -1
- package/dist/_internal/server/jobs/core/index.js +2 -1
- package/dist/_internal/server/jobs/core/jobRunners.js +45 -0
- package/dist/_internal/server/jobs/core/onJobCreated.d.ts +30 -7
- package/dist/_internal/server/jobs/core/onJobCreated.js +78 -45
- package/dist/_internal/server/jobs/core/onOrderStatusChange.d.ts +7 -0
- package/dist/_internal/server/jobs/core/onOrderStatusChange.js +65 -0
- package/dist/_internal/server/jobs/core/paymentWindowTimeout.js +33 -0
- package/dist/_internal/server/jobs/core/reservationExpiry.d.ts +17 -0
- package/dist/_internal/server/jobs/core/reservationExpiry.js +40 -0
- package/dist/_internal/server/jobs/core/runJobOnce.d.ts +48 -0
- package/dist/_internal/server/jobs/core/runJobOnce.js +195 -0
- package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.js +25 -2
- package/dist/_internal/server/jobs/handlers/index.d.ts +1 -0
- package/dist/_internal/server/jobs/handlers/index.js +1 -0
- package/dist/_internal/server/jobs/handlers/onOrderStatusChange.js +17 -0
- package/dist/_internal/server/jobs/handlers/reservationExpiry.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/reservationExpiry.js +2 -0
- package/dist/_internal/server/notifications/channel-health.d.ts +26 -3
- package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
- package/dist/_internal/shared/actions/action-registry.js +296 -0
- package/dist/_internal/shared/checkout/coupon-discount.d.ts +43 -1
- package/dist/_internal/shared/checkout/coupon-discount.js +26 -1
- package/dist/_internal/shared/checkout/order-math.d.ts +174 -0
- package/dist/_internal/shared/checkout/order-math.js +159 -0
- package/dist/_internal/shared/checkout/refundable-base.d.ts +25 -0
- package/dist/_internal/shared/checkout/refundable-base.js +13 -1
- package/dist/_internal/shared/checkout/rules/index.d.ts +1 -1
- package/dist/_internal/shared/checkout/rules/index.js +1 -1
- package/dist/_internal/shared/checkout/rules/payment-gate.d.ts +18 -0
- package/dist/_internal/shared/checkout/rules/payment-gate.js +25 -0
- package/dist/_internal/shared/checkout/split.d.ts +75 -0
- package/dist/_internal/shared/checkout/split.js +120 -0
- package/dist/_internal/shared/content/disclaimers.d.ts +88 -0
- package/dist/_internal/shared/content/disclaimers.js +217 -0
- package/dist/_internal/shared/content/published-values.d.ts +93 -0
- package/dist/_internal/shared/content/published-values.js +206 -0
- package/dist/_internal/shared/features/admin/integrations.d.ts +139 -0
- package/dist/_internal/shared/features/admin/integrations.js +263 -0
- package/dist/_internal/shared/features/dashboard/hub-sections.d.ts +72 -0
- package/dist/_internal/shared/features/dashboard/hub-sections.js +75 -0
- package/dist/_internal/shared/features/emi/choice.d.ts +98 -0
- package/dist/_internal/shared/features/emi/choice.js +69 -0
- package/dist/_internal/shared/features/emi/group.d.ts +84 -0
- package/dist/_internal/shared/features/emi/group.js +126 -0
- package/dist/_internal/shared/features/ledger/posting.d.ts +107 -0
- package/dist/_internal/shared/features/ledger/posting.js +165 -0
- package/dist/_internal/shared/features/ledger/reports.d.ts +76 -0
- package/dist/_internal/shared/features/ledger/reports.js +127 -0
- package/dist/_internal/shared/features/ledger/rules.d.ts +170 -0
- package/dist/_internal/shared/features/ledger/rules.js +221 -0
- package/dist/_internal/shared/features/offers/coordination.d.ts +122 -0
- package/dist/_internal/shared/features/offers/coordination.js +80 -0
- package/dist/_internal/shared/features/orders/delivery-snapshot.d.ts +114 -0
- package/dist/_internal/shared/features/orders/delivery-snapshot.js +116 -0
- package/dist/_internal/shared/features/orders/dispute-reasons.d.ts +113 -0
- package/dist/_internal/shared/features/orders/dispute-reasons.js +181 -0
- package/dist/_internal/shared/features/orders/refund-copy.d.ts +1 -1
- package/dist/_internal/shared/features/orders/refund-copy.js +18 -1
- package/dist/_internal/shared/features/payouts/pay-period.d.ts +91 -0
- package/dist/_internal/shared/features/payouts/pay-period.js +104 -0
- package/dist/_internal/shared/features/points/accepts.d.ts +29 -0
- package/dist/_internal/shared/features/points/accepts.js +49 -0
- package/dist/_internal/shared/features/pricing/rate-registry.d.ts +150 -0
- package/dist/_internal/shared/features/pricing/rate-registry.js +246 -0
- package/dist/_internal/shared/features/shipping/parcel.d.ts +123 -0
- package/dist/_internal/shared/features/shipping/parcel.js +139 -0
- package/dist/_internal/shared/features/shipping/shared-purchase.d.ts +91 -0
- package/dist/_internal/shared/features/shipping/shared-purchase.js +108 -0
- package/dist/_internal/shared/features/site-settings/fees.d.ts +16 -8
- package/dist/_internal/shared/features/site-settings/fees.js +12 -8
- package/dist/_internal/shared/features/site-settings/types.d.ts +11 -0
- package/dist/_internal/shared/fees/calculator.d.ts +33 -1
- package/dist/_internal/shared/fees/calculator.js +32 -2
- package/dist/_internal/shared/fees/explain.d.ts +81 -0
- package/dist/_internal/shared/fees/explain.js +101 -0
- package/dist/_internal/shared/history/index.d.ts +1 -1
- package/dist/_internal/shared/history/index.js +1 -1
- package/dist/_internal/shared/history/types.d.ts +7 -1
- package/dist/_internal/shared/history/types.js +25 -0
- package/dist/client.d.ts +21 -0
- package/dist/client.js +43 -0
- package/dist/constants/api-endpoints.d.ts +114 -0
- package/dist/constants/api-endpoints.js +55 -0
- package/dist/constants/field-names.d.ts +42 -0
- package/dist/constants/field-names.js +52 -0
- package/dist/contracts/index.d.ts +1 -1
- package/dist/contracts/shipping.d.ts +45 -0
- package/dist/contracts/shipping.js +15 -0
- package/dist/features/about/components/AboutView.js +1 -1
- package/dist/features/account/components/BuyerAuctionsGuideView.js +4 -1
- package/dist/features/account/components/UserOrdersView.js +47 -35
- package/dist/features/admin/components/AdminCouponEditorView.js +17 -0
- package/dist/features/admin/components/AdminIntegrationsView.d.ts +55 -0
- package/dist/features/admin/components/AdminIntegrationsView.js +74 -0
- package/dist/features/admin/components/AdminInvoicingView.d.ts +2 -0
- package/dist/features/admin/components/AdminInvoicingView.js +65 -0
- package/dist/features/admin/components/AdminOrderEditorView.d.ts +33 -1
- package/dist/features/admin/components/AdminOrderEditorView.js +81 -3
- package/dist/features/admin/components/AdminOrdersGuideView.js +23 -2
- package/dist/features/admin/components/AdminOrdersView.js +86 -5
- package/dist/features/admin/components/OwnerQuickActions.js +24 -2
- package/dist/features/admin/constants/filter-tabs.d.ts +6 -0
- package/dist/features/admin/constants/filter-tabs.js +6 -0
- package/dist/features/admin/constants/site-settings-tabs.d.ts +1 -1
- package/dist/features/admin/hooks/useAdminListingData.js +16 -0
- package/dist/features/admin/schemas/admin-user-form.d.ts +2 -2
- package/dist/features/admin/schemas/firestore.d.ts +62 -0
- package/dist/features/admin/schemas/firestore.js +5 -0
- package/dist/features/ads/schemas/booking-write.d.ts +120 -0
- package/dist/features/ads/schemas/booking-write.js +75 -0
- package/dist/features/ads/schemas/creative-form.d.ts +18 -0
- package/dist/features/ads/schemas/creative-form.js +51 -0
- package/dist/features/ads/schemas/firestore.d.ts +140 -0
- package/dist/features/ads/schemas/firestore.js +109 -0
- package/dist/features/auctions/repository/bid.repository.js +3 -1
- package/dist/features/audit-log/schemas/firestore.d.ts +140 -0
- package/dist/features/audit-log/schemas/firestore.js +89 -0
- package/dist/features/auth/actions/profile-actions.d.ts +69 -1
- package/dist/features/auth/actions/profile-actions.js +62 -1
- package/dist/features/auth/permissions/constants.js +13 -0
- package/dist/features/auth/schemas/firestore.d.ts +16 -2
- package/dist/features/auth/schemas/firestore.js +2 -1
- package/dist/features/blog/actions/blog-actions.d.ts +6 -0
- package/dist/features/blog/actions/blog-actions.js +17 -2
- package/dist/features/blog/api/route.js +4 -1
- package/dist/features/blog/columns/index.js +5 -0
- package/dist/features/blog/components/BlogIndexPageView.js +2 -1
- package/dist/features/blog/repository/blog.repository.d.ts +4 -0
- package/dist/features/blog/repository/blog.repository.js +5 -0
- package/dist/features/blog/schemas/blog-form.d.ts +3 -0
- package/dist/features/blog/schemas/blog-form.js +1 -0
- package/dist/features/blog/schemas/firestore.d.ts +38 -1
- package/dist/features/blog/schemas/firestore.js +23 -0
- package/dist/features/blog/schemas/index.d.ts +6 -0
- package/dist/features/blog/schemas/index.js +2 -0
- package/dist/features/blog/types/index.d.ts +2 -0
- package/dist/features/cart/components/CartPriceBreakdown.d.ts +25 -1
- package/dist/features/cart/components/CartPriceBreakdown.js +29 -6
- package/dist/features/cart/components/PointsTenderPicker.d.ts +61 -0
- package/dist/features/cart/components/PointsTenderPicker.js +15 -0
- package/dist/features/cart/components/StoreAddonsPicker.js +2 -1
- package/dist/features/cart/components/index.d.ts +2 -0
- package/dist/features/cart/components/index.js +1 -0
- package/dist/features/cart/repository/cart.repository.d.ts +33 -0
- package/dist/features/cart/repository/cart.repository.js +47 -0
- package/dist/features/cart/schemas/firestore.d.ts +116 -0
- package/dist/features/contact/email.d.ts +27 -10
- package/dist/features/contact/email.js +20 -3
- package/dist/features/dashboard/components/DashboardHubView.d.ts +83 -0
- package/dist/features/dashboard/components/DashboardHubView.js +56 -0
- package/dist/features/dashboard/components/DashboardSectionsClient.d.ts +23 -0
- package/dist/features/dashboard/components/DashboardSectionsClient.js +66 -0
- package/dist/features/dispute-reasons/components/AdminDisputeReasonsView.d.ts +55 -0
- package/dist/features/dispute-reasons/components/AdminDisputeReasonsView.js +175 -0
- package/dist/features/dispute-reasons/repository/dispute-reasons.repository.d.ts +62 -0
- package/dist/features/dispute-reasons/repository/dispute-reasons.repository.js +108 -0
- package/dist/features/dispute-reasons/schemas/firestore.d.ts +62 -0
- package/dist/features/dispute-reasons/schemas/firestore.js +40 -0
- package/dist/features/events/components/EventSaleBanner.js +1 -1
- package/dist/features/faq/components/FAQAccordion.d.ts +13 -1
- package/dist/features/faq/components/FAQAccordion.js +29 -4
- package/dist/features/faq/components/FAQPageContent.js +2 -2
- package/dist/features/gateway-events/schemas/index.d.ts +2 -2
- package/dist/features/homepage/schemas/index.d.ts +8 -8
- package/dist/features/inventory/schemas/stock-reservation.d.ts +114 -0
- package/dist/features/inventory/schemas/stock-reservation.js +103 -0
- package/dist/features/invoicing/schemas/firestore.d.ts +112 -0
- package/dist/features/invoicing/schemas/firestore.js +45 -0
- package/dist/features/invoicing/utils/financial-year.d.ts +43 -0
- package/dist/features/invoicing/utils/financial-year.js +53 -0
- package/dist/features/jobs/actions/enqueue-job.js +18 -1
- package/dist/features/jobs/repository/jobs.repository.d.ts +62 -1
- package/dist/features/jobs/repository/jobs.repository.js +84 -1
- package/dist/features/jobs/schemas/firestore.d.ts +80 -0
- package/dist/features/jobs/schemas/firestore.js +37 -0
- package/dist/features/layout/AppLayoutShell.d.ts +9 -1
- package/dist/features/layout/AppLayoutShell.js +12 -4
- package/dist/features/layout/BottomActions.js +2 -1
- package/dist/features/layout/BottomNavbar.d.ts +10 -2
- package/dist/features/layout/SideActionDock.js +52 -2
- package/dist/features/layout/TitleBarLayout.js +13 -4
- package/dist/features/layout/TitleBarLayout.style.css +59 -0
- package/dist/features/layout/useCtaReveal.d.ts +16 -1
- package/dist/features/layout/useCtaReveal.js +17 -26
- package/dist/features/ledger/repository/journal.repository.d.ts +110 -0
- package/dist/features/ledger/repository/journal.repository.js +312 -0
- package/dist/features/ledger/schemas/expenses.d.ts +87 -0
- package/dist/features/ledger/schemas/expenses.js +27 -0
- package/dist/features/ledger/schemas/firestore.d.ts +183 -0
- package/dist/features/ledger/schemas/firestore.js +69 -0
- package/dist/features/lottery/schemas/zod.d.ts +6 -6
- package/dist/features/media/MediaImage.js +22 -1
- package/dist/features/media/upload/ImageUpload.js +1 -1
- package/dist/features/obligations/constants/policies.js +24 -1
- package/dist/features/orders/components/BalancePaymentPanel.d.ts +12 -0
- package/dist/features/orders/components/BalancePaymentPanel.js +94 -0
- package/dist/features/orders/components/OrderPaymentSummary.js +10 -1
- package/dist/features/orders/components/OrderProvenanceCard.d.ts +8 -0
- package/dist/features/orders/components/OrderProvenanceCard.js +185 -0
- package/dist/features/orders/components/RaiseDisputeForm.d.ts +14 -0
- package/dist/features/orders/components/RaiseDisputeForm.js +119 -0
- package/dist/features/orders/components/RefundRequestView.js +19 -1
- package/dist/features/orders/components/index.d.ts +4 -0
- package/dist/features/orders/components/index.js +2 -0
- package/dist/features/orders/constants/order-lane-tabs.d.ts +69 -0
- package/dist/features/orders/constants/order-lane-tabs.js +88 -0
- package/dist/features/orders/repository/orders.repository.d.ts +85 -1
- package/dist/features/orders/repository/orders.repository.js +205 -6
- package/dist/features/orders/schemas/balance.d.ts +40 -0
- package/dist/features/orders/schemas/balance.js +47 -0
- package/dist/features/orders/schemas/firestore.d.ts +398 -1
- package/dist/features/orders/schemas/firestore.js +43 -0
- package/dist/features/orders/schemas/index.d.ts +56 -8
- package/dist/features/orders/schemas/index.js +12 -0
- package/dist/features/orders/types/index.d.ts +47 -0
- package/dist/features/orders/utils/courier-block.d.ts +25 -0
- package/dist/features/orders/utils/courier-block.js +23 -0
- package/dist/features/payment-cases/schemas/firestore.d.ts +26 -1
- package/dist/features/payment-cases/schemas/firestore.js +1 -0
- package/dist/features/payments/repository/payout.repository.js +3 -2
- package/dist/features/payments/schemas/firestore.d.ts +92 -1
- package/dist/features/payments/schemas/firestore.js +23 -0
- package/dist/features/pricing/components/AdminPricingView.d.ts +13 -0
- package/dist/features/pricing/components/AdminPricingView.js +157 -0
- package/dist/features/products/components/PrizeDrawDetailPageView.js +2 -2
- package/dist/features/products/components/ProductDetailPageView.d.ts +17 -1
- package/dist/features/products/components/ProductDetailPageView.js +2 -2
- package/dist/features/products/schemas/firestore.d.ts +26 -1
- package/dist/features/products/schemas/firestore.js +2 -0
- package/dist/features/products/schemas/index.d.ts +2 -2
- package/dist/features/products/schemas/product-features.validators.d.ts +10 -10
- package/dist/features/promotions/actions/coupon-stacking.d.ts +30 -3
- package/dist/features/promotions/actions/coupon-stacking.js +21 -2
- package/dist/features/promotions/components/CouponCard.js +13 -0
- package/dist/features/promotions/constants/coupon-help.d.ts +2 -2
- package/dist/features/promotions/constants/coupon-help.js +9 -1
- package/dist/features/promotions/schemas/firestore.d.ts +24 -0
- package/dist/features/promotions/schemas/firestore.js +4 -0
- package/dist/features/promotions/types/index.d.ts +19 -1
- package/dist/features/reviews/repository/reviews.repository.d.ts +14 -0
- package/dist/features/reviews/repository/reviews.repository.js +16 -0
- package/dist/features/scams/components/ScamProfileView.js +2 -2
- package/dist/features/scams/components/ScamRegistryView.js +2 -2
- package/dist/features/scams/repository/scammer.repository.js +2 -1
- package/dist/features/scams/schemas/firestore.d.ts +2 -1
- package/dist/features/scams/schemas/firestore.js +2 -1
- package/dist/features/search/action-index/tab-entries.js +1 -1
- package/dist/features/seller/actions/offer-actions.js +56 -0
- package/dist/features/seller/actions/seller-actions.d.ts +1 -1
- package/dist/features/seller/actions/seller-actions.js +37 -3
- package/dist/features/seller/components/DispatchForm.d.ts +11 -0
- package/dist/features/seller/components/DispatchForm.js +190 -0
- package/dist/features/seller/components/SellerOrdersView.js +221 -27
- package/dist/features/seller/components/index.d.ts +1 -0
- package/dist/features/seller/components/index.js +1 -0
- package/dist/features/seller/hooks/useSellerListingData.js +25 -0
- package/dist/features/seller/repository/offer.repository.js +4 -3
- package/dist/features/seller/schemas/firestore.d.ts +23 -2
- package/dist/features/seller/schemas/firestore.js +3 -2
- package/dist/features/seller/schemas/index.d.ts +4 -4
- package/dist/features/seller/schemas/order-forms.d.ts +61 -4
- package/dist/features/seller/schemas/order-forms.js +41 -8
- package/dist/features/shipments/schemas/firestore.d.ts +25 -0
- package/dist/features/shipments/schemas/validation.d.ts +4 -4
- package/dist/features/shipping-boxes/repository/shipping-boxes.repository.d.ts +82 -0
- package/dist/features/shipping-boxes/repository/shipping-boxes.repository.js +145 -0
- package/dist/features/shipping-boxes/schemas/firestore.d.ts +80 -0
- package/dist/features/shipping-boxes/schemas/firestore.js +53 -0
- package/dist/features/store-extensions/schemas/report-create-form.d.ts +2 -2
- package/dist/features/store-extensions/schemas/shipping-config-form.d.ts +2 -2
- package/dist/features/stores/components/StoreOrdersGuideView.js +6 -1
- package/dist/features/stores/repository/store.repository.d.ts +18 -0
- package/dist/features/stores/repository/store.repository.js +27 -1
- package/dist/features/stores/schemas/firestore.d.ts +112 -0
- package/dist/features/stores/schemas/firestore.js +20 -0
- package/dist/features/stores/schemas/index.d.ts +6 -6
- package/dist/features/stores/types/index.d.ts +19 -0
- package/dist/features/support/repository/support.repository.js +72 -6
- package/dist/features/support/schemas/firestore.d.ts +17 -0
- package/dist/features/support/schemas/index.d.ts +8 -8
- package/dist/features/wishlist/hooks/useWishlistWithGuest.d.ts +1 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.js +33 -1
- package/dist/next/routing/route-map.d.ts +112 -0
- package/dist/next/routing/route-map.js +63 -0
- package/dist/providers/shipping-shiprocket/index.d.ts +27 -1
- package/dist/providers/shipping-shiprocket/index.js +84 -1
- package/dist/react/contexts/SessionContext.d.ts +17 -1
- package/dist/schemas/registry.d.ts +69 -34
- package/dist/schemas/sieve.d.ts +2 -2
- package/dist/security/pii-schemas.d.ts +1 -1
- package/dist/security/pii-schemas.js +45 -0
- package/dist/server-entry.d.ts +2 -2
- package/dist/server-entry.js +8 -1
- package/dist/server.d.ts +36 -1
- package/dist/server.js +183 -1
- package/dist/styles.css +412 -80
- package/dist/tailwind-utilities.css +1 -1
- package/dist/tokens/themes/default-dark.js +1 -0
- package/dist/tokens/themes/default-light.js +1 -0
- package/dist/tokens/themes/required.d.ts +1 -1
- package/dist/tokens/themes/required.js +1 -0
- package/dist/tokens/tokens.css +15 -0
- package/dist/ui/components/Button.d.ts +10 -1
- package/dist/ui/components/Button.js +25 -3
- package/dist/ui/components/Chart.d.ts +63 -0
- package/dist/ui/components/Chart.js +169 -0
- package/dist/ui/components/Chart.style.css +214 -0
- package/dist/ui/components/Disclaimer.d.ts +19 -0
- package/dist/ui/components/Disclaimer.js +83 -0
- package/dist/ui/components/OverflowRow.js +54 -2
- package/dist/ui/components/OverflowRow.style.css +38 -0
- package/dist/ui/components/RichTextEditor.js +99 -8
- package/dist/ui/components/chart-spec.d.ts +68 -0
- package/dist/ui/components/chart-spec.js +140 -0
- package/dist/ui/components/index.style.css +1 -0
- package/dist/ui/components/surface-tokens.d.ts +1 -1
- package/dist/ui/components/surface-tokens.js +9 -0
- package/dist/ui/components/tabs-overflow.js +64 -11
- package/dist/ui/components/toolbar-collapse.d.ts +13 -0
- package/dist/ui/components/toolbar-collapse.js +10 -1
- package/dist/ui/index.d.ts +8 -0
- package/dist/ui/index.js +9 -0
- package/dist/ui/rich-text/RichText.d.ts +10 -1
- package/dist/ui/rich-text/RichText.js +33 -2
- package/dist/ui/rich-text/RichText.style.css +83 -79
- package/dist/ui/rich-text/RichTextRenderer.d.ts +30 -1
- package/dist/ui/rich-text/RichTextRenderer.js +34 -2
- package/dist/ui/rich-text/chart-blocks.d.ts +62 -0
- package/dist/ui/rich-text/chart-blocks.js +87 -0
- package/package.json +1 -1
- package/scripts/seed-cli.mjs +1834 -1822
|
@@ -79,6 +79,129 @@ export declare function normaliseDimensions(d: ParcelSource["dimensionsCm"]): Pa
|
|
|
79
79
|
* whichever tier won on weight would discard information that exists.
|
|
80
80
|
*/
|
|
81
81
|
export declare function resolveParcel(shipment: ParcelSource | null | undefined, product: ParcelSource | null | undefined, category: ParcelSource | null | undefined): Parcel | null;
|
|
82
|
+
/**
|
|
83
|
+
* Divisors, by service class.
|
|
84
|
+
*
|
|
85
|
+
* A carrier sells space, not mass, so it bills the greater of actual weight and
|
|
86
|
+
* `l × w × h ÷ divisor`. The divisor is the whole ballgame on this catalogue:
|
|
87
|
+
* collectible packaging is mostly air, so for a stadium box the volumetric
|
|
88
|
+
* figure is ~5× the actual and no per-kilo negotiation touches it.
|
|
89
|
+
*
|
|
90
|
+
* 🛑 `surfaceTight` is not a typo. Some Indian surface B2C plans quote ÷4000,
|
|
91
|
+
* which is a silent 25% increase over ÷5000 on every bulky parcel and is
|
|
92
|
+
* never the number on the front of the rate card. Read the contract, then set
|
|
93
|
+
* this per carrier — do not assume 5000 because it is the common default.
|
|
94
|
+
*
|
|
95
|
+
* Air uses a LARGER divisor, which means a very light bulky box can genuinely
|
|
96
|
+
* cost less by air than by surface. That is counter-intuitive and real.
|
|
97
|
+
*/
|
|
98
|
+
export declare const VOLUMETRIC_DIVISORS: {
|
|
99
|
+
readonly surfaceTight: 4000;
|
|
100
|
+
readonly standard: 5000;
|
|
101
|
+
readonly air: 6000;
|
|
102
|
+
};
|
|
103
|
+
export declare const DEFAULT_VOLUMETRIC_DIVISOR: 5000;
|
|
104
|
+
/**
|
|
105
|
+
* Where a parcel sits against the two thresholds, and therefore which carrier
|
|
106
|
+
* class is cheaper. See `carrierClassFor` for why these numbers.
|
|
107
|
+
*/
|
|
108
|
+
export declare const VOLUMETRIC_RATIO_THRESHOLDS: {
|
|
109
|
+
/** Below this the two weights are close enough that the rate card decides. */
|
|
110
|
+
readonly private: 1.5;
|
|
111
|
+
/** At or above this the box is mostly air and a postal service wins. */
|
|
112
|
+
readonly postal: 2;
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* The first billing slab, in grams — the region where R means nothing.
|
|
116
|
+
*
|
|
117
|
+
* 🛑 This guard exists because the ratio rule is WRONG below it, and the error
|
|
118
|
+
* was caught by checking the rule against real tariffs instead of trusting it.
|
|
119
|
+
*
|
|
120
|
+
* A single boxed bey is 250 g actual / 448 g volumetric — R 1.79, which the
|
|
121
|
+
* thresholds above call `"either"`. The real bill at >2000 km is ₹106 by Speed
|
|
122
|
+
* Post against ₹50 by private courier: private wins by 2×, not "either".
|
|
123
|
+
*
|
|
124
|
+
* The reason is that both figures land inside each carrier's MINIMUM charge, so
|
|
125
|
+
* the comparison is floor against floor and the ratio describes nothing. India
|
|
126
|
+
* Post's 201–500 g floor is ₹90; a private first slab is around ₹42. Whenever
|
|
127
|
+
* both weights sit in that first slab, the lower floor wins and that is private.
|
|
128
|
+
*/
|
|
129
|
+
export declare const FIRST_SLAB_G = 500;
|
|
130
|
+
export interface ChargeableWeight {
|
|
131
|
+
actualG: number;
|
|
132
|
+
/**
|
|
133
|
+
* `null` when the dimension triple is unknown — NEVER 0.
|
|
134
|
+
*
|
|
135
|
+
* A carrier with no dimensions bills actual weight, so `chargeableG` is still
|
|
136
|
+
* correct in that case. But a `0` here would read as "this box has no volume",
|
|
137
|
+
* and `ratio` would compute to 0, which routes a stadium to the private
|
|
138
|
+
* carrier that bills it at 7.3 kg. Unknown has to stay distinguishable from
|
|
139
|
+
* dense — same discipline as `resolveParcel` refusing to return weight 0.
|
|
140
|
+
*/
|
|
141
|
+
volumetricG: number | null;
|
|
142
|
+
/** `max(actual, volumetric)` — what you are billed for. */
|
|
143
|
+
chargeableG: number;
|
|
144
|
+
divisor: number;
|
|
145
|
+
billedOn: "actual" | "volumetric";
|
|
146
|
+
/**
|
|
147
|
+
* **The R value**: volumetric ÷ actual, 2dp. `null` without dimensions.
|
|
148
|
+
*
|
|
149
|
+
* 1 means the box is exactly at the divisor's break-even density. Above 1 you
|
|
150
|
+
* are paying for air; below 1 the volume is free and actual weight bills.
|
|
151
|
+
*/
|
|
152
|
+
ratio: number | null;
|
|
153
|
+
/** Packed density in kg/m³. `null` without dimensions. */
|
|
154
|
+
densityKgM3: number | null;
|
|
155
|
+
/**
|
|
156
|
+
* The density at which volumetric starts to bite, derived from the divisor
|
|
157
|
+
* rather than hardcoded: `1e6 / divisor`. 200 kg/m³ at ÷5000, 250 at ÷4000,
|
|
158
|
+
* ~167 at ÷6000. A parcel below this is billed on volume.
|
|
159
|
+
*/
|
|
160
|
+
breakEvenKgM3: number;
|
|
161
|
+
}
|
|
162
|
+
/** Volumetric weight in grams. `l × w × h ÷ divisor` is kilos, hence ×1000. */
|
|
163
|
+
export declare function volumetricWeightG(d: ParcelDimensionsCm, divisor?: number): number;
|
|
164
|
+
/**
|
|
165
|
+
* What this parcel is billed at, and by how much volume beats mass.
|
|
166
|
+
*
|
|
167
|
+
* Pure arithmetic — it reports, it does not decide. `carrierClassFor` turns the
|
|
168
|
+
* result into a routing opinion, deliberately as a separate step so a surface
|
|
169
|
+
* can show the numbers without adopting the recommendation.
|
|
170
|
+
*/
|
|
171
|
+
export declare function chargeableWeight(parcel: Pick<Parcel, "weightG" | "dimensionsCm">, divisor?: number): ChargeableWeight;
|
|
172
|
+
/**
|
|
173
|
+
* Which carrier class is cheaper for this parcel, on freight alone.
|
|
174
|
+
*
|
|
175
|
+
* India Post Speed Post bills ACTUAL weight and applies no volumetric
|
|
176
|
+
* calculation; every private carrier bills the greater of the two. So the
|
|
177
|
+
* freight comparison reduces to the R value:
|
|
178
|
+
*
|
|
179
|
+
* R < 1.5 the two weights are close; the rate card decides, and a private
|
|
180
|
+
* card is usually cheaper at low weight → `"private"`
|
|
181
|
+
* 1.5 ≤ R < 2 genuinely close; decide on pincode serviceability and
|
|
182
|
+
* whether the item needs insurance → `"either"`
|
|
183
|
+
* R ≥ 2 the box is mostly air and postal is materially cheaper → `"postal"`
|
|
184
|
+
*
|
|
185
|
+
* 🛑 `"unknown"` when dimensions are missing, and callers must not collapse it
|
|
186
|
+
* into a default. Defaulting to `"private"` is precisely the wrong way round:
|
|
187
|
+
* the parcels whose dimensions nobody recorded are disproportionately the big
|
|
188
|
+
* awkward ones, which are the parcels this function exists to divert.
|
|
189
|
+
*
|
|
190
|
+
* 🛑 This is a FREIGHT opinion and nothing more. Above roughly ₹8,000 of order
|
|
191
|
+
* value the decision stops being about freight — the delta is a few hundred
|
|
192
|
+
* rupees against an uninsured loss of the whole item — so an order-value test
|
|
193
|
+
* and serviceability both outrank this. It answers "which is cheaper", never
|
|
194
|
+
* "which should we book".
|
|
195
|
+
*
|
|
196
|
+
* ## Where it is weakest, stated rather than hidden
|
|
197
|
+
*
|
|
198
|
+
* At HIGH weight the per-additional-slab rates start to matter more than the
|
|
199
|
+
* ratio, and those are negotiated. A 8 kg / 14 kg parcel is R 1.75 → `"either"`,
|
|
200
|
+
* while one representative card puts it at ₹991 postal against ₹1,197 private —
|
|
201
|
+
* a real 21% gap the ratio does not see. `"either"` is the honest answer there:
|
|
202
|
+
* it means your own card decides, not that the two are equal.
|
|
203
|
+
*/
|
|
204
|
+
export declare function carrierClassFor(c: Pick<ChargeableWeight, "ratio" | "actualG" | "volumetricG">): "private" | "either" | "postal" | "unknown";
|
|
82
205
|
/**
|
|
83
206
|
* The weight of a whole order group — what a single shipment actually carries.
|
|
84
207
|
*
|
|
@@ -88,6 +88,145 @@ export function resolveParcel(shipment, product, category) {
|
|
|
88
88
|
}
|
|
89
89
|
return { weightG, source, ...(dimensionsCm ? { dimensionsCm } : {}) };
|
|
90
90
|
}
|
|
91
|
+
/* ── Volumetric weight — what the carrier actually bills ──────────────────── */
|
|
92
|
+
/**
|
|
93
|
+
* Divisors, by service class.
|
|
94
|
+
*
|
|
95
|
+
* A carrier sells space, not mass, so it bills the greater of actual weight and
|
|
96
|
+
* `l × w × h ÷ divisor`. The divisor is the whole ballgame on this catalogue:
|
|
97
|
+
* collectible packaging is mostly air, so for a stadium box the volumetric
|
|
98
|
+
* figure is ~5× the actual and no per-kilo negotiation touches it.
|
|
99
|
+
*
|
|
100
|
+
* 🛑 `surfaceTight` is not a typo. Some Indian surface B2C plans quote ÷4000,
|
|
101
|
+
* which is a silent 25% increase over ÷5000 on every bulky parcel and is
|
|
102
|
+
* never the number on the front of the rate card. Read the contract, then set
|
|
103
|
+
* this per carrier — do not assume 5000 because it is the common default.
|
|
104
|
+
*
|
|
105
|
+
* Air uses a LARGER divisor, which means a very light bulky box can genuinely
|
|
106
|
+
* cost less by air than by surface. That is counter-intuitive and real.
|
|
107
|
+
*/
|
|
108
|
+
export const VOLUMETRIC_DIVISORS = {
|
|
109
|
+
surfaceTight: 4000,
|
|
110
|
+
standard: 5000,
|
|
111
|
+
air: 6000,
|
|
112
|
+
};
|
|
113
|
+
export const DEFAULT_VOLUMETRIC_DIVISOR = VOLUMETRIC_DIVISORS.standard;
|
|
114
|
+
/**
|
|
115
|
+
* Where a parcel sits against the two thresholds, and therefore which carrier
|
|
116
|
+
* class is cheaper. See `carrierClassFor` for why these numbers.
|
|
117
|
+
*/
|
|
118
|
+
export const VOLUMETRIC_RATIO_THRESHOLDS = {
|
|
119
|
+
/** Below this the two weights are close enough that the rate card decides. */
|
|
120
|
+
private: 1.5,
|
|
121
|
+
/** At or above this the box is mostly air and a postal service wins. */
|
|
122
|
+
postal: 2,
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* The first billing slab, in grams — the region where R means nothing.
|
|
126
|
+
*
|
|
127
|
+
* 🛑 This guard exists because the ratio rule is WRONG below it, and the error
|
|
128
|
+
* was caught by checking the rule against real tariffs instead of trusting it.
|
|
129
|
+
*
|
|
130
|
+
* A single boxed bey is 250 g actual / 448 g volumetric — R 1.79, which the
|
|
131
|
+
* thresholds above call `"either"`. The real bill at >2000 km is ₹106 by Speed
|
|
132
|
+
* Post against ₹50 by private courier: private wins by 2×, not "either".
|
|
133
|
+
*
|
|
134
|
+
* The reason is that both figures land inside each carrier's MINIMUM charge, so
|
|
135
|
+
* the comparison is floor against floor and the ratio describes nothing. India
|
|
136
|
+
* Post's 201–500 g floor is ₹90; a private first slab is around ₹42. Whenever
|
|
137
|
+
* both weights sit in that first slab, the lower floor wins and that is private.
|
|
138
|
+
*/
|
|
139
|
+
export const FIRST_SLAB_G = 500;
|
|
140
|
+
/** Volumetric weight in grams. `l × w × h ÷ divisor` is kilos, hence ×1000. */
|
|
141
|
+
export function volumetricWeightG(d, divisor = DEFAULT_VOLUMETRIC_DIVISOR) {
|
|
142
|
+
if (!(divisor > 0)) {
|
|
143
|
+
throw new RangeError(`volumetricWeightG: divisor must be > 0, got ${divisor}`);
|
|
144
|
+
}
|
|
145
|
+
return Math.round(((d.l * d.w * d.h) / divisor) * 1000);
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* What this parcel is billed at, and by how much volume beats mass.
|
|
149
|
+
*
|
|
150
|
+
* Pure arithmetic — it reports, it does not decide. `carrierClassFor` turns the
|
|
151
|
+
* result into a routing opinion, deliberately as a separate step so a surface
|
|
152
|
+
* can show the numbers without adopting the recommendation.
|
|
153
|
+
*/
|
|
154
|
+
export function chargeableWeight(parcel, divisor = DEFAULT_VOLUMETRIC_DIVISOR) {
|
|
155
|
+
const actualG = parcel.weightG;
|
|
156
|
+
const breakEvenKgM3 = Math.round((1000000 / divisor) * 10) / 10;
|
|
157
|
+
const d = parcel.dimensionsCm;
|
|
158
|
+
if (!d) {
|
|
159
|
+
return {
|
|
160
|
+
actualG,
|
|
161
|
+
volumetricG: null,
|
|
162
|
+
chargeableG: actualG,
|
|
163
|
+
divisor,
|
|
164
|
+
billedOn: "actual",
|
|
165
|
+
ratio: null,
|
|
166
|
+
densityKgM3: null,
|
|
167
|
+
breakEvenKgM3,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
const volumetricG = volumetricWeightG(d, divisor);
|
|
171
|
+
const cm3 = d.l * d.w * d.h;
|
|
172
|
+
return {
|
|
173
|
+
actualG,
|
|
174
|
+
volumetricG,
|
|
175
|
+
chargeableG: Math.max(actualG, volumetricG),
|
|
176
|
+
divisor,
|
|
177
|
+
billedOn: volumetricG > actualG ? "volumetric" : "actual",
|
|
178
|
+
ratio: actualG > 0 ? Math.round((volumetricG / actualG) * 100) / 100 : null,
|
|
179
|
+
densityKgM3: cm3 > 0 ? Math.round(((actualG * 1000) / cm3) * 10) / 10 : null,
|
|
180
|
+
breakEvenKgM3,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Which carrier class is cheaper for this parcel, on freight alone.
|
|
185
|
+
*
|
|
186
|
+
* India Post Speed Post bills ACTUAL weight and applies no volumetric
|
|
187
|
+
* calculation; every private carrier bills the greater of the two. So the
|
|
188
|
+
* freight comparison reduces to the R value:
|
|
189
|
+
*
|
|
190
|
+
* R < 1.5 the two weights are close; the rate card decides, and a private
|
|
191
|
+
* card is usually cheaper at low weight → `"private"`
|
|
192
|
+
* 1.5 ≤ R < 2 genuinely close; decide on pincode serviceability and
|
|
193
|
+
* whether the item needs insurance → `"either"`
|
|
194
|
+
* R ≥ 2 the box is mostly air and postal is materially cheaper → `"postal"`
|
|
195
|
+
*
|
|
196
|
+
* 🛑 `"unknown"` when dimensions are missing, and callers must not collapse it
|
|
197
|
+
* into a default. Defaulting to `"private"` is precisely the wrong way round:
|
|
198
|
+
* the parcels whose dimensions nobody recorded are disproportionately the big
|
|
199
|
+
* awkward ones, which are the parcels this function exists to divert.
|
|
200
|
+
*
|
|
201
|
+
* 🛑 This is a FREIGHT opinion and nothing more. Above roughly ₹8,000 of order
|
|
202
|
+
* value the decision stops being about freight — the delta is a few hundred
|
|
203
|
+
* rupees against an uninsured loss of the whole item — so an order-value test
|
|
204
|
+
* and serviceability both outrank this. It answers "which is cheaper", never
|
|
205
|
+
* "which should we book".
|
|
206
|
+
*
|
|
207
|
+
* ## Where it is weakest, stated rather than hidden
|
|
208
|
+
*
|
|
209
|
+
* At HIGH weight the per-additional-slab rates start to matter more than the
|
|
210
|
+
* ratio, and those are negotiated. A 8 kg / 14 kg parcel is R 1.75 → `"either"`,
|
|
211
|
+
* while one representative card puts it at ₹991 postal against ₹1,197 private —
|
|
212
|
+
* a real 21% gap the ratio does not see. `"either"` is the honest answer there:
|
|
213
|
+
* it means your own card decides, not that the two are equal.
|
|
214
|
+
*/
|
|
215
|
+
export function carrierClassFor(c) {
|
|
216
|
+
if (c.ratio == null)
|
|
217
|
+
return "unknown";
|
|
218
|
+
// Both weights inside the first slab → floor vs floor; see FIRST_SLAB_G.
|
|
219
|
+
if (c.actualG <= FIRST_SLAB_G &&
|
|
220
|
+
c.volumetricG != null &&
|
|
221
|
+
c.volumetricG <= FIRST_SLAB_G) {
|
|
222
|
+
return "private";
|
|
223
|
+
}
|
|
224
|
+
if (c.ratio >= VOLUMETRIC_RATIO_THRESHOLDS.postal)
|
|
225
|
+
return "postal";
|
|
226
|
+
if (c.ratio >= VOLUMETRIC_RATIO_THRESHOLDS.private)
|
|
227
|
+
return "either";
|
|
228
|
+
return "private";
|
|
229
|
+
}
|
|
91
230
|
/**
|
|
92
231
|
* The weight of a whole order group — what a single shipment actually carries.
|
|
93
232
|
*
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared purchase, S5a — one payer, N destinations.
|
|
3
|
+
*
|
|
4
|
+
* ## What this is, and what it deliberately is not
|
|
5
|
+
*
|
|
6
|
+
* The coordinator buys everything and assigns a destination per item, so one
|
|
7
|
+
* paid order becomes N parcels. That is **~20% of the shared-purchase work for
|
|
8
|
+
* most of its value** (the plan's own assessment), because it needs none of
|
|
9
|
+
* the hard parts: no multi-party payment, no coordinator deposit, no approval
|
|
10
|
+
* cascade, no per-buyer invoicing, no per-buyer GST, and no stock-reservation
|
|
11
|
+
* primitive.
|
|
12
|
+
*
|
|
13
|
+
* 🛑 It is NOT S5b. There is exactly ONE payer and ONE place of supply, which
|
|
14
|
+
* is what keeps the tax, the invoice and the refund path unchanged. The moment
|
|
15
|
+
* a second person pays, every one of those becomes per-buyer and the design is
|
|
16
|
+
* a different design.
|
|
17
|
+
*
|
|
18
|
+
* ## 🛑 Why the fees are SNAPSHOTTED, and the precedent that proves it
|
|
19
|
+
*
|
|
20
|
+
* A coordinator commits to a quoted total. If the handling fee or the
|
|
21
|
+
* per-destination shipping is re-read at settle, a seller can raise it after
|
|
22
|
+
* the quote and the coordinator absorbs the difference.
|
|
23
|
+
*
|
|
24
|
+
* The codebase already has this exact hole and this exact fix: the refund path
|
|
25
|
+
* reads `finalSale` from the ORDER snapshot rather than the live product,
|
|
26
|
+
* because — in its own words — "re-reading the live product would let a seller
|
|
27
|
+
* flip the switch afterwards". D61 generalises it: *any agreement with a gap
|
|
28
|
+
* between "terms agreed" and "money taken" must snapshot its terms at
|
|
29
|
+
* agreement.*
|
|
30
|
+
*
|
|
31
|
+
* So `quoteSharedPurchase` takes the rates as ARGUMENTS and the caller
|
|
32
|
+
* snapshots the result onto the order. There is no settings read in here.
|
|
33
|
+
*/
|
|
34
|
+
/** The two rates, read from the store document at quote time. */
|
|
35
|
+
export interface SharedPurchaseRates {
|
|
36
|
+
allowSharedPurchase?: boolean;
|
|
37
|
+
sharedPurchaseHandlingFee?: number;
|
|
38
|
+
sharedPurchaseExtraShippingPerDestination?: number;
|
|
39
|
+
}
|
|
40
|
+
export interface SharedPurchaseQuoteInput {
|
|
41
|
+
/**
|
|
42
|
+
* Distinct destinations in this order group, INCLUDING the first.
|
|
43
|
+
*
|
|
44
|
+
* 🛑 A count of DISTINCT addresses, not of items. Three items to one address
|
|
45
|
+
* is one parcel and no extra leg; two items to two addresses is two. Passing
|
|
46
|
+
* an item count would charge a coordinator for splitting an order they did
|
|
47
|
+
* not split.
|
|
48
|
+
*/
|
|
49
|
+
destinationCount: number;
|
|
50
|
+
/** The store's snapshotted rates. */
|
|
51
|
+
rates: SharedPurchaseRates;
|
|
52
|
+
}
|
|
53
|
+
export interface SharedPurchaseQuote {
|
|
54
|
+
/** True when this is actually a multi-destination order. */
|
|
55
|
+
isShared: boolean;
|
|
56
|
+
/** Flat handling fee, or 0. */
|
|
57
|
+
handlingFee: number;
|
|
58
|
+
/** Extra shipping for destinations beyond the first, or 0. */
|
|
59
|
+
extraShippingFee: number;
|
|
60
|
+
/** `handlingFee + extraShippingFee`, the figure added to the order total. */
|
|
61
|
+
total: number;
|
|
62
|
+
/**
|
|
63
|
+
* Set when the arrangement cannot be priced — the seller allows it but has
|
|
64
|
+
* not configured a rate.
|
|
65
|
+
*
|
|
66
|
+
* 🛑 The caller MUST act on this rather than treating the fee as ₹0. That is
|
|
67
|
+
* D44 exactly: `shippingUnavailable` existed with its own docstring saying
|
|
68
|
+
* "the caller MUST act on this rather than trusting `shippingFee: 0`", had
|
|
69
|
+
* ZERO consumers, and an `estimate`-mode store shipped free on every path as
|
|
70
|
+
* a result. An unpriced arrangement must be refused, not given away.
|
|
71
|
+
*/
|
|
72
|
+
unpriced?: "handling" | "extra-shipping";
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Price a shared-purchase arrangement for ONE order group.
|
|
76
|
+
*
|
|
77
|
+
* Pure: no settings read, no Firestore, no clock. The rates come in, the
|
|
78
|
+
* figure comes out, and the caller snapshots it.
|
|
79
|
+
*/
|
|
80
|
+
export declare function quoteSharedPurchase(input: SharedPurchaseQuoteInput): SharedPurchaseQuote;
|
|
81
|
+
/**
|
|
82
|
+
* Distinct destinations across a set of lines.
|
|
83
|
+
*
|
|
84
|
+
* 🛑 Lines with NO `destinationAddressId` collapse into one bucket — the
|
|
85
|
+
* order's own address — rather than counting as a destination each. Otherwise
|
|
86
|
+
* an ordinary three-item order would look like three destinations and be
|
|
87
|
+
* charged two extra legs.
|
|
88
|
+
*/
|
|
89
|
+
export declare function countDestinations(lines: readonly {
|
|
90
|
+
destinationAddressId?: string;
|
|
91
|
+
}[]): number;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared purchase, S5a — one payer, N destinations.
|
|
3
|
+
*
|
|
4
|
+
* ## What this is, and what it deliberately is not
|
|
5
|
+
*
|
|
6
|
+
* The coordinator buys everything and assigns a destination per item, so one
|
|
7
|
+
* paid order becomes N parcels. That is **~20% of the shared-purchase work for
|
|
8
|
+
* most of its value** (the plan's own assessment), because it needs none of
|
|
9
|
+
* the hard parts: no multi-party payment, no coordinator deposit, no approval
|
|
10
|
+
* cascade, no per-buyer invoicing, no per-buyer GST, and no stock-reservation
|
|
11
|
+
* primitive.
|
|
12
|
+
*
|
|
13
|
+
* 🛑 It is NOT S5b. There is exactly ONE payer and ONE place of supply, which
|
|
14
|
+
* is what keeps the tax, the invoice and the refund path unchanged. The moment
|
|
15
|
+
* a second person pays, every one of those becomes per-buyer and the design is
|
|
16
|
+
* a different design.
|
|
17
|
+
*
|
|
18
|
+
* ## 🛑 Why the fees are SNAPSHOTTED, and the precedent that proves it
|
|
19
|
+
*
|
|
20
|
+
* A coordinator commits to a quoted total. If the handling fee or the
|
|
21
|
+
* per-destination shipping is re-read at settle, a seller can raise it after
|
|
22
|
+
* the quote and the coordinator absorbs the difference.
|
|
23
|
+
*
|
|
24
|
+
* The codebase already has this exact hole and this exact fix: the refund path
|
|
25
|
+
* reads `finalSale` from the ORDER snapshot rather than the live product,
|
|
26
|
+
* because — in its own words — "re-reading the live product would let a seller
|
|
27
|
+
* flip the switch afterwards". D61 generalises it: *any agreement with a gap
|
|
28
|
+
* between "terms agreed" and "money taken" must snapshot its terms at
|
|
29
|
+
* agreement.*
|
|
30
|
+
*
|
|
31
|
+
* So `quoteSharedPurchase` takes the rates as ARGUMENTS and the caller
|
|
32
|
+
* snapshots the result onto the order. There is no settings read in here.
|
|
33
|
+
*/
|
|
34
|
+
import { roundRupees } from "../../../../utils/number.formatter.js";
|
|
35
|
+
/**
|
|
36
|
+
* Price a shared-purchase arrangement for ONE order group.
|
|
37
|
+
*
|
|
38
|
+
* Pure: no settings read, no Firestore, no clock. The rates come in, the
|
|
39
|
+
* figure comes out, and the caller snapshots it.
|
|
40
|
+
*/
|
|
41
|
+
export function quoteSharedPurchase(input) {
|
|
42
|
+
const none = {
|
|
43
|
+
isShared: false,
|
|
44
|
+
handlingFee: 0,
|
|
45
|
+
extraShippingFee: 0,
|
|
46
|
+
total: 0,
|
|
47
|
+
};
|
|
48
|
+
/*
|
|
49
|
+
* One destination is an ordinary order. Checked BEFORE the allow flag, so a
|
|
50
|
+
* seller who has not opted in is unaffected by this code path entirely —
|
|
51
|
+
* rather than being refused an order they were always able to take.
|
|
52
|
+
*/
|
|
53
|
+
const destinations = Math.max(1, Math.floor(input.destinationCount));
|
|
54
|
+
if (destinations <= 1)
|
|
55
|
+
return none;
|
|
56
|
+
if (input.rates.allowSharedPurchase !== true) {
|
|
57
|
+
/*
|
|
58
|
+
* 🛑 Returns `isShared: false` rather than throwing, and the CALLER
|
|
59
|
+
* refuses. This function prices; it does not authorise. A thrown error
|
|
60
|
+
* here would be caught by a preview path and rendered as a broken page,
|
|
61
|
+
* where the correct behaviour is to tell the buyer this seller does not
|
|
62
|
+
* split orders.
|
|
63
|
+
*/
|
|
64
|
+
return none;
|
|
65
|
+
}
|
|
66
|
+
const handling = input.rates.sharedPurchaseHandlingFee;
|
|
67
|
+
const perExtra = input.rates.sharedPurchaseExtraShippingPerDestination;
|
|
68
|
+
/*
|
|
69
|
+
* 🛑 `undefined` is UNPRICED, not zero — see the `unpriced` field. A seller
|
|
70
|
+
* who opted in without setting a rate has not agreed to do it for free, and
|
|
71
|
+
* charging ₹0 would hand them the extra labour at their own cost silently.
|
|
72
|
+
*/
|
|
73
|
+
if (typeof handling !== "number" || !Number.isFinite(handling)) {
|
|
74
|
+
return { ...none, isShared: true, unpriced: "handling" };
|
|
75
|
+
}
|
|
76
|
+
if (typeof perExtra !== "number" || !Number.isFinite(perExtra)) {
|
|
77
|
+
return { ...none, isShared: true, unpriced: "extra-shipping" };
|
|
78
|
+
}
|
|
79
|
+
const handlingFee = roundRupees(Math.max(0, handling));
|
|
80
|
+
// BEYOND THE FIRST: the first destination's shipping is what the order would
|
|
81
|
+
// have paid anyway, so only the marginal legs are charged here.
|
|
82
|
+
const extraShippingFee = roundRupees(Math.max(0, perExtra) * (destinations - 1));
|
|
83
|
+
return {
|
|
84
|
+
isShared: true,
|
|
85
|
+
handlingFee,
|
|
86
|
+
extraShippingFee,
|
|
87
|
+
total: roundRupees(handlingFee + extraShippingFee),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Distinct destinations across a set of lines.
|
|
92
|
+
*
|
|
93
|
+
* 🛑 Lines with NO `destinationAddressId` collapse into one bucket — the
|
|
94
|
+
* order's own address — rather than counting as a destination each. Otherwise
|
|
95
|
+
* an ordinary three-item order would look like three destinations and be
|
|
96
|
+
* charged two extra legs.
|
|
97
|
+
*/
|
|
98
|
+
export function countDestinations(lines) {
|
|
99
|
+
const ids = new Set();
|
|
100
|
+
let usesOrderAddress = false;
|
|
101
|
+
for (const line of lines) {
|
|
102
|
+
if (line.destinationAddressId)
|
|
103
|
+
ids.add(line.destinationAddressId);
|
|
104
|
+
else
|
|
105
|
+
usesOrderAddress = true;
|
|
106
|
+
}
|
|
107
|
+
return ids.size + (usesOrderAddress ? 1 : 0);
|
|
108
|
+
}
|
|
@@ -38,17 +38,25 @@ export interface BuyerFacingFees {
|
|
|
38
38
|
codHandlingFeeCap?: number;
|
|
39
39
|
codHandlingFeePercent?: number;
|
|
40
40
|
codDepositPercent?: number;
|
|
41
|
+
/** Commission rate applied to the cart subtotal, before the cap. */
|
|
42
|
+
platformFeePercent?: number;
|
|
43
|
+
/** Rupee ceiling on the commission — the reason a ₹39,500 order pays ₹10. */
|
|
44
|
+
platformFeeMax?: number;
|
|
45
|
+
/** GST rate levied on the commission actually charged (never on the uncapped figure). */
|
|
46
|
+
gstPercent?: number;
|
|
47
|
+
/** Rupee floor on `platformFee + gstOnFee` combined. */
|
|
48
|
+
minimumTransactionFee?: number;
|
|
41
49
|
}
|
|
42
50
|
/**
|
|
43
|
-
* Withheld on purpose (
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
51
|
+
* Withheld on purpose (11 of 25): gatewayFeePercent, sellerShippingFixed,
|
|
52
|
+
* platformShippingPercent, platformShippingFixedMin, autoPayoutWindowDays,
|
|
53
|
+
* payoutHoldDays, minPayoutAmount, auctionListingFee, preOrderListingFee,
|
|
54
|
+
* featuredSlotFee, promotedSlotFee — plus `surchargeSellerSharePercent`, which
|
|
55
|
+
* lives on the EMI block and is excluded by `BuyerEmiSettings` below.
|
|
48
56
|
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
57
|
+
* Every one of those prices something between us and a seller or a gateway.
|
|
58
|
+
* None of them changes what the buyer is asked to pay, so none of them has a
|
|
59
|
+
* reader in a browser.
|
|
52
60
|
*/
|
|
53
61
|
export declare function toBuyerFacingFees(commissions: SiteSettingsDocument["commissions"] | null | undefined): BuyerFacingFees | null;
|
|
54
62
|
/**
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Withheld on purpose (
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
2
|
+
* Withheld on purpose (11 of 25): gatewayFeePercent, sellerShippingFixed,
|
|
3
|
+
* platformShippingPercent, platformShippingFixedMin, autoPayoutWindowDays,
|
|
4
|
+
* payoutHoldDays, minPayoutAmount, auctionListingFee, preOrderListingFee,
|
|
5
|
+
* featuredSlotFee, promotedSlotFee — plus `surchargeSellerSharePercent`, which
|
|
6
|
+
* lives on the EMI block and is excluded by `BuyerEmiSettings` below.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* Every one of those prices something between us and a seller or a gateway.
|
|
9
|
+
* None of them changes what the buyer is asked to pay, so none of them has a
|
|
10
|
+
* reader in a browser.
|
|
11
11
|
*/
|
|
12
12
|
export function toBuyerFacingFees(commissions) {
|
|
13
13
|
if (!commissions)
|
|
@@ -24,6 +24,10 @@ export function toBuyerFacingFees(commissions) {
|
|
|
24
24
|
codHandlingFeeCap: commissions.codHandlingFeeCap,
|
|
25
25
|
codHandlingFeePercent: commissions.codHandlingFeePercent,
|
|
26
26
|
codDepositPercent: commissions.codDepositPercent,
|
|
27
|
+
platformFeePercent: commissions.platformFeePercent,
|
|
28
|
+
platformFeeMax: commissions.platformFeeMax,
|
|
29
|
+
gstPercent: commissions.gstPercent,
|
|
30
|
+
minimumTransactionFee: commissions.minimumTransactionFee,
|
|
27
31
|
};
|
|
28
32
|
}
|
|
29
33
|
export function toBuyerEmiSettings(emi) {
|
|
@@ -42,6 +42,17 @@ export interface PublicSiteSettings {
|
|
|
42
42
|
chat?: {
|
|
43
43
|
enabled: boolean;
|
|
44
44
|
};
|
|
45
|
+
/**
|
|
46
|
+
* Is the support desk reachable — read by `UserLayoutClient`, a client
|
|
47
|
+
* component. Narrowed to the one boolean rather than passed by reference,
|
|
48
|
+
* so a field added to the document's `support` group later is not published
|
|
49
|
+
* by accident; `PUBLIC_SITE_SETTINGS_FIELDS` carries the same caveat beside
|
|
50
|
+
* its entry. Optional here because the group is absent on a settings
|
|
51
|
+
* document written before it existed.
|
|
52
|
+
*/
|
|
53
|
+
support?: {
|
|
54
|
+
enabled: boolean;
|
|
55
|
+
};
|
|
45
56
|
/**
|
|
46
57
|
* The browser-side search index kill switch. **ON by default** — the
|
|
47
58
|
* projection emits `indexEnabled: doc.search?.indexEnabled !== false`, so
|
|
@@ -79,6 +79,17 @@ export interface PayoutDeduction {
|
|
|
79
79
|
* plus ₹80 postage" is a sentence; one net figure is not.
|
|
80
80
|
*/
|
|
81
81
|
shippingReimbursement: number;
|
|
82
|
+
/**
|
|
83
|
+
* Rupee value of buyer points this order was settled with, deducted from
|
|
84
|
+
* `netAmount` (D46/D47, decisions 3 and 17 — the accepting store funds the
|
|
85
|
+
* redemption).
|
|
86
|
+
*
|
|
87
|
+
* Returned as its own figure rather than folded into `totalDeduction` for the
|
|
88
|
+
* same reason `shippingReimbursement` is: *"'₹900 less ₹30 commission plus
|
|
89
|
+
* ₹80 postage' is a sentence; one net figure is not."* A seller looking at a
|
|
90
|
+
* short payout needs to see which of the four terms shortened it.
|
|
91
|
+
*/
|
|
92
|
+
pointsFunded: number;
|
|
82
93
|
}
|
|
83
94
|
/**
|
|
84
95
|
* What a seller is actually paid.
|
|
@@ -101,8 +112,29 @@ export interface PayoutDeduction {
|
|
|
101
112
|
*
|
|
102
113
|
* Defaulted to 0, so the three call sites that do not yet pass it keep their
|
|
103
114
|
* current behaviour exactly rather than silently gaining a term.
|
|
115
|
+
*
|
|
116
|
+
* ## 🛑 `pointsFunded` is the mirror of that, and it is a DEDUCTION
|
|
117
|
+
*
|
|
118
|
+
* Decisions 3 and 17: the programme is seller-funded at both ends — the
|
|
119
|
+
* accepting store absorbs the redemption, the originating store bears the
|
|
120
|
+
* earn — and the platform funds neither. So points spent on an order reduce
|
|
121
|
+
* that order's payout by the rupee value spent.
|
|
122
|
+
*
|
|
123
|
+
* It sits in the SAME position as postage and for the inverse reason: outside
|
|
124
|
+
* the commission and gateway bases. The seller agreed to fund a discount, not
|
|
125
|
+
* to pay us a commission on the discount they funded, and a gateway percentage
|
|
126
|
+
* on money no gateway touched is not a card fee at all.
|
|
127
|
+
*
|
|
128
|
+
* 🛑 So `grossAmount` is untouched and the fee figures are IDENTICAL whether
|
|
129
|
+
* points were used or not. That is what keeps the commission the seller is
|
|
130
|
+
* charged a function of the sale rather than of how the buyer chose to settle
|
|
131
|
+
* it — and it is why this cannot be implemented by passing a smaller
|
|
132
|
+
* `grossAmount`, which is the obvious shortcut and silently reduces our own
|
|
133
|
+
* commission by 2% of every redemption.
|
|
134
|
+
*
|
|
135
|
+
* Also defaulted to 0, for the same reason.
|
|
104
136
|
*/
|
|
105
|
-
export declare function computePayoutDeduction(grossAmount: number, commissions: FeeCommissionRates, shippingReimbursement?: number): PayoutDeduction;
|
|
137
|
+
export declare function computePayoutDeduction(grossAmount: number, commissions: FeeCommissionRates, shippingReimbursement?: number, pointsFunded?: number): PayoutDeduction;
|
|
106
138
|
export interface CodHandlingFeeRates {
|
|
107
139
|
/**
|
|
108
140
|
* Rupee CEILING on the COD handling fee. Optional so a `siteSettings`
|
|
@@ -114,8 +114,29 @@ export function allocateCheckoutFees(groupSubtotals, fees) {
|
|
|
114
114
|
*
|
|
115
115
|
* Defaulted to 0, so the three call sites that do not yet pass it keep their
|
|
116
116
|
* current behaviour exactly rather than silently gaining a term.
|
|
117
|
+
*
|
|
118
|
+
* ## 🛑 `pointsFunded` is the mirror of that, and it is a DEDUCTION
|
|
119
|
+
*
|
|
120
|
+
* Decisions 3 and 17: the programme is seller-funded at both ends — the
|
|
121
|
+
* accepting store absorbs the redemption, the originating store bears the
|
|
122
|
+
* earn — and the platform funds neither. So points spent on an order reduce
|
|
123
|
+
* that order's payout by the rupee value spent.
|
|
124
|
+
*
|
|
125
|
+
* It sits in the SAME position as postage and for the inverse reason: outside
|
|
126
|
+
* the commission and gateway bases. The seller agreed to fund a discount, not
|
|
127
|
+
* to pay us a commission on the discount they funded, and a gateway percentage
|
|
128
|
+
* on money no gateway touched is not a card fee at all.
|
|
129
|
+
*
|
|
130
|
+
* 🛑 So `grossAmount` is untouched and the fee figures are IDENTICAL whether
|
|
131
|
+
* points were used or not. That is what keeps the commission the seller is
|
|
132
|
+
* charged a function of the sale rather than of how the buyer chose to settle
|
|
133
|
+
* it — and it is why this cannot be implemented by passing a smaller
|
|
134
|
+
* `grossAmount`, which is the obvious shortcut and silently reduces our own
|
|
135
|
+
* commission by 2% of every redemption.
|
|
136
|
+
*
|
|
137
|
+
* Also defaulted to 0, for the same reason.
|
|
117
138
|
*/
|
|
118
|
-
export function computePayoutDeduction(grossAmount, commissions, shippingReimbursement = 0) {
|
|
139
|
+
export function computePayoutDeduction(grossAmount, commissions, shippingReimbursement = 0, pointsFunded = 0) {
|
|
119
140
|
const platformFee = roundRupees(grossAmount * (commissions.platformFeePercent / 100));
|
|
120
141
|
const gatewayFee = roundRupees(grossAmount * ((commissions.gatewayFeePercent ?? 0) / 100));
|
|
121
142
|
const gstOnFee = roundRupees(platformFee * (commissions.gstPercent / 100));
|
|
@@ -123,7 +144,15 @@ export function computePayoutDeduction(grossAmount, commissions, shippingReimbur
|
|
|
123
144
|
const postage = Number.isFinite(shippingReimbursement)
|
|
124
145
|
? Math.max(0, shippingReimbursement)
|
|
125
146
|
: 0;
|
|
126
|
-
const
|
|
147
|
+
const points = Number.isFinite(pointsFunded) ? Math.max(0, pointsFunded) : 0;
|
|
148
|
+
/*
|
|
149
|
+
* Clamped at zero, as it already was. A redemption cannot exceed 50% of the
|
|
150
|
+
* order total, so it cannot plausibly exceed the net — but a floor here means
|
|
151
|
+
* no caller can ever hand a seller a negative payout, which would be written
|
|
152
|
+
* to a `PayoutDocument.amount` that every downstream sum then treats as a
|
|
153
|
+
* credit against the platform.
|
|
154
|
+
*/
|
|
155
|
+
const netAmount = Math.max(0, roundRupees(grossAmount - totalDeduction + postage - points));
|
|
127
156
|
return {
|
|
128
157
|
platformFee,
|
|
129
158
|
gatewayFee,
|
|
@@ -131,6 +160,7 @@ export function computePayoutDeduction(grossAmount, commissions, shippingReimbur
|
|
|
131
160
|
totalDeduction,
|
|
132
161
|
netAmount,
|
|
133
162
|
shippingReimbursement: roundRupees(postage),
|
|
163
|
+
pointsFunded: roundRupees(points),
|
|
134
164
|
};
|
|
135
165
|
}
|
|
136
166
|
/** Buyer-facing COD handling ceiling, in decimal rupees. */
|