@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
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { roundRupees } from "../../../utils/number.formatter.js";
|
|
2
2
|
import { calculateGstInclusive, taxableFromInclusive } from "../fees/calculator.js";
|
|
3
|
+
/*
|
|
4
|
+
* Points: the CAP arithmetic only. `maxRedeemablePoints` lives beside
|
|
5
|
+
* `POINTS_MAX_REDEMPTION_PERCENT`, which is the constant that defines it, so
|
|
6
|
+
* importing it here keeps one owner for the rule rather than a second copy of
|
|
7
|
+
* the percentage (Root Cause #75). This file stays pure — the points SCHEMA is
|
|
8
|
+
* plain data with no Firestore import.
|
|
9
|
+
*/
|
|
10
|
+
import { maxRedeemablePoints } from "../../../features/points/schemas/firestore.js";
|
|
3
11
|
/**
|
|
4
12
|
* The single source of truth for "what do we charge for ONE COPY of this line".
|
|
5
13
|
*
|
|
@@ -593,14 +601,165 @@ export function orderPointsFunded(order) {
|
|
|
593
601
|
? roundRupees(Math.max(0, awarded))
|
|
594
602
|
: 0;
|
|
595
603
|
}
|
|
604
|
+
/**
|
|
605
|
+
* Points this order CONSUMED, which the accepting store also funds (D46/D47).
|
|
606
|
+
*
|
|
607
|
+
* Decision 3's other end. The earn above is borne by the originating store;
|
|
608
|
+
* the redemption is absorbed by the store that agreed to accept points
|
|
609
|
+
* (`StoreDocument.acceptsPoints`, defaulting to NOT accepted precisely so no
|
|
610
|
+
* seller is enrolled in funding discounts they never agreed to). The platform
|
|
611
|
+
* funds neither end.
|
|
612
|
+
*
|
|
613
|
+
* Reads `pointsApplied` off the order for the same reason the earn reads
|
|
614
|
+
* `pointsAwarded`: it must be what was actually spent. Recomputing the cap from
|
|
615
|
+
* today's total would deduct a figure the buyer never received the benefit of —
|
|
616
|
+
* and on a partially-cancelled order the total has moved.
|
|
617
|
+
*/
|
|
618
|
+
export function orderPointsRedeemed(order) {
|
|
619
|
+
const applied = order.pointsApplied;
|
|
620
|
+
return typeof applied === "number" && Number.isFinite(applied)
|
|
621
|
+
? roundRupees(Math.max(0, applied))
|
|
622
|
+
: 0;
|
|
623
|
+
}
|
|
596
624
|
/** Sum of `orderPointsFunded` across a batch. */
|
|
597
625
|
export function ordersPointsFunded(orders) {
|
|
598
626
|
return roundRupees(orders.reduce((sum, o) => sum + orderPointsFunded(o), 0));
|
|
599
627
|
}
|
|
628
|
+
/**
|
|
629
|
+
* Everything the store funds through the points programme, for one batch:
|
|
630
|
+
* points ISSUED on these orders plus points SPENT on them.
|
|
631
|
+
*
|
|
632
|
+
* ## 🛑 One figure, because they are one obligation
|
|
633
|
+
*
|
|
634
|
+
* Both ends are seller-funded (decisions 3 and 17) and both are deducted from
|
|
635
|
+
* the same payout at the same moment, so splitting them across two parameters
|
|
636
|
+
* of `computePayoutDeduction` would be two chances for a call site to pass one
|
|
637
|
+
* and forget the other — and a payout that deducts the earn but not the
|
|
638
|
+
* redemption is short by exactly the amount nobody noticed.
|
|
639
|
+
*
|
|
640
|
+
* 🛑 This helper exists because `ordersPointsFunded` had **ZERO consumers**
|
|
641
|
+
* from the day it was written — the earn deduction was built, documented at
|
|
642
|
+
* length, and never passed to the function it was built for, so every payout
|
|
643
|
+
* since has quietly been funded by the platform. That is the dead-field
|
|
644
|
+
* pattern (Rule: every declared field has both a writer and a reader) occurring
|
|
645
|
+
* inside the work that catalogues it. Wiring the combined figure at all four
|
|
646
|
+
* call sites is what closes it.
|
|
647
|
+
*/
|
|
648
|
+
export function ordersPointsBorneByStore(orders) {
|
|
649
|
+
return roundRupees(orders.reduce((sum, o) => sum + orderPointsFunded(o) + orderPointsRedeemed(o), 0));
|
|
650
|
+
}
|
|
600
651
|
/** Sum of `orderShippingReimbursement` across a batch. */
|
|
601
652
|
export function ordersShippingReimbursement(orders) {
|
|
602
653
|
return roundRupees(orders.reduce((sum, o) => sum + orderShippingReimbursement(o), 0));
|
|
603
654
|
}
|
|
655
|
+
/**
|
|
656
|
+
* How many points may be spent on ONE order group, and what is left to charge.
|
|
657
|
+
*
|
|
658
|
+
* ## 🛑 A PIPELINE STAGE, after the final rounding — never a post-order debit
|
|
659
|
+
*
|
|
660
|
+
* This is the whole lesson of D46. The deleted code redeemed points AFTER the
|
|
661
|
+
* orders existed and the gateway had captured `orderTotal`, so a successful
|
|
662
|
+
* redemption took points from a buyer who had just paid full price: nothing in
|
|
663
|
+
* the pipeline knew about the spend, so nothing reduced the charge.
|
|
664
|
+
*
|
|
665
|
+
* So the tender is a STAGE. `amountDue = orderTotal − pointsApplied` is
|
|
666
|
+
* computed here, and `amountDue` is what the gateway captures and what the
|
|
667
|
+
* post-capture guard compares. A sixth way for the captured amount to diverge
|
|
668
|
+
* from the recorded total is the D37/D38/D40 family; this is how it is avoided.
|
|
669
|
+
*
|
|
670
|
+
* ## 🛑 Applied AFTER rounding, deliberately
|
|
671
|
+
*
|
|
672
|
+
* `orderTotal` is rounded ONCE at the end of its own nine-term sum (D42).
|
|
673
|
+
* Folding points in before that rounding would put a discount inside the sum
|
|
674
|
+
* being rounded, so the figure shown to the buyer and the figure captured could
|
|
675
|
+
* differ by a paisa. They must be provably equal, which is why `amountDue` is
|
|
676
|
+
* derived here and never recomputed at the gateway.
|
|
677
|
+
*
|
|
678
|
+
* ## Per order group, because the ACCEPTING STORE absorbs it
|
|
679
|
+
*
|
|
680
|
+
* Decision 3: a redeemed point reduces THAT store's payout for THAT order. A
|
|
681
|
+
* cart spanning an accepting and a non-accepting store must not pool the
|
|
682
|
+
* discount — each group gets its own cap and its own figure. That is the same
|
|
683
|
+
* granularity `splitCartIntoOrderGroups` and `allocateCheckoutFees` already
|
|
684
|
+
* use, and its absence is what caused Root Cause #65's per-store
|
|
685
|
+
* multiplication bug.
|
|
686
|
+
*
|
|
687
|
+
* ## All-or-nothing, and the remainder STAYS
|
|
688
|
+
*
|
|
689
|
+
* Owner's rule: *"if use point it is all and then the balance is returned if
|
|
690
|
+
* excess"*. There is no requested amount — the balance is spent down as far as
|
|
691
|
+
* the cap allows, and whatever will not fit is simply not spent. It stays in
|
|
692
|
+
* the ledger for a later order; nothing is forfeited, and no caller can ask for
|
|
693
|
+
* a partial spend.
|
|
694
|
+
*
|
|
695
|
+
* 🛑 The 50% cap is not optional, and removing it was explicitly declined.
|
|
696
|
+
* `POINTS_MAX_REDEMPTION_PERCENT` exists because a ₹0 order breaks the gateway
|
|
697
|
+
* (a ₹0 Razorpay order is not a thing) and because a balance that can settle a
|
|
698
|
+
* whole purchase behaves like the stored value the points schema is written to
|
|
699
|
+
* avoid.
|
|
700
|
+
*/
|
|
701
|
+
export function resolvePointsTender(input) {
|
|
702
|
+
const total = roundRupees(Math.max(0, input.orderTotal));
|
|
703
|
+
if (!input.optedIn || !input.accepted)
|
|
704
|
+
return { pointsApplied: 0, amountDue: total };
|
|
705
|
+
const balance = Math.floor(Math.max(0, input.balance));
|
|
706
|
+
if (!Number.isFinite(balance) || balance <= 0)
|
|
707
|
+
return { pointsApplied: 0, amountDue: total };
|
|
708
|
+
/*
|
|
709
|
+
* `maxRedeemablePoints` owns the cap arithmetic — it floors to whole points
|
|
710
|
+
* and applies `POINTS_MAX_REDEMPTION_PERCENT`. Re-deriving the percentage
|
|
711
|
+
* here would be a second copy of a money rule (Root Cause #75), and the one
|
|
712
|
+
* place it already lives sits beside the constant that defines it.
|
|
713
|
+
*/
|
|
714
|
+
const pointsApplied = maxRedeemablePoints(total, balance);
|
|
715
|
+
return { pointsApplied, amountDue: roundRupees(total - pointsApplied) };
|
|
716
|
+
}
|
|
717
|
+
/**
|
|
718
|
+
* The payable total a points allocation is measured against.
|
|
719
|
+
*
|
|
720
|
+
* 🛑 ONE implementation, because it was two. `POST /api/payment/create-order`
|
|
721
|
+
* and `verifyAndPlaceRazorpayOrderAction`'s amount guard each built this sum
|
|
722
|
+
* by hand, in the same shape, from the same six parts — and they are the
|
|
723
|
+
* *shown* figure and the *charged* figure for the same cart. Two hand-written
|
|
724
|
+
* copies of one money rule is Root Cause #75 exactly, and the failure mode is
|
|
725
|
+
* the worst kind: they only disagree on carts where the arithmetic differs, so
|
|
726
|
+
* nothing errors and the buyer is quoted one number and charged another.
|
|
727
|
+
*
|
|
728
|
+
* The coupon is floored at zero before the fees are added, never after — a
|
|
729
|
+
* discount larger than the goods must not eat the shipping and platform fee.
|
|
730
|
+
*/
|
|
731
|
+
export function pointsBaseForGroup(parts) {
|
|
732
|
+
return {
|
|
733
|
+
total: roundRupees(Math.max(0, parts.goods - parts.couponDiscount) +
|
|
734
|
+
parts.shippingFee +
|
|
735
|
+
parts.addonFee +
|
|
736
|
+
parts.platformFee +
|
|
737
|
+
parts.gstOnFee),
|
|
738
|
+
accepted: parts.acceptsPoints,
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
export function allocatePointsAcrossGroups(groups, balance, optedIn) {
|
|
742
|
+
const perGroup = groups.map(() => 0);
|
|
743
|
+
if (!optedIn)
|
|
744
|
+
return { perGroup, pointsApplied: 0 };
|
|
745
|
+
let remaining = Math.floor(Math.max(0, balance));
|
|
746
|
+
if (!Number.isFinite(remaining) || remaining <= 0)
|
|
747
|
+
return { perGroup, pointsApplied: 0 };
|
|
748
|
+
let applied = 0;
|
|
749
|
+
for (let i = 0; i < groups.length; i += 1) {
|
|
750
|
+
const g = groups[i];
|
|
751
|
+
const { pointsApplied } = resolvePointsTender({
|
|
752
|
+
orderTotal: g.total,
|
|
753
|
+
balance: g.accepted ? remaining : 0,
|
|
754
|
+
accepted: g.accepted,
|
|
755
|
+
optedIn: true,
|
|
756
|
+
});
|
|
757
|
+
perGroup[i] = pointsApplied;
|
|
758
|
+
remaining -= pointsApplied;
|
|
759
|
+
applied += pointsApplied;
|
|
760
|
+
}
|
|
761
|
+
return { perGroup, pointsApplied: applied };
|
|
762
|
+
}
|
|
604
763
|
/**
|
|
605
764
|
* P-6 — pre-order groups charge each product's own `preOrderDepositPercent`
|
|
606
765
|
* (falling back to the generic COD deposit % when a product doesn't have one
|
|
@@ -36,6 +36,21 @@ export interface RefundableOrderLike {
|
|
|
36
36
|
amount: number;
|
|
37
37
|
status?: string;
|
|
38
38
|
}>;
|
|
39
|
+
/**
|
|
40
|
+
* D46/D47 — points applied at checkout, in points (1 point = ₹1).
|
|
41
|
+
*
|
|
42
|
+
* 🛑 Subtracted from the refundable base, because **a refund can only return
|
|
43
|
+
* money that was collected.** On a ₹1,000 order settled with 250 points the
|
|
44
|
+
* card was charged ₹750; refunding the full base would hand the buyer ₹1,000
|
|
45
|
+
* and then `reverseRedemptionForOrder` would hand back 250 points on top —
|
|
46
|
+
* ₹250 of real money created out of a discount.
|
|
47
|
+
*
|
|
48
|
+
* The points themselves come back as POINTS, never as cash. That is not a
|
|
49
|
+
* stylistic choice: `pointsLedger`'s header states it as a legal boundary,
|
|
50
|
+
* because paying a balance out in rupees is what makes it stored value, which
|
|
51
|
+
* in India is PPI territory with RBI authorisation attached.
|
|
52
|
+
*/
|
|
53
|
+
pointsApplied?: number;
|
|
39
54
|
}
|
|
40
55
|
/**
|
|
41
56
|
* The platform fee actually withheld on a refund: the amount CHARGED, never a
|
|
@@ -77,6 +92,16 @@ legacyGstPercent?: number): number;
|
|
|
77
92
|
* has to compare against THIS, or the largest possible refund is strictly less
|
|
78
93
|
* than `totalPrice` and **an order can never reach `status: "refunded"`** —
|
|
79
94
|
* which is what the old `amount >= totalPrice` test guaranteed.
|
|
95
|
+
*
|
|
96
|
+
* 🛑 And `pointsApplied` comes off too (D46/D47). A refund returns MONEY, and
|
|
97
|
+
* the money collected was `totalPrice − pointsApplied`; the points go back
|
|
98
|
+
* through `reverseRedemptionForOrder` as points. Leaving them in the base would
|
|
99
|
+
* refund them twice — once in rupees here and once in points there — which is
|
|
100
|
+
* the one way this feature could manufacture real money from a discount.
|
|
101
|
+
*
|
|
102
|
+
* Absent means zero, so every order written before the tender existed is
|
|
103
|
+
* unaffected, and `isFull` still reaches the exhausted state on them exactly as
|
|
104
|
+
* before.
|
|
80
105
|
*/
|
|
81
106
|
export declare function refundableBase(order: RefundableOrderLike, legacyGstPercent?: number): number;
|
|
82
107
|
/**
|
|
@@ -75,9 +75,21 @@ legacyGstPercent) {
|
|
|
75
75
|
* has to compare against THIS, or the largest possible refund is strictly less
|
|
76
76
|
* than `totalPrice` and **an order can never reach `status: "refunded"`** —
|
|
77
77
|
* which is what the old `amount >= totalPrice` test guaranteed.
|
|
78
|
+
*
|
|
79
|
+
* 🛑 And `pointsApplied` comes off too (D46/D47). A refund returns MONEY, and
|
|
80
|
+
* the money collected was `totalPrice − pointsApplied`; the points go back
|
|
81
|
+
* through `reverseRedemptionForOrder` as points. Leaving them in the base would
|
|
82
|
+
* refund them twice — once in rupees here and once in points there — which is
|
|
83
|
+
* the one way this feature could manufacture real money from a discount.
|
|
84
|
+
*
|
|
85
|
+
* Absent means zero, so every order written before the tender existed is
|
|
86
|
+
* unaffected, and `isFull` still reaches the exhausted state on them exactly as
|
|
87
|
+
* before.
|
|
78
88
|
*/
|
|
79
89
|
export function refundableBase(order, legacyGstPercent) {
|
|
80
|
-
return roundRupees(Math.max(0, order.totalPrice -
|
|
90
|
+
return roundRupees(Math.max(0, order.totalPrice -
|
|
91
|
+
platformFeeWithheld(order, legacyGstPercent) -
|
|
92
|
+
Math.max(0, order.pointsApplied ?? 0)));
|
|
81
93
|
}
|
|
82
94
|
/**
|
|
83
95
|
* Sum of refunds that have COMMITTED money, i.e. everything not `failed`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export type { ListingCheckoutRule, CategoryCheckoutRule, CartItemProductPair, OrderItemInput, RefundPolicy, } from "./types";
|
|
2
2
|
export { CHECKOUT_RULES, CATEGORY_CHECKOUT_RULES, getListingRule, getCategoryRule, pickOrderType, getSplitKey, runSyncPreflight, } from "./_registry";
|
|
3
|
-
export { assertPaymentMethodAllowed, blockedMethodsForCart, type BlockedMethod, } from "./payment-gate";
|
|
3
|
+
export { assertPaymentMethodAllowed, assertEmiOptInAllowed, blockedMethodsForCart, type BlockedMethod, } from "./payment-gate";
|
|
4
4
|
export { CART_MAX_ITEMS, CHECKOUT_MAX_ORDERS_PER_TX, PRIZE_DRAW_MAX_REVEALS_PER_ORDER, PRIZE_DRAW_DURATION_DAYS_MIN, PRIZE_DRAW_DURATION_DAYS_MAX, BUNDLE_MAX_QTY_PER_TX, STANDARD_MAX_QTY_PER_LINE, } from "./_limits";
|
|
5
5
|
export { standardRule } from "./standard.rule";
|
|
6
6
|
export { auctionRule } from "./auction.rule";
|
|
@@ -6,7 +6,7 @@ export { CHECKOUT_RULES, CATEGORY_CHECKOUT_RULES, getListingRule, getCategoryRul
|
|
|
6
6
|
* apart is what stops someone folding it back into preflight, where it would
|
|
7
7
|
* silently stop covering bundles and grouped lines.
|
|
8
8
|
*/
|
|
9
|
-
export { assertPaymentMethodAllowed, blockedMethodsForCart, } from "./payment-gate.js";
|
|
9
|
+
export { assertPaymentMethodAllowed, assertEmiOptInAllowed, blockedMethodsForCart, } from "./payment-gate.js";
|
|
10
10
|
export { CART_MAX_ITEMS, CHECKOUT_MAX_ORDERS_PER_TX, PRIZE_DRAW_MAX_REVEALS_PER_ORDER, PRIZE_DRAW_DURATION_DAYS_MIN, PRIZE_DRAW_DURATION_DAYS_MAX, BUNDLE_MAX_QTY_PER_TX, STANDARD_MAX_QTY_PER_LINE, } from "./_limits.js";
|
|
11
11
|
// Individual rules — exported for tests and direct access.
|
|
12
12
|
export { standardRule } from "./standard.rule.js";
|
|
@@ -24,3 +24,21 @@ export declare function blockedMethodsForCart(items: readonly CartItemDocument[]
|
|
|
24
24
|
* decision.
|
|
25
25
|
*/
|
|
26
26
|
export declare function assertPaymentMethodAllowed(items: readonly CartItemDocument[], productById: ReadonlyMap<string, ProductDocument>, paymentMethod: CheckoutPaymentMethod | undefined): void;
|
|
27
|
+
/**
|
|
28
|
+
* Throw when anything in the cart forbids an instalment plan.
|
|
29
|
+
*
|
|
30
|
+
* 🛑 Reads the SAME `blockedPaymentMethods` declaration, under the key
|
|
31
|
+
* `"emi"`, rather than introducing a parallel `blocksEmi` field. The listing
|
|
32
|
+
* rules already say "this listing type cannot be paid in instalments" — they
|
|
33
|
+
* said it by naming a payment method, because that is what EMI was. Once EMI
|
|
34
|
+
* became an order-level opt-in, that declaration needed a second reader, not
|
|
35
|
+
* a second declaration: a rule stated twice is a rule that drifts (Root Cause
|
|
36
|
+
* #61), and `prizeDrawRule`'s entry would otherwise have gone inert the day
|
|
37
|
+
* the tender disappeared.
|
|
38
|
+
*
|
|
39
|
+
* `blockedPaymentMessage` is reused verbatim for the same reason the gate
|
|
40
|
+
* above prefers it to a generated sentence: it names the REASON (winner
|
|
41
|
+
* assignment waits on confirmed payment), which is what lets a buyer choose
|
|
42
|
+
* differently instead of abandoning.
|
|
43
|
+
*/
|
|
44
|
+
export declare function assertEmiOptInAllowed(items: readonly CartItemDocument[], productById: ReadonlyMap<string, ProductDocument>, emiOptIn: boolean): void;
|
|
@@ -131,3 +131,28 @@ export function assertPaymentMethodAllowed(items, productById, paymentMethod) {
|
|
|
131
131
|
? `${offender.message} Available instead: ${allowed.join(", ")}.`
|
|
132
132
|
: `${offender.message} Nothing in this cart's combination can be paid for — remove the item and buy it on its own.`), { code: "PAYMENT_METHOD_BLOCKED" });
|
|
133
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
* Throw when anything in the cart forbids an instalment plan.
|
|
136
|
+
*
|
|
137
|
+
* 🛑 Reads the SAME `blockedPaymentMethods` declaration, under the key
|
|
138
|
+
* `"emi"`, rather than introducing a parallel `blocksEmi` field. The listing
|
|
139
|
+
* rules already say "this listing type cannot be paid in instalments" — they
|
|
140
|
+
* said it by naming a payment method, because that is what EMI was. Once EMI
|
|
141
|
+
* became an order-level opt-in, that declaration needed a second reader, not
|
|
142
|
+
* a second declaration: a rule stated twice is a rule that drifts (Root Cause
|
|
143
|
+
* #61), and `prizeDrawRule`'s entry would otherwise have gone inert the day
|
|
144
|
+
* the tender disappeared.
|
|
145
|
+
*
|
|
146
|
+
* `blockedPaymentMessage` is reused verbatim for the same reason the gate
|
|
147
|
+
* above prefers it to a generated sentence: it names the REASON (winner
|
|
148
|
+
* assignment waits on confirmed payment), which is what lets a buyer choose
|
|
149
|
+
* differently instead of abandoning.
|
|
150
|
+
*/
|
|
151
|
+
export function assertEmiOptInAllowed(items, productById, emiOptIn) {
|
|
152
|
+
if (!emiOptIn)
|
|
153
|
+
return;
|
|
154
|
+
const offender = blockedMethodsForCart(items, productById).get("emi");
|
|
155
|
+
if (!offender)
|
|
156
|
+
return;
|
|
157
|
+
throw Object.assign(new ValidationError(`${offender.message} Pay for this order in full instead, or remove the item and buy it on its own.`), { code: "EMI_NOT_ALLOWED" });
|
|
158
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Group-purchase contribution splits — the ONE owner of the invariant.
|
|
3
|
+
*
|
|
4
|
+
* A coordinator divides what a grouped line costs among its members. They may
|
|
5
|
+
* type absolute amounts or percentages, and the total may come out at or ABOVE
|
|
6
|
+
* the landed cost; the excess belongs to the seller.
|
|
7
|
+
*
|
|
8
|
+
* ## The invariant
|
|
9
|
+
*
|
|
10
|
+
* ```
|
|
11
|
+
* landedCost = goods + shipping + fees + add-ons (per order group)
|
|
12
|
+
*
|
|
13
|
+
* contribution(member) = percent × landedCost OR a typed amount
|
|
14
|
+
* require: Σ(contributions) ≥ landedCost
|
|
15
|
+
* surplus: Σ(contributions) − landedCost
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* Percentages summing above 100% and typed amounts summing above the landed
|
|
19
|
+
* cost are **the same case**, so one rule covers both and there is no
|
|
20
|
+
* mode-specific branch to get wrong.
|
|
21
|
+
*
|
|
22
|
+
* ## Why the surplus becomes `lockedPrice`
|
|
23
|
+
*
|
|
24
|
+
* `unitPriceFor` already honours `lockedPrice` ahead of everything else — that
|
|
25
|
+
* is how an accepted offer BELOW list is charged correctly. An agreed total
|
|
26
|
+
* ABOVE list is the same mechanism in the other direction, so GST is charged on
|
|
27
|
+
* what was actually paid, the payout base rises by the surplus,
|
|
28
|
+
* `refundableBase` ceilings at the agreed amount, and the invoice needs no new
|
|
29
|
+
* line. No new money term anywhere.
|
|
30
|
+
*/
|
|
31
|
+
/** A member's share, as the coordinator expressed it. */
|
|
32
|
+
export interface SplitContribution {
|
|
33
|
+
productId: string;
|
|
34
|
+
/** `"percent"` reads `percent`; `"amount"` reads `amount`. */
|
|
35
|
+
splitMode: "amount" | "percent";
|
|
36
|
+
/** 0–100. Required when `splitMode === "percent"`. */
|
|
37
|
+
percent?: number;
|
|
38
|
+
/** Decimal rupees. Required when `splitMode === "amount"`. */
|
|
39
|
+
amount?: number;
|
|
40
|
+
}
|
|
41
|
+
export interface SplitResolution {
|
|
42
|
+
/** Per member, in input order, after rounding. */
|
|
43
|
+
resolved: Array<{
|
|
44
|
+
productId: string;
|
|
45
|
+
amount: number;
|
|
46
|
+
}>;
|
|
47
|
+
/** What the members together put in. */
|
|
48
|
+
contributed: number;
|
|
49
|
+
/** `contributed − landedCost`, never negative (see `shortfall`). */
|
|
50
|
+
surplus: number;
|
|
51
|
+
/** `landedCost − contributed` when the split is short, else 0. */
|
|
52
|
+
shortfall: number;
|
|
53
|
+
/** The invariant holds. A caller must refuse to commit when false. */
|
|
54
|
+
valid: boolean;
|
|
55
|
+
}
|
|
56
|
+
export declare function resolveSplit(contributions: readonly SplitContribution[], landedCost: number): SplitResolution;
|
|
57
|
+
/**
|
|
58
|
+
* The price to lock on the line, given the goods subtotal and a surplus.
|
|
59
|
+
*
|
|
60
|
+
* ## 🛑 THE TRAP THIS FUNCTION EXISTS TO PREVENT
|
|
61
|
+
*
|
|
62
|
+
* The percentage BASE is the landed cost — goods **plus shipping plus fees** —
|
|
63
|
+
* because that is what the coordinator is really dividing. But `lockedPrice` is
|
|
64
|
+
* the GOODS price of the line: the checkout adds shipping, the platform fee,
|
|
65
|
+
* GST and the add-ons on top of it, independently.
|
|
66
|
+
*
|
|
67
|
+
* So locking the landed cost would charge shipping and every fee **TWICE** —
|
|
68
|
+
* once inside `lockedPrice` and once again as the checkout's own terms. The
|
|
69
|
+
* surplus rides on the goods price alone.
|
|
70
|
+
*
|
|
71
|
+
* That is the whole reason this is a named function rather than an expression
|
|
72
|
+
* at a call site: `goods + surplus` and `landedCost + surplus` are both
|
|
73
|
+
* plausible-looking one-liners and only one of them is a correct charge.
|
|
74
|
+
*/
|
|
75
|
+
export declare function lockedPriceWithSurplus(goodsSubtotal: number, surplus: number): number;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Group-purchase contribution splits — the ONE owner of the invariant.
|
|
3
|
+
*
|
|
4
|
+
* A coordinator divides what a grouped line costs among its members. They may
|
|
5
|
+
* type absolute amounts or percentages, and the total may come out at or ABOVE
|
|
6
|
+
* the landed cost; the excess belongs to the seller.
|
|
7
|
+
*
|
|
8
|
+
* ## The invariant
|
|
9
|
+
*
|
|
10
|
+
* ```
|
|
11
|
+
* landedCost = goods + shipping + fees + add-ons (per order group)
|
|
12
|
+
*
|
|
13
|
+
* contribution(member) = percent × landedCost OR a typed amount
|
|
14
|
+
* require: Σ(contributions) ≥ landedCost
|
|
15
|
+
* surplus: Σ(contributions) − landedCost
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* Percentages summing above 100% and typed amounts summing above the landed
|
|
19
|
+
* cost are **the same case**, so one rule covers both and there is no
|
|
20
|
+
* mode-specific branch to get wrong.
|
|
21
|
+
*
|
|
22
|
+
* ## Why the surplus becomes `lockedPrice`
|
|
23
|
+
*
|
|
24
|
+
* `unitPriceFor` already honours `lockedPrice` ahead of everything else — that
|
|
25
|
+
* is how an accepted offer BELOW list is charged correctly. An agreed total
|
|
26
|
+
* ABOVE list is the same mechanism in the other direction, so GST is charged on
|
|
27
|
+
* what was actually paid, the payout base rises by the surplus,
|
|
28
|
+
* `refundableBase` ceilings at the agreed amount, and the invoice needs no new
|
|
29
|
+
* line. No new money term anywhere.
|
|
30
|
+
*/
|
|
31
|
+
import { roundRupees } from "../../../utils/number.formatter.js";
|
|
32
|
+
/**
|
|
33
|
+
* Resolve contributions against a landed cost.
|
|
34
|
+
*
|
|
35
|
+
* Pure. No I/O, no clock — the landed cost is computed by the caller from the
|
|
36
|
+
* order group it already has.
|
|
37
|
+
*
|
|
38
|
+
* 🛑 ROUNDS ONCE, at the end of each member's amount, and then puts the
|
|
39
|
+
* ROUNDING REMAINDER on the last member. Rounding each percentage
|
|
40
|
+
* independently and summing is how a 3-way 33.33% split charges a rupee less
|
|
41
|
+
* than the agreed total and the surplus silently goes negative — the same
|
|
42
|
+
* remainder discipline `allocateAcrossMembers` uses for bundle tax.
|
|
43
|
+
*/
|
|
44
|
+
/**
|
|
45
|
+
* `percent` of `amount`, where `percent` is 0–100.
|
|
46
|
+
*
|
|
47
|
+
* 🛑 A NAMED HELPER rather than the division written inline, for legibility
|
|
48
|
+
* to a reader AND to `audit-money-units`. That audit flags a scale division
|
|
49
|
+
* beside a money identifier because it is the exact shape of the 2026-05
|
|
50
|
+
* minor-unit bug — a conversion left behind by a migration — and a
|
|
51
|
+
* percentage conversion is visually identical to it. Two such lines are two
|
|
52
|
+
* judgement calls; one helper is a single place to establish that this
|
|
53
|
+
* divisor is about PERCENTAGES and never about currency scale.
|
|
54
|
+
*
|
|
55
|
+
* 🛑 That audit reads COMMENTS as well as code, so this one cannot quote the
|
|
56
|
+
* expression it is about: a worked example of the shape is indistinguishable
|
|
57
|
+
* from the shape. Reading comments is correct of it — a stale "stored in
|
|
58
|
+
* minor units" remark in prose is one of the things it hunts, and Root Cause
|
|
59
|
+
* #87 is the opposite mistake, an audit that stripped comments and so
|
|
60
|
+
* counted a commented-out registration as live.
|
|
61
|
+
*/
|
|
62
|
+
// audit-money-units-ok: a percent-to-fraction conversion, not a minor-unit conversion
|
|
63
|
+
const applyPercent = (percent, amount) => (percent / 100) * amount;
|
|
64
|
+
export function resolveSplit(contributions, landedCost) {
|
|
65
|
+
const resolved = [];
|
|
66
|
+
for (const c of contributions) {
|
|
67
|
+
const raw = c.splitMode === "percent" ? applyPercent(c.percent ?? 0, landedCost) : (c.amount ?? 0);
|
|
68
|
+
resolved.push({ productId: c.productId, amount: roundRupees(raw) });
|
|
69
|
+
}
|
|
70
|
+
/*
|
|
71
|
+
* The remainder goes on the LAST member rather than being spread, so the
|
|
72
|
+
* parts reconcile to the total exactly and the discrepancy is one member's
|
|
73
|
+
* single rupee rather than a fraction on everybody.
|
|
74
|
+
*
|
|
75
|
+
* Only for a pure PERCENT split: typed amounts are what the coordinator
|
|
76
|
+
* actually said, and silently adjusting one of them would charge somebody a
|
|
77
|
+
* figure they did not enter.
|
|
78
|
+
*/
|
|
79
|
+
const allPercent = contributions.every((c) => c.splitMode === "percent");
|
|
80
|
+
if (allPercent && resolved.length > 0) {
|
|
81
|
+
const pctTotal = contributions.reduce((s, c) => s + (c.percent ?? 0), 0);
|
|
82
|
+
const target = roundRupees(applyPercent(pctTotal, landedCost));
|
|
83
|
+
const sum = resolved.reduce((s, r) => s + r.amount, 0);
|
|
84
|
+
const drift = roundRupees(target - sum);
|
|
85
|
+
if (drift !== 0) {
|
|
86
|
+
const last = resolved[resolved.length - 1];
|
|
87
|
+
resolved[resolved.length - 1] = { ...last, amount: roundRupees(last.amount + drift) };
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const contributed = roundRupees(resolved.reduce((s, r) => s + r.amount, 0));
|
|
91
|
+
const diff = roundRupees(contributed - landedCost);
|
|
92
|
+
return {
|
|
93
|
+
resolved,
|
|
94
|
+
contributed,
|
|
95
|
+
surplus: diff > 0 ? diff : 0,
|
|
96
|
+
shortfall: diff < 0 ? -diff : 0,
|
|
97
|
+
valid: diff >= 0,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* The price to lock on the line, given the goods subtotal and a surplus.
|
|
102
|
+
*
|
|
103
|
+
* ## 🛑 THE TRAP THIS FUNCTION EXISTS TO PREVENT
|
|
104
|
+
*
|
|
105
|
+
* The percentage BASE is the landed cost — goods **plus shipping plus fees** —
|
|
106
|
+
* because that is what the coordinator is really dividing. But `lockedPrice` is
|
|
107
|
+
* the GOODS price of the line: the checkout adds shipping, the platform fee,
|
|
108
|
+
* GST and the add-ons on top of it, independently.
|
|
109
|
+
*
|
|
110
|
+
* So locking the landed cost would charge shipping and every fee **TWICE** —
|
|
111
|
+
* once inside `lockedPrice` and once again as the checkout's own terms. The
|
|
112
|
+
* surplus rides on the goods price alone.
|
|
113
|
+
*
|
|
114
|
+
* That is the whole reason this is a named function rather than an expression
|
|
115
|
+
* at a call site: `goods + surplus` and `landedCost + surplus` are both
|
|
116
|
+
* plausible-looking one-liners and only one of them is a correct charge.
|
|
117
|
+
*/
|
|
118
|
+
export function lockedPriceWithSurplus(goodsSubtotal, surplus) {
|
|
119
|
+
return roundRupees(goodsSubtotal + surplus);
|
|
120
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Disclaimers — one registry, rendered by `<Disclaimer id>` (Phase 12).
|
|
3
|
+
*
|
|
4
|
+
* ## 🛑 Why a registry and not a sentence per surface
|
|
5
|
+
*
|
|
6
|
+
* Same failure mode as the published numbers in Phase 9: if each surface
|
|
7
|
+
* writes its own, they drift, and **the legally material ones end up
|
|
8
|
+
* weakest** — because the surface that most needs a careful disclaimer is
|
|
9
|
+
* usually the one whose author was busiest. The scam registry is the example:
|
|
10
|
+
* naming a person a scammer is defamation exposure, and it had no disclaimer
|
|
11
|
+
* at all.
|
|
12
|
+
*
|
|
13
|
+
* ## The three rules every entry obeys
|
|
14
|
+
*
|
|
15
|
+
* 1. **Visible BEFORE the decision it qualifies**, not only on a policy page
|
|
16
|
+
* reachable from the footer. The protection disclaimer belongs beside the
|
|
17
|
+
* checkbox, not in `/refund-policy`.
|
|
18
|
+
* 2. **It names a LIMIT or an EXCLUSION.** A disclaimer that only says "we
|
|
19
|
+
* try our best" qualifies nothing and is worse than none — it reads as
|
|
20
|
+
* cover while providing none.
|
|
21
|
+
* 3. **It AGREES with the code.** Limits render from the constants that
|
|
22
|
+
* enforce them (`SALE_PROTECTION_MAX_VALUE`, the claim windows), through
|
|
23
|
+
* the same `{{token}}` mechanism as Phase 9, so a constant change updates
|
|
24
|
+
* the published terms rather than contradicting them.
|
|
25
|
+
*
|
|
26
|
+
* ## 🛑 NOT a cookie-banner blanket
|
|
27
|
+
*
|
|
28
|
+
* A disclaimer that appears everywhere is read nowhere. Each entry names the
|
|
29
|
+
* specific surfaces that need it, and `audit-disclaimer-coverage` checks those
|
|
30
|
+
* surfaces render one — not that every page does.
|
|
31
|
+
*/
|
|
32
|
+
export type DisclaimerId =
|
|
33
|
+
/** Naming a person a scammer. The highest-exposure entry in this file. */
|
|
34
|
+
"scam-registry"
|
|
35
|
+
/** Prize draws and the lottery — state-specific gaming law. */
|
|
36
|
+
| "prize-draw"
|
|
37
|
+
/** Collectibles shown with historical prices. */
|
|
38
|
+
| "not-investment-advice"
|
|
39
|
+
/** The realised-price index. */
|
|
40
|
+
| "price-index"
|
|
41
|
+
/** Authenticity and grading. */
|
|
42
|
+
| "authenticity"
|
|
43
|
+
/** Buyer protection cover — OUR cover, not insurance. */
|
|
44
|
+
| "protection-cover"
|
|
45
|
+
/** P&L, trial balance, GSTR-1 draft. */
|
|
46
|
+
| "accounting-output"
|
|
47
|
+
/** Live animals and plants. */
|
|
48
|
+
| "live-items"
|
|
49
|
+
/** Pre-orders. */
|
|
50
|
+
| "pre-order"
|
|
51
|
+
/** Auctions. */
|
|
52
|
+
| "auction-binding"
|
|
53
|
+
/** EMI. */
|
|
54
|
+
| "emi"
|
|
55
|
+
/** Delivery estimates. */
|
|
56
|
+
| "delivery-estimate"
|
|
57
|
+
/** Reviews, catalogue entries, blog comments. */
|
|
58
|
+
| "user-content"
|
|
59
|
+
/** GST shown on an invoice. */
|
|
60
|
+
| "tax-computation"
|
|
61
|
+
/** An automated decision — a timer cancelled, approved or completed something. */
|
|
62
|
+
| "automated-decision";
|
|
63
|
+
export interface DisclaimerEntry {
|
|
64
|
+
/** Short heading, when the surface renders one. Omit for inline notes. */
|
|
65
|
+
heading?: string;
|
|
66
|
+
/**
|
|
67
|
+
* The text. May contain `{{token}}`s resolved by `resolvePublishedCopy`.
|
|
68
|
+
*
|
|
69
|
+
* 🛑 Must name a limit or an exclusion — see rule 2 in the header. An entry
|
|
70
|
+
* that does not is not a disclaimer, and `audit-disclaimer-coverage` checks
|
|
71
|
+
* for it rather than trusting the author.
|
|
72
|
+
*/
|
|
73
|
+
body: string;
|
|
74
|
+
/**
|
|
75
|
+
* Tone, which decides the rendered variant.
|
|
76
|
+
*
|
|
77
|
+
* `legal` is the quiet grey note; `warning` is the one a user must not scroll
|
|
78
|
+
* past. 🛑 Reserved for the entries where ignoring it has a consequence the
|
|
79
|
+
* user cannot undo — not used to make a disclaimer feel important.
|
|
80
|
+
*/
|
|
81
|
+
tone: "legal" | "warning";
|
|
82
|
+
/**
|
|
83
|
+
* Where this must appear, as a free-text note for the reviewer and the
|
|
84
|
+
* audit's own registry.
|
|
85
|
+
*/
|
|
86
|
+
surfaces: readonly string[];
|
|
87
|
+
}
|
|
88
|
+
export declare const DISCLAIMERS: Record<DisclaimerId, DisclaimerEntry>;
|