@aglyn/plugins-commerce 1.0.0-beta.143
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/LICENSE +201 -0
- package/README.md +10 -0
- package/package.json +57 -0
- package/src/index.d.ts +38 -0
- package/src/index.js +38 -0
- package/src/index.js.map +1 -0
- package/src/lib/components/account.d.ts +31 -0
- package/src/lib/components/account.js +645 -0
- package/src/lib/components/account.js.map +1 -0
- package/src/lib/components/cart.d.ts +38 -0
- package/src/lib/components/cart.js +851 -0
- package/src/lib/components/cart.js.map +1 -0
- package/src/lib/components/commerce-console-page.d.ts +32 -0
- package/src/lib/components/commerce-console-page.js +296 -0
- package/src/lib/components/commerce-console-page.js.map +1 -0
- package/src/lib/components/commerce-console-sections.d.ts +34 -0
- package/src/lib/components/commerce-console-sections.js +62 -0
- package/src/lib/components/commerce-console-sections.js.map +1 -0
- package/src/lib/components/console/catalog-organization-card.component.d.ts +14 -0
- package/src/lib/components/console/catalog-organization-card.component.js +1087 -0
- package/src/lib/components/console/catalog-organization-card.component.js.map +1 -0
- package/src/lib/components/console/commerce-analytics-card.component.d.ts +27 -0
- package/src/lib/components/console/commerce-analytics-card.component.js +310 -0
- package/src/lib/components/console/commerce-analytics-card.component.js.map +1 -0
- package/src/lib/components/console/commerce-glance-card.component.d.ts +20 -0
- package/src/lib/components/console/commerce-glance-card.component.js +340 -0
- package/src/lib/components/console/commerce-glance-card.component.js.map +1 -0
- package/src/lib/components/console/commerce-stat-tile.component.d.ts +37 -0
- package/src/lib/components/console/commerce-stat-tile.component.js +72 -0
- package/src/lib/components/console/commerce-stat-tile.component.js.map +1 -0
- package/src/lib/components/console/discounts-card.component.d.ts +14 -0
- package/src/lib/components/console/discounts-card.component.js +443 -0
- package/src/lib/components/console/discounts-card.component.js.map +1 -0
- package/src/lib/components/console/entitlement-gate.component.d.ts +76 -0
- package/src/lib/components/console/entitlement-gate.component.js +115 -0
- package/src/lib/components/console/entitlement-gate.component.js.map +1 -0
- package/src/lib/components/console/gift-cards-card.component.d.ts +29 -0
- package/src/lib/components/console/gift-cards-card.component.js +379 -0
- package/src/lib/components/console/gift-cards-card.component.js.map +1 -0
- package/src/lib/components/console/host-coupons-card.component.d.ts +14 -0
- package/src/lib/components/console/host-coupons-card.component.js +252 -0
- package/src/lib/components/console/host-coupons-card.component.js.map +1 -0
- package/src/lib/components/console/host-orders-card.component.d.ts +13 -0
- package/src/lib/components/console/host-orders-card.component.js +861 -0
- package/src/lib/components/console/host-orders-card.component.js.map +1 -0
- package/src/lib/components/console/locations-card.component.d.ts +14 -0
- package/src/lib/components/console/locations-card.component.js +256 -0
- package/src/lib/components/console/locations-card.component.js.map +1 -0
- package/src/lib/components/console/member-posts-card.component.d.ts +8 -0
- package/src/lib/components/console/member-posts-card.component.js +283 -0
- package/src/lib/components/console/member-posts-card.component.js.map +1 -0
- package/src/lib/components/console/newest-site-users-card.component.d.ts +36 -0
- package/src/lib/components/console/newest-site-users-card.component.js +126 -0
- package/src/lib/components/console/newest-site-users-card.component.js.map +1 -0
- package/src/lib/components/console/order-detail-dialog.component.d.ts +28 -0
- package/src/lib/components/console/order-detail-dialog.component.js +976 -0
- package/src/lib/components/console/order-detail-dialog.component.js.map +1 -0
- package/src/lib/components/console/paid-media.d.ts +127 -0
- package/src/lib/components/console/paid-media.js +397 -0
- package/src/lib/components/console/paid-media.js.map +1 -0
- package/src/lib/components/console/payments-settings-card.component.d.ts +13 -0
- package/src/lib/components/console/payments-settings-card.component.js +295 -0
- package/src/lib/components/console/payments-settings-card.component.js.map +1 -0
- package/src/lib/components/console/pos-page.component.d.ts +13 -0
- package/src/lib/components/console/pos-page.component.js +916 -0
- package/src/lib/components/console/pos-page.component.js.map +1 -0
- package/src/lib/components/console/product-editor-dialog.component.d.ts +32 -0
- package/src/lib/components/console/product-editor-dialog.component.js +1374 -0
- package/src/lib/components/console/product-editor-dialog.component.js.map +1 -0
- package/src/lib/components/console/products-hub-card.component.d.ts +16 -0
- package/src/lib/components/console/products-hub-card.component.js +1280 -0
- package/src/lib/components/console/products-hub-card.component.js.map +1 -0
- package/src/lib/components/console/products-hub-zone.component.d.ts +50 -0
- package/src/lib/components/console/products-hub-zone.component.js +200 -0
- package/src/lib/components/console/products-hub-zone.component.js.map +1 -0
- package/src/lib/components/console/recovery-queue-card.component.d.ts +39 -0
- package/src/lib/components/console/recovery-queue-card.component.js +262 -0
- package/src/lib/components/console/recovery-queue-card.component.js.map +1 -0
- package/src/lib/components/console/registers-card.component.d.ts +21 -0
- package/src/lib/components/console/registers-card.component.js +296 -0
- package/src/lib/components/console/registers-card.component.js.map +1 -0
- package/src/lib/components/console/reservations-card.component.d.ts +14 -0
- package/src/lib/components/console/reservations-card.component.js +650 -0
- package/src/lib/components/console/reservations-card.component.js.map +1 -0
- package/src/lib/components/console/reviews-moderation-card.component.d.ts +8 -0
- package/src/lib/components/console/reviews-moderation-card.component.js +235 -0
- package/src/lib/components/console/reviews-moderation-card.component.js.map +1 -0
- package/src/lib/components/console/shipping-settings-card.component.d.ts +38 -0
- package/src/lib/components/console/shipping-settings-card.component.js +560 -0
- package/src/lib/components/console/shipping-settings-card.component.js.map +1 -0
- package/src/lib/components/console/stock-movements-card.component.d.ts +31 -0
- package/src/lib/components/console/stock-movements-card.component.js +333 -0
- package/src/lib/components/console/stock-movements-card.component.js.map +1 -0
- package/src/lib/components/console/store-settings-card.component.d.ts +14 -0
- package/src/lib/components/console/store-settings-card.component.js +300 -0
- package/src/lib/components/console/store-settings-card.component.js.map +1 -0
- package/src/lib/components/console/storefront-tax-summary-card.component.d.ts +73 -0
- package/src/lib/components/console/storefront-tax-summary-card.component.js +408 -0
- package/src/lib/components/console/storefront-tax-summary-card.component.js.map +1 -0
- package/src/lib/components/console/suppliers-card.component.d.ts +8 -0
- package/src/lib/components/console/suppliers-card.component.js +328 -0
- package/src/lib/components/console/suppliers-card.component.js.map +1 -0
- package/src/lib/components/console/tax-settings-card.component.d.ts +14 -0
- package/src/lib/components/console/tax-settings-card.component.js +473 -0
- package/src/lib/components/console/tax-settings-card.component.js.map +1 -0
- package/src/lib/components/gate.d.ts +39 -0
- package/src/lib/components/gate.js +202 -0
- package/src/lib/components/gate.js.map +1 -0
- package/src/lib/components/gated-video.d.ts +40 -0
- package/src/lib/components/gated-video.js +366 -0
- package/src/lib/components/gated-video.js.map +1 -0
- package/src/lib/components/member-feed.d.ts +32 -0
- package/src/lib/components/member-feed.js +198 -0
- package/src/lib/components/member-feed.js.map +1 -0
- package/src/lib/components/member-recovery.d.ts +35 -0
- package/src/lib/components/member-recovery.js +313 -0
- package/src/lib/components/member-recovery.js.map +1 -0
- package/src/lib/components/member-signin.d.ts +35 -0
- package/src/lib/components/member-signin.js +257 -0
- package/src/lib/components/member-signin.js.map +1 -0
- package/src/lib/components/member-signup.d.ts +34 -0
- package/src/lib/components/member-signup.js +287 -0
- package/src/lib/components/member-signup.js.map +1 -0
- package/src/lib/components/newsletter-signup.d.ts +39 -0
- package/src/lib/components/newsletter-signup.js +229 -0
- package/src/lib/components/newsletter-signup.js.map +1 -0
- package/src/lib/components/product-detail.d.ts +38 -0
- package/src/lib/components/product-detail.js +1022 -0
- package/src/lib/components/product-detail.js.map +1 -0
- package/src/lib/components/product-grid.d.ts +67 -0
- package/src/lib/components/product-grid.js +909 -0
- package/src/lib/components/product-grid.js.map +1 -0
- package/src/lib/components/product-reviews.d.ts +32 -0
- package/src/lib/components/product-reviews.js +349 -0
- package/src/lib/components/product-reviews.js.map +1 -0
- package/src/lib/components/related-products.d.ts +33 -0
- package/src/lib/components/related-products.js +232 -0
- package/src/lib/components/related-products.js.map +1 -0
- package/src/lib/components/reservation-widget.d.ts +33 -0
- package/src/lib/components/reservation-widget.js +418 -0
- package/src/lib/components/reservation-widget.js.map +1 -0
- package/src/lib/components/storefront-payment-element-fallback.d.ts +18 -0
- package/src/lib/components/storefront-payment-element-fallback.js +51 -0
- package/src/lib/components/storefront-payment-element-fallback.js.map +1 -0
- package/src/lib/components/storefront-payment-element.d.ts +78 -0
- package/src/lib/components/storefront-payment-element.js +156 -0
- package/src/lib/components/storefront-payment-element.js.map +1 -0
- package/src/lib/components/wishlist.d.ts +46 -0
- package/src/lib/components/wishlist.js +304 -0
- package/src/lib/components/wishlist.js.map +1 -0
- package/src/lib/constants/bundle-common.d.ts +18 -0
- package/src/lib/constants/bundle-common.js +18 -0
- package/src/lib/constants/bundle-common.js.map +1 -0
- package/src/lib/constants/product-filters.d.ts +35 -0
- package/src/lib/constants/product-filters.js +109 -0
- package/src/lib/constants/product-filters.js.map +1 -0
- package/src/lib/model/commerce-cart.d.ts +52 -0
- package/src/lib/model/commerce-cart.js +102 -0
- package/src/lib/model/commerce-cart.js.map +1 -0
- package/src/lib/model/commerce-connect-transfer.d.ts +243 -0
- package/src/lib/model/commerce-connect-transfer.js +231 -0
- package/src/lib/model/commerce-connect-transfer.js.map +1 -0
- package/src/lib/model/commerce-discounts.d.ts +164 -0
- package/src/lib/model/commerce-discounts.js +231 -0
- package/src/lib/model/commerce-discounts.js.map +1 -0
- package/src/lib/model/commerce-dispute.d.ts +124 -0
- package/src/lib/model/commerce-dispute.js +225 -0
- package/src/lib/model/commerce-dispute.js.map +1 -0
- package/src/lib/model/commerce-gift-cards.d.ts +107 -0
- package/src/lib/model/commerce-gift-cards.js +121 -0
- package/src/lib/model/commerce-gift-cards.js.map +1 -0
- package/src/lib/model/commerce-io.d.ts +36 -0
- package/src/lib/model/commerce-io.js +245 -0
- package/src/lib/model/commerce-io.js.map +1 -0
- package/src/lib/model/commerce-orders.d.ts +1040 -0
- package/src/lib/model/commerce-orders.js +1022 -0
- package/src/lib/model/commerce-orders.js.map +1 -0
- package/src/lib/model/commerce-promotions.d.ts +188 -0
- package/src/lib/model/commerce-promotions.js +199 -0
- package/src/lib/model/commerce-promotions.js.map +1 -0
- package/src/lib/model/commerce-reservations.d.ts +175 -0
- package/src/lib/model/commerce-reservations.js +157 -0
- package/src/lib/model/commerce-reservations.js.map +1 -0
- package/src/lib/model/commerce-shipping.d.ts +316 -0
- package/src/lib/model/commerce-shipping.js +484 -0
- package/src/lib/model/commerce-shipping.js.map +1 -0
- package/src/lib/model/commerce-stock-holds.d.ts +199 -0
- package/src/lib/model/commerce-stock-holds.js +190 -0
- package/src/lib/model/commerce-stock-holds.js.map +1 -0
- package/src/lib/model/commerce-subscription-status.d.ts +67 -0
- package/src/lib/model/commerce-subscription-status.js +76 -0
- package/src/lib/model/commerce-subscription-status.js.map +1 -0
- package/src/lib/model/commerce-tax-decision.d.ts +222 -0
- package/src/lib/model/commerce-tax-decision.js +165 -0
- package/src/lib/model/commerce-tax-decision.js.map +1 -0
- package/src/lib/model/commerce-tax.d.ts +176 -0
- package/src/lib/model/commerce-tax.js +92 -0
- package/src/lib/model/commerce-tax.js.map +1 -0
- package/src/lib/model/commerce.d.ts +551 -0
- package/src/lib/model/commerce.js +739 -0
- package/src/lib/model/commerce.js.map +1 -0
- package/src/lib/model/index.d.ts +40 -0
- package/src/lib/model/index.js +40 -0
- package/src/lib/model/index.js.map +1 -0
- package/src/lib/model/order-figures.d.ts +48 -0
- package/src/lib/model/order-figures.js +74 -0
- package/src/lib/model/order-figures.js.map +1 -0
- package/src/lib/model/plugin-permissions.d.ts +23 -0
- package/src/lib/model/plugin-permissions.js +34 -0
- package/src/lib/model/plugin-permissions.js.map +1 -0
- package/src/lib/model/purchase-analytics.d.ts +186 -0
- package/src/lib/model/purchase-analytics.js +216 -0
- package/src/lib/model/purchase-analytics.js.map +1 -0
- package/src/lib/plugin-config.d.ts +62 -0
- package/src/lib/plugin-config.js +78 -0
- package/src/lib/plugin-config.js.map +1 -0
- package/src/lib/plugin.d.ts +28 -0
- package/src/lib/plugin.js +147 -0
- package/src/lib/plugin.js.map +1 -0
- package/src/lib/server/billing-webhook.d.ts +26 -0
- package/src/lib/server/billing-webhook.js +4011 -0
- package/src/lib/server/billing-webhook.js.map +1 -0
- package/src/lib/server/cancel-order.d.ts +87 -0
- package/src/lib/server/cancel-order.js +368 -0
- package/src/lib/server/cancel-order.js.map +1 -0
- package/src/lib/server/cart-checkout.d.ts +25 -0
- package/src/lib/server/cart-checkout.js +976 -0
- package/src/lib/server/cart-checkout.js.map +1 -0
- package/src/lib/server/cart-cookie.d.ts +32 -0
- package/src/lib/server/cart-cookie.js +77 -0
- package/src/lib/server/cart-cookie.js.map +1 -0
- package/src/lib/server/cart.d.ts +34 -0
- package/src/lib/server/cart.js +181 -0
- package/src/lib/server/cart.js.map +1 -0
- package/src/lib/server/catalog.d.ts +127 -0
- package/src/lib/server/catalog.js +277 -0
- package/src/lib/server/catalog.js.map +1 -0
- package/src/lib/server/checkout.d.ts +36 -0
- package/src/lib/server/checkout.js +915 -0
- package/src/lib/server/checkout.js.map +1 -0
- package/src/lib/server/connect.d.ts +26 -0
- package/src/lib/server/connect.js +238 -0
- package/src/lib/server/connect.js.map +1 -0
- package/src/lib/server/contact-refund.d.ts +117 -0
- package/src/lib/server/contact-refund.js +196 -0
- package/src/lib/server/contact-refund.js.map +1 -0
- package/src/lib/server/download.d.ts +39 -0
- package/src/lib/server/download.js +206 -0
- package/src/lib/server/download.js.map +1 -0
- package/src/lib/server/draft-order.d.ts +26 -0
- package/src/lib/server/draft-order.js +706 -0
- package/src/lib/server/draft-order.js.map +1 -0
- package/src/lib/server/feed.d.ts +24 -0
- package/src/lib/server/feed.js +59 -0
- package/src/lib/server/feed.js.map +1 -0
- package/src/lib/server/fulfill-order.d.ts +97 -0
- package/src/lib/server/fulfill-order.js +235 -0
- package/src/lib/server/fulfill-order.js.map +1 -0
- package/src/lib/server/gate.d.ts +36 -0
- package/src/lib/server/gate.js +112 -0
- package/src/lib/server/gate.js.map +1 -0
- package/src/lib/server/gift-cards.d.ts +42 -0
- package/src/lib/server/gift-cards.js +219 -0
- package/src/lib/server/gift-cards.js.map +1 -0
- package/src/lib/server/low-stock.d.ts +49 -0
- package/src/lib/server/low-stock.js +60 -0
- package/src/lib/server/low-stock.js.map +1 -0
- package/src/lib/server/manual-tax-rate.d.ts +82 -0
- package/src/lib/server/manual-tax-rate.js +113 -0
- package/src/lib/server/manual-tax-rate.js.map +1 -0
- package/src/lib/server/member-feed.d.ts +24 -0
- package/src/lib/server/member-feed.js +72 -0
- package/src/lib/server/member-feed.js.map +1 -0
- package/src/lib/server/member-name-search.d.ts +37 -0
- package/src/lib/server/member-name-search.js +42 -0
- package/src/lib/server/member-name-search.js.map +1 -0
- package/src/lib/server/member-post.d.ts +23 -0
- package/src/lib/server/member-post.js +166 -0
- package/src/lib/server/member-post.js.map +1 -0
- package/src/lib/server/membership-account.d.ts +37 -0
- package/src/lib/server/membership-account.js +148 -0
- package/src/lib/server/membership-account.js.map +1 -0
- package/src/lib/server/membership-admin-password.d.ts +33 -0
- package/src/lib/server/membership-admin-password.js +202 -0
- package/src/lib/server/membership-admin-password.js.map +1 -0
- package/src/lib/server/membership-content.d.ts +23 -0
- package/src/lib/server/membership-content.js +105 -0
- package/src/lib/server/membership-content.js.map +1 -0
- package/src/lib/server/membership-login.d.ts +19 -0
- package/src/lib/server/membership-login.js +137 -0
- package/src/lib/server/membership-login.js.map +1 -0
- package/src/lib/server/membership-logout.d.ts +19 -0
- package/src/lib/server/membership-logout.js +35 -0
- package/src/lib/server/membership-logout.js.map +1 -0
- package/src/lib/server/membership-recover.d.ts +60 -0
- package/src/lib/server/membership-recover.js +244 -0
- package/src/lib/server/membership-recover.js.map +1 -0
- package/src/lib/server/membership-register.d.ts +22 -0
- package/src/lib/server/membership-register.js +241 -0
- package/src/lib/server/membership-register.js.map +1 -0
- package/src/lib/server/membership-reset.d.ts +26 -0
- package/src/lib/server/membership-reset.js +88 -0
- package/src/lib/server/membership-reset.js.map +1 -0
- package/src/lib/server/membership-wishlist.d.ts +23 -0
- package/src/lib/server/membership-wishlist.js +89 -0
- package/src/lib/server/membership-wishlist.js.map +1 -0
- package/src/lib/server/membership.d.ts +96 -0
- package/src/lib/server/membership.js +222 -0
- package/src/lib/server/membership.js.map +1 -0
- package/src/lib/server/native-checkout.d.ts +170 -0
- package/src/lib/server/native-checkout.js +193 -0
- package/src/lib/server/native-checkout.js.map +1 -0
- package/src/lib/server/newsletter.d.ts +23 -0
- package/src/lib/server/newsletter.js +323 -0
- package/src/lib/server/newsletter.js.map +1 -0
- package/src/lib/server/notify-restock.d.ts +22 -0
- package/src/lib/server/notify-restock.js +84 -0
- package/src/lib/server/notify-restock.js.map +1 -0
- package/src/lib/server/order-analytics.d.ts +134 -0
- package/src/lib/server/order-analytics.js +263 -0
- package/src/lib/server/order-analytics.js.map +1 -0
- package/src/lib/server/order-figures.d.ts +33 -0
- package/src/lib/server/order-figures.js +220 -0
- package/src/lib/server/order-figures.js.map +1 -0
- package/src/lib/server/paid-media-delivery.d.ts +173 -0
- package/src/lib/server/paid-media-delivery.js +212 -0
- package/src/lib/server/paid-media-delivery.js.map +1 -0
- package/src/lib/server/pos-order.d.ts +54 -0
- package/src/lib/server/pos-order.js +1137 -0
- package/src/lib/server/pos-order.js.map +1 -0
- package/src/lib/server/process-abandoned.d.ts +54 -0
- package/src/lib/server/process-abandoned.js +222 -0
- package/src/lib/server/process-abandoned.js.map +1 -0
- package/src/lib/server/process-restock.d.ts +42 -0
- package/src/lib/server/process-restock.js +219 -0
- package/src/lib/server/process-restock.js.map +1 -0
- package/src/lib/server/product-card.d.ts +29 -0
- package/src/lib/server/product-card.js +54 -0
- package/src/lib/server/product-card.js.map +1 -0
- package/src/lib/server/product.d.ts +70 -0
- package/src/lib/server/product.js +105 -0
- package/src/lib/server/product.js.map +1 -0
- package/src/lib/server/promotion-hold.d.ts +144 -0
- package/src/lib/server/promotion-hold.js +174 -0
- package/src/lib/server/promotion-hold.js.map +1 -0
- package/src/lib/server/reconcile-stock.d.ts +106 -0
- package/src/lib/server/reconcile-stock.js +349 -0
- package/src/lib/server/reconcile-stock.js.map +1 -0
- package/src/lib/server/refund.d.ts +45 -0
- package/src/lib/server/refund.js +607 -0
- package/src/lib/server/refund.js.map +1 -0
- package/src/lib/server/related.d.ts +24 -0
- package/src/lib/server/related.js +104 -0
- package/src/lib/server/related.js.map +1 -0
- package/src/lib/server/reservation-availability.d.ts +23 -0
- package/src/lib/server/reservation-availability.js +111 -0
- package/src/lib/server/reservation-availability.js.map +1 -0
- package/src/lib/server/reserve-stock.d.ts +156 -0
- package/src/lib/server/reserve-stock.js +146 -0
- package/src/lib/server/reserve-stock.js.map +1 -0
- package/src/lib/server/reserve.d.ts +25 -0
- package/src/lib/server/reserve.js +426 -0
- package/src/lib/server/reserve.js.map +1 -0
- package/src/lib/server/restock-flag.d.ts +202 -0
- package/src/lib/server/restock-flag.js +449 -0
- package/src/lib/server/restock-flag.js.map +1 -0
- package/src/lib/server/reviews.d.ts +51 -0
- package/src/lib/server/reviews.js +132 -0
- package/src/lib/server/reviews.js.map +1 -0
- package/src/lib/server/site-page-enricher.d.ts +42 -0
- package/src/lib/server/site-page-enricher.js +149 -0
- package/src/lib/server/site-page-enricher.js.map +1 -0
- package/src/lib/server/site-page-resolver.d.ts +26 -0
- package/src/lib/server/site-page-resolver.js +223 -0
- package/src/lib/server/site-page-resolver.js.map +1 -0
- package/src/lib/server/stock-hold.d.ts +127 -0
- package/src/lib/server/stock-hold.js +258 -0
- package/src/lib/server/stock-hold.js.map +1 -0
- package/src/lib/server/storefront-tax-record.d.ts +22 -0
- package/src/lib/server/storefront-tax-record.js +218 -0
- package/src/lib/server/storefront-tax-record.js.map +1 -0
- package/src/lib/server/storefront-tax.d.ts +197 -0
- package/src/lib/server/storefront-tax.js +245 -0
- package/src/lib/server/storefront-tax.js.map +1 -0
- package/src/lib/server/stream.d.ts +25 -0
- package/src/lib/server/stream.js +191 -0
- package/src/lib/server/stream.js.map +1 -0
- package/src/lib/server/subscription-portal.d.ts +24 -0
- package/src/lib/server/subscription-portal.js +91 -0
- package/src/lib/server/subscription-portal.js.map +1 -0
- package/src/lib/server/supplier-outbox.d.ts +190 -0
- package/src/lib/server/supplier-outbox.js +342 -0
- package/src/lib/server/supplier-outbox.js.map +1 -0
- package/src/lib/server/supplier-update.d.ts +23 -0
- package/src/lib/server/supplier-update.js +289 -0
- package/src/lib/server/supplier-update.js.map +1 -0
- package/src/lib/server/tax-profile.d.ts +29 -0
- package/src/lib/server/tax-profile.js +40 -0
- package/src/lib/server/tax-profile.js.map +1 -0
- package/src/lib/server.d.ts +32 -0
- package/src/lib/server.js +311 -0
- package/src/lib/server.js.map +1 -0
- package/src/lib/site.d.ts +27 -0
- package/src/lib/site.js +134 -0
- package/src/lib/site.js.map +1 -0
- package/src/lib/utils/escape-html.d.ts +41 -0
- package/src/lib/utils/escape-html.js +41 -0
- package/src/lib/utils/escape-html.js.map +1 -0
- package/src/lib/utils/generate-preset-id.d.ts +19 -0
- package/src/lib/utils/generate-preset-id.js +25 -0
- package/src/lib/utils/generate-preset-id.js.map +1 -0
- package/src/lib/utils/member-continue.d.ts +45 -0
- package/src/lib/utils/member-continue.js +49 -0
- package/src/lib/utils/member-continue.js.map +1 -0
- package/src/lib/utils/use-storefront-purchase-event.d.ts +60 -0
- package/src/lib/utils/use-storefront-purchase-event.js +142 -0
- package/src/lib/utils/use-storefront-purchase-event.js.map +1 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
import type { TaxSettings } from './commerce-tax';
|
|
18
|
+
/**
|
|
19
|
+
* Whether a storefront sale computes tax, and — when it does not — WHY
|
|
20
|
+
* (AGL-1999).
|
|
21
|
+
*
|
|
22
|
+
* ## The defect this exists to remove
|
|
23
|
+
*
|
|
24
|
+
* Nothing seeds `hosts/{hostId}/settings/store`. It is written only when the
|
|
25
|
+
* merchant opens the Taxes card and saves. Until then `tax.mode` is
|
|
26
|
+
* `undefined`, and every server-side branch tested for a specific string:
|
|
27
|
+
*
|
|
28
|
+
* checkout.ts `mode === 'stripe'` / `mode === 'manual'`
|
|
29
|
+
* cart-checkout.ts `mode === 'stripe'` / `mode === 'manual'`
|
|
30
|
+
* draft-order.ts `mode === 'stripe'` / `mode === 'manual'`
|
|
31
|
+
* pos-order.ts `mode === 'manual'`
|
|
32
|
+
*
|
|
33
|
+
* `undefined` matched neither. No branch was taken, no tax was computed, and
|
|
34
|
+
* no path refused the sale — so buy-now, cart, draft orders and POS all
|
|
35
|
+
* charged the shopper an untaxed total. The `{ mode: 'manual' }` default that
|
|
36
|
+
* makes this look safe lives ONLY in the console card's local state
|
|
37
|
+
* (`tax-settings-card.component.tsx`) and never reaches Firestore unless the
|
|
38
|
+
* merchant presses Save. A merchant who never visits the card — the default
|
|
39
|
+
* state of every new storefront — sold untaxed, and was never told.
|
|
40
|
+
*
|
|
41
|
+
* The failure is silent in both directions: the shopper is undercharged, and
|
|
42
|
+
* the merchant accrues an unremitted liability nobody mentioned. Undercharging
|
|
43
|
+
* cannot be recovered — by the time anyone notices, the shopper is gone.
|
|
44
|
+
*
|
|
45
|
+
* ## The decision taken (AGL-1999 option 1, with an explicit opt-out)
|
|
46
|
+
*
|
|
47
|
+
* **An unset tax mode REFUSES the sale.** This follows the precedent AGL-1791
|
|
48
|
+
* set for shipping: a destination no zone covers is refused, not silently
|
|
49
|
+
* zero-rated. Refusal is recoverable — the merchant sees it and configures —
|
|
50
|
+
* where undercharging is not.
|
|
51
|
+
*
|
|
52
|
+
* Defaulting to `stripe` instead was rejected, and not on ergonomics: Stripe
|
|
53
|
+
* Tax computes storefront sessions against AGLYN's registrations with
|
|
54
|
+
* `liability: self` (MEASURED — see `storefront-tax.ts`), so defaulting there
|
|
55
|
+
* silently makes Aglyn the collecting party for merchants who never asked.
|
|
56
|
+
* That is a legal position (AGL-1904 / AGL-1956), it belongs to counsel, and a
|
|
57
|
+
* default is the wrong way to take it.
|
|
58
|
+
*
|
|
59
|
+
* **But refusing every unconfigured store would be wrong too**, because plenty
|
|
60
|
+
* of merchants genuinely owe no tax — under a nexus threshold, or selling
|
|
61
|
+
* non-taxable goods. So `mode: 'none'` is a first-class, RECORDED decision
|
|
62
|
+
* meaning "I have decided not to collect", and it is honoured silently. The
|
|
63
|
+
* refusal is reserved for the one state that is not a decision at all: nobody
|
|
64
|
+
* has answered the question yet.
|
|
65
|
+
*
|
|
66
|
+
* A merchant who opens the card and saves `manual` with no rates still
|
|
67
|
+
* collects nothing. That is fine and deliberate — they were asked and they
|
|
68
|
+
* answered. The point is never that tax gets collected; it is that a human
|
|
69
|
+
* decided.
|
|
70
|
+
*
|
|
71
|
+
* Pure and total, so every path can share one answer instead of four
|
|
72
|
+
* hand-rolled string tests that already drifted once (AGL-1953).
|
|
73
|
+
*/
|
|
74
|
+
export type StorefrontTaxDecision =
|
|
75
|
+
/** Stripe Tax computes it. See the AGL-1904 liability note. */
|
|
76
|
+
{
|
|
77
|
+
kind: 'stripe-automatic';
|
|
78
|
+
}
|
|
79
|
+
/** The merchant's own configured rate for the store origin. */
|
|
80
|
+
| {
|
|
81
|
+
kind: 'manual';
|
|
82
|
+
}
|
|
83
|
+
/** This PRODUCT is exempt; the store's mode is irrelevant to it. */
|
|
84
|
+
| {
|
|
85
|
+
kind: 'exempt';
|
|
86
|
+
reason: string;
|
|
87
|
+
}
|
|
88
|
+
/** The merchant decided not to collect. Honoured, and recorded. */
|
|
89
|
+
| {
|
|
90
|
+
kind: 'none';
|
|
91
|
+
reason: string;
|
|
92
|
+
}
|
|
93
|
+
/** Nobody has decided. The sale must be refused, not zero-rated. */
|
|
94
|
+
| {
|
|
95
|
+
kind: 'undecided';
|
|
96
|
+
reason: string;
|
|
97
|
+
};
|
|
98
|
+
export interface StorefrontTaxDecisionInput {
|
|
99
|
+
/** `hosts/{hostId}/settings/store.tax`, absent doc included. */
|
|
100
|
+
settings: TaxSettings | undefined | null;
|
|
101
|
+
/** The product's own `taxExempt` flag, where the path has one. */
|
|
102
|
+
taxExempt?: boolean;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* What every storefront sales-tax path should do about tax, and why.
|
|
106
|
+
*
|
|
107
|
+
* Reservations deliberately do NOT call this: a stay is not goods, lodging is
|
|
108
|
+
* a different regime from the sales rate the AGL-285 editor configures, and
|
|
109
|
+
* that no-tax outcome is its own stated decision in `reserve.ts`.
|
|
110
|
+
*/
|
|
111
|
+
export declare function storefrontTaxDecision(input: StorefrontTaxDecisionInput): StorefrontTaxDecision;
|
|
112
|
+
/**
|
|
113
|
+
* The message a refused shopper's merchant needs to act on. Kept beside the
|
|
114
|
+
* decision so all four paths refuse in the same words.
|
|
115
|
+
*/
|
|
116
|
+
export declare const STOREFRONT_TAX_UNDECIDED_MESSAGE: string;
|
|
117
|
+
/**
|
|
118
|
+
* A second refusal, for the two states that ARE decisions but that the path
|
|
119
|
+
* about to run cannot honour (AGL-2145).
|
|
120
|
+
*
|
|
121
|
+
* `storefrontTaxDecision` above answers "did a human decide?", and its
|
|
122
|
+
* docblock is careful about the difference between an undecided store and one
|
|
123
|
+
* that decided to collect nothing. Both of the states below sit outside that
|
|
124
|
+
* distinction: the merchant decided to collect tax, and the sale then charged
|
|
125
|
+
* zero anyway, silently, leaving the liability with them.
|
|
126
|
+
*
|
|
127
|
+
* 1. **Manual mode with no store origin.** `resolveTaxRate` opens with
|
|
128
|
+
* `if (!country) return null`, and every caller reads that null as "no
|
|
129
|
+
* rate applies" — the same value it returns for a shopper in a
|
|
130
|
+
* jurisdiction the merchant has no rate for, which is a legitimate zero.
|
|
131
|
+
* An empty `origin.country` is not a jurisdiction miss, it is an
|
|
132
|
+
* unfinished settings card: the merchant chose Manual, and *every* order
|
|
133
|
+
* is then untaxed regardless of who buys. A merchant who saved `manual`
|
|
134
|
+
* with an origin and no matching rates still collects nothing, and that
|
|
135
|
+
* stays fine — they answered, and the answer applies per shopper.
|
|
136
|
+
*
|
|
137
|
+
* 2. **Stripe-automatic at the REGISTER.** `pos-order.ts` sends the whole
|
|
138
|
+
* basket as one opaque `In-store purchase` line at `totals.totalCents` and
|
|
139
|
+
* sets no `automatic_tax[enabled]` — it cannot, there is no customer
|
|
140
|
+
* address at a till — and the cash and folio tenders never reach Stripe at
|
|
141
|
+
* all. So a store that chose "Stripe computes my tax" got **zero** tax on
|
|
142
|
+
* every in-person sale, on both tenders, with no refusal and no log. This
|
|
143
|
+
* is the same defect AGL-1999 closed for the three online paths, still
|
|
144
|
+
* open at the one place a shopper stands in front of you.
|
|
145
|
+
*
|
|
146
|
+
* `inPerson` is what separates them: (2) is a property of the REGISTER, not of
|
|
147
|
+
* the store, and online Stripe-Tax sales are correct and must not be refused.
|
|
148
|
+
*
|
|
149
|
+
* Returns the message to refuse with, or null to proceed. Never a boolean —
|
|
150
|
+
* the four paths must refuse in the merchant's own words, and a boolean is how
|
|
151
|
+
* four hand-rolled strings drift.
|
|
152
|
+
*/
|
|
153
|
+
export declare function storefrontTaxMisconfiguration(settings: TaxSettings | undefined | null, options?: {
|
|
154
|
+
inPerson?: boolean;
|
|
155
|
+
}): string | null;
|
|
156
|
+
/** @see storefrontTaxMisconfiguration — case 1. */
|
|
157
|
+
export declare const STOREFRONT_TAX_NO_ORIGIN_MESSAGE: string;
|
|
158
|
+
/** @see storefrontTaxMisconfiguration — case 2. */
|
|
159
|
+
export declare const STOREFRONT_TAX_POS_STRIPE_MESSAGE: string;
|
|
160
|
+
/**
|
|
161
|
+
* WHICH MACHINERY produced the tax on a storefront sale (AGL-1904).
|
|
162
|
+
*
|
|
163
|
+
* The canonical home for the union, because two different things need it:
|
|
164
|
+
* the `storefrontTaxCollected` record that Aglyn's own return reads
|
|
165
|
+
* (`server/storefront-tax.ts`, which re-exports this) and the `taxMode` field
|
|
166
|
+
* stamped on the merchant's ORDER (AGL-2451). One union, so the two can never
|
|
167
|
+
* disagree about what a value means.
|
|
168
|
+
*
|
|
169
|
+
* - **`stripe-automatic`** — Stripe Tax computed it, against whichever
|
|
170
|
+
* account `automatic_tax.liability` names. On a storefront session that is
|
|
171
|
+
* AGLYN's platform account (MEASURED — see `server/storefront-tax.ts`).
|
|
172
|
+
* - **`manual`** — the merchant's own configured rate, applied to their own
|
|
173
|
+
* declared origin. Aglyn's registrations never enter into it.
|
|
174
|
+
* - **`none`** — no tax was charged on this sale.
|
|
175
|
+
*
|
|
176
|
+
* ABSENT is a fourth state and is NOT `none`: it means "not recorded", which
|
|
177
|
+
* is what every order written before AGL-2451 genuinely is. Nothing may
|
|
178
|
+
* default it — see `describeOrderTaxMode` and the warning on `liftLegacyOrder`.
|
|
179
|
+
*/
|
|
180
|
+
export type StorefrontTaxMode = 'stripe-automatic' | 'manual' | 'none';
|
|
181
|
+
/**
|
|
182
|
+
* THE derivation, in one place, for every path that resolves a tax mode.
|
|
183
|
+
*
|
|
184
|
+
* `automatic` is `automatic_tax.enabled` on the Stripe object, or
|
|
185
|
+
* `decision.kind === 'stripe-automatic'` where the sale never reaches Stripe
|
|
186
|
+
* at all (the register's cash and folio tenders). It is **never** "were there
|
|
187
|
+
* tax lines": a manual-mode subscription renewal carries a real Stripe Tax
|
|
188
|
+
* Rate (AGL-1751) and a manual cart or draft order has since AGL-1953, so
|
|
189
|
+
* their invoices and sessions arrive with populated tax breakdowns that are
|
|
190
|
+
* byte-indistinguishable from a Stripe Tax one. Summing lines would silently
|
|
191
|
+
* book merchant-configured tax as Aglyn-collected. **Read the flag.**
|
|
192
|
+
*
|
|
193
|
+
* `taxCents` only ever separates `manual` from `none`, and only when the flag
|
|
194
|
+
* is off: a `stripe-automatic` sale stays `stripe-automatic` at zero tax,
|
|
195
|
+
* because "Stripe Tax answered not-collecting" is itself the audit answer to
|
|
196
|
+
* why a jurisdiction is absent from a return.
|
|
197
|
+
*/
|
|
198
|
+
export declare function storefrontTaxMode(input: {
|
|
199
|
+
automatic: boolean;
|
|
200
|
+
taxCents: number;
|
|
201
|
+
}): StorefrontTaxMode;
|
|
202
|
+
/**
|
|
203
|
+
* The same derivation, from a `StorefrontTaxDecision` — for the paths that
|
|
204
|
+
* resolve tax before any Stripe object exists (`pos-order.ts`,
|
|
205
|
+
* `draft-order.ts`). `exempt` and `none` both charge nothing and land on
|
|
206
|
+
* `none`; `undecided` never reaches a write, because every caller refuses it.
|
|
207
|
+
*/
|
|
208
|
+
export declare function storefrontTaxModeForDecision(decision: StorefrontTaxDecision, taxCents: number): StorefrontTaxMode;
|
|
209
|
+
/**
|
|
210
|
+
* How the tax on ONE order was computed, in the merchant's words (AGL-2451).
|
|
211
|
+
*
|
|
212
|
+
* Describes the MECHANISM and makes **no remittance determination** — the same
|
|
213
|
+
* constraint AGL-2440's report ships under. Who owes which authority what is a
|
|
214
|
+
* legal conclusion that attaches by operation of law (AGL-1904/AGL-1956); it
|
|
215
|
+
* belongs to counsel, and a sentence in an order dialog is the wrong place to
|
|
216
|
+
* take it.
|
|
217
|
+
*
|
|
218
|
+
* An absent mode answers "not recorded", never "no tax" — every order written
|
|
219
|
+
* before this shipped has no stamp, and rendering that as `none` would state a
|
|
220
|
+
* tax fact nobody recorded.
|
|
221
|
+
*/
|
|
222
|
+
export declare function describeOrderTaxMode(mode: StorefrontTaxMode | undefined | null): string;
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ /**
|
|
17
|
+
* What every storefront sales-tax path should do about tax, and why.
|
|
18
|
+
*
|
|
19
|
+
* Reservations deliberately do NOT call this: a stay is not goods, lodging is
|
|
20
|
+
* a different regime from the sales rate the AGL-285 editor configures, and
|
|
21
|
+
* that no-tax outcome is its own stated decision in `reserve.ts`.
|
|
22
|
+
*/ export function storefrontTaxDecision(input) {
|
|
23
|
+
var _input_settings;
|
|
24
|
+
// The product flag wins over the store mode, exactly as the inline
|
|
25
|
+
// `&& !lifted.taxExempt` tests did — an exempt product is exempt whichever
|
|
26
|
+
// machinery the store uses.
|
|
27
|
+
if (input.taxExempt === true) {
|
|
28
|
+
return {
|
|
29
|
+
kind: 'exempt',
|
|
30
|
+
reason: 'the product is marked tax-exempt'
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
const mode = (_input_settings = input.settings) == null ? void 0 : _input_settings.mode;
|
|
34
|
+
if (mode === 'stripe') return {
|
|
35
|
+
kind: 'stripe-automatic'
|
|
36
|
+
};
|
|
37
|
+
if (mode === 'manual') return {
|
|
38
|
+
kind: 'manual'
|
|
39
|
+
};
|
|
40
|
+
if (mode === 'none') {
|
|
41
|
+
return {
|
|
42
|
+
kind: 'none',
|
|
43
|
+
reason: 'the store has decided not to collect sales tax'
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
// Anything else — an absent settings document, an absent `mode`, or a value
|
|
47
|
+
// written by a future version this build does not know — is NOT a decision.
|
|
48
|
+
// Refusing an unrecognised string is deliberate: guessing at it is how the
|
|
49
|
+
// original defect behaved.
|
|
50
|
+
return {
|
|
51
|
+
kind: 'undecided',
|
|
52
|
+
reason: 'no one has chosen how this store handles sales tax'
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The message a refused shopper's merchant needs to act on. Kept beside the
|
|
57
|
+
* decision so all four paths refuse in the same words.
|
|
58
|
+
*/ export const STOREFRONT_TAX_UNDECIDED_MESSAGE = 'This store has not set up sales tax yet, so we can’t take the order. ' + 'The store owner can fix this in Commerce → Settings → Taxes.';
|
|
59
|
+
/**
|
|
60
|
+
* A second refusal, for the two states that ARE decisions but that the path
|
|
61
|
+
* about to run cannot honour (AGL-2145).
|
|
62
|
+
*
|
|
63
|
+
* `storefrontTaxDecision` above answers "did a human decide?", and its
|
|
64
|
+
* docblock is careful about the difference between an undecided store and one
|
|
65
|
+
* that decided to collect nothing. Both of the states below sit outside that
|
|
66
|
+
* distinction: the merchant decided to collect tax, and the sale then charged
|
|
67
|
+
* zero anyway, silently, leaving the liability with them.
|
|
68
|
+
*
|
|
69
|
+
* 1. **Manual mode with no store origin.** `resolveTaxRate` opens with
|
|
70
|
+
* `if (!country) return null`, and every caller reads that null as "no
|
|
71
|
+
* rate applies" — the same value it returns for a shopper in a
|
|
72
|
+
* jurisdiction the merchant has no rate for, which is a legitimate zero.
|
|
73
|
+
* An empty `origin.country` is not a jurisdiction miss, it is an
|
|
74
|
+
* unfinished settings card: the merchant chose Manual, and *every* order
|
|
75
|
+
* is then untaxed regardless of who buys. A merchant who saved `manual`
|
|
76
|
+
* with an origin and no matching rates still collects nothing, and that
|
|
77
|
+
* stays fine — they answered, and the answer applies per shopper.
|
|
78
|
+
*
|
|
79
|
+
* 2. **Stripe-automatic at the REGISTER.** `pos-order.ts` sends the whole
|
|
80
|
+
* basket as one opaque `In-store purchase` line at `totals.totalCents` and
|
|
81
|
+
* sets no `automatic_tax[enabled]` — it cannot, there is no customer
|
|
82
|
+
* address at a till — and the cash and folio tenders never reach Stripe at
|
|
83
|
+
* all. So a store that chose "Stripe computes my tax" got **zero** tax on
|
|
84
|
+
* every in-person sale, on both tenders, with no refusal and no log. This
|
|
85
|
+
* is the same defect AGL-1999 closed for the three online paths, still
|
|
86
|
+
* open at the one place a shopper stands in front of you.
|
|
87
|
+
*
|
|
88
|
+
* `inPerson` is what separates them: (2) is a property of the REGISTER, not of
|
|
89
|
+
* the store, and online Stripe-Tax sales are correct and must not be refused.
|
|
90
|
+
*
|
|
91
|
+
* Returns the message to refuse with, or null to proceed. Never a boolean —
|
|
92
|
+
* the four paths must refuse in the merchant's own words, and a boolean is how
|
|
93
|
+
* four hand-rolled strings drift.
|
|
94
|
+
*/ export function storefrontTaxMisconfiguration(settings, options = {}) {
|
|
95
|
+
var _ref;
|
|
96
|
+
var _settings_origin;
|
|
97
|
+
const mode = settings == null ? void 0 : settings.mode;
|
|
98
|
+
if (mode === 'manual' && !String((_ref = settings == null ? void 0 : (_settings_origin = settings.origin) == null ? void 0 : _settings_origin.country) != null ? _ref : '').trim()) {
|
|
99
|
+
return STOREFRONT_TAX_NO_ORIGIN_MESSAGE;
|
|
100
|
+
}
|
|
101
|
+
if (mode === 'stripe' && options.inPerson === true) {
|
|
102
|
+
return STOREFRONT_TAX_POS_STRIPE_MESSAGE;
|
|
103
|
+
}
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
/** @see storefrontTaxMisconfiguration — case 1. */ export const STOREFRONT_TAX_NO_ORIGIN_MESSAGE = 'This store collects sales tax manually but has no store address set, so ' + 'no rate can be applied. The store owner can add it in Commerce → ' + 'Settings → Taxes.';
|
|
107
|
+
/** @see storefrontTaxMisconfiguration — case 2. */ export const STOREFRONT_TAX_POS_STRIPE_MESSAGE = 'This store uses automatic tax, which the register can’t calculate for an ' + 'in-person sale. The store owner can switch Taxes to Manual and add a rate ' + 'for the store address in Commerce → Settings → Taxes.';
|
|
108
|
+
/**
|
|
109
|
+
* THE derivation, in one place, for every path that resolves a tax mode.
|
|
110
|
+
*
|
|
111
|
+
* `automatic` is `automatic_tax.enabled` on the Stripe object, or
|
|
112
|
+
* `decision.kind === 'stripe-automatic'` where the sale never reaches Stripe
|
|
113
|
+
* at all (the register's cash and folio tenders). It is **never** "were there
|
|
114
|
+
* tax lines": a manual-mode subscription renewal carries a real Stripe Tax
|
|
115
|
+
* Rate (AGL-1751) and a manual cart or draft order has since AGL-1953, so
|
|
116
|
+
* their invoices and sessions arrive with populated tax breakdowns that are
|
|
117
|
+
* byte-indistinguishable from a Stripe Tax one. Summing lines would silently
|
|
118
|
+
* book merchant-configured tax as Aglyn-collected. **Read the flag.**
|
|
119
|
+
*
|
|
120
|
+
* `taxCents` only ever separates `manual` from `none`, and only when the flag
|
|
121
|
+
* is off: a `stripe-automatic` sale stays `stripe-automatic` at zero tax,
|
|
122
|
+
* because "Stripe Tax answered not-collecting" is itself the audit answer to
|
|
123
|
+
* why a jurisdiction is absent from a return.
|
|
124
|
+
*/ export function storefrontTaxMode(input) {
|
|
125
|
+
var _input_taxCents;
|
|
126
|
+
if (input.automatic) return 'stripe-automatic';
|
|
127
|
+
return Number((_input_taxCents = input.taxCents) != null ? _input_taxCents : 0) > 0 ? 'manual' : 'none';
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* The same derivation, from a `StorefrontTaxDecision` — for the paths that
|
|
131
|
+
* resolve tax before any Stripe object exists (`pos-order.ts`,
|
|
132
|
+
* `draft-order.ts`). `exempt` and `none` both charge nothing and land on
|
|
133
|
+
* `none`; `undecided` never reaches a write, because every caller refuses it.
|
|
134
|
+
*/ export function storefrontTaxModeForDecision(decision, taxCents) {
|
|
135
|
+
return storefrontTaxMode({
|
|
136
|
+
automatic: decision.kind === 'stripe-automatic',
|
|
137
|
+
taxCents
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* How the tax on ONE order was computed, in the merchant's words (AGL-2451).
|
|
142
|
+
*
|
|
143
|
+
* Describes the MECHANISM and makes **no remittance determination** — the same
|
|
144
|
+
* constraint AGL-2440's report ships under. Who owes which authority what is a
|
|
145
|
+
* legal conclusion that attaches by operation of law (AGL-1904/AGL-1956); it
|
|
146
|
+
* belongs to counsel, and a sentence in an order dialog is the wrong place to
|
|
147
|
+
* take it.
|
|
148
|
+
*
|
|
149
|
+
* An absent mode answers "not recorded", never "no tax" — every order written
|
|
150
|
+
* before this shipped has no stamp, and rendering that as `none` would state a
|
|
151
|
+
* tax fact nobody recorded.
|
|
152
|
+
*/ export function describeOrderTaxMode(mode) {
|
|
153
|
+
if (mode === 'stripe-automatic') {
|
|
154
|
+
return 'Calculated automatically by Stripe Tax at checkout, from the shopper’s address.';
|
|
155
|
+
}
|
|
156
|
+
if (mode === 'manual') {
|
|
157
|
+
return 'Calculated from this store’s own configured tax rate.';
|
|
158
|
+
}
|
|
159
|
+
if (mode === 'none') {
|
|
160
|
+
return 'No sales tax was calculated on this order.';
|
|
161
|
+
}
|
|
162
|
+
return 'How this tax was calculated was not recorded on this order.';
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
//# sourceMappingURL=commerce-tax-decision.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/model/commerce-tax-decision.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TaxSettings } from './commerce-tax'\n\n/**\n * Whether a storefront sale computes tax, and — when it does not — WHY\n * (AGL-1999).\n *\n * ## The defect this exists to remove\n *\n * Nothing seeds `hosts/{hostId}/settings/store`. It is written only when the\n * merchant opens the Taxes card and saves. Until then `tax.mode` is\n * `undefined`, and every server-side branch tested for a specific string:\n *\n * checkout.ts `mode === 'stripe'` / `mode === 'manual'`\n * cart-checkout.ts `mode === 'stripe'` / `mode === 'manual'`\n * draft-order.ts `mode === 'stripe'` / `mode === 'manual'`\n * pos-order.ts `mode === 'manual'`\n *\n * `undefined` matched neither. No branch was taken, no tax was computed, and\n * no path refused the sale — so buy-now, cart, draft orders and POS all\n * charged the shopper an untaxed total. The `{ mode: 'manual' }` default that\n * makes this look safe lives ONLY in the console card's local state\n * (`tax-settings-card.component.tsx`) and never reaches Firestore unless the\n * merchant presses Save. A merchant who never visits the card — the default\n * state of every new storefront — sold untaxed, and was never told.\n *\n * The failure is silent in both directions: the shopper is undercharged, and\n * the merchant accrues an unremitted liability nobody mentioned. Undercharging\n * cannot be recovered — by the time anyone notices, the shopper is gone.\n *\n * ## The decision taken (AGL-1999 option 1, with an explicit opt-out)\n *\n * **An unset tax mode REFUSES the sale.** This follows the precedent AGL-1791\n * set for shipping: a destination no zone covers is refused, not silently\n * zero-rated. Refusal is recoverable — the merchant sees it and configures —\n * where undercharging is not.\n *\n * Defaulting to `stripe` instead was rejected, and not on ergonomics: Stripe\n * Tax computes storefront sessions against AGLYN's registrations with\n * `liability: self` (MEASURED — see `storefront-tax.ts`), so defaulting there\n * silently makes Aglyn the collecting party for merchants who never asked.\n * That is a legal position (AGL-1904 / AGL-1956), it belongs to counsel, and a\n * default is the wrong way to take it.\n *\n * **But refusing every unconfigured store would be wrong too**, because plenty\n * of merchants genuinely owe no tax — under a nexus threshold, or selling\n * non-taxable goods. So `mode: 'none'` is a first-class, RECORDED decision\n * meaning \"I have decided not to collect\", and it is honoured silently. The\n * refusal is reserved for the one state that is not a decision at all: nobody\n * has answered the question yet.\n *\n * A merchant who opens the card and saves `manual` with no rates still\n * collects nothing. That is fine and deliberate — they were asked and they\n * answered. The point is never that tax gets collected; it is that a human\n * decided.\n *\n * Pure and total, so every path can share one answer instead of four\n * hand-rolled string tests that already drifted once (AGL-1953).\n */\nexport type StorefrontTaxDecision =\n /** Stripe Tax computes it. See the AGL-1904 liability note. */\n | { kind: 'stripe-automatic' }\n /** The merchant's own configured rate for the store origin. */\n | { kind: 'manual' }\n /** This PRODUCT is exempt; the store's mode is irrelevant to it. */\n | { kind: 'exempt'; reason: string }\n /** The merchant decided not to collect. Honoured, and recorded. */\n | { kind: 'none'; reason: string }\n /** Nobody has decided. The sale must be refused, not zero-rated. */\n | { kind: 'undecided'; reason: string }\n\nexport interface StorefrontTaxDecisionInput {\n /** `hosts/{hostId}/settings/store.tax`, absent doc included. */\n settings: TaxSettings | undefined | null\n /** The product's own `taxExempt` flag, where the path has one. */\n taxExempt?: boolean\n}\n\n/**\n * What every storefront sales-tax path should do about tax, and why.\n *\n * Reservations deliberately do NOT call this: a stay is not goods, lodging is\n * a different regime from the sales rate the AGL-285 editor configures, and\n * that no-tax outcome is its own stated decision in `reserve.ts`.\n */\nexport function storefrontTaxDecision(\n input: StorefrontTaxDecisionInput,\n): StorefrontTaxDecision {\n // The product flag wins over the store mode, exactly as the inline\n // `&& !lifted.taxExempt` tests did — an exempt product is exempt whichever\n // machinery the store uses.\n if (input.taxExempt === true) {\n return {\n kind: 'exempt',\n reason: 'the product is marked tax-exempt',\n }\n }\n const mode = input.settings?.mode\n if (mode === 'stripe') return { kind: 'stripe-automatic' }\n if (mode === 'manual') return { kind: 'manual' }\n if (mode === 'none') {\n return {\n kind: 'none',\n reason: 'the store has decided not to collect sales tax',\n }\n }\n // Anything else — an absent settings document, an absent `mode`, or a value\n // written by a future version this build does not know — is NOT a decision.\n // Refusing an unrecognised string is deliberate: guessing at it is how the\n // original defect behaved.\n return {\n kind: 'undecided',\n reason: 'no one has chosen how this store handles sales tax',\n }\n}\n\n/**\n * The message a refused shopper's merchant needs to act on. Kept beside the\n * decision so all four paths refuse in the same words.\n */\nexport const STOREFRONT_TAX_UNDECIDED_MESSAGE =\n 'This store has not set up sales tax yet, so we can’t take the order. ' +\n 'The store owner can fix this in Commerce → Settings → Taxes.'\n\n/**\n * A second refusal, for the two states that ARE decisions but that the path\n * about to run cannot honour (AGL-2145).\n *\n * `storefrontTaxDecision` above answers \"did a human decide?\", and its\n * docblock is careful about the difference between an undecided store and one\n * that decided to collect nothing. Both of the states below sit outside that\n * distinction: the merchant decided to collect tax, and the sale then charged\n * zero anyway, silently, leaving the liability with them.\n *\n * 1. **Manual mode with no store origin.** `resolveTaxRate` opens with\n * `if (!country) return null`, and every caller reads that null as \"no\n * rate applies\" — the same value it returns for a shopper in a\n * jurisdiction the merchant has no rate for, which is a legitimate zero.\n * An empty `origin.country` is not a jurisdiction miss, it is an\n * unfinished settings card: the merchant chose Manual, and *every* order\n * is then untaxed regardless of who buys. A merchant who saved `manual`\n * with an origin and no matching rates still collects nothing, and that\n * stays fine — they answered, and the answer applies per shopper.\n *\n * 2. **Stripe-automatic at the REGISTER.** `pos-order.ts` sends the whole\n * basket as one opaque `In-store purchase` line at `totals.totalCents` and\n * sets no `automatic_tax[enabled]` — it cannot, there is no customer\n * address at a till — and the cash and folio tenders never reach Stripe at\n * all. So a store that chose \"Stripe computes my tax\" got **zero** tax on\n * every in-person sale, on both tenders, with no refusal and no log. This\n * is the same defect AGL-1999 closed for the three online paths, still\n * open at the one place a shopper stands in front of you.\n *\n * `inPerson` is what separates them: (2) is a property of the REGISTER, not of\n * the store, and online Stripe-Tax sales are correct and must not be refused.\n *\n * Returns the message to refuse with, or null to proceed. Never a boolean —\n * the four paths must refuse in the merchant's own words, and a boolean is how\n * four hand-rolled strings drift.\n */\nexport function storefrontTaxMisconfiguration(\n settings: TaxSettings | undefined | null,\n options: { inPerson?: boolean } = {},\n): string | null {\n const mode = settings?.mode\n if (mode === 'manual' && !String(settings?.origin?.country ?? '').trim()) {\n return STOREFRONT_TAX_NO_ORIGIN_MESSAGE\n }\n if (mode === 'stripe' && options.inPerson === true) {\n return STOREFRONT_TAX_POS_STRIPE_MESSAGE\n }\n return null\n}\n\n/** @see storefrontTaxMisconfiguration — case 1. */\nexport const STOREFRONT_TAX_NO_ORIGIN_MESSAGE =\n 'This store collects sales tax manually but has no store address set, so ' +\n 'no rate can be applied. The store owner can add it in Commerce → ' +\n 'Settings → Taxes.'\n\n/** @see storefrontTaxMisconfiguration — case 2. */\nexport const STOREFRONT_TAX_POS_STRIPE_MESSAGE =\n 'This store uses automatic tax, which the register can’t calculate for an ' +\n 'in-person sale. The store owner can switch Taxes to Manual and add a rate ' +\n 'for the store address in Commerce → Settings → Taxes.'\n\n/**\n * WHICH MACHINERY produced the tax on a storefront sale (AGL-1904).\n *\n * The canonical home for the union, because two different things need it:\n * the `storefrontTaxCollected` record that Aglyn's own return reads\n * (`server/storefront-tax.ts`, which re-exports this) and the `taxMode` field\n * stamped on the merchant's ORDER (AGL-2451). One union, so the two can never\n * disagree about what a value means.\n *\n * - **`stripe-automatic`** — Stripe Tax computed it, against whichever\n * account `automatic_tax.liability` names. On a storefront session that is\n * AGLYN's platform account (MEASURED — see `server/storefront-tax.ts`).\n * - **`manual`** — the merchant's own configured rate, applied to their own\n * declared origin. Aglyn's registrations never enter into it.\n * - **`none`** — no tax was charged on this sale.\n *\n * ABSENT is a fourth state and is NOT `none`: it means \"not recorded\", which\n * is what every order written before AGL-2451 genuinely is. Nothing may\n * default it — see `describeOrderTaxMode` and the warning on `liftLegacyOrder`.\n */\nexport type StorefrontTaxMode = 'stripe-automatic' | 'manual' | 'none'\n\n/**\n * THE derivation, in one place, for every path that resolves a tax mode.\n *\n * `automatic` is `automatic_tax.enabled` on the Stripe object, or\n * `decision.kind === 'stripe-automatic'` where the sale never reaches Stripe\n * at all (the register's cash and folio tenders). It is **never** \"were there\n * tax lines\": a manual-mode subscription renewal carries a real Stripe Tax\n * Rate (AGL-1751) and a manual cart or draft order has since AGL-1953, so\n * their invoices and sessions arrive with populated tax breakdowns that are\n * byte-indistinguishable from a Stripe Tax one. Summing lines would silently\n * book merchant-configured tax as Aglyn-collected. **Read the flag.**\n *\n * `taxCents` only ever separates `manual` from `none`, and only when the flag\n * is off: a `stripe-automatic` sale stays `stripe-automatic` at zero tax,\n * because \"Stripe Tax answered not-collecting\" is itself the audit answer to\n * why a jurisdiction is absent from a return.\n */\nexport function storefrontTaxMode(input: {\n automatic: boolean\n taxCents: number\n}): StorefrontTaxMode {\n if (input.automatic) return 'stripe-automatic'\n return Number(input.taxCents ?? 0) > 0 ? 'manual' : 'none'\n}\n\n/**\n * The same derivation, from a `StorefrontTaxDecision` — for the paths that\n * resolve tax before any Stripe object exists (`pos-order.ts`,\n * `draft-order.ts`). `exempt` and `none` both charge nothing and land on\n * `none`; `undecided` never reaches a write, because every caller refuses it.\n */\nexport function storefrontTaxModeForDecision(\n decision: StorefrontTaxDecision,\n taxCents: number,\n): StorefrontTaxMode {\n return storefrontTaxMode({\n automatic: decision.kind === 'stripe-automatic',\n taxCents,\n })\n}\n\n/**\n * How the tax on ONE order was computed, in the merchant's words (AGL-2451).\n *\n * Describes the MECHANISM and makes **no remittance determination** — the same\n * constraint AGL-2440's report ships under. Who owes which authority what is a\n * legal conclusion that attaches by operation of law (AGL-1904/AGL-1956); it\n * belongs to counsel, and a sentence in an order dialog is the wrong place to\n * take it.\n *\n * An absent mode answers \"not recorded\", never \"no tax\" — every order written\n * before this shipped has no stamp, and rendering that as `none` would state a\n * tax fact nobody recorded.\n */\nexport function describeOrderTaxMode(\n mode: StorefrontTaxMode | undefined | null,\n): string {\n if (mode === 'stripe-automatic') {\n return 'Calculated automatically by Stripe Tax at checkout, from the shopper’s address.'\n }\n if (mode === 'manual') {\n return 'Calculated from this store’s own configured tax rate.'\n }\n if (mode === 'none') {\n return 'No sales tax was calculated on this order.'\n }\n return 'How this tax was calculated was not recorded on this order.'\n}\n"],"names":["storefrontTaxDecision","input","taxExempt","kind","reason","mode","settings","STOREFRONT_TAX_UNDECIDED_MESSAGE","storefrontTaxMisconfiguration","options","String","origin","country","trim","STOREFRONT_TAX_NO_ORIGIN_MESSAGE","inPerson","STOREFRONT_TAX_POS_STRIPE_MESSAGE","storefrontTaxMode","automatic","Number","taxCents","storefrontTaxModeForDecision","decision","describeOrderTaxMode"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GA+ED;;;;;;CAMC,GACD,OAAO,SAASA,sBACdC,KAAiC;QAWpBA;IATb,mEAAmE;IACnE,2EAA2E;IAC3E,4BAA4B;IAC5B,IAAIA,MAAMC,SAAS,KAAK,MAAM;QAC5B,OAAO;YACLC,MAAM;YACNC,QAAQ;QACV;IACF;IACA,MAAMC,QAAOJ,kBAAAA,MAAMK,QAAQ,qBAAdL,gBAAgBI,IAAI;IACjC,IAAIA,SAAS,UAAU,OAAO;QAAEF,MAAM;IAAmB;IACzD,IAAIE,SAAS,UAAU,OAAO;QAAEF,MAAM;IAAS;IAC/C,IAAIE,SAAS,QAAQ;QACnB,OAAO;YACLF,MAAM;YACNC,QAAQ;QACV;IACF;IACA,4EAA4E;IAC5E,4EAA4E;IAC5E,2EAA2E;IAC3E,2BAA2B;IAC3B,OAAO;QACLD,MAAM;QACNC,QAAQ;IACV;AACF;AAEA;;;CAGC,GACD,OAAO,MAAMG,mCACX,0EACA,+DAA8D;AAEhE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmCC,GACD,OAAO,SAASC,8BACdF,QAAwC,EACxCG,UAAkC,CAAC,CAAC;;QAGHH;IADjC,MAAMD,OAAOC,4BAAAA,SAAUD,IAAI;IAC3B,IAAIA,SAAS,YAAY,CAACK,eAAOJ,6BAAAA,mBAAAA,SAAUK,MAAM,qBAAhBL,iBAAkBM,OAAO,mBAAI,IAAIC,IAAI,IAAI;QACxE,OAAOC;IACT;IACA,IAAIT,SAAS,YAAYI,QAAQM,QAAQ,KAAK,MAAM;QAClD,OAAOC;IACT;IACA,OAAO;AACT;AAEA,iDAAiD,GACjD,OAAO,MAAMF,mCACX,6EACA,sEACA,oBAAmB;AAErB,iDAAiD,GACjD,OAAO,MAAME,oCACX,8EACA,+EACA,wDAAuD;AAwBzD;;;;;;;;;;;;;;;;CAgBC,GACD,OAAO,SAASC,kBAAkBhB,KAGjC;QAEeA;IADd,IAAIA,MAAMiB,SAAS,EAAE,OAAO;IAC5B,OAAOC,QAAOlB,kBAAAA,MAAMmB,QAAQ,YAAdnB,kBAAkB,KAAK,IAAI,WAAW;AACtD;AAEA;;;;;CAKC,GACD,OAAO,SAASoB,6BACdC,QAA+B,EAC/BF,QAAgB;IAEhB,OAAOH,kBAAkB;QACvBC,WAAWI,SAASnB,IAAI,KAAK;QAC7BiB;IACF;AACF;AAEA;;;;;;;;;;;;CAYC,GACD,OAAO,SAASG,qBACdlB,IAA0C;IAE1C,IAAIA,SAAS,oBAAoB;QAC/B,OAAO;IACT;IACA,IAAIA,SAAS,UAAU;QACrB,OAAO;IACT;IACA,IAAIA,SAAS,QAAQ;QACnB,OAAO;IACT;IACA,OAAO;AACT"}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Taxes v1 (AGL-285): manual rates per region resolved most-specific
|
|
19
|
+
* first (country+state beats country), or Stripe Tax automatic
|
|
20
|
+
* calculation when the host opts in. Settings live on the
|
|
21
|
+
* `hosts/{hostId}/settings/store` doc under `tax`. Pure — checkout and
|
|
22
|
+
* POS call these; Stripe Tax mode bypasses them entirely.
|
|
23
|
+
*/
|
|
24
|
+
export interface TaxRate {
|
|
25
|
+
/** ISO-3166 alpha-2, e.g. 'US'. */
|
|
26
|
+
country: string;
|
|
27
|
+
/** Region/state code, e.g. 'TX'; absent = whole country. */
|
|
28
|
+
state?: string;
|
|
29
|
+
/** Percent, e.g. 8.25. */
|
|
30
|
+
pct: number;
|
|
31
|
+
/** Receipt label, e.g. 'TX sales tax'. */
|
|
32
|
+
label?: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* A FLAT, merchant-entered rate for a regime the goods sales-tax machinery
|
|
36
|
+
* above does not describe (AGL-1969 lodging, AGL-2028 services).
|
|
37
|
+
*
|
|
38
|
+
* ## Why this is not another `TaxRate`
|
|
39
|
+
*
|
|
40
|
+
* `rates[]` is a SALES tax table resolved against an address, most-specific
|
|
41
|
+
* first. Lodging (occupancy/hotel tax) and service tax are separate regimes
|
|
42
|
+
* with their own rates, their own registration and their own return, and the
|
|
43
|
+
* number a merchant typed into the goods table is not the right number for a
|
|
44
|
+
* night or an appointment. Reading `rates[]` for either would be confidently
|
|
45
|
+
* wrong rather than merely absent — which is exactly why `reserve.ts` and
|
|
46
|
+
* `bookings/server.ts` charged nothing at all until the merchant was given a
|
|
47
|
+
* field of their own to answer in.
|
|
48
|
+
*
|
|
49
|
+
* ## Off is the default and the default is load-bearing
|
|
50
|
+
*
|
|
51
|
+
* An absent, zero, negative, non-finite or out-of-range `pct` resolves to
|
|
52
|
+
* ZERO. Nothing an existing merchant is charging today moves because this
|
|
53
|
+
* shipped; a rate applies only once a merchant has typed one and saved.
|
|
54
|
+
*
|
|
55
|
+
* ## It is always MANUAL, in every store mode
|
|
56
|
+
*
|
|
57
|
+
* Deliberately independent of `TaxSettings.mode`. Stripe Tax cannot compute
|
|
58
|
+
* either regime from these sessions — it needs a lodging or service tax code
|
|
59
|
+
* no handler here sends — so a `mode: 'stripe'` store would otherwise have no
|
|
60
|
+
* way to collect them at all. Riding as an ordinary line item makes the
|
|
61
|
+
* derived `taxMode` read `manual`: the merchant's own rate, never computed
|
|
62
|
+
* against Aglyn's registrations (AGL-1904).
|
|
63
|
+
*
|
|
64
|
+
* ## Aglyn takes NO position on what is owed
|
|
65
|
+
*
|
|
66
|
+
* This is a calculator the merchant configures, records and can read back. It
|
|
67
|
+
* states no view on whether a jurisdiction imposes the tax, on who must
|
|
68
|
+
* register, or on who must remit — those attach by operation of law and
|
|
69
|
+
* belong to counsel (AGL-1904).
|
|
70
|
+
*
|
|
71
|
+
* ⚠️ The sentence that used to stand here — "Terms §10.3 already puts the
|
|
72
|
+
* question on the merchant" — is FALSE as of 2026-08-24 (AGL-1956). Aglyn
|
|
73
|
+
* accepts marketplace-facilitator status, ToS §10.3 no longer assigns sales
|
|
74
|
+
* tax to the merchant, and the new ToS §10.7 says Aglyn calculates, collects
|
|
75
|
+
* and remits it WHERE IT HAS A FACILITATOR OBLIGATION. Do not cite §10.3 as
|
|
76
|
+
* authority for merchant-facing tax copy again.
|
|
77
|
+
*
|
|
78
|
+
* What is still true, and is why this module did not change: these FLAT RATES
|
|
79
|
+
* are the manual/lodging/service path, which never touches Aglyn's
|
|
80
|
+
* registrations and is not what §10.7 covers. The rates a merchant types here
|
|
81
|
+
* remain theirs to determine.
|
|
82
|
+
*
|
|
83
|
+
* The merchant-facing copy this note used to call an OWED follow-up is DONE.
|
|
84
|
+
* `storefront-tax-summary-card.component.tsx` said "Aglyn does not make that
|
|
85
|
+
* determination for you" and was rewritten to §10.7 in `f7e5465f5`.
|
|
86
|
+
* `tax-settings-card.component.tsx` was read and needed no change — it governs
|
|
87
|
+
* exactly these flat lodging/service rates, which §10.7 does not reach, so it
|
|
88
|
+
* was already saying the right thing about the right taxes. Recorded rather
|
|
89
|
+
* than deleted: the next reader should not have to re-derive that the second
|
|
90
|
+
* card's silence is correct rather than overlooked.
|
|
91
|
+
*/
|
|
92
|
+
export interface FlatTaxRate {
|
|
93
|
+
/** Percent, e.g. 6. Absent or non-positive = off, which is the default. */
|
|
94
|
+
pct?: number;
|
|
95
|
+
/** Receipt label, e.g. 'Occupancy tax'. */
|
|
96
|
+
label?: string;
|
|
97
|
+
}
|
|
98
|
+
/** What a flat rate resolved to for one charge. */
|
|
99
|
+
export interface ResolvedFlatTax {
|
|
100
|
+
taxCents: number;
|
|
101
|
+
/** The label to put on the receipt line; empty when there is no tax. */
|
|
102
|
+
label: string;
|
|
103
|
+
/** The percentage actually applied — 0 when the rate is off or invalid. */
|
|
104
|
+
pct: number;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* The highest percentage this accepts. A rate above 100% is a decimal-point
|
|
108
|
+
* typo (`825` for `8.25`), not a jurisdiction, and multiplying a guest's
|
|
109
|
+
* deposit by nine because of one is a far worse failure than collecting
|
|
110
|
+
* nothing. Out of range resolves to OFF rather than being clamped to a number
|
|
111
|
+
* the merchant did not choose — and the editor says so on screen, so the
|
|
112
|
+
* refusal is never silent.
|
|
113
|
+
*/
|
|
114
|
+
export declare const FLAT_TAX_MAX_PCT = 100;
|
|
115
|
+
/** True when a typed percentage is one this will actually apply. */
|
|
116
|
+
export declare function isUsableFlatTaxPct(pct: unknown): boolean;
|
|
117
|
+
/**
|
|
118
|
+
* Tax cents for a flat merchant rate on one charged amount, EXCLUSIVE — added
|
|
119
|
+
* on top of the price, never back-calculated out of it.
|
|
120
|
+
*
|
|
121
|
+
* `pricesIncludeTax` is deliberately not consulted: it is a goods-pricing
|
|
122
|
+
* setting, and honouring it here would mean a merchant types a lodging rate,
|
|
123
|
+
* saves, and the guest's total does not move — a setting that reads as
|
|
124
|
+
* configured while collecting nothing is the AGL-1999 failure restated.
|
|
125
|
+
*
|
|
126
|
+
* Pure and total. Unusable input answers zero and never throws.
|
|
127
|
+
*/
|
|
128
|
+
export declare function resolveFlatTaxCents(rate: FlatTaxRate | undefined | null, chargeCents: number, fallbackLabel: string): ResolvedFlatTax;
|
|
129
|
+
export interface TaxSettings {
|
|
130
|
+
/**
|
|
131
|
+
* 'manual' rates below, 'stripe' for Stripe Tax automatic, or 'none' —
|
|
132
|
+
* an EXPLICIT decision not to collect (AGL-1999). `undefined` is not a
|
|
133
|
+
* fourth mode: it means nobody has decided, and `storefrontTaxDecision`
|
|
134
|
+
* refuses the sale rather than zero-rating it silently.
|
|
135
|
+
*/
|
|
136
|
+
mode?: 'manual' | 'stripe' | 'none';
|
|
137
|
+
/** Displayed prices already include tax (VAT-style). */
|
|
138
|
+
pricesIncludeTax?: boolean;
|
|
139
|
+
/**
|
|
140
|
+
* Store origin (AGL-285): the legacy single-product checkout taxes by
|
|
141
|
+
* origin because the buyer address arrives inside Stripe Checkout;
|
|
142
|
+
* Checkout v2 (AGL-296) collects the address first and taxes by
|
|
143
|
+
* destination.
|
|
144
|
+
*/
|
|
145
|
+
origin?: TaxAddress;
|
|
146
|
+
rates?: TaxRate[];
|
|
147
|
+
/**
|
|
148
|
+
* OCCUPANCY / LODGING tax on a reservation deposit (AGL-1969). Off unless
|
|
149
|
+
* the merchant sets it — see `FlatTaxRate`. Read by `reserve.ts` only.
|
|
150
|
+
*/
|
|
151
|
+
lodging?: FlatTaxRate;
|
|
152
|
+
/**
|
|
153
|
+
* SERVICE tax on a paid booking (AGL-2028). Off unless the merchant sets
|
|
154
|
+
* it — see `FlatTaxRate`. Read by the bookings plugin only.
|
|
155
|
+
*
|
|
156
|
+
* ITS EXISTENCE IS THE OPT-IN. AGL-2000 declined to apply the goods
|
|
157
|
+
* `rates[]` to an appointment partly because nothing said the merchant
|
|
158
|
+
* meant those settings to cover bookings — they are another plugin's
|
|
159
|
+
* surface. A field of its own, labelled for services and blank until
|
|
160
|
+
* somebody fills it in, is the merchant saying so explicitly. Reading
|
|
161
|
+
* `rates[]` for a booking is still wrong and still nothing does it.
|
|
162
|
+
*/
|
|
163
|
+
service?: FlatTaxRate;
|
|
164
|
+
}
|
|
165
|
+
export interface TaxAddress {
|
|
166
|
+
country?: string;
|
|
167
|
+
state?: string;
|
|
168
|
+
}
|
|
169
|
+
/** Most-specific matching rate, or null (no tax). */
|
|
170
|
+
export declare function resolveTaxRate(settings: TaxSettings | undefined, address: TaxAddress): TaxRate | null;
|
|
171
|
+
/**
|
|
172
|
+
* Tax cents for a taxable amount. Exclusive pricing adds on top;
|
|
173
|
+
* inclusive pricing back-calculates the contained tax (for receipts —
|
|
174
|
+
* the charge total does not change).
|
|
175
|
+
*/
|
|
176
|
+
export declare function computeTaxCents(taxableCents: number, pct: number, pricesIncludeTax?: boolean): number;
|