@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,87 @@
|
|
|
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 PluginApiHandler } from '@aglyn/aglyn/server';
|
|
18
|
+
/**
|
|
19
|
+
* Cancelling an order RELEASES its stock (AGL-1808) — the opposite of what the
|
|
20
|
+
* reversal doors do, and for a structural reason rather than a preference.
|
|
21
|
+
*
|
|
22
|
+
* AGL-1797 refused to increment on a refund or a chargeback because the goods
|
|
23
|
+
* may well be gone: a refund with no return, or a shopper who kept the item and
|
|
24
|
+
* took the money, leaves stock that incrementing would INVENT. It flags and
|
|
25
|
+
* lets the merchant answer. Cancellation carries no such question, and the
|
|
26
|
+
* guarantee is `ORDER_TRANSITIONS`:
|
|
27
|
+
*
|
|
28
|
+
* pending: ['paid', 'cancelled'],
|
|
29
|
+
* paid: ['partially_fulfilled', 'fulfilled', 'cancelled', 'refunded'],
|
|
30
|
+
* partially_fulfilled | fulfilled | delivered: no 'cancelled'
|
|
31
|
+
*
|
|
32
|
+
* so a cancelled order was never fulfilled and nothing ever shipped. The units
|
|
33
|
+
* are still on the shelf; the only wrong number is ours.
|
|
34
|
+
*
|
|
35
|
+
* THE GUARANTEE HAD TO BE ENFORCED BEFORE IT COULD BE RELIED ON, and that is
|
|
36
|
+
* why this is a handler rather than a few lines in the console. The transition
|
|
37
|
+
* table said the right thing but nothing consulted it on the way IN: the order
|
|
38
|
+
* dialog cancelled with a client `updateDoc`, and `canTransitionOrder` only
|
|
39
|
+
* decided whether to render the button. The Firestore rules impose no status
|
|
40
|
+
* machine — an order update is allowed to any admin or editor — so a dialog
|
|
41
|
+
* held open while the order shipped in another tab (or any other client) could
|
|
42
|
+
* write `cancelled` straight onto a `fulfilled` order, and an automatic
|
|
43
|
+
* increment behind that would restock goods already in the post. Re-asking the
|
|
44
|
+
* transition INSIDE the transaction that writes the status is what turns the
|
|
45
|
+
* comment into a guarantee, and it is what makes the release safe.
|
|
46
|
+
*
|
|
47
|
+
* `pending` RELEASES NOTHING, which is the other half the issue's premise
|
|
48
|
+
* missed. Stock is decremented when the money lands, not when the order is
|
|
49
|
+
* written: `draft-order.ts` and the POS card path both open a `pending` order
|
|
50
|
+
* and decrement only in the webhook that pays it. Incrementing on a cancelled
|
|
51
|
+
* `pending` order would invent inventory exactly the way AGL-1797 refused to —
|
|
52
|
+
* so only a `paid` order, the one status reachable here whose sale provably
|
|
53
|
+
* decremented, releases anything.
|
|
54
|
+
*
|
|
55
|
+
* ONE LEDGER, NOT A SECOND STOCK WRITER. The increment goes through
|
|
56
|
+
* `adjustVariantInventory` and logs an `InventoryAdjustment` per line, the same
|
|
57
|
+
* pair the sale paths and the products hub's "Adjust stock" write, with the new
|
|
58
|
+
* `cancellation` reason and the `orderId`. An increment with no ledger row
|
|
59
|
+
* would leave the hub's stock history unable to explain a count that moved on
|
|
60
|
+
* its own — the mirror of AGL-1797's argument against writing a row for stock
|
|
61
|
+
* that had NOT moved.
|
|
62
|
+
*
|
|
63
|
+
* ONLY WHAT THE SALE DECREMENTED comes back: `resolveTrackedRestockLines`, the
|
|
64
|
+
* helper AGL-1797 already built, applies the sale path's own
|
|
65
|
+
* `variant.inventory != null` test to the products as they stand now. A store
|
|
66
|
+
* that tracks no stock gets a plain cancellation and no adjustment rows.
|
|
67
|
+
*
|
|
68
|
+
* IT FAILS THE CANCEL RATHER THAN LOSING THE RELEASE. `flagOrderRestock`
|
|
69
|
+
* swallows its errors because the money had already moved and the flag was a
|
|
70
|
+
* postscript; here the status flip and the stock write are one act, so they
|
|
71
|
+
* share a transaction and a failure leaves the order uncancelled for the
|
|
72
|
+
* merchant to retry. A cancelled order whose stock never came back is the
|
|
73
|
+
* original bug.
|
|
74
|
+
*
|
|
75
|
+
* ONCE. The transaction's own read is the guard: a second cancel — a retried
|
|
76
|
+
* request, two admins clicking together — finds `cancelled`, which
|
|
77
|
+
* `canTransitionOrder` cannot leave, and returns without touching stock. Two
|
|
78
|
+
* increments of the same units is the failure mode this shape exists to
|
|
79
|
+
* prevent, and it is measured rather than asserted (`cancel-order.spec.ts`).
|
|
80
|
+
*
|
|
81
|
+
* REACHED FROM THE CONSOLE since AGL-1818: `order-detail-dialog`'s
|
|
82
|
+
* `handleCancel` POSTs here with the console id token, and the client
|
|
83
|
+
* `updateDoc` cancel it replaced is gone. (The wiring landed separately from
|
|
84
|
+
* the route because the dialog belonged to a concurrent agent, AGL-1806,
|
|
85
|
+
* when the route was written.)
|
|
86
|
+
*/
|
|
87
|
+
export declare const cancelOrderHandler: PluginApiHandler;
|
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
2
|
+
/**
|
|
3
|
+
* @license
|
|
4
|
+
* Copyright 2026 Aglyn LLC
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*/ import * as CommerceModel from "../model/index.js";
|
|
18
|
+
import { firebaseAdmin } from "@aglyn/tenant-data-admin";
|
|
19
|
+
import { capRestockLines, resolveTrackedRestockLines, saleReleaseCaps } from "./restock-flag.js";
|
|
20
|
+
/**
|
|
21
|
+
* Cancelling an order RELEASES its stock (AGL-1808) — the opposite of what the
|
|
22
|
+
* reversal doors do, and for a structural reason rather than a preference.
|
|
23
|
+
*
|
|
24
|
+
* AGL-1797 refused to increment on a refund or a chargeback because the goods
|
|
25
|
+
* may well be gone: a refund with no return, or a shopper who kept the item and
|
|
26
|
+
* took the money, leaves stock that incrementing would INVENT. It flags and
|
|
27
|
+
* lets the merchant answer. Cancellation carries no such question, and the
|
|
28
|
+
* guarantee is `ORDER_TRANSITIONS`:
|
|
29
|
+
*
|
|
30
|
+
* pending: ['paid', 'cancelled'],
|
|
31
|
+
* paid: ['partially_fulfilled', 'fulfilled', 'cancelled', 'refunded'],
|
|
32
|
+
* partially_fulfilled | fulfilled | delivered: no 'cancelled'
|
|
33
|
+
*
|
|
34
|
+
* so a cancelled order was never fulfilled and nothing ever shipped. The units
|
|
35
|
+
* are still on the shelf; the only wrong number is ours.
|
|
36
|
+
*
|
|
37
|
+
* THE GUARANTEE HAD TO BE ENFORCED BEFORE IT COULD BE RELIED ON, and that is
|
|
38
|
+
* why this is a handler rather than a few lines in the console. The transition
|
|
39
|
+
* table said the right thing but nothing consulted it on the way IN: the order
|
|
40
|
+
* dialog cancelled with a client `updateDoc`, and `canTransitionOrder` only
|
|
41
|
+
* decided whether to render the button. The Firestore rules impose no status
|
|
42
|
+
* machine — an order update is allowed to any admin or editor — so a dialog
|
|
43
|
+
* held open while the order shipped in another tab (or any other client) could
|
|
44
|
+
* write `cancelled` straight onto a `fulfilled` order, and an automatic
|
|
45
|
+
* increment behind that would restock goods already in the post. Re-asking the
|
|
46
|
+
* transition INSIDE the transaction that writes the status is what turns the
|
|
47
|
+
* comment into a guarantee, and it is what makes the release safe.
|
|
48
|
+
*
|
|
49
|
+
* `pending` RELEASES NOTHING, which is the other half the issue's premise
|
|
50
|
+
* missed. Stock is decremented when the money lands, not when the order is
|
|
51
|
+
* written: `draft-order.ts` and the POS card path both open a `pending` order
|
|
52
|
+
* and decrement only in the webhook that pays it. Incrementing on a cancelled
|
|
53
|
+
* `pending` order would invent inventory exactly the way AGL-1797 refused to —
|
|
54
|
+
* so only a `paid` order, the one status reachable here whose sale provably
|
|
55
|
+
* decremented, releases anything.
|
|
56
|
+
*
|
|
57
|
+
* ONE LEDGER, NOT A SECOND STOCK WRITER. The increment goes through
|
|
58
|
+
* `adjustVariantInventory` and logs an `InventoryAdjustment` per line, the same
|
|
59
|
+
* pair the sale paths and the products hub's "Adjust stock" write, with the new
|
|
60
|
+
* `cancellation` reason and the `orderId`. An increment with no ledger row
|
|
61
|
+
* would leave the hub's stock history unable to explain a count that moved on
|
|
62
|
+
* its own — the mirror of AGL-1797's argument against writing a row for stock
|
|
63
|
+
* that had NOT moved.
|
|
64
|
+
*
|
|
65
|
+
* ONLY WHAT THE SALE DECREMENTED comes back: `resolveTrackedRestockLines`, the
|
|
66
|
+
* helper AGL-1797 already built, applies the sale path's own
|
|
67
|
+
* `variant.inventory != null` test to the products as they stand now. A store
|
|
68
|
+
* that tracks no stock gets a plain cancellation and no adjustment rows.
|
|
69
|
+
*
|
|
70
|
+
* IT FAILS THE CANCEL RATHER THAN LOSING THE RELEASE. `flagOrderRestock`
|
|
71
|
+
* swallows its errors because the money had already moved and the flag was a
|
|
72
|
+
* postscript; here the status flip and the stock write are one act, so they
|
|
73
|
+
* share a transaction and a failure leaves the order uncancelled for the
|
|
74
|
+
* merchant to retry. A cancelled order whose stock never came back is the
|
|
75
|
+
* original bug.
|
|
76
|
+
*
|
|
77
|
+
* ONCE. The transaction's own read is the guard: a second cancel — a retried
|
|
78
|
+
* request, two admins clicking together — finds `cancelled`, which
|
|
79
|
+
* `canTransitionOrder` cannot leave, and returns without touching stock. Two
|
|
80
|
+
* increments of the same units is the failure mode this shape exists to
|
|
81
|
+
* prevent, and it is measured rather than asserted (`cancel-order.spec.ts`).
|
|
82
|
+
*
|
|
83
|
+
* REACHED FROM THE CONSOLE since AGL-1818: `order-detail-dialog`'s
|
|
84
|
+
* `handleCancel` POSTs here with the console id token, and the client
|
|
85
|
+
* `updateDoc` cancel it replaced is gone. (The wiring landed separately from
|
|
86
|
+
* the route because the dialog belonged to a concurrent agent, AGL-1806,
|
|
87
|
+
* when the route was written.)
|
|
88
|
+
*/ export const cancelOrderHandler = async (req, res)=>{
|
|
89
|
+
var _req_headers_authorization, _req_body, _body_hostId, _body_orderId;
|
|
90
|
+
if (req.method !== 'POST') {
|
|
91
|
+
return res.status(405).json({
|
|
92
|
+
error: 'Method not allowed'
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
const authorization = String((_req_headers_authorization = req.headers.authorization) != null ? _req_headers_authorization : '');
|
|
96
|
+
const idToken = authorization.startsWith('Bearer ') ? authorization.slice('Bearer '.length) : undefined;
|
|
97
|
+
if (!idToken) return res.status(401).json({
|
|
98
|
+
error: 'Unauthenticated'
|
|
99
|
+
});
|
|
100
|
+
const body = typeof req.body === 'string' ? JSON.parse(req.body) : (_req_body = req.body) != null ? _req_body : {};
|
|
101
|
+
const hostId = String((_body_hostId = body.hostId) != null ? _body_hostId : '');
|
|
102
|
+
const orderId = String((_body_orderId = body.orderId) != null ? _body_orderId : '');
|
|
103
|
+
if (!hostId || !orderId) {
|
|
104
|
+
return res.status(400).json({
|
|
105
|
+
error: 'Missing hostId or orderId'
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
// Firestore reserves `__…__` ids and `.doc()` throws SYNCHRONOUSLY on one,
|
|
109
|
+
// which would surface as a 500 on a caller's typo rather than the 400 it is.
|
|
110
|
+
if (/^__.*__$/.test(hostId) || /^__.*__$/.test(orderId)) {
|
|
111
|
+
return res.status(400).json({
|
|
112
|
+
error: 'Missing hostId or orderId'
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
try {
|
|
116
|
+
var _hostSnapshot_get;
|
|
117
|
+
const decoded = await firebaseAdmin.app().auth().verifyIdToken(idToken);
|
|
118
|
+
const firestore = firebaseAdmin.app().firestore();
|
|
119
|
+
const hostRef = firestore.collection('hosts').doc(hostId);
|
|
120
|
+
const hostSnapshot = await hostRef.get();
|
|
121
|
+
if (!hostSnapshot.exists) {
|
|
122
|
+
return res.status(404).json({
|
|
123
|
+
error: 'Unknown site'
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
// The role the CLIENT write already had, not a stricter one. Order updates
|
|
127
|
+
// fall through the rules' host catch-all, which admits `admin` and
|
|
128
|
+
// `editor` — narrowing to admin here would take the cancel button away
|
|
129
|
+
// from editors who have always had it, and widening it past what the rules
|
|
130
|
+
// allow would make this endpoint the way around them.
|
|
131
|
+
const memberRole = ((_hostSnapshot_get = hostSnapshot.get('memberRoles')) != null ? _hostSnapshot_get : {})[decoded.uid];
|
|
132
|
+
if (memberRole !== 'admin' && memberRole !== 'editor') {
|
|
133
|
+
return res.status(403).json({
|
|
134
|
+
error: 'Not permitted'
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
const orderRef = hostRef.collection('orders').doc(orderId);
|
|
138
|
+
const outcome = await firestore.runTransaction(async (transaction)=>{
|
|
139
|
+
var _snapshot_data, _order_checkoutSessionId;
|
|
140
|
+
const snapshot = await transaction.get(orderRef);
|
|
141
|
+
if (!snapshot.exists) {
|
|
142
|
+
return {
|
|
143
|
+
status: 404,
|
|
144
|
+
body: {
|
|
145
|
+
error: 'Unknown order'
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
const order = CommerceModel.liftLegacyOrder((_snapshot_data = snapshot.data()) != null ? _snapshot_data : {});
|
|
150
|
+
// A redelivered click, or the second of two admins. Answered as success
|
|
151
|
+
// because it IS the state the caller asked for — reporting 409 here
|
|
152
|
+
// teaches an admin that the cancel failed and invites a third attempt —
|
|
153
|
+
// but nothing is written, so the units are released exactly once.
|
|
154
|
+
if (order.status === 'cancelled') {
|
|
155
|
+
return {
|
|
156
|
+
status: 200,
|
|
157
|
+
body: {
|
|
158
|
+
ok: true,
|
|
159
|
+
alreadyCancelled: true,
|
|
160
|
+
released: 0,
|
|
161
|
+
units: 0
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
if (!CommerceModel.canTransitionOrder(order.status, 'cancelled')) {
|
|
166
|
+
return {
|
|
167
|
+
status: 409,
|
|
168
|
+
body: {
|
|
169
|
+
error: `Orders in "${order.status}" cannot cancel`
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
// A POS CARD order's decrement happens in the webhook that pays it —
|
|
174
|
+
// and before AGL-1825 it did not happen AT ALL: the paying branch's
|
|
175
|
+
// decrement was gated on `productId` metadata the register's session
|
|
176
|
+
// never carried. Releasing such an order restocks units that were never
|
|
177
|
+
// taken, turning the silent under-count into a silent over-count. The
|
|
178
|
+
// sale's own ledger is the discriminator: every decrement pairs with a
|
|
179
|
+
// `reason: 'sale'` row (AGL-1807 closed the last hole, and the AGL-1825
|
|
180
|
+
// decrement writes them from day one), so a paid card order with no
|
|
181
|
+
// sale row is one whose sale took nothing — and nothing is released.
|
|
182
|
+
//
|
|
183
|
+
// Scoped to card orders (the `pos-card-pending` timeline event) rather
|
|
184
|
+
// than applied to every order, because one historical path decremented
|
|
185
|
+
// WITHOUT rows — draft links paid before AGL-1807 — and asking the
|
|
186
|
+
// ledger to vouch for those would wrongly strand their stock. The
|
|
187
|
+
// residual is stated plainly: the sibling-shaped decrement/ledger pair
|
|
188
|
+
// is two swallowed sequential writes, so a card order whose ledger add
|
|
189
|
+
// alone failed will not release — a bounded under-count on that one
|
|
190
|
+
// order, visible as a sale missing from the hub's history, against the
|
|
191
|
+
// alternative of inflating stock on every pre-fix cancel.
|
|
192
|
+
//
|
|
193
|
+
// One equality filter, so the automatic single-field index answers it;
|
|
194
|
+
// the reason test runs here, over the handful of rows one order has.
|
|
195
|
+
//
|
|
196
|
+
// THE SAME READ NOW ALSO BOUNDS HOW MUCH COMES BACK (AGL-2149), so it is
|
|
197
|
+
// no longer scoped to card orders. `adjustVariantInventory` floors at
|
|
198
|
+
// zero, and that floor silently absorbs the overshoot on a BACKORDER
|
|
199
|
+
// product: stock 0, `canPurchase` admits the sale because the policy says
|
|
200
|
+
// to, three units sell, `Math.max(0, 0 + -3)` leaves the count at 0 —
|
|
201
|
+
// and a `+3` here would hand the merchant three units nobody has and a
|
|
202
|
+
// stock badge offering them. The sale rows carry `appliedDelta` for
|
|
203
|
+
// exactly this: `delta` stays the units sold (the merchant's history),
|
|
204
|
+
// `appliedDelta` says how many the count could actually give up.
|
|
205
|
+
//
|
|
206
|
+
// Only lines the ledger DESCRIBES are capped. A pair the ledger says
|
|
207
|
+
// nothing about restores as before, which is what keeps the pre-AGL-1807
|
|
208
|
+
// draft links — decremented with no row at all — from having their stock
|
|
209
|
+
// stranded, and what keeps a single swallowed ledger write from turning
|
|
210
|
+
// into a lost restock on an unrelated line of the same order.
|
|
211
|
+
let saleDecremented = true;
|
|
212
|
+
// The cap rule itself lives beside the restock flag, which now bounds
|
|
213
|
+
// the question it ASKS by the same ledger this bounds the stock it
|
|
214
|
+
// RETURNS (AGL-2325). One implementation, so a prompt naming more units
|
|
215
|
+
// than a cancellation would put back is not expressible.
|
|
216
|
+
let releaseCap = new Map();
|
|
217
|
+
if (order.status === 'paid') {
|
|
218
|
+
var _order_timeline;
|
|
219
|
+
const orderAdjustments = await transaction.get(hostRef.collection('inventoryAdjustments').where('orderId', '==', orderId));
|
|
220
|
+
const saleRows = orderAdjustments.docs.filter((row)=>row.get('reason') === 'sale');
|
|
221
|
+
if (order.channel === 'pos' && ((_order_timeline = order.timeline) != null ? _order_timeline : []).some((event)=>event.event === 'pos-card-pending')) {
|
|
222
|
+
saleDecremented = saleRows.length > 0;
|
|
223
|
+
}
|
|
224
|
+
releaseCap = saleReleaseCaps(saleRows);
|
|
225
|
+
}
|
|
226
|
+
// `paid` is the only status reachable here whose sale decremented; see
|
|
227
|
+
// the header. Reads happen before any write, as a transaction requires.
|
|
228
|
+
const { lines, products } = order.status === 'paid' && saleDecremented ? await resolveTrackedRestockLines(hostRef, order, (ref)=>transaction.get(ref)) : {
|
|
229
|
+
lines: [],
|
|
230
|
+
products: new Map()
|
|
231
|
+
};
|
|
232
|
+
const atMs = Date.now();
|
|
233
|
+
// Grouped by product, because two lines of one product (two variants, or
|
|
234
|
+
// the same variant twice) are two deltas against ONE document: writing
|
|
235
|
+
// them separately would compute both from the same read and land only
|
|
236
|
+
// the last, silently dropping units.
|
|
237
|
+
const byProduct = new Map();
|
|
238
|
+
// Never more than the sale actually took off the shelf (AGL-2149).
|
|
239
|
+
for (const line of capRestockLines(lines, releaseCap)){
|
|
240
|
+
var _byProduct_get;
|
|
241
|
+
byProduct.set(line.productId, [
|
|
242
|
+
...(_byProduct_get = byProduct.get(line.productId)) != null ? _byProduct_get : [],
|
|
243
|
+
line
|
|
244
|
+
]);
|
|
245
|
+
}
|
|
246
|
+
for (const [productId, productLines] of byProduct){
|
|
247
|
+
const product = products.get(productId);
|
|
248
|
+
if (!product) continue;
|
|
249
|
+
let variants = product.variants;
|
|
250
|
+
for (const line of productLines){
|
|
251
|
+
variants = CommerceModel.adjustVariantInventory({
|
|
252
|
+
variants
|
|
253
|
+
}, line.variantId, line.quantity, // The bucket the sale came out of, for a location-tracked store
|
|
254
|
+
// (AGL-286). Absent on every path that decremented the flat count,
|
|
255
|
+
// where `adjustVariantInventory` puts it back the same way.
|
|
256
|
+
order.locationId || undefined);
|
|
257
|
+
}
|
|
258
|
+
// `update()`, not `set(…, { merge: true })` as the sale paths use: the
|
|
259
|
+
// transaction has just read this product, so it exists, and a product
|
|
260
|
+
// deleted under us must not be conjured back as a stub holding nothing
|
|
261
|
+
// but a variants array.
|
|
262
|
+
transaction.update(hostRef.collection('products').doc(productId), {
|
|
263
|
+
variants,
|
|
264
|
+
inventory: CommerceModel.productInventory({
|
|
265
|
+
variants
|
|
266
|
+
}),
|
|
267
|
+
updatedAtMs: atMs
|
|
268
|
+
});
|
|
269
|
+
for (const line of productLines){
|
|
270
|
+
transaction.create(hostRef.collection('inventoryAdjustments').doc(), _extends({
|
|
271
|
+
productId,
|
|
272
|
+
variantId: line.variantId,
|
|
273
|
+
delta: line.quantity,
|
|
274
|
+
reason: 'cancellation',
|
|
275
|
+
orderId
|
|
276
|
+
}, order.locationId ? {
|
|
277
|
+
locationId: order.locationId
|
|
278
|
+
} : {}, {
|
|
279
|
+
atMs
|
|
280
|
+
}));
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
// From the CAPPED lines, not the order's, so the timeline reports what
|
|
284
|
+
// was actually put back (AGL-2149).
|
|
285
|
+
const releasedLines = [
|
|
286
|
+
...byProduct.values()
|
|
287
|
+
].flat();
|
|
288
|
+
const units = releasedLines.reduce((sum, line)=>sum + line.quantity, 0);
|
|
289
|
+
const patch = {
|
|
290
|
+
status: 'cancelled',
|
|
291
|
+
timeline: CommerceModel.appendOrderEvent(order, 'cancelled', units > 0 ? `${units} ${units === 1 ? 'unit' : 'units'} returned to stock` : undefined, atMs)
|
|
292
|
+
};
|
|
293
|
+
// An open restock question about THIS order's stock, raised by a partial
|
|
294
|
+
// refund before the cancellation (AGL-1797). The units it asked about are
|
|
295
|
+
// the ones just put back, so leaving it open would invite the merchant to
|
|
296
|
+
// restock them a second time from the order dialog — the double-count
|
|
297
|
+
// that flag exists to avoid. Answered with what actually happened.
|
|
298
|
+
if (units > 0 && order.restockCheck && !order.restockCheck.resolution) {
|
|
299
|
+
patch.restockCheck = _extends({}, order.restockCheck, {
|
|
300
|
+
resolution: 'restocked',
|
|
301
|
+
resolvedAtMs: atMs,
|
|
302
|
+
resolvedBy: decoded.uid
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
transaction.update(orderRef, patch);
|
|
306
|
+
return {
|
|
307
|
+
status: 200,
|
|
308
|
+
body: {
|
|
309
|
+
ok: true,
|
|
310
|
+
released: releasedLines.length,
|
|
311
|
+
units
|
|
312
|
+
},
|
|
313
|
+
// The live Stripe page this cancellation orphans, if any (AGL-2244).
|
|
314
|
+
// Read inside the transaction that flips the status so the expiry
|
|
315
|
+
// below cannot act on an order some other writer paid meanwhile.
|
|
316
|
+
expireSessionId: order.status === 'pending' ? (_order_checkoutSessionId = order.checkoutSessionId) != null ? _order_checkoutSessionId : '' : ''
|
|
317
|
+
};
|
|
318
|
+
});
|
|
319
|
+
// EXPIRE THE PAYMENT LINK (AGL-2244). Cancelling a `pending` draft order or
|
|
320
|
+
// POS card sale left its Checkout Session live: the URL is on the
|
|
321
|
+
// customer's phone or in the email the merchant sent, and Stripe keeps it
|
|
322
|
+
// payable for 24 hours. Paying it captured real money on the merchant's
|
|
323
|
+
// account and the completing webhook then discarded the event — its
|
|
324
|
+
// `status !== 'pending'` guard cannot tell a redelivery from a cancelled
|
|
325
|
+
// order — so the sale existed in Stripe and nowhere in the product: no
|
|
326
|
+
// order, no stock move, no contact, no notification, not even a timeline
|
|
327
|
+
// line. The webhook now says so when it happens; this is the half that
|
|
328
|
+
// stops it happening.
|
|
329
|
+
//
|
|
330
|
+
// OUTSIDE the transaction, because it is a network call, and best-effort
|
|
331
|
+
// by design: the cancellation itself already landed and is what the
|
|
332
|
+
// merchant asked for. A failure here leaves the pre-existing behaviour
|
|
333
|
+
// (a payable link) plus the webhook's new record of it, which is strictly
|
|
334
|
+
// better than failing a cancel that has already released stock. Stripe
|
|
335
|
+
// answers 400 for a session that is already expired or already paid, and
|
|
336
|
+
// both are states this has nothing to add to.
|
|
337
|
+
const expireSessionId = outcome.expireSessionId;
|
|
338
|
+
if (expireSessionId && process.env.STRIPE_SECRET_KEY) {
|
|
339
|
+
const expiry = await fetch(`https://api.stripe.com/v1/checkout/sessions/${expireSessionId}/expire`, {
|
|
340
|
+
method: 'POST',
|
|
341
|
+
headers: {
|
|
342
|
+
Authorization: `Bearer ${process.env.STRIPE_SECRET_KEY}`,
|
|
343
|
+
'Content-Type': 'application/x-www-form-urlencoded'
|
|
344
|
+
}
|
|
345
|
+
}).catch(()=>null);
|
|
346
|
+
if (!(expiry == null ? void 0 : expiry.ok)) {
|
|
347
|
+
console.error('Cancelled order: Stripe session not expired, the payment link may still be payable', {
|
|
348
|
+
hostId,
|
|
349
|
+
orderId,
|
|
350
|
+
sessionId: expireSessionId
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
return res.status(outcome.status).json(outcome.body);
|
|
355
|
+
} catch (error) {
|
|
356
|
+
// Nothing landed — the transaction is all-or-nothing — so the order is
|
|
357
|
+
// still open and the merchant can try again. Deliberately NOT the swallow
|
|
358
|
+
// `flagOrderRestock` uses: there the money had already moved and only a
|
|
359
|
+
// postscript was at risk; here a swallowed failure is a cancelled order
|
|
360
|
+
// whose stock never came back, which is the bug this closes.
|
|
361
|
+
console.error('cancelOrder failed', error);
|
|
362
|
+
return res.status(500).json({
|
|
363
|
+
error: 'Cancel failed'
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
//# sourceMappingURL=cancel-order.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/server/cancel-order.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 * as CommerceModel from '../model'\nimport { firebaseAdmin } from '@aglyn/tenant-data-admin'\nimport { type PluginApiHandler } from '@aglyn/aglyn/server'\nimport {\n capRestockLines,\n resolveTrackedRestockLines,\n saleReleaseCaps,\n} from './restock-flag'\n\n/**\n * Cancelling an order RELEASES its stock (AGL-1808) — the opposite of what the\n * reversal doors do, and for a structural reason rather than a preference.\n *\n * AGL-1797 refused to increment on a refund or a chargeback because the goods\n * may well be gone: a refund with no return, or a shopper who kept the item and\n * took the money, leaves stock that incrementing would INVENT. It flags and\n * lets the merchant answer. Cancellation carries no such question, and the\n * guarantee is `ORDER_TRANSITIONS`:\n *\n * pending: ['paid', 'cancelled'],\n * paid: ['partially_fulfilled', 'fulfilled', 'cancelled', 'refunded'],\n * partially_fulfilled | fulfilled | delivered: no 'cancelled'\n *\n * so a cancelled order was never fulfilled and nothing ever shipped. The units\n * are still on the shelf; the only wrong number is ours.\n *\n * THE GUARANTEE HAD TO BE ENFORCED BEFORE IT COULD BE RELIED ON, and that is\n * why this is a handler rather than a few lines in the console. The transition\n * table said the right thing but nothing consulted it on the way IN: the order\n * dialog cancelled with a client `updateDoc`, and `canTransitionOrder` only\n * decided whether to render the button. The Firestore rules impose no status\n * machine — an order update is allowed to any admin or editor — so a dialog\n * held open while the order shipped in another tab (or any other client) could\n * write `cancelled` straight onto a `fulfilled` order, and an automatic\n * increment behind that would restock goods already in the post. Re-asking the\n * transition INSIDE the transaction that writes the status is what turns the\n * comment into a guarantee, and it is what makes the release safe.\n *\n * `pending` RELEASES NOTHING, which is the other half the issue's premise\n * missed. Stock is decremented when the money lands, not when the order is\n * written: `draft-order.ts` and the POS card path both open a `pending` order\n * and decrement only in the webhook that pays it. Incrementing on a cancelled\n * `pending` order would invent inventory exactly the way AGL-1797 refused to —\n * so only a `paid` order, the one status reachable here whose sale provably\n * decremented, releases anything.\n *\n * ONE LEDGER, NOT A SECOND STOCK WRITER. The increment goes through\n * `adjustVariantInventory` and logs an `InventoryAdjustment` per line, the same\n * pair the sale paths and the products hub's \"Adjust stock\" write, with the new\n * `cancellation` reason and the `orderId`. An increment with no ledger row\n * would leave the hub's stock history unable to explain a count that moved on\n * its own — the mirror of AGL-1797's argument against writing a row for stock\n * that had NOT moved.\n *\n * ONLY WHAT THE SALE DECREMENTED comes back: `resolveTrackedRestockLines`, the\n * helper AGL-1797 already built, applies the sale path's own\n * `variant.inventory != null` test to the products as they stand now. A store\n * that tracks no stock gets a plain cancellation and no adjustment rows.\n *\n * IT FAILS THE CANCEL RATHER THAN LOSING THE RELEASE. `flagOrderRestock`\n * swallows its errors because the money had already moved and the flag was a\n * postscript; here the status flip and the stock write are one act, so they\n * share a transaction and a failure leaves the order uncancelled for the\n * merchant to retry. A cancelled order whose stock never came back is the\n * original bug.\n *\n * ONCE. The transaction's own read is the guard: a second cancel — a retried\n * request, two admins clicking together — finds `cancelled`, which\n * `canTransitionOrder` cannot leave, and returns without touching stock. Two\n * increments of the same units is the failure mode this shape exists to\n * prevent, and it is measured rather than asserted (`cancel-order.spec.ts`).\n *\n * REACHED FROM THE CONSOLE since AGL-1818: `order-detail-dialog`'s\n * `handleCancel` POSTs here with the console id token, and the client\n * `updateDoc` cancel it replaced is gone. (The wiring landed separately from\n * the route because the dialog belonged to a concurrent agent, AGL-1806,\n * when the route was written.)\n */\nexport const cancelOrderHandler: PluginApiHandler = async (req, res) => {\n if (req.method !== 'POST') {\n return res.status(405).json({ error: 'Method not allowed' })\n }\n const authorization = String(req.headers.authorization ?? '')\n const idToken = authorization.startsWith('Bearer ')\n ? authorization.slice('Bearer '.length)\n : undefined\n if (!idToken) return res.status(401).json({ error: 'Unauthenticated' })\n const body =\n typeof req.body === 'string' ? JSON.parse(req.body) : (req.body ?? {})\n const hostId = String(body.hostId ?? '')\n const orderId = String(body.orderId ?? '')\n if (!hostId || !orderId) {\n return res.status(400).json({ error: 'Missing hostId or orderId' })\n }\n // Firestore reserves `__…__` ids and `.doc()` throws SYNCHRONOUSLY on one,\n // which would surface as a 500 on a caller's typo rather than the 400 it is.\n if (/^__.*__$/.test(hostId) || /^__.*__$/.test(orderId)) {\n return res.status(400).json({ error: 'Missing hostId or orderId' })\n }\n\n try {\n const decoded = await firebaseAdmin.app().auth().verifyIdToken(idToken)\n const firestore = firebaseAdmin.app().firestore()\n const hostRef = firestore.collection('hosts').doc(hostId)\n const hostSnapshot = await hostRef.get()\n if (!hostSnapshot.exists) {\n return res.status(404).json({ error: 'Unknown site' })\n }\n // The role the CLIENT write already had, not a stricter one. Order updates\n // fall through the rules' host catch-all, which admits `admin` and\n // `editor` — narrowing to admin here would take the cancel button away\n // from editors who have always had it, and widening it past what the rules\n // allow would make this endpoint the way around them.\n const memberRole = (hostSnapshot.get('memberRoles') ?? {})[decoded.uid]\n if (memberRole !== 'admin' && memberRole !== 'editor') {\n return res.status(403).json({ error: 'Not permitted' })\n }\n const orderRef = hostRef.collection('orders').doc(orderId)\n\n const outcome = await firestore.runTransaction(async (transaction) => {\n const snapshot = await transaction.get(orderRef)\n if (!snapshot.exists) {\n return { status: 404, body: { error: 'Unknown order' } }\n }\n const order = CommerceModel.liftLegacyOrder(\n (snapshot.data() ?? {}) as never,\n )\n // A redelivered click, or the second of two admins. Answered as success\n // because it IS the state the caller asked for — reporting 409 here\n // teaches an admin that the cancel failed and invites a third attempt —\n // but nothing is written, so the units are released exactly once.\n if (order.status === 'cancelled') {\n return {\n status: 200,\n body: { ok: true, alreadyCancelled: true, released: 0, units: 0 },\n }\n }\n if (!CommerceModel.canTransitionOrder(order.status, 'cancelled')) {\n return {\n status: 409,\n body: { error: `Orders in \"${order.status}\" cannot cancel` },\n }\n }\n\n // A POS CARD order's decrement happens in the webhook that pays it —\n // and before AGL-1825 it did not happen AT ALL: the paying branch's\n // decrement was gated on `productId` metadata the register's session\n // never carried. Releasing such an order restocks units that were never\n // taken, turning the silent under-count into a silent over-count. The\n // sale's own ledger is the discriminator: every decrement pairs with a\n // `reason: 'sale'` row (AGL-1807 closed the last hole, and the AGL-1825\n // decrement writes them from day one), so a paid card order with no\n // sale row is one whose sale took nothing — and nothing is released.\n //\n // Scoped to card orders (the `pos-card-pending` timeline event) rather\n // than applied to every order, because one historical path decremented\n // WITHOUT rows — draft links paid before AGL-1807 — and asking the\n // ledger to vouch for those would wrongly strand their stock. The\n // residual is stated plainly: the sibling-shaped decrement/ledger pair\n // is two swallowed sequential writes, so a card order whose ledger add\n // alone failed will not release — a bounded under-count on that one\n // order, visible as a sale missing from the hub's history, against the\n // alternative of inflating stock on every pre-fix cancel.\n //\n // One equality filter, so the automatic single-field index answers it;\n // the reason test runs here, over the handful of rows one order has.\n //\n // THE SAME READ NOW ALSO BOUNDS HOW MUCH COMES BACK (AGL-2149), so it is\n // no longer scoped to card orders. `adjustVariantInventory` floors at\n // zero, and that floor silently absorbs the overshoot on a BACKORDER\n // product: stock 0, `canPurchase` admits the sale because the policy says\n // to, three units sell, `Math.max(0, 0 + -3)` leaves the count at 0 —\n // and a `+3` here would hand the merchant three units nobody has and a\n // stock badge offering them. The sale rows carry `appliedDelta` for\n // exactly this: `delta` stays the units sold (the merchant's history),\n // `appliedDelta` says how many the count could actually give up.\n //\n // Only lines the ledger DESCRIBES are capped. A pair the ledger says\n // nothing about restores as before, which is what keeps the pre-AGL-1807\n // draft links — decremented with no row at all — from having their stock\n // stranded, and what keeps a single swallowed ledger write from turning\n // into a lost restock on an unrelated line of the same order.\n let saleDecremented = true\n // The cap rule itself lives beside the restock flag, which now bounds\n // the question it ASKS by the same ledger this bounds the stock it\n // RETURNS (AGL-2325). One implementation, so a prompt naming more units\n // than a cancellation would put back is not expressible.\n let releaseCap: ReadonlyMap<string, number> = new Map<string, number>()\n if (order.status === 'paid') {\n const orderAdjustments = await transaction.get(\n hostRef\n .collection('inventoryAdjustments')\n .where('orderId', '==', orderId),\n )\n const saleRows = orderAdjustments.docs.filter(\n (row) => row.get('reason') === 'sale',\n )\n if (\n order.channel === 'pos' &&\n (order.timeline ?? []).some(\n (event) => event.event === 'pos-card-pending',\n )\n ) {\n saleDecremented = saleRows.length > 0\n }\n releaseCap = saleReleaseCaps(saleRows)\n }\n\n // `paid` is the only status reachable here whose sale decremented; see\n // the header. Reads happen before any write, as a transaction requires.\n const { lines, products } =\n order.status === 'paid' && saleDecremented\n ? await resolveTrackedRestockLines(hostRef, order, (ref) =>\n transaction.get(ref),\n )\n : {\n lines: [],\n products: new Map<string, CommerceModel.HostProduct>(),\n }\n\n const atMs = Date.now()\n // Grouped by product, because two lines of one product (two variants, or\n // the same variant twice) are two deltas against ONE document: writing\n // them separately would compute both from the same read and land only\n // the last, silently dropping units.\n const byProduct = new Map<string, CommerceModel.OrderRestockLine[]>()\n // Never more than the sale actually took off the shelf (AGL-2149).\n for (const line of capRestockLines(lines, releaseCap)) {\n byProduct.set(line.productId, [\n ...(byProduct.get(line.productId) ?? []),\n line,\n ])\n }\n for (const [productId, productLines] of byProduct) {\n const product = products.get(productId)\n if (!product) continue\n let variants = product.variants\n for (const line of productLines) {\n variants = CommerceModel.adjustVariantInventory(\n { variants },\n line.variantId,\n line.quantity,\n // The bucket the sale came out of, for a location-tracked store\n // (AGL-286). Absent on every path that decremented the flat count,\n // where `adjustVariantInventory` puts it back the same way.\n order.locationId || undefined,\n )\n }\n // `update()`, not `set(…, { merge: true })` as the sale paths use: the\n // transaction has just read this product, so it exists, and a product\n // deleted under us must not be conjured back as a stub holding nothing\n // but a variants array.\n transaction.update(hostRef.collection('products').doc(productId), {\n variants,\n inventory: CommerceModel.productInventory({ variants }),\n updatedAtMs: atMs,\n })\n for (const line of productLines) {\n transaction.create(hostRef.collection('inventoryAdjustments').doc(), {\n productId,\n variantId: line.variantId,\n delta: line.quantity,\n reason: 'cancellation',\n orderId,\n ...(order.locationId ? { locationId: order.locationId } : {}),\n atMs,\n } satisfies CommerceModel.InventoryAdjustment)\n }\n }\n\n // From the CAPPED lines, not the order's, so the timeline reports what\n // was actually put back (AGL-2149).\n const releasedLines = [...byProduct.values()].flat()\n const units = releasedLines.reduce((sum, line) => sum + line.quantity, 0)\n const patch: Record<string, unknown> = {\n status: 'cancelled',\n timeline: CommerceModel.appendOrderEvent(\n order,\n 'cancelled',\n units > 0\n ? `${units} ${units === 1 ? 'unit' : 'units'} returned to stock`\n : undefined,\n atMs,\n ),\n }\n // An open restock question about THIS order's stock, raised by a partial\n // refund before the cancellation (AGL-1797). The units it asked about are\n // the ones just put back, so leaving it open would invite the merchant to\n // restock them a second time from the order dialog — the double-count\n // that flag exists to avoid. Answered with what actually happened.\n if (units > 0 && order.restockCheck && !order.restockCheck.resolution) {\n patch.restockCheck = {\n ...order.restockCheck,\n resolution: 'restocked',\n resolvedAtMs: atMs,\n resolvedBy: decoded.uid,\n } satisfies CommerceModel.OrderRestockCheck\n }\n transaction.update(orderRef, patch)\n return {\n status: 200,\n body: { ok: true, released: releasedLines.length, units },\n // The live Stripe page this cancellation orphans, if any (AGL-2244).\n // Read inside the transaction that flips the status so the expiry\n // below cannot act on an order some other writer paid meanwhile.\n expireSessionId:\n order.status === 'pending' ? (order.checkoutSessionId ?? '') : '',\n }\n })\n // EXPIRE THE PAYMENT LINK (AGL-2244). Cancelling a `pending` draft order or\n // POS card sale left its Checkout Session live: the URL is on the\n // customer's phone or in the email the merchant sent, and Stripe keeps it\n // payable for 24 hours. Paying it captured real money on the merchant's\n // account and the completing webhook then discarded the event — its\n // `status !== 'pending'` guard cannot tell a redelivery from a cancelled\n // order — so the sale existed in Stripe and nowhere in the product: no\n // order, no stock move, no contact, no notification, not even a timeline\n // line. The webhook now says so when it happens; this is the half that\n // stops it happening.\n //\n // OUTSIDE the transaction, because it is a network call, and best-effort\n // by design: the cancellation itself already landed and is what the\n // merchant asked for. A failure here leaves the pre-existing behaviour\n // (a payable link) plus the webhook's new record of it, which is strictly\n // better than failing a cancel that has already released stock. Stripe\n // answers 400 for a session that is already expired or already paid, and\n // both are states this has nothing to add to.\n const expireSessionId = (outcome as { expireSessionId?: string })\n .expireSessionId\n if (expireSessionId && process.env.STRIPE_SECRET_KEY) {\n const expiry = await fetch(\n `https://api.stripe.com/v1/checkout/sessions/${expireSessionId}/expire`,\n {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${process.env.STRIPE_SECRET_KEY}`,\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n },\n ).catch(() => null)\n if (!expiry?.ok) {\n console.error(\n 'Cancelled order: Stripe session not expired, the payment link may still be payable',\n { hostId, orderId, sessionId: expireSessionId },\n )\n }\n }\n return res.status(outcome.status).json(outcome.body)\n } catch (error) {\n // Nothing landed — the transaction is all-or-nothing — so the order is\n // still open and the merchant can try again. Deliberately NOT the swallow\n // `flagOrderRestock` uses: there the money had already moved and only a\n // postscript was at risk; here a swallowed failure is a cancelled order\n // whose stock never came back, which is the bug this closes.\n console.error('cancelOrder failed', error)\n return res.status(500).json({ error: 'Cancel failed' })\n }\n}\n"],"names":["CommerceModel","firebaseAdmin","capRestockLines","resolveTrackedRestockLines","saleReleaseCaps","cancelOrderHandler","req","res","body","method","status","json","error","authorization","String","headers","idToken","startsWith","slice","length","undefined","JSON","parse","hostId","orderId","test","hostSnapshot","decoded","app","auth","verifyIdToken","firestore","hostRef","collection","doc","get","exists","memberRole","uid","orderRef","outcome","runTransaction","transaction","snapshot","order","liftLegacyOrder","data","ok","alreadyCancelled","released","units","canTransitionOrder","saleDecremented","releaseCap","Map","orderAdjustments","where","saleRows","docs","filter","row","channel","timeline","some","event","lines","products","ref","atMs","Date","now","byProduct","line","set","productId","productLines","product","variants","adjustVariantInventory","variantId","quantity","locationId","update","inventory","productInventory","updatedAtMs","create","delta","reason","releasedLines","values","flat","reduce","sum","patch","appendOrderEvent","restockCheck","resolution","resolvedAtMs","resolvedBy","expireSessionId","checkoutSessionId","process","env","STRIPE_SECRET_KEY","expiry","fetch","Authorization","catch","console","sessionId"],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
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 { PluginApiHandler } from '@aglyn/aglyn/server';
|
|
18
|
+
/**
|
|
19
|
+
* Cart checkout (AGL-293): the whole cart in one Stripe Checkout
|
|
20
|
+
* session on the merchant's account. Every line re-prices from its
|
|
21
|
+
* product doc, unavailable lines block with a visible error, the
|
|
22
|
+
* platform fee sums per line by product type (AGL-278 ladder), and the
|
|
23
|
+
* webhook creates one multi-line order and clears the cart.
|
|
24
|
+
*/
|
|
25
|
+
export declare const cartCheckoutHandler: PluginApiHandler;
|