@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
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What each business event posts.
|
|
3
|
+
*
|
|
4
|
+
* ## 🛑 THIS FILE IS THE WHOLE SAFETY ARGUMENT
|
|
5
|
+
*
|
|
6
|
+
* "Every journal entry is machine-generated from a business event" is the
|
|
7
|
+
* one constraint that makes a ledger maintained by a web application
|
|
8
|
+
* trustworthy. If a human has to remember that a gateway fee is
|
|
9
|
+
* `Dr Bank Charges / Cr Bank`, it will eventually be posted backwards — and
|
|
10
|
+
* a backwards entry still balances, so nothing downstream objects. These
|
|
11
|
+
* functions are where that memory lives instead.
|
|
12
|
+
*
|
|
13
|
+
* Pure, and returning a `PostingInput` rather than writing: the caller hands
|
|
14
|
+
* the result to `journalRepository.post`, which is the only thing that
|
|
15
|
+
* touches Firestore and the only thing that checks the period lock. That
|
|
16
|
+
* separation is also what lets `verify-posting-rules` exercise the rules
|
|
17
|
+
* against real order shapes without a database.
|
|
18
|
+
*
|
|
19
|
+
* ## 🛑 Codes are referenced through ACCOUNT, never as bare strings
|
|
20
|
+
*
|
|
21
|
+
* A literal `"2200"` scattered across six rules is six chances to type
|
|
22
|
+
* `"2000"`, and a posting to an account that does not exist is silently
|
|
23
|
+
* dropped from the P&L by `profitAndLoss`'s unknown-account skip. One map,
|
|
24
|
+
* named, so a wrong code is a compile error.
|
|
25
|
+
*/
|
|
26
|
+
import type { PostingInput } from "./posting";
|
|
27
|
+
import type { ExpenseCategory } from "../../../../features/ledger/schemas/expenses";
|
|
28
|
+
/** The accounts these rules post to. Codes match `chartOfAccountsSeedData`. */
|
|
29
|
+
export declare const ACCOUNT: {
|
|
30
|
+
readonly BANK: "1100";
|
|
31
|
+
readonly COURIER_FLOAT: "1150";
|
|
32
|
+
readonly GATEWAY_RECEIVABLE: "1200";
|
|
33
|
+
readonly INPUT_GST: "1300";
|
|
34
|
+
readonly SELLER_PAYABLE: "2100";
|
|
35
|
+
readonly ACCOUNTS_PAYABLE: "2300";
|
|
36
|
+
readonly OUTPUT_GST: "2200";
|
|
37
|
+
readonly BUYER_DEPOSITS: "2400";
|
|
38
|
+
readonly REFUNDS_PAYABLE: "2500";
|
|
39
|
+
readonly OPENING_EQUITY: "3900";
|
|
40
|
+
readonly COMMISSION_INCOME: "4100";
|
|
41
|
+
readonly SHIPPING_RECOVERED: "4200";
|
|
42
|
+
readonly ADDON_INCOME: "4300";
|
|
43
|
+
readonly GATEWAY_CHARGES: "5100";
|
|
44
|
+
readonly FREIGHT_PAID: "5200";
|
|
45
|
+
};
|
|
46
|
+
export interface OrderPostingInput {
|
|
47
|
+
orderId: string;
|
|
48
|
+
storeId: string;
|
|
49
|
+
placedAt: Date;
|
|
50
|
+
/** What the buyer paid in total, GST included. */
|
|
51
|
+
totalPrice: number;
|
|
52
|
+
/** Product GST inside `totalPrice`. */
|
|
53
|
+
gstAmount?: number;
|
|
54
|
+
/** Our commission, and the GST we charge on it. */
|
|
55
|
+
platformFee?: number;
|
|
56
|
+
platformFeeGst?: number;
|
|
57
|
+
/** What the buyer paid for delivery, inside `totalPrice`. */
|
|
58
|
+
shippingFee?: number;
|
|
59
|
+
/** Gift wrap, protection, WhatsApp — inside `totalPrice`. */
|
|
60
|
+
addonFees?: number;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* A paid order.
|
|
64
|
+
*
|
|
65
|
+
* 🛑 **The seller payable is the RESIDUAL, not a computed share.** Everything
|
|
66
|
+
* the platform keeps is recognised explicitly — commission, its GST, the
|
|
67
|
+
* shipping the buyer paid, add-ons, and output GST — and what remains is what
|
|
68
|
+
* the seller is owed. Computing the seller's share independently and letting
|
|
69
|
+
* the two meet in the middle is how a rounding difference becomes an
|
|
70
|
+
* unbalanced entry that `assertBalanced` then refuses at checkout, turning a
|
|
71
|
+
* half-paisa into a failed order.
|
|
72
|
+
*
|
|
73
|
+
* 🛑 **Output GST is a LIABILITY, which is the entire point of the exercise.**
|
|
74
|
+
* `revenueRollup.totalRevenue` sums `order.totalPrice`, so today's "revenue"
|
|
75
|
+
* includes tax owed to the government and freight owed to a courier. Crediting
|
|
76
|
+
* 2200 here is what separates turnover from takings for the first time.
|
|
77
|
+
*
|
|
78
|
+
* 🛑 The debit is to GATEWAY RECEIVABLE, not Bank. Money captured is not
|
|
79
|
+
* money arrived — the settlement lands days later, net of MDR, and
|
|
80
|
+
* `settlementPosting` is what clears this account. Debiting Bank here would
|
|
81
|
+
* overstate cash by the whole float for the length of the settlement cycle.
|
|
82
|
+
*/
|
|
83
|
+
export declare function orderPlacedPosting(o: OrderPostingInput): PostingInput;
|
|
84
|
+
export interface SettlementPostingInput {
|
|
85
|
+
settlementId: string;
|
|
86
|
+
settledAt: Date;
|
|
87
|
+
/** Gross captured in this settlement, matching what was debited to 1200. */
|
|
88
|
+
gross: number;
|
|
89
|
+
/** The gateway's real MDR for it. */
|
|
90
|
+
fee: number;
|
|
91
|
+
/** GST on that fee — an INPUT credit, not a cost. */
|
|
92
|
+
feeGst: number;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* A gateway settlement arriving in the bank.
|
|
96
|
+
*
|
|
97
|
+
* 🛑 `fee` here is the gateway's REAL charge from the settlement report, and
|
|
98
|
+
* it is NOT `PayoutDocument.gatewayFee` — that field is our own withholding
|
|
99
|
+
* against a seller's gross, a different number with a different meaning.
|
|
100
|
+
* Posting one as the other overstates our costs and understates what we
|
|
101
|
+
* withheld, in opposite directions, so the error compounds.
|
|
102
|
+
*
|
|
103
|
+
* 🛑 The GST on the fee is an ASSET (input credit), not an expense. Nothing
|
|
104
|
+
* in this codebase could receive input tax before Part 4, so this was simply
|
|
105
|
+
* unrecoverable — which is money, every month, that was never claimable.
|
|
106
|
+
*/
|
|
107
|
+
export declare function settlementPosting(s: SettlementPostingInput): PostingInput;
|
|
108
|
+
export interface PayoutPostingInput {
|
|
109
|
+
payoutId: string;
|
|
110
|
+
storeId: string;
|
|
111
|
+
paidAt: Date;
|
|
112
|
+
amount: number;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Paying a seller.
|
|
116
|
+
*
|
|
117
|
+
* Clears the payable raised at order time against real cash. Two legs and no
|
|
118
|
+
* income or expense — paying a debt is not a cost, and treating it as one
|
|
119
|
+
* double-counts every sale.
|
|
120
|
+
*/
|
|
121
|
+
export declare function payoutPosting(p: PayoutPostingInput): PostingInput;
|
|
122
|
+
export interface ExpensePostingInput {
|
|
123
|
+
expenseId: string;
|
|
124
|
+
vendorId?: string;
|
|
125
|
+
vendorName: string;
|
|
126
|
+
category: ExpenseCategory;
|
|
127
|
+
billDate: Date;
|
|
128
|
+
amount: number;
|
|
129
|
+
inputGst?: number;
|
|
130
|
+
/** Paid outright, or on credit? Decides the funding leg. */
|
|
131
|
+
paid: boolean;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* A bill.
|
|
135
|
+
*
|
|
136
|
+
* 🛑 The funding leg depends on whether it was PAID, and conflating the two
|
|
137
|
+
* is the commonest small-business bookkeeping error: crediting Bank for a
|
|
138
|
+
* bill not yet paid shows cash leaving that is still there, and crediting
|
|
139
|
+
* Accounts payable for one already settled leaves a debt that does not
|
|
140
|
+
* exist. Both balance; both are wrong; neither announces itself.
|
|
141
|
+
*
|
|
142
|
+
* 🛑 `inputGst` is DEBITED to an asset, never added to the cost. Expensing
|
|
143
|
+
* it is how input credit silently stops being claimable — the money is
|
|
144
|
+
* spent either way, but only one of the two gets it back.
|
|
145
|
+
*/
|
|
146
|
+
export declare function expensePosting(e: ExpensePostingInput): PostingInput;
|
|
147
|
+
export interface RefundPostingInput {
|
|
148
|
+
orderId: string;
|
|
149
|
+
refundId: string;
|
|
150
|
+
refundedAt: Date;
|
|
151
|
+
amount: number;
|
|
152
|
+
/** The product GST inside the refunded amount, which is reclaimable. */
|
|
153
|
+
gstAmount?: number;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* A refund.
|
|
157
|
+
*
|
|
158
|
+
* 🛑 **A refund is NOT a negative sale, and that distinction is why the top
|
|
159
|
+
* line is currently wrong.** `revenueRollup` removes a fully-refunded order
|
|
160
|
+
* from its sum entirely and does not reduce it at all for a partial — so
|
|
161
|
+
* revenue silently rewrites itself retroactively, and no two runs of the same
|
|
162
|
+
* report over the same period agree.
|
|
163
|
+
*
|
|
164
|
+
* Here it is its own event with its own date: the sale stays in the month it
|
|
165
|
+
* happened, the refund lands in the month it happened, and both are visible.
|
|
166
|
+
*
|
|
167
|
+
* 🛑 It DEBITS output GST, reclaiming tax already declared. Omitting that leg
|
|
168
|
+
* means paying GST on money that was given back.
|
|
169
|
+
*/
|
|
170
|
+
export declare function refundPosting(r: RefundPostingInput): PostingInput;
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What each business event posts.
|
|
3
|
+
*
|
|
4
|
+
* ## 🛑 THIS FILE IS THE WHOLE SAFETY ARGUMENT
|
|
5
|
+
*
|
|
6
|
+
* "Every journal entry is machine-generated from a business event" is the
|
|
7
|
+
* one constraint that makes a ledger maintained by a web application
|
|
8
|
+
* trustworthy. If a human has to remember that a gateway fee is
|
|
9
|
+
* `Dr Bank Charges / Cr Bank`, it will eventually be posted backwards — and
|
|
10
|
+
* a backwards entry still balances, so nothing downstream objects. These
|
|
11
|
+
* functions are where that memory lives instead.
|
|
12
|
+
*
|
|
13
|
+
* Pure, and returning a `PostingInput` rather than writing: the caller hands
|
|
14
|
+
* the result to `journalRepository.post`, which is the only thing that
|
|
15
|
+
* touches Firestore and the only thing that checks the period lock. That
|
|
16
|
+
* separation is also what lets `verify-posting-rules` exercise the rules
|
|
17
|
+
* against real order shapes without a database.
|
|
18
|
+
*
|
|
19
|
+
* ## 🛑 Codes are referenced through ACCOUNT, never as bare strings
|
|
20
|
+
*
|
|
21
|
+
* A literal `"2200"` scattered across six rules is six chances to type
|
|
22
|
+
* `"2000"`, and a posting to an account that does not exist is silently
|
|
23
|
+
* dropped from the P&L by `profitAndLoss`'s unknown-account skip. One map,
|
|
24
|
+
* named, so a wrong code is a compile error.
|
|
25
|
+
*/
|
|
26
|
+
/** The accounts these rules post to. Codes match `chartOfAccountsSeedData`. */
|
|
27
|
+
export const ACCOUNT = {
|
|
28
|
+
BANK: "1100",
|
|
29
|
+
COURIER_FLOAT: "1150",
|
|
30
|
+
GATEWAY_RECEIVABLE: "1200",
|
|
31
|
+
INPUT_GST: "1300",
|
|
32
|
+
SELLER_PAYABLE: "2100",
|
|
33
|
+
ACCOUNTS_PAYABLE: "2300",
|
|
34
|
+
OUTPUT_GST: "2200",
|
|
35
|
+
BUYER_DEPOSITS: "2400",
|
|
36
|
+
REFUNDS_PAYABLE: "2500",
|
|
37
|
+
OPENING_EQUITY: "3900",
|
|
38
|
+
COMMISSION_INCOME: "4100",
|
|
39
|
+
SHIPPING_RECOVERED: "4200",
|
|
40
|
+
ADDON_INCOME: "4300",
|
|
41
|
+
GATEWAY_CHARGES: "5100",
|
|
42
|
+
FREIGHT_PAID: "5200",
|
|
43
|
+
};
|
|
44
|
+
/** Drop legs that rounded to nothing, so a zero fee does not fail `assertBalanced`. */
|
|
45
|
+
function compact(lines) {
|
|
46
|
+
return lines.filter((l) => (l.debit ?? 0) !== 0 || (l.credit ?? 0) !== 0);
|
|
47
|
+
}
|
|
48
|
+
const r2 = (n) => Math.round((n ?? 0) * 100) / 100;
|
|
49
|
+
/**
|
|
50
|
+
* A paid order.
|
|
51
|
+
*
|
|
52
|
+
* 🛑 **The seller payable is the RESIDUAL, not a computed share.** Everything
|
|
53
|
+
* the platform keeps is recognised explicitly — commission, its GST, the
|
|
54
|
+
* shipping the buyer paid, add-ons, and output GST — and what remains is what
|
|
55
|
+
* the seller is owed. Computing the seller's share independently and letting
|
|
56
|
+
* the two meet in the middle is how a rounding difference becomes an
|
|
57
|
+
* unbalanced entry that `assertBalanced` then refuses at checkout, turning a
|
|
58
|
+
* half-paisa into a failed order.
|
|
59
|
+
*
|
|
60
|
+
* 🛑 **Output GST is a LIABILITY, which is the entire point of the exercise.**
|
|
61
|
+
* `revenueRollup.totalRevenue` sums `order.totalPrice`, so today's "revenue"
|
|
62
|
+
* includes tax owed to the government and freight owed to a courier. Crediting
|
|
63
|
+
* 2200 here is what separates turnover from takings for the first time.
|
|
64
|
+
*
|
|
65
|
+
* 🛑 The debit is to GATEWAY RECEIVABLE, not Bank. Money captured is not
|
|
66
|
+
* money arrived — the settlement lands days later, net of MDR, and
|
|
67
|
+
* `settlementPosting` is what clears this account. Debiting Bank here would
|
|
68
|
+
* overstate cash by the whole float for the length of the settlement cycle.
|
|
69
|
+
*/
|
|
70
|
+
export function orderPlacedPosting(o) {
|
|
71
|
+
const commission = r2(o.platformFee ?? 0);
|
|
72
|
+
const commissionGst = r2(o.platformFeeGst ?? 0);
|
|
73
|
+
const shipping = r2(o.shippingFee ?? 0);
|
|
74
|
+
const addons = r2(o.addonFees ?? 0);
|
|
75
|
+
const outputGst = r2((o.gstAmount ?? 0) + commissionGst);
|
|
76
|
+
const sellerPayable = r2(o.totalPrice - commission - commissionGst - shipping - addons - (o.gstAmount ?? 0));
|
|
77
|
+
return {
|
|
78
|
+
entryDate: o.placedAt,
|
|
79
|
+
sourceEvent: "order-placed",
|
|
80
|
+
sourceId: o.orderId,
|
|
81
|
+
narration: `Order ${o.orderId}`,
|
|
82
|
+
lines: compact([
|
|
83
|
+
{ accountCode: ACCOUNT.GATEWAY_RECEIVABLE, debit: r2(o.totalPrice), credit: 0, memo: "Captured, awaiting settlement" },
|
|
84
|
+
{ accountCode: ACCOUNT.SELLER_PAYABLE, debit: 0, credit: sellerPayable, counterpartyId: o.storeId, memo: "Owed to the seller" },
|
|
85
|
+
{ accountCode: ACCOUNT.OUTPUT_GST, debit: 0, credit: outputGst, memo: "Tax collected, owed to the government" },
|
|
86
|
+
{ accountCode: ACCOUNT.COMMISSION_INCOME, debit: 0, credit: commission },
|
|
87
|
+
{ accountCode: ACCOUNT.SHIPPING_RECOVERED, debit: 0, credit: shipping },
|
|
88
|
+
{ accountCode: ACCOUNT.ADDON_INCOME, debit: 0, credit: addons },
|
|
89
|
+
]),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* A gateway settlement arriving in the bank.
|
|
94
|
+
*
|
|
95
|
+
* 🛑 `fee` here is the gateway's REAL charge from the settlement report, and
|
|
96
|
+
* it is NOT `PayoutDocument.gatewayFee` — that field is our own withholding
|
|
97
|
+
* against a seller's gross, a different number with a different meaning.
|
|
98
|
+
* Posting one as the other overstates our costs and understates what we
|
|
99
|
+
* withheld, in opposite directions, so the error compounds.
|
|
100
|
+
*
|
|
101
|
+
* 🛑 The GST on the fee is an ASSET (input credit), not an expense. Nothing
|
|
102
|
+
* in this codebase could receive input tax before Part 4, so this was simply
|
|
103
|
+
* unrecoverable — which is money, every month, that was never claimable.
|
|
104
|
+
*/
|
|
105
|
+
export function settlementPosting(s) {
|
|
106
|
+
const net = r2(s.gross - s.fee - s.feeGst);
|
|
107
|
+
return {
|
|
108
|
+
entryDate: s.settledAt,
|
|
109
|
+
sourceEvent: "settlement-ingest",
|
|
110
|
+
sourceId: s.settlementId,
|
|
111
|
+
narration: `Settlement ${s.settlementId}`,
|
|
112
|
+
lines: compact([
|
|
113
|
+
{ accountCode: ACCOUNT.BANK, debit: net, credit: 0 },
|
|
114
|
+
{ accountCode: ACCOUNT.GATEWAY_CHARGES, debit: r2(s.fee), credit: 0, memo: "MDR from the settlement report" },
|
|
115
|
+
{ accountCode: ACCOUNT.INPUT_GST, debit: r2(s.feeGst), credit: 0, memo: "ITC on the gateway fee" },
|
|
116
|
+
{ accountCode: ACCOUNT.GATEWAY_RECEIVABLE, debit: 0, credit: r2(s.gross) },
|
|
117
|
+
]),
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Paying a seller.
|
|
122
|
+
*
|
|
123
|
+
* Clears the payable raised at order time against real cash. Two legs and no
|
|
124
|
+
* income or expense — paying a debt is not a cost, and treating it as one
|
|
125
|
+
* double-counts every sale.
|
|
126
|
+
*/
|
|
127
|
+
export function payoutPosting(p) {
|
|
128
|
+
return {
|
|
129
|
+
entryDate: p.paidAt,
|
|
130
|
+
sourceEvent: "payout-paid",
|
|
131
|
+
sourceId: p.payoutId,
|
|
132
|
+
narration: `Payout ${p.payoutId} to ${p.storeId}`,
|
|
133
|
+
lines: [
|
|
134
|
+
{ accountCode: ACCOUNT.SELLER_PAYABLE, debit: r2(p.amount), credit: 0, counterpartyId: p.storeId },
|
|
135
|
+
{ accountCode: ACCOUNT.BANK, debit: 0, credit: r2(p.amount) },
|
|
136
|
+
],
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Which expense account each category posts to.
|
|
141
|
+
*
|
|
142
|
+
* 🛑 A `Record<ExpenseCategory, …>`, so adding a category is a COMPILE
|
|
143
|
+
* ERROR until someone says where it lands. The alternative — a lookup with
|
|
144
|
+
* a default — silently files every new kind of spend into "other", and
|
|
145
|
+
* "other" growing is indistinguishable from nobody having noticed.
|
|
146
|
+
*
|
|
147
|
+
* 🛑 `asset` maps to a BALANCE-SHEET account, not an expense, and that is
|
|
148
|
+
* the one entry here that changes a P&L. A camera bought for ₹80,000 is not
|
|
149
|
+
* an ₹80,000 trading loss in the month it was bought; depreciation is the
|
|
150
|
+
* CA's and this system deliberately does not attempt it.
|
|
151
|
+
*/
|
|
152
|
+
const EXPENSE_ACCOUNT = {
|
|
153
|
+
freight: ACCOUNT.FREIGHT_PAID,
|
|
154
|
+
"platform-software": "5500",
|
|
155
|
+
wages: "5400",
|
|
156
|
+
packaging: "5900",
|
|
157
|
+
asset: "1500",
|
|
158
|
+
other: "5900",
|
|
159
|
+
};
|
|
160
|
+
/**
|
|
161
|
+
* A bill.
|
|
162
|
+
*
|
|
163
|
+
* 🛑 The funding leg depends on whether it was PAID, and conflating the two
|
|
164
|
+
* is the commonest small-business bookkeeping error: crediting Bank for a
|
|
165
|
+
* bill not yet paid shows cash leaving that is still there, and crediting
|
|
166
|
+
* Accounts payable for one already settled leaves a debt that does not
|
|
167
|
+
* exist. Both balance; both are wrong; neither announces itself.
|
|
168
|
+
*
|
|
169
|
+
* 🛑 `inputGst` is DEBITED to an asset, never added to the cost. Expensing
|
|
170
|
+
* it is how input credit silently stops being claimable — the money is
|
|
171
|
+
* spent either way, but only one of the two gets it back.
|
|
172
|
+
*/
|
|
173
|
+
export function expensePosting(e) {
|
|
174
|
+
const net = r2(e.amount);
|
|
175
|
+
const gst = r2(e.inputGst ?? 0);
|
|
176
|
+
return {
|
|
177
|
+
entryDate: e.billDate,
|
|
178
|
+
sourceEvent: "expense-recorded",
|
|
179
|
+
sourceId: e.expenseId,
|
|
180
|
+
narration: `${e.vendorName} — ${e.category}`,
|
|
181
|
+
lines: compact([
|
|
182
|
+
{ accountCode: EXPENSE_ACCOUNT[e.category], debit: net, credit: 0, ...(e.vendorId ? { counterpartyId: e.vendorId } : {}) },
|
|
183
|
+
{ accountCode: ACCOUNT.INPUT_GST, debit: gst, credit: 0, memo: "ITC on this bill" },
|
|
184
|
+
{
|
|
185
|
+
accountCode: e.paid ? ACCOUNT.BANK : ACCOUNT.ACCOUNTS_PAYABLE,
|
|
186
|
+
debit: 0,
|
|
187
|
+
credit: r2(net + gst),
|
|
188
|
+
...(e.vendorId ? { counterpartyId: e.vendorId } : {}),
|
|
189
|
+
},
|
|
190
|
+
]),
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* A refund.
|
|
195
|
+
*
|
|
196
|
+
* 🛑 **A refund is NOT a negative sale, and that distinction is why the top
|
|
197
|
+
* line is currently wrong.** `revenueRollup` removes a fully-refunded order
|
|
198
|
+
* from its sum entirely and does not reduce it at all for a partial — so
|
|
199
|
+
* revenue silently rewrites itself retroactively, and no two runs of the same
|
|
200
|
+
* report over the same period agree.
|
|
201
|
+
*
|
|
202
|
+
* Here it is its own event with its own date: the sale stays in the month it
|
|
203
|
+
* happened, the refund lands in the month it happened, and both are visible.
|
|
204
|
+
*
|
|
205
|
+
* 🛑 It DEBITS output GST, reclaiming tax already declared. Omitting that leg
|
|
206
|
+
* means paying GST on money that was given back.
|
|
207
|
+
*/
|
|
208
|
+
export function refundPosting(r) {
|
|
209
|
+
const gst = r2(r.gstAmount ?? 0);
|
|
210
|
+
return {
|
|
211
|
+
entryDate: r.refundedAt,
|
|
212
|
+
sourceEvent: "order-refunded",
|
|
213
|
+
sourceId: r.refundId,
|
|
214
|
+
narration: `Refund ${r.refundId} on order ${r.orderId}`,
|
|
215
|
+
lines: compact([
|
|
216
|
+
{ accountCode: ACCOUNT.COMMISSION_INCOME, debit: r2(r.amount - gst), credit: 0, memo: "Sale reversed" },
|
|
217
|
+
{ accountCode: ACCOUNT.OUTPUT_GST, debit: gst, credit: 0, memo: "Tax reclaimed on the refunded amount" },
|
|
218
|
+
{ accountCode: ACCOUNT.REFUNDS_PAYABLE, debit: 0, credit: r2(r.amount) },
|
|
219
|
+
]),
|
|
220
|
+
};
|
|
221
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coordinated purchase — several people chipping in on one listing.
|
|
3
|
+
*
|
|
4
|
+
* ## 🛑 It is a SPECIALISED OFFER. Almost nothing here is new.
|
|
5
|
+
*
|
|
6
|
+
* Owner, 2026-10-22: *"it is not a variant, it is similar to an offer, which
|
|
7
|
+
* the seller enables on the listing, then the customer can coordinate on it,
|
|
8
|
+
* it is a specialized offer."*
|
|
9
|
+
*
|
|
10
|
+
* What that framing DELETES is the valuable part, because every one of these
|
|
11
|
+
* is a thing somebody would otherwise build:
|
|
12
|
+
*
|
|
13
|
+
* | Looks required | Actually |
|
|
14
|
+
* |---|---|
|
|
15
|
+
* | a 7th `OrderSourceContext` variant | none — it is `offer-accepted`, and the provenance card renders that branch already |
|
|
16
|
+
* | an `orderType` tab | none — the Offer-wins tab covers it |
|
|
17
|
+
* | a commit / settlement path | the offer lifecycle: `made → countered → accepted → paid`, with its chain fields, `checkoutDeadline` and lapse sweep |
|
|
18
|
+
* | a new money term | none — `unitPriceFor` honours `lockedPrice`, so tax, payout base, refund ceiling and the invoice all follow |
|
|
19
|
+
* | a cart lane | none — the existing `offer` lane, not locked, lapsing at `checkoutDeadline` |
|
|
20
|
+
*
|
|
21
|
+
* So this module holds exactly two things the offer did not already have: WHO
|
|
22
|
+
* is chipping in and how much, and WHERE each of them wants their parcel.
|
|
23
|
+
*
|
|
24
|
+
* The arithmetic is Part 2's and is not re-derived here — `resolveSplit` and
|
|
25
|
+
* `lockedPriceWithSurplus` live in `checkout/split.ts`, already committed,
|
|
26
|
+
* already carrying the rounding-remainder discipline and the
|
|
27
|
+
* goods-not-landed-cost argument that makes the surplus a correct charge.
|
|
28
|
+
*/
|
|
29
|
+
import type { SplitContribution } from "../../checkout/split";
|
|
30
|
+
/**
|
|
31
|
+
* 🛑 FIVE, and the ceiling is about carrier quotes rather than taste.
|
|
32
|
+
*
|
|
33
|
+
* Each distinct destination needs its own `Shipment` and its own real
|
|
34
|
+
* `checkServiceability` call, so members multiply outbound API calls on a
|
|
35
|
+
* path a buyer is waiting on — against Rule #6's ~3-round-trip budget and a
|
|
36
|
+
* 10s function ceiling. Five is what fits with room for the rest of checkout.
|
|
37
|
+
*
|
|
38
|
+
* It is NOT a statement that six people may not club together; it is the
|
|
39
|
+
* number of parcels one offer can quote for synchronously. Raising it means
|
|
40
|
+
* moving quoting off the request path first.
|
|
41
|
+
*/
|
|
42
|
+
export declare const SHARED_PURCHASE_MAX_MEMBERS = 5;
|
|
43
|
+
/**
|
|
44
|
+
* One contributor.
|
|
45
|
+
*
|
|
46
|
+
* ## 🛑 There is deliberately NO member NAME field
|
|
47
|
+
*
|
|
48
|
+
* 🛑 **CORRECTED — the reason first given here was false.** It said
|
|
49
|
+
* `encryptPiiFields` *"is a FLAT top-level loop that never descends into
|
|
50
|
+
* arrays"*, taken from CLAUDE.md and wrong: the function handles dotted paths
|
|
51
|
+
* and `array[].key` via `encryptInArray`, and `CONVERSATION_PII_FIELDS` ships
|
|
52
|
+
* `"lastMessage.body"` in production.
|
|
53
|
+
*
|
|
54
|
+
* The real argument is narrower and still decisive. The encryptor does not
|
|
55
|
+
* INFER — a field is protected only where it is NAMED, in notation matching
|
|
56
|
+
* the object the list is applied to. So a `name` here would need
|
|
57
|
+
* `"coordination.members[].name"` in `OFFER_PII_FIELDS`, and the near-miss
|
|
58
|
+
* `"name"` would read as covered in review while storing plaintext: both are
|
|
59
|
+
* `string`, and `Encrypted<string>` is erased at runtime.
|
|
60
|
+
*
|
|
61
|
+
* A member is a uid; names resolve from it at render time. That costs one
|
|
62
|
+
* lookup the renderer was making anyway and removes the field from the
|
|
63
|
+
* document entirely, which is stronger than encrypting it — there is nothing
|
|
64
|
+
* to classify, nothing to retain, and nothing to get the notation wrong for.
|
|
65
|
+
*/
|
|
66
|
+
export interface CoordinationMember extends SplitContribution {
|
|
67
|
+
/** Firebase Auth uid of the person chipping in. */
|
|
68
|
+
uid: string;
|
|
69
|
+
/**
|
|
70
|
+
* WHERE this member's parcel goes — an ID into `addresses`, never a copy.
|
|
71
|
+
*
|
|
72
|
+
* 🛑 **A reference, and this is not a style preference.** Copying the
|
|
73
|
+
* address inline would put a name, a phone number and a street into the
|
|
74
|
+
* offer document — a cart-adjacent record with no encryption story and no
|
|
75
|
+
* retention story, which is two new obligations to serve one picker.
|
|
76
|
+
*
|
|
77
|
+
* 🛑 **The id MUST be verified server-side to belong to the submitting
|
|
78
|
+
* buyer.** An id is guessable in a way an address is not: without the check,
|
|
79
|
+
* a member supplies any `addresses` document id and the parcel ships to a
|
|
80
|
+
* stranger's house at the coordinator's expense. See `assertOwnedAddresses`.
|
|
81
|
+
*
|
|
82
|
+
* Absent means "same as the coordinator's" — one parcel, which is the
|
|
83
|
+
* ordinary case and must not require every member to pick.
|
|
84
|
+
*/
|
|
85
|
+
destinationAddressId?: string;
|
|
86
|
+
}
|
|
87
|
+
export interface OfferCoordination {
|
|
88
|
+
/**
|
|
89
|
+
* The coordinator is the offer's own `buyerUid` and is NOT repeated here.
|
|
90
|
+
*
|
|
91
|
+
* A second copy is a mirror, and a mirror drifts the first time a write
|
|
92
|
+
* path sets one and not the other (Root Cause #42). The coordinator is also
|
|
93
|
+
* a contributing member, so they appear in `members` like everyone else —
|
|
94
|
+
* what makes them the coordinator is owning the offer.
|
|
95
|
+
*/
|
|
96
|
+
members: CoordinationMember[];
|
|
97
|
+
/**
|
|
98
|
+
* The landed cost the split was resolved against, snapshotted at the moment
|
|
99
|
+
* the coordinator committed.
|
|
100
|
+
*
|
|
101
|
+
* 🛑 Snapshotted, not recomputed. Shipping and fees move; a split agreed on
|
|
102
|
+
* Monday must still mean the same amounts on Friday, and recomputing would
|
|
103
|
+
* silently re-divide what people already agreed to pay.
|
|
104
|
+
*/
|
|
105
|
+
landedCostAtSplit: number;
|
|
106
|
+
/** `contributed − landedCostAtSplit`, which rides on `lockedPrice`. */
|
|
107
|
+
surplus: number;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Is this set of members committable?
|
|
111
|
+
*
|
|
112
|
+
* Returns a MESSAGE rather than a boolean, for the same reason
|
|
113
|
+
* `rejectRateChange` does: "too many members" and "the split is short" need
|
|
114
|
+
* different corrections, and a bare `false` makes the form guess.
|
|
115
|
+
*
|
|
116
|
+
* 🛑 It does NOT check the split arithmetic — `resolveSplit` owns that, and
|
|
117
|
+
* duplicating the `Σ(contributions) ≥ landedCost` test here would be a second
|
|
118
|
+
* implementation of the one invariant Part 2 exists to hold.
|
|
119
|
+
*/
|
|
120
|
+
export declare function rejectCoordination(members: readonly CoordinationMember[]): string | null;
|
|
121
|
+
/** The distinct destinations this offer will have to ship to. */
|
|
122
|
+
export declare function destinationIds(members: readonly CoordinationMember[]): string[];
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coordinated purchase — several people chipping in on one listing.
|
|
3
|
+
*
|
|
4
|
+
* ## 🛑 It is a SPECIALISED OFFER. Almost nothing here is new.
|
|
5
|
+
*
|
|
6
|
+
* Owner, 2026-10-22: *"it is not a variant, it is similar to an offer, which
|
|
7
|
+
* the seller enables on the listing, then the customer can coordinate on it,
|
|
8
|
+
* it is a specialized offer."*
|
|
9
|
+
*
|
|
10
|
+
* What that framing DELETES is the valuable part, because every one of these
|
|
11
|
+
* is a thing somebody would otherwise build:
|
|
12
|
+
*
|
|
13
|
+
* | Looks required | Actually |
|
|
14
|
+
* |---|---|
|
|
15
|
+
* | a 7th `OrderSourceContext` variant | none — it is `offer-accepted`, and the provenance card renders that branch already |
|
|
16
|
+
* | an `orderType` tab | none — the Offer-wins tab covers it |
|
|
17
|
+
* | a commit / settlement path | the offer lifecycle: `made → countered → accepted → paid`, with its chain fields, `checkoutDeadline` and lapse sweep |
|
|
18
|
+
* | a new money term | none — `unitPriceFor` honours `lockedPrice`, so tax, payout base, refund ceiling and the invoice all follow |
|
|
19
|
+
* | a cart lane | none — the existing `offer` lane, not locked, lapsing at `checkoutDeadline` |
|
|
20
|
+
*
|
|
21
|
+
* So this module holds exactly two things the offer did not already have: WHO
|
|
22
|
+
* is chipping in and how much, and WHERE each of them wants their parcel.
|
|
23
|
+
*
|
|
24
|
+
* The arithmetic is Part 2's and is not re-derived here — `resolveSplit` and
|
|
25
|
+
* `lockedPriceWithSurplus` live in `checkout/split.ts`, already committed,
|
|
26
|
+
* already carrying the rounding-remainder discipline and the
|
|
27
|
+
* goods-not-landed-cost argument that makes the surplus a correct charge.
|
|
28
|
+
*/
|
|
29
|
+
/**
|
|
30
|
+
* 🛑 FIVE, and the ceiling is about carrier quotes rather than taste.
|
|
31
|
+
*
|
|
32
|
+
* Each distinct destination needs its own `Shipment` and its own real
|
|
33
|
+
* `checkServiceability` call, so members multiply outbound API calls on a
|
|
34
|
+
* path a buyer is waiting on — against Rule #6's ~3-round-trip budget and a
|
|
35
|
+
* 10s function ceiling. Five is what fits with room for the rest of checkout.
|
|
36
|
+
*
|
|
37
|
+
* It is NOT a statement that six people may not club together; it is the
|
|
38
|
+
* number of parcels one offer can quote for synchronously. Raising it means
|
|
39
|
+
* moving quoting off the request path first.
|
|
40
|
+
*/
|
|
41
|
+
export const SHARED_PURCHASE_MAX_MEMBERS = 5;
|
|
42
|
+
/**
|
|
43
|
+
* Is this set of members committable?
|
|
44
|
+
*
|
|
45
|
+
* Returns a MESSAGE rather than a boolean, for the same reason
|
|
46
|
+
* `rejectRateChange` does: "too many members" and "the split is short" need
|
|
47
|
+
* different corrections, and a bare `false` makes the form guess.
|
|
48
|
+
*
|
|
49
|
+
* 🛑 It does NOT check the split arithmetic — `resolveSplit` owns that, and
|
|
50
|
+
* duplicating the `Σ(contributions) ≥ landedCost` test here would be a second
|
|
51
|
+
* implementation of the one invariant Part 2 exists to hold.
|
|
52
|
+
*/
|
|
53
|
+
export function rejectCoordination(members) {
|
|
54
|
+
if (members.length === 0)
|
|
55
|
+
return "A coordinated purchase needs at least one contributor.";
|
|
56
|
+
if (members.length > SHARED_PURCHASE_MAX_MEMBERS) {
|
|
57
|
+
return `A coordinated purchase is limited to ${SHARED_PURCHASE_MAX_MEMBERS} contributors.`;
|
|
58
|
+
}
|
|
59
|
+
const uids = new Set(members.map((m) => m.uid));
|
|
60
|
+
if (uids.size !== members.length) {
|
|
61
|
+
/*
|
|
62
|
+
* One person twice is almost always a UI slip, and letting it through
|
|
63
|
+
* means their two rows are summed into one charge they did not agree to.
|
|
64
|
+
*/
|
|
65
|
+
return "The same person appears more than once.";
|
|
66
|
+
}
|
|
67
|
+
for (const m of members) {
|
|
68
|
+
if (m.splitMode === "percent" && (m.percent == null || m.percent <= 0 || m.percent > 100)) {
|
|
69
|
+
return "Every percentage share must be between 0 and 100.";
|
|
70
|
+
}
|
|
71
|
+
if (m.splitMode === "amount" && (m.amount == null || m.amount <= 0)) {
|
|
72
|
+
return "Every fixed share must be more than zero.";
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
/** The distinct destinations this offer will have to ship to. */
|
|
78
|
+
export function destinationIds(members) {
|
|
79
|
+
return [...new Set(members.map((m) => m.destinationAddressId).filter((id) => !!id))];
|
|
80
|
+
}
|