@aglyn/plugins-commerce 1.0.0-beta.285 → 1.0.0-beta.288
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/README.md +1 -1
- package/package.json +13 -13
- package/src/lib/components/cart.js +25 -12
- package/src/lib/components/cart.js.map +1 -1
- package/src/lib/components/commerce-console-page.js +70 -13
- package/src/lib/components/commerce-console-page.js.map +1 -1
- package/src/lib/components/console/order-detail-dialog.component.js +2 -1
- package/src/lib/components/console/order-detail-dialog.component.js.map +1 -1
- package/src/lib/components/console/order-webhooks-card.component.js +1 -1
- package/src/lib/components/console/order-webhooks-card.component.js.map +1 -1
- package/src/lib/components/console/payment-methods-card.component.js +1 -1
- package/src/lib/components/console/payment-methods-card.component.js.map +1 -1
- package/src/lib/components/console/pos/pos-cart-panel.component.d.ts +5 -0
- package/src/lib/components/console/pos/pos-cart-panel.component.js +18 -12
- package/src/lib/components/console/pos/pos-cart-panel.component.js.map +1 -1
- package/src/lib/components/console/pos/pos-hardware-api.d.ts +76 -5
- package/src/lib/components/console/pos/pos-hardware-api.js +53 -11
- package/src/lib/components/console/pos/pos-hardware-api.js.map +1 -1
- package/src/lib/components/console/pos/pos-hardware-buyer.component.d.ts +18 -0
- package/src/lib/components/console/pos/pos-hardware-buyer.component.js +629 -0
- package/src/lib/components/console/pos/pos-hardware-buyer.component.js.map +1 -0
- package/src/lib/components/console/pos/pos-hardware-sale-api.d.ts +162 -0
- package/src/lib/components/console/pos/pos-hardware-sale-api.js +122 -0
- package/src/lib/components/console/pos/pos-hardware-sale-api.js.map +1 -0
- package/src/lib/components/console/pos/pos-hardware-sale-terms.component.d.ts +39 -0
- package/src/lib/components/console/pos/pos-hardware-sale-terms.component.js +251 -0
- package/src/lib/components/console/pos/pos-hardware-sale-terms.component.js.map +1 -0
- package/src/lib/components/console/pos/use-pos-display.js +50 -0
- package/src/lib/components/console/pos/use-pos-display.js.map +1 -1
- package/src/lib/components/console/pos-cellular-control.component.d.ts +41 -0
- package/src/lib/components/console/pos-cellular-control.component.js +211 -0
- package/src/lib/components/console/pos-cellular-control.component.js.map +1 -0
- package/src/lib/components/console/pos-devices-card.component.d.ts +9 -1
- package/src/lib/components/console/pos-devices-card.component.js +47 -15
- package/src/lib/components/console/pos-devices-card.component.js.map +1 -1
- package/src/lib/components/console/pos-display/pos-display-api.d.ts +6 -0
- package/src/lib/components/console/pos-display/pos-display-api.js +8 -1
- package/src/lib/components/console/pos-display/pos-display-api.js.map +1 -1
- package/src/lib/components/console/pos-display-page.component.d.ts +13 -0
- package/src/lib/components/console/pos-display-page.component.js +44 -2
- package/src/lib/components/console/pos-display-page.component.js.map +1 -1
- package/src/lib/components/console/pos-hardware-card.component.d.ts +12 -4
- package/src/lib/components/console/pos-hardware-card.component.js +157 -36
- package/src/lib/components/console/pos-hardware-card.component.js.map +1 -1
- package/src/lib/components/console/pos-hardware-orders-staff-page.component.js +360 -80
- package/src/lib/components/console/pos-hardware-orders-staff-page.component.js.map +1 -1
- package/src/lib/components/console/pos-hardware-terms-page.component.d.ts +34 -0
- package/src/lib/components/console/pos-hardware-terms-page.component.js +257 -0
- package/src/lib/components/console/pos-hardware-terms-page.component.js.map +1 -0
- package/src/lib/components/console/pos-hardware-terms-sign-page.component.d.ts +27 -0
- package/src/lib/components/console/pos-hardware-terms-sign-page.component.js +104 -0
- package/src/lib/components/console/pos-hardware-terms-sign-page.component.js.map +1 -0
- package/src/lib/components/console/pos-hardware-waiting-card.component.d.ts +24 -0
- package/src/lib/components/console/pos-hardware-waiting-card.component.js +205 -0
- package/src/lib/components/console/pos-hardware-waiting-card.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-check-in-dialog.component.js +297 -201
- package/src/lib/components/console/pos-ops/pos-check-in-dialog.component.js.map +1 -1
- package/src/lib/components/console/pos-ops/pos-check-ins-card.component.d.ts +3 -0
- package/src/lib/components/console/pos-ops/pos-check-ins-card.component.js +260 -92
- package/src/lib/components/console/pos-ops/pos-check-ins-card.component.js.map +1 -1
- package/src/lib/components/console/pos-ops/pos-operations-bar.component.d.ts +9 -0
- package/src/lib/components/console/pos-ops/pos-operations-bar.component.js +15 -6
- package/src/lib/components/console/pos-ops/pos-operations-bar.component.js.map +1 -1
- package/src/lib/components/console/pos-ops/pos-rain-check-dialog.component.d.ts +25 -0
- package/src/lib/components/console/pos-ops/pos-rain-check-dialog.component.js +136 -0
- package/src/lib/components/console/pos-ops/pos-rain-check-dialog.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-shift-panel.component.d.ts +6 -0
- package/src/lib/components/console/pos-ops/pos-shift-panel.component.js +48 -31
- package/src/lib/components/console/pos-ops/pos-shift-panel.component.js.map +1 -1
- package/src/lib/components/console/pos-page.component.d.ts +1 -1
- package/src/lib/components/console/pos-page.component.js +63 -12
- package/src/lib/components/console/pos-page.component.js.map +1 -1
- package/src/lib/components/console/pos-reader-splash-setting.component.js +1 -1
- package/src/lib/components/console/pos-reader-splash-setting.component.js.map +1 -1
- package/src/lib/components/console/product-check-in-fields.component.d.ts +4 -2
- package/src/lib/components/console/product-check-in-fields.component.js +60 -14
- package/src/lib/components/console/product-check-in-fields.component.js.map +1 -1
- package/src/lib/components/console/product-editor-dialog.component.js +44 -1
- package/src/lib/components/console/product-editor-dialog.component.js.map +1 -1
- package/src/lib/components/console/product-hardware-sku-field.component.d.ts +19 -0
- package/src/lib/components/console/product-hardware-sku-field.component.js +92 -0
- package/src/lib/components/console/product-hardware-sku-field.component.js.map +1 -0
- package/src/lib/components/console/product-kiosk-offer-field.component.d.ts +22 -0
- package/src/lib/components/console/product-kiosk-offer-field.component.js +94 -0
- package/src/lib/components/console/product-kiosk-offer-field.component.js.map +1 -0
- package/src/lib/components/console/product-register-fields.component.d.ts +4 -0
- package/src/lib/components/console/product-register-fields.component.js +31 -2
- package/src/lib/components/console/product-register-fields.component.js.map +1 -1
- package/src/lib/components/console/products-hub-card.component.js +11 -2
- package/src/lib/components/console/products-hub-card.component.js.map +1 -1
- package/src/lib/components/console/register-hardware-card.component.d.ts +11 -0
- package/src/lib/components/console/register-hardware-card.component.js +56 -27
- package/src/lib/components/console/register-hardware-card.component.js.map +1 -1
- package/src/lib/components/console/reservation-guests-dialog.component.d.ts +28 -0
- package/src/lib/components/console/reservation-guests-dialog.component.js +189 -0
- package/src/lib/components/console/reservation-guests-dialog.component.js.map +1 -0
- package/src/lib/components/console/reservations-card.component.d.ts +9 -0
- package/src/lib/components/console/reservations-card.component.js +158 -23
- package/src/lib/components/console/reservations-card.component.js.map +1 -1
- package/src/lib/components/console/shippingeasy-card.component.js +1 -1
- package/src/lib/components/console/shippingeasy-card.component.js.map +1 -1
- package/src/lib/components/console/shipstation-card.component.d.ts +1 -1
- package/src/lib/components/console/shipstation-card.component.js +3 -3
- package/src/lib/components/console/shipstation-card.component.js.map +1 -1
- package/src/lib/components/product-detail.d.ts +4 -0
- package/src/lib/components/product-detail.js +40 -5
- package/src/lib/components/product-detail.js.map +1 -1
- package/src/lib/components/product-reviews.js +28 -11
- package/src/lib/components/product-reviews.js.map +1 -1
- package/src/lib/components/reservation-widget.js +28 -5
- package/src/lib/components/reservation-widget.js.map +1 -1
- package/src/lib/components/use-day-picker.d.ts +25 -0
- package/src/lib/components/use-day-picker.js +57 -0
- package/src/lib/components/use-day-picker.js.map +1 -0
- package/src/lib/constants/operator-alerts.d.ts +55 -0
- package/src/lib/constants/operator-alerts.js +156 -1
- package/src/lib/constants/operator-alerts.js.map +1 -1
- package/src/lib/declarations.console-server.js +54 -1
- package/src/lib/declarations.console-server.js.map +1 -1
- package/src/lib/declarations.d.ts +4 -2
- package/src/lib/declarations.js +15 -4
- package/src/lib/declarations.js.map +1 -1
- package/src/lib/declarations.server.js +9 -0
- package/src/lib/declarations.server.js.map +1 -1
- package/src/lib/model/commerce-cart.d.ts +9 -1
- package/src/lib/model/commerce-cart.js +4 -3
- package/src/lib/model/commerce-cart.js.map +1 -1
- package/src/lib/model/commerce-check-in-product.d.ts +26 -0
- package/src/lib/model/commerce-check-in-product.js +64 -2
- package/src/lib/model/commerce-check-in-product.js.map +1 -1
- package/src/lib/model/commerce-check-in-record.d.ts +127 -0
- package/src/lib/model/commerce-check-in-record.js +36 -0
- package/src/lib/model/commerce-check-in-record.js.map +1 -0
- package/src/lib/model/commerce-check-in.d.ts +91 -87
- package/src/lib/model/commerce-check-in.js +186 -62
- package/src/lib/model/commerce-check-in.js.map +1 -1
- package/src/lib/model/commerce-kiosk-offer.d.ts +31 -0
- package/src/lib/model/commerce-kiosk-offer.js +35 -0
- package/src/lib/model/commerce-kiosk-offer.js.map +1 -0
- package/src/lib/model/commerce-orders.d.ts +76 -0
- package/src/lib/model/commerce-orders.js +6 -0
- package/src/lib/model/commerce-orders.js.map +1 -1
- package/src/lib/model/commerce-pos-day-report.d.ts +54 -1
- package/src/lib/model/commerce-pos-day-report.js +39 -2
- package/src/lib/model/commerce-pos-day-report.js.map +1 -1
- package/src/lib/model/commerce-pos-offline.d.ts +1 -1
- package/src/lib/model/commerce-pos-offline.js +6 -1
- package/src/lib/model/commerce-pos-offline.js.map +1 -1
- package/src/lib/model/commerce-pos-ops.js +3 -2
- package/src/lib/model/commerce-pos-ops.js.map +1 -1
- package/src/lib/model/commerce-pos.d.ts +36 -3
- package/src/lib/model/commerce-pos.js +14 -6
- package/src/lib/model/commerce-pos.js.map +1 -1
- package/src/lib/model/commerce-receipt.js +3 -2
- package/src/lib/model/commerce-receipt.js.map +1 -1
- package/src/lib/model/commerce-reservations.d.ts +69 -4
- package/src/lib/model/commerce-reservations.js +57 -5
- package/src/lib/model/commerce-reservations.js.map +1 -1
- package/src/lib/model/commerce.d.ts +66 -0
- package/src/lib/model/commerce.js +15 -0
- package/src/lib/model/commerce.js.map +1 -1
- package/src/lib/model/order-list-fields.d.ts +11 -0
- package/src/lib/model/order-list-fields.js +17 -1
- package/src/lib/model/order-list-fields.js.map +1 -1
- package/src/lib/model/own-store-tax-summary.d.ts +152 -0
- package/src/lib/model/own-store-tax-summary.js +288 -0
- package/src/lib/model/own-store-tax-summary.js.map +1 -0
- package/src/lib/model/plugin-permissions.d.ts +74 -0
- package/src/lib/model/plugin-permissions.js +224 -7
- package/src/lib/model/plugin-permissions.js.map +1 -1
- package/src/lib/model/pos-cellular.d.ts +223 -0
- package/src/lib/model/pos-cellular.js +293 -0
- package/src/lib/model/pos-cellular.js.map +1 -0
- package/src/lib/model/pos-hardware-in-person.d.ts +98 -0
- package/src/lib/model/pos-hardware-in-person.js +224 -0
- package/src/lib/model/pos-hardware-in-person.js.map +1 -0
- package/src/lib/model/pos-hardware-tax-summary.d.ts +166 -0
- package/src/lib/model/pos-hardware-tax-summary.js +225 -0
- package/src/lib/model/pos-hardware-tax-summary.js.map +1 -0
- package/src/lib/model/pos-hardware-terms.d.ts +74 -0
- package/src/lib/model/pos-hardware-terms.js +115 -0
- package/src/lib/model/pos-hardware-terms.js.map +1 -0
- package/src/lib/model/pos-hardware.d.ts +349 -7
- package/src/lib/model/pos-hardware.js +291 -20
- package/src/lib/model/pos-hardware.js.map +1 -1
- package/src/lib/model/product-write.d.ts +10 -0
- package/src/lib/model/product-write.js +4 -2
- package/src/lib/model/product-write.js.map +1 -1
- package/src/lib/model/workspace-site-permissions.d.ts +26 -0
- package/src/lib/model/workspace-site-permissions.js +81 -0
- package/src/lib/model/workspace-site-permissions.js.map +1 -0
- package/src/lib/plugin.js +16 -0
- package/src/lib/plugin.js.map +1 -1
- package/src/lib/server/billing-webhook.js +25 -1
- package/src/lib/server/billing-webhook.js.map +1 -1
- package/src/lib/server/cancel-order.js +7 -5
- package/src/lib/server/cancel-order.js.map +1 -1
- package/src/lib/server/cart-checkout.js +20 -8
- package/src/lib/server/cart-checkout.js.map +1 -1
- package/src/lib/server/cart.js +29 -0
- package/src/lib/server/cart.js.map +1 -1
- package/src/lib/server/checkout.js +42 -13
- package/src/lib/server/checkout.js.map +1 -1
- package/src/lib/server/collection-membership.d.ts +4 -0
- package/src/lib/server/collection-membership.js +5 -10
- package/src/lib/server/collection-membership.js.map +1 -1
- package/src/lib/server/commerce-site-keys.d.ts +48 -0
- package/src/lib/server/commerce-site-keys.js +61 -0
- package/src/lib/server/commerce-site-keys.js.map +1 -0
- package/src/lib/server/draft-order.js +8 -5
- package/src/lib/server/draft-order.js.map +1 -1
- package/src/lib/server/fulfill-order.js +7 -5
- package/src/lib/server/fulfill-order.js.map +1 -1
- package/src/lib/server/gift-cards.js +8 -5
- package/src/lib/server/gift-cards.js.map +1 -1
- package/src/lib/server/local-fulfillment-status.js +9 -6
- package/src/lib/server/local-fulfillment-status.js.map +1 -1
- package/src/lib/server/member-post.js +6 -5
- package/src/lib/server/member-post.js.map +1 -1
- package/src/lib/server/membership-admin-password.d.ts +4 -2
- package/src/lib/server/membership-admin-password.js +10 -8
- package/src/lib/server/membership-admin-password.js.map +1 -1
- package/src/lib/server/membership-admin-remove.d.ts +7 -5
- package/src/lib/server/membership-admin-remove.js +9 -9
- package/src/lib/server/membership-admin-remove.js.map +1 -1
- package/src/lib/server/order-notifications.js +5 -2
- package/src/lib/server/order-notifications.js.map +1 -1
- package/src/lib/server/order-print.js +7 -5
- package/src/lib/server/order-print.js.map +1 -1
- package/src/lib/server/order-receipt-send.js +8 -5
- package/src/lib/server/order-receipt-send.js.map +1 -1
- package/src/lib/server/order-webhooks.js +8 -8
- package/src/lib/server/order-webhooks.js.map +1 -1
- package/src/lib/server/orders-shipping-prepare.js +9 -6
- package/src/lib/server/orders-shipping-prepare.js.map +1 -1
- package/src/lib/server/own-store-tax-return-source.d.ts +47 -0
- package/src/lib/server/own-store-tax-return-source.js +312 -0
- package/src/lib/server/own-store-tax-return-source.js.map +1 -0
- package/src/lib/server/payment-methods.js +13 -9
- package/src/lib/server/payment-methods.js.map +1 -1
- package/src/lib/server/pos-auth.d.ts +37 -6
- package/src/lib/server/pos-auth.js +40 -15
- package/src/lib/server/pos-auth.js.map +1 -1
- package/src/lib/server/pos-cellular-billing.d.ts +81 -0
- package/src/lib/server/pos-cellular-billing.js +711 -0
- package/src/lib/server/pos-cellular-billing.js.map +1 -0
- package/src/lib/server/pos-cellular-notify.d.ts +47 -0
- package/src/lib/server/pos-cellular-notify.js +150 -0
- package/src/lib/server/pos-cellular-notify.js.map +1 -0
- package/src/lib/server/pos-cellular.d.ts +88 -0
- package/src/lib/server/pos-cellular.js +339 -0
- package/src/lib/server/pos-cellular.js.map +1 -0
- package/src/lib/server/pos-check-in.d.ts +5 -1
- package/src/lib/server/pos-check-in.js +296 -28
- package/src/lib/server/pos-check-in.js.map +1 -1
- package/src/lib/server/pos-day-report.js +29 -3
- package/src/lib/server/pos-day-report.js.map +1 -1
- package/src/lib/server/pos-display.d.ts +16 -0
- package/src/lib/server/pos-display.js +129 -2
- package/src/lib/server/pos-display.js.map +1 -1
- package/src/lib/server/pos-hardware-admin.d.ts +10 -1
- package/src/lib/server/pos-hardware-admin.js +250 -84
- package/src/lib/server/pos-hardware-admin.js.map +1 -1
- package/src/lib/server/pos-hardware-attach.d.ts +105 -0
- package/src/lib/server/pos-hardware-attach.js +443 -0
- package/src/lib/server/pos-hardware-attach.js.map +1 -0
- package/src/lib/server/pos-hardware-buyer-lookup.d.ts +58 -0
- package/src/lib/server/pos-hardware-buyer-lookup.js +180 -0
- package/src/lib/server/pos-hardware-buyer-lookup.js.map +1 -0
- package/src/lib/server/pos-hardware-buyer-record.d.ts +29 -0
- package/src/lib/server/pos-hardware-buyer-record.js +86 -0
- package/src/lib/server/pos-hardware-buyer-record.js.map +1 -0
- package/src/lib/server/pos-hardware-cancel.d.ts +58 -0
- package/src/lib/server/pos-hardware-cancel.js +147 -0
- package/src/lib/server/pos-hardware-cancel.js.map +1 -0
- package/src/lib/server/pos-hardware-closure-notices.d.ts +27 -0
- package/src/lib/server/pos-hardware-closure-notices.js +85 -0
- package/src/lib/server/pos-hardware-closure-notices.js.map +1 -0
- package/src/lib/server/pos-hardware-closure.d.ts +60 -0
- package/src/lib/server/pos-hardware-closure.js +153 -0
- package/src/lib/server/pos-hardware-closure.js.map +1 -0
- package/src/lib/server/pos-hardware-in-person.d.ts +61 -0
- package/src/lib/server/pos-hardware-in-person.js +236 -0
- package/src/lib/server/pos-hardware-in-person.js.map +1 -0
- package/src/lib/server/pos-hardware-notify.d.ts +40 -2
- package/src/lib/server/pos-hardware-notify.js +195 -14
- package/src/lib/server/pos-hardware-notify.js.map +1 -1
- package/src/lib/server/pos-hardware-readers.d.ts +115 -0
- package/src/lib/server/pos-hardware-readers.js +430 -0
- package/src/lib/server/pos-hardware-readers.js.map +1 -0
- package/src/lib/server/pos-hardware-returns.d.ts +116 -0
- package/src/lib/server/pos-hardware-returns.js +502 -0
- package/src/lib/server/pos-hardware-returns.js.map +1 -0
- package/src/lib/server/pos-hardware-sale-fields.d.ts +28 -0
- package/src/lib/server/pos-hardware-sale-fields.js +44 -0
- package/src/lib/server/pos-hardware-sale-fields.js.map +1 -0
- package/src/lib/server/pos-hardware-sale.d.ts +54 -0
- package/src/lib/server/pos-hardware-sale.js +369 -0
- package/src/lib/server/pos-hardware-sale.js.map +1 -0
- package/src/lib/server/pos-hardware-tax-return-source.d.ts +99 -0
- package/src/lib/server/pos-hardware-tax-return-source.js +462 -0
- package/src/lib/server/pos-hardware-tax-return-source.js.map +1 -0
- package/src/lib/server/pos-hardware-terms.d.ts +64 -0
- package/src/lib/server/pos-hardware-terms.js +154 -0
- package/src/lib/server/pos-hardware-terms.js.map +1 -0
- package/src/lib/server/pos-hardware-user-eraser.d.ts +3 -0
- package/src/lib/server/pos-hardware-user-eraser.js +31 -7
- package/src/lib/server/pos-hardware-user-eraser.js.map +1 -1
- package/src/lib/server/pos-hardware-webhook.d.ts +5 -0
- package/src/lib/server/pos-hardware-webhook.js +51 -6
- package/src/lib/server/pos-hardware-webhook.js.map +1 -1
- package/src/lib/server/pos-hardware.d.ts +74 -1
- package/src/lib/server/pos-hardware.js +175 -10
- package/src/lib/server/pos-hardware.js.map +1 -1
- package/src/lib/server/pos-kiosk.d.ts +2 -0
- package/src/lib/server/pos-kiosk.js +17 -12
- package/src/lib/server/pos-kiosk.js.map +1 -1
- package/src/lib/server/pos-offline-card-order.d.ts +64 -0
- package/src/lib/server/pos-offline-card-order.js +102 -0
- package/src/lib/server/pos-offline-card-order.js.map +1 -0
- package/src/lib/server/pos-offline-card-reconcile.d.ts +67 -1
- package/src/lib/server/pos-offline-card-reconcile.js +215 -18
- package/src/lib/server/pos-offline-card-reconcile.js.map +1 -1
- package/src/lib/server/pos-offline-sync.d.ts +39 -0
- package/src/lib/server/pos-offline-sync.js +190 -55
- package/src/lib/server/pos-offline-sync.js.map +1 -1
- package/src/lib/server/pos-ops-gate.d.ts +28 -9
- package/src/lib/server/pos-ops-gate.js +50 -19
- package/src/lib/server/pos-ops-gate.js.map +1 -1
- package/src/lib/server/pos-ops-routes.js +24 -0
- package/src/lib/server/pos-ops-routes.js.map +1 -1
- package/src/lib/server/pos-order-refund-ids.d.ts +28 -0
- package/src/lib/server/pos-order-refund-ids.js +31 -0
- package/src/lib/server/pos-order-refund-ids.js.map +1 -0
- package/src/lib/server/pos-order.js +52 -49
- package/src/lib/server/pos-order.js.map +1 -1
- package/src/lib/server/pos-payment.js +1 -1
- package/src/lib/server/pos-payment.js.map +1 -1
- package/src/lib/server/pos-reader-splash-admin.js +30 -32
- package/src/lib/server/pos-reader-splash-admin.js.map +1 -1
- package/src/lib/server/pos-reader-splash-images-route.d.ts +17 -0
- package/src/lib/server/pos-reader-splash-images-route.js +113 -0
- package/src/lib/server/pos-reader-splash-images-route.js.map +1 -0
- package/src/lib/server/pos-reader-splash-images.d.ts +51 -0
- package/src/lib/server/pos-reader-splash-images.js +123 -0
- package/src/lib/server/pos-reader-splash-images.js.map +1 -0
- package/src/lib/server/pos-reader-splash.d.ts +68 -1
- package/src/lib/server/pos-reader-splash.js +182 -11
- package/src/lib/server/pos-reader-splash.js.map +1 -1
- package/src/lib/server/pos-readers.d.ts +29 -0
- package/src/lib/server/pos-readers.js +134 -35
- package/src/lib/server/pos-readers.js.map +1 -1
- package/src/lib/server/pos-refund-authority.d.ts +3 -1
- package/src/lib/server/pos-refund-authority.js +3 -2
- package/src/lib/server/pos-refund-authority.js.map +1 -1
- package/src/lib/server/pos-return.d.ts +10 -0
- package/src/lib/server/pos-return.js +29 -7
- package/src/lib/server/pos-return.js.map +1 -1
- package/src/lib/server/pos-sale.js +6 -1
- package/src/lib/server/pos-sale.js.map +1 -1
- package/src/lib/server/pos-shift.js +11 -0
- package/src/lib/server/pos-shift.js.map +1 -1
- package/src/lib/server/pos-staff-pin.js +29 -24
- package/src/lib/server/pos-staff-pin.js.map +1 -1
- package/src/lib/server/pos-terminal.d.ts +14 -4
- package/src/lib/server/pos-terminal.js +34 -38
- package/src/lib/server/pos-terminal.js.map +1 -1
- package/src/lib/server/printers.d.ts +7 -3
- package/src/lib/server/printers.js +18 -12
- package/src/lib/server/printers.js.map +1 -1
- package/src/lib/server/product-drafts.d.ts +11 -1
- package/src/lib/server/product-drafts.js +12 -8
- package/src/lib/server/product-drafts.js.map +1 -1
- package/src/lib/server/product.d.ts +15 -1
- package/src/lib/server/product.js +16 -3
- package/src/lib/server/product.js.map +1 -1
- package/src/lib/server/products-write.d.ts +26 -2
- package/src/lib/server/products-write.js +19 -7
- package/src/lib/server/products-write.js.map +1 -1
- package/src/lib/server/refund.js +55 -42
- package/src/lib/server/refund.js.map +1 -1
- package/src/lib/server/reservation-availability-query.d.ts +8 -0
- package/src/lib/server/reservation-availability-query.js +11 -1
- package/src/lib/server/reservation-availability-query.js.map +1 -1
- package/src/lib/server/reservation-availability.d.ts +1 -1
- package/src/lib/server/reservation-availability.js +7 -2
- package/src/lib/server/reservation-availability.js.map +1 -1
- package/src/lib/server/reservation-guests.d.ts +32 -0
- package/src/lib/server/reservation-guests.js +285 -0
- package/src/lib/server/reservation-guests.js.map +1 -0
- package/src/lib/server/reservation-walk-in.d.ts +11 -1
- package/src/lib/server/reservation-walk-in.js +56 -12
- package/src/lib/server/reservation-walk-in.js.map +1 -1
- package/src/lib/server/reserve.js +18 -5
- package/src/lib/server/reserve.js.map +1 -1
- package/src/lib/server/returns.js +9 -6
- package/src/lib/server/returns.js.map +1 -1
- package/src/lib/server/reviews.d.ts +22 -2
- package/src/lib/server/reviews.js +88 -20
- package/src/lib/server/reviews.js.map +1 -1
- package/src/lib/server/shipping-connectors.js +10 -11
- package/src/lib/server/shipping-connectors.js.map +1 -1
- package/src/lib/server/site-page-resolver.js +20 -3
- package/src/lib/server/site-page-resolver.js.map +1 -1
- package/src/lib/server/store-day.d.ts +33 -0
- package/src/lib/server/store-day.js +46 -0
- package/src/lib/server/store-day.js.map +1 -0
- package/src/lib/server/store-setup-ai-writer.d.ts +2 -1
- package/src/lib/server/store-setup-ai-writer.js +5 -6
- package/src/lib/server/store-setup-ai-writer.js.map +1 -1
- package/src/lib/server/storefront-tax.d.ts +13 -0
- package/src/lib/server/storefront-tax.js +8 -1
- package/src/lib/server/storefront-tax.js.map +1 -1
- package/src/lib/server/tax-return-source.d.ts +32 -3
- package/src/lib/server/tax-return-source.js +99 -20
- package/src/lib/server/tax-return-source.js.map +1 -1
- package/src/lib/server.js +100 -2
- package/src/lib/server.js.map +1 -1
- package/src/lib/testing/fake-firestore.js +58 -16
- package/src/lib/testing/fake-firestore.js.map +1 -1
- package/src/lib/testing/pos-ops-memory-firestore.js +18 -4
- package/src/lib/testing/pos-ops-memory-firestore.js.map +1 -1
- package/src/lib/testing/site-register-permissions.d.ts +29 -0
- package/src/lib/testing/site-register-permissions.js +38 -0
- package/src/lib/testing/site-register-permissions.js.map +1 -0
- package/src/lib/transfer/tracking.server.js +8 -5
- package/src/lib/transfer/tracking.server.js.map +1 -1
- package/src/lib/utils/add-to-cart.d.ts +2 -0
- package/src/lib/utils/add-to-cart.js +6 -3
- package/src/lib/utils/add-to-cart.js.map +1 -1
|
@@ -0,0 +1,236 @@
|
|
|
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
|
+
*/ import { firebaseAdmin, getOrgForHost } from "@aglyn/tenant-data-admin";
|
|
17
|
+
import * as CommerceModel from "../model/index.js";
|
|
18
|
+
import { isPosHardwareSkuId, normalizePosHardwareSerial } from "../model/pos-hardware.js";
|
|
19
|
+
import { inPersonPosHardwareOrder, posHardwareRegisterShare } from "../model/pos-hardware-in-person.js";
|
|
20
|
+
import { hardwareOrdersRef, posHardwareInPersonConfig, posHardwareInPersonOrderId } from "./pos-hardware.js";
|
|
21
|
+
import { recordPosHardwareOrder } from "./pos-hardware-webhook.js";
|
|
22
|
+
import { posStripeTestMode } from "./pos-stripe.js";
|
|
23
|
+
/** How many marked sales one sweep records at most. */ export const IN_PERSON_SWEEP_LIMIT = 25;
|
|
24
|
+
/** Statuses after which a marked sale can never be paid, so the mark is dropped. */ const NEVER_PAID = new Set([
|
|
25
|
+
'cancelled',
|
|
26
|
+
'canceled',
|
|
27
|
+
'voided',
|
|
28
|
+
'refunded',
|
|
29
|
+
'expired'
|
|
30
|
+
]);
|
|
31
|
+
const text = (value)=>typeof value === 'string' && value.trim() ? value.trim() : null;
|
|
32
|
+
function firestore() {
|
|
33
|
+
return firebaseAdmin.app().firestore();
|
|
34
|
+
}
|
|
35
|
+
function registerOrderRef(hostId, orderId) {
|
|
36
|
+
return firestore().collection('hosts').doc(hostId).collection('orders').doc(orderId);
|
|
37
|
+
}
|
|
38
|
+
/** Where the store taxes from, and its rate there, from its own tax settings. */ async function storeTax(hostId) {
|
|
39
|
+
var _settings_get, _tax_origin, _ref, _ref1;
|
|
40
|
+
var _text, _text1;
|
|
41
|
+
const settings = await firestore().collection('hosts').doc(hostId).collection('settings').doc('store').get();
|
|
42
|
+
const tax = (_settings_get = settings.get('tax')) != null ? _settings_get : {};
|
|
43
|
+
const origin = (_tax_origin = tax.origin) != null ? _tax_origin : {};
|
|
44
|
+
const country = (_ref = (_text = text(origin.country)) == null ? void 0 : _text.toUpperCase()) != null ? _ref : null;
|
|
45
|
+
const rate = country ? CommerceModel.resolveTaxRate(tax, origin) : null;
|
|
46
|
+
return {
|
|
47
|
+
region: country ? {
|
|
48
|
+
country,
|
|
49
|
+
state: (_ref1 = (_text1 = text(origin.state)) == null ? void 0 : _text1.toUpperCase()) != null ? _ref1 : null,
|
|
50
|
+
postalCode: null
|
|
51
|
+
} : null,
|
|
52
|
+
ratePct: rate && Number.isFinite(rate.pct) ? rate.pct : null
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/** The store owner's connected Stripe account, where the store's card money goes. */ async function storeStripeAccount(hostId) {
|
|
56
|
+
var _owner_org;
|
|
57
|
+
const owner = await getOrgForHost(hostId).catch(()=>null);
|
|
58
|
+
const ownerUid = text(owner == null ? void 0 : (_owner_org = owner.org) == null ? void 0 : _owner_org.ownerUid);
|
|
59
|
+
if (!ownerUid) return null;
|
|
60
|
+
const profile = await firestore().collection('profiles').doc(ownerUid).get();
|
|
61
|
+
return text(profile.get('stripeAccountId'));
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Records the hardware order of one register sale on the seller store, once.
|
|
65
|
+
* Never throws for a sale that is not one: it says why it did nothing.
|
|
66
|
+
*/ export async function recordInPersonPosHardwareSale(hostId, registerOrderId, options = {}) {
|
|
67
|
+
var _ref, _ref1, _ref2, _ref3, _order_paidAtMs, _text, _ref4, _order_currency;
|
|
68
|
+
var _order_totals, _order_totals1, _payments_find, _text1, _hardwareOrder_attachment, _hardwareOrder_attachment1;
|
|
69
|
+
const config = options.config === undefined ? posHardwareInPersonConfig() : options.config;
|
|
70
|
+
if (!config) return {
|
|
71
|
+
outcome: 'off'
|
|
72
|
+
};
|
|
73
|
+
if (hostId !== config.sellerHostId) return {
|
|
74
|
+
outcome: 'not-seller'
|
|
75
|
+
};
|
|
76
|
+
const orderRef = registerOrderRef(hostId, registerOrderId);
|
|
77
|
+
const snapshot = await orderRef.get();
|
|
78
|
+
if (!snapshot.exists) return {
|
|
79
|
+
outcome: 'missing'
|
|
80
|
+
};
|
|
81
|
+
const order = snapshot.data();
|
|
82
|
+
if (order.status !== 'paid') return {
|
|
83
|
+
outcome: 'not-paid'
|
|
84
|
+
};
|
|
85
|
+
const lineItems = Array.isArray(order.lineItems) ? order.lineItems : [];
|
|
86
|
+
const productIds = [
|
|
87
|
+
...new Set(lineItems.map((line)=>{
|
|
88
|
+
var _line_productId;
|
|
89
|
+
return String((_line_productId = line.productId) != null ? _line_productId : '');
|
|
90
|
+
}).filter(Boolean))
|
|
91
|
+
];
|
|
92
|
+
const products = new Map((await Promise.all(productIds.map((id)=>firestore().collection('hosts').doc(hostId).collection('products').doc(id).get()))).map((doc)=>[
|
|
93
|
+
String(doc.id),
|
|
94
|
+
doc.exists ? doc.data() : null
|
|
95
|
+
]));
|
|
96
|
+
const lines = lineItems.map((line)=>{
|
|
97
|
+
var _products_get;
|
|
98
|
+
const sku = (_products_get = products.get(String(line.productId))) == null ? void 0 : _products_get.hardwareSku;
|
|
99
|
+
return {
|
|
100
|
+
sku: isPosHardwareSkuId(sku) ? sku : null,
|
|
101
|
+
quantity: Number(line.quantity),
|
|
102
|
+
unitAmountCents: Number(line.unitAmountCents)
|
|
103
|
+
};
|
|
104
|
+
});
|
|
105
|
+
const share = posHardwareRegisterShare({
|
|
106
|
+
lines,
|
|
107
|
+
discountCents: Number((_ref = (_order_totals = order.totals) == null ? void 0 : _order_totals.discountCents) != null ? _ref : 0),
|
|
108
|
+
taxCents: Number((_ref1 = (_order_totals1 = order.totals) == null ? void 0 : _order_totals1.taxCents) != null ? _ref1 : 0)
|
|
109
|
+
});
|
|
110
|
+
if (!share) {
|
|
111
|
+
// Marked when it was rung, but no line is hardware now: nothing to record.
|
|
112
|
+
if (order.hardwareSalePending) {
|
|
113
|
+
await orderRef.set({
|
|
114
|
+
hardwareSalePending: firebaseAdmin.firestore.FieldValue.delete()
|
|
115
|
+
}, {
|
|
116
|
+
merge: true
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
outcome: 'no-hardware'
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
const orderId = posHardwareInPersonOrderId(hostId, registerOrderId);
|
|
124
|
+
const payments = CommerceModel.orderPayments(order).filter((payment)=>payment.status === 'succeeded');
|
|
125
|
+
const livemodes = payments.map((payment)=>payment.livemode).filter((mode)=>typeof mode === 'boolean');
|
|
126
|
+
const [tax, stripeAccountId] = await Promise.all([
|
|
127
|
+
storeTax(hostId),
|
|
128
|
+
storeStripeAccount(hostId)
|
|
129
|
+
]);
|
|
130
|
+
const paidAtMs = Number((_ref2 = (_ref3 = (_order_paidAtMs = order.paidAtMs) != null ? _order_paidAtMs : order.createdAtMs) != null ? _ref3 : options.now) != null ? _ref2 : Date.now());
|
|
131
|
+
const hardwareOrder = inPersonPosHardwareOrder({
|
|
132
|
+
sellerHostId: config.sellerHostId,
|
|
133
|
+
sellerOrgId: config.sellerOrgId,
|
|
134
|
+
registerOrderId,
|
|
135
|
+
number: Number.isFinite(Number(order.number)) ? Number(order.number) : null,
|
|
136
|
+
registerId: text(order.registerId),
|
|
137
|
+
kiosk: order.posSource === 'kiosk',
|
|
138
|
+
offline: options.offline === true || Boolean(order.offline),
|
|
139
|
+
share,
|
|
140
|
+
paidAtMs,
|
|
141
|
+
tenders: payments.map((payment)=>payment.method),
|
|
142
|
+
paymentLinkSessionId: (_text = text((_payments_find = payments.find((payment)=>payment.checkoutSessionId)) == null ? void 0 : _payments_find.checkoutSessionId)) != null ? _text : text(order.checkoutSessionId),
|
|
143
|
+
receiptEmail: (_ref4 = (_text1 = text(order.customerEmail)) == null ? void 0 : _text1.toLowerCase()) != null ? _ref4 : null,
|
|
144
|
+
buyer: order.hardwareBuyer,
|
|
145
|
+
termsAcceptance: order.hardwareTermsAcceptance,
|
|
146
|
+
serials: (Array.isArray(order.hardwareSerials) ? order.hardwareSerials : []).map(normalizePosHardwareSerial).filter(Boolean),
|
|
147
|
+
taxRegion: tax.region,
|
|
148
|
+
ratePct: tax.ratePct,
|
|
149
|
+
stripeAccountId,
|
|
150
|
+
// A card payment says which mode it was in; a cash sale takes the
|
|
151
|
+
// deployment's, so a test deployment's booth is never a real sale.
|
|
152
|
+
livemode: livemodes.length ? livemodes.every(Boolean) : !posStripeTestMode(),
|
|
153
|
+
currency: String((_order_currency = order.currency) != null ? _order_currency : 'usd').toLowerCase()
|
|
154
|
+
});
|
|
155
|
+
const { created } = await recordPosHardwareOrder(orderId, hardwareOrder);
|
|
156
|
+
// The mark comes off once the order exists, by this call or an earlier one.
|
|
157
|
+
await orderRef.set({
|
|
158
|
+
hardwareOrderId: orderId,
|
|
159
|
+
hardwareSalePending: firebaseAdmin.firestore.FieldValue.delete()
|
|
160
|
+
}, {
|
|
161
|
+
merge: true
|
|
162
|
+
});
|
|
163
|
+
// A buyer with no account, named at the register while the sale was open,
|
|
164
|
+
// is invited to sign up now that there is an order to point them at.
|
|
165
|
+
if (created && ((_hardwareOrder_attachment = hardwareOrder.attachment) == null ? void 0 : _hardwareOrder_attachment.state) === 'pending' && hardwareOrder.attachment.email) {
|
|
166
|
+
await (await import("./pos-hardware-attach.js")).invitePendingBuyer(orderId, hardwareOrder.orgId, hardwareOrder);
|
|
167
|
+
}
|
|
168
|
+
return {
|
|
169
|
+
outcome: created ? 'recorded' : 'already',
|
|
170
|
+
orderId,
|
|
171
|
+
orgId: hardwareOrder.orgId,
|
|
172
|
+
pending: ((_hardwareOrder_attachment1 = hardwareOrder.attachment) == null ? void 0 : _hardwareOrder_attachment1.state) === 'pending'
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Records every paid sale on the seller store that is still marked, at most
|
|
177
|
+
* {@link IN_PERSON_SWEEP_LIMIT} a time, and drops the mark from a sale that
|
|
178
|
+
* can no longer be paid. Never throws: a sale it cannot record stays marked
|
|
179
|
+
* for the next sweep.
|
|
180
|
+
*/ export async function sweepInPersonPosHardwareSales(config = posHardwareInPersonConfig()) {
|
|
181
|
+
if (!config) return {
|
|
182
|
+
recorded: 0,
|
|
183
|
+
failed: 0
|
|
184
|
+
};
|
|
185
|
+
const marked = await firestore().collection('hosts').doc(config.sellerHostId).collection('orders').where('hardwareSalePending', '==', true).limit(IN_PERSON_SWEEP_LIMIT).get();
|
|
186
|
+
let recorded = 0;
|
|
187
|
+
let failed = 0;
|
|
188
|
+
for (const doc of marked.docs){
|
|
189
|
+
var _doc_get;
|
|
190
|
+
const status = String((_doc_get = doc.get('status')) != null ? _doc_get : '');
|
|
191
|
+
try {
|
|
192
|
+
if (NEVER_PAID.has(status)) {
|
|
193
|
+
await doc.ref.set({
|
|
194
|
+
hardwareSalePending: firebaseAdmin.firestore.FieldValue.delete()
|
|
195
|
+
}, {
|
|
196
|
+
merge: true
|
|
197
|
+
});
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
if (status !== 'paid') continue;
|
|
201
|
+
const outcome = await recordInPersonPosHardwareSale(config.sellerHostId, String(doc.id), {
|
|
202
|
+
config
|
|
203
|
+
});
|
|
204
|
+
if (outcome.outcome === 'recorded') recorded += 1;
|
|
205
|
+
} catch (error) {
|
|
206
|
+
failed += 1;
|
|
207
|
+
console.error('[pos-hardware-in-person] a marked sale could not be recorded', doc.id, error);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return {
|
|
211
|
+
recorded,
|
|
212
|
+
failed
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
/** The "To attach" list: the selling workspace's pending in-person orders, newest first. */ export async function pendingInPersonPosHardwareOrders(config, limit = 50) {
|
|
216
|
+
const snapshot = await hardwareOrdersRef(config.sellerOrgId).where('attachment.state', '==', 'pending').orderBy('createdAtMs', 'desc').limit(limit).get();
|
|
217
|
+
return snapshot.docs.map((doc)=>({
|
|
218
|
+
id: String(doc.id),
|
|
219
|
+
order: doc.data()
|
|
220
|
+
}));
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* What the completion listener runs for a sale on the seller store. Never
|
|
224
|
+
* throws into a sale: a failure is logged and the sale stays marked for the
|
|
225
|
+
* sweep.
|
|
226
|
+
*/ export async function recordCompletedSaleHardware(event) {
|
|
227
|
+
try {
|
|
228
|
+
await recordInPersonPosHardwareSale(event.hostId, event.orderId, {
|
|
229
|
+
offline: event.offline === true
|
|
230
|
+
});
|
|
231
|
+
} catch (error) {
|
|
232
|
+
console.error('[pos-hardware-in-person] sale not recorded; the sweep will', event.orderId, error);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
//# sourceMappingURL=pos-hardware-in-person.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/server/pos-hardware-in-person.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 { firebaseAdmin, getOrgForHost } from '@aglyn/tenant-data-admin'\nimport * as CommerceModel from '../model'\nimport {\n isPosHardwareSkuId,\n normalizePosHardwareSerial,\n type PosHardwareInPersonConfig,\n type PosHardwareOrder,\n type PosHardwareTaxRegion,\n} from '../model/pos-hardware'\nimport {\n inPersonPosHardwareOrder,\n posHardwareRegisterShare,\n type PosHardwareRegisterLine,\n} from '../model/pos-hardware-in-person'\nimport { hardwareOrdersRef, posHardwareInPersonConfig, posHardwareInPersonOrderId } from './pos-hardware'\nimport { recordPosHardwareOrder } from './pos-hardware-webhook'\nimport { posStripeTestMode } from './pos-stripe'\n\n/*==========================================\n * RECORDING A REGISTER SALE OF HARDWARE (AGL-4038).\n *\n * The platform's own store sells a card reader at its register; once the\n * sale is paid this writes the hardware order it becomes — attached to the\n * buyer's workspace when a register user attached one, PENDING on the\n * selling workspace's \"To attach\" list otherwise — and its retained sale\n * record, through the shop's own recorder.\n *\n * ONE SALE IS ONE ORDER. The order's id is derived from the register sale\n * (`posHardwareInPersonOrderId`) and the recorder writes it once by that id,\n * so the completion listener, a replayed webhook, an offline sync and the\n * sweep below can all reach the same sale and only the first writes.\n *\n * NOTHING IS LOST TO A FAILED LISTENER. Listeners on a completed sale are\n * logged and swallowed (the money is already taken), so the sale is marked\n * `hardwareSalePending` when it is written (`pos-hardware-sale-fields.ts`)\n * and the mark is cleared only once the order exists. The sweep records\n * every paid sale still marked, each time the To attach list is read.\n *=========================================*/\n\nexport type InPersonRecordOutcome =\n | { outcome: 'off' | 'not-seller' | 'missing' | 'not-paid' | 'no-hardware' }\n | { outcome: 'recorded' | 'already'; orderId: string; orgId: string; pending: boolean }\n\n/** How many marked sales one sweep records at most. */\nexport const IN_PERSON_SWEEP_LIMIT = 25\n\n/** Statuses after which a marked sale can never be paid, so the mark is dropped. */\nconst NEVER_PAID = new Set(['cancelled', 'canceled', 'voided', 'refunded', 'expired'])\n\nconst text = (value: unknown): string | null =>\n typeof value === 'string' && value.trim() ? value.trim() : null\n\nfunction firestore() {\n return firebaseAdmin.app().firestore()\n}\n\nfunction registerOrderRef(hostId: string, orderId: string) {\n return firestore().collection('hosts').doc(hostId).collection('orders').doc(orderId)\n}\n\n/** Where the store taxes from, and its rate there, from its own tax settings. */\nasync function storeTax(hostId: string): Promise<{ region: PosHardwareTaxRegion | null; ratePct: number | null }> {\n const settings = await firestore().collection('hosts').doc(hostId).collection('settings').doc('store').get()\n const tax = (settings.get('tax') ?? {}) as CommerceModel.TaxSettings\n const origin = tax.origin ?? {}\n const country = text(origin.country)?.toUpperCase() ?? null\n const rate = country ? CommerceModel.resolveTaxRate(tax, origin) : null\n return {\n region: country ? { country, state: text(origin.state)?.toUpperCase() ?? null, postalCode: null } : null,\n ratePct: rate && Number.isFinite(rate.pct) ? rate.pct : null,\n }\n}\n\n/** The store owner's connected Stripe account, where the store's card money goes. */\nasync function storeStripeAccount(hostId: string): Promise<string | null> {\n const owner = await getOrgForHost(hostId).catch(() => null)\n const ownerUid = text((owner?.org as { ownerUid?: unknown } | undefined)?.ownerUid)\n if (!ownerUid) return null\n const profile = await firestore().collection('profiles').doc(ownerUid).get()\n return text(profile.get('stripeAccountId'))\n}\n\n/**\n * Records the hardware order of one register sale on the seller store, once.\n * Never throws for a sale that is not one: it says why it did nothing.\n */\nexport async function recordInPersonPosHardwareSale(\n hostId: string,\n registerOrderId: string,\n options: { offline?: boolean; config?: PosHardwareInPersonConfig | null; now?: number } = {},\n): Promise<InPersonRecordOutcome> {\n const config = options.config === undefined ? posHardwareInPersonConfig() : options.config\n if (!config) return { outcome: 'off' }\n if (hostId !== config.sellerHostId) return { outcome: 'not-seller' }\n const orderRef = registerOrderRef(hostId, registerOrderId)\n const snapshot = await orderRef.get()\n if (!snapshot.exists) return { outcome: 'missing' }\n const order = snapshot.data() as CommerceModel.HostOrder & {\n paidAtMs?: number\n checkoutSessionId?: string\n customerEmail?: string | null\n }\n if (order.status !== 'paid') return { outcome: 'not-paid' }\n\n const lineItems = Array.isArray(order.lineItems) ? order.lineItems : []\n const productIds = [...new Set(lineItems.map((line) => String(line.productId ?? '')).filter(Boolean))]\n const products = new Map(\n (\n await Promise.all(\n productIds.map((id) => firestore().collection('hosts').doc(hostId).collection('products').doc(id).get()),\n )\n ).map((doc: any) => [String(doc.id), doc.exists ? (doc.data() as CommerceModel.HostProduct) : null]),\n )\n const lines: PosHardwareRegisterLine[] = lineItems.map((line) => {\n const sku = products.get(String(line.productId))?.hardwareSku\n return {\n sku: isPosHardwareSkuId(sku) ? sku : null,\n quantity: Number(line.quantity),\n unitAmountCents: Number(line.unitAmountCents),\n }\n })\n const share = posHardwareRegisterShare({\n lines,\n discountCents: Number(order.totals?.discountCents ?? 0),\n taxCents: Number(order.totals?.taxCents ?? 0),\n })\n if (!share) {\n // Marked when it was rung, but no line is hardware now: nothing to record.\n if (order.hardwareSalePending) {\n await orderRef.set({ hardwareSalePending: firebaseAdmin.firestore.FieldValue.delete() }, { merge: true })\n }\n return { outcome: 'no-hardware' }\n }\n\n const orderId = posHardwareInPersonOrderId(hostId, registerOrderId)\n const payments = CommerceModel.orderPayments(order).filter((payment) => payment.status === 'succeeded')\n const livemodes = payments.map((payment) => payment.livemode).filter((mode): mode is boolean => typeof mode === 'boolean')\n const [tax, stripeAccountId] = await Promise.all([storeTax(hostId), storeStripeAccount(hostId)])\n const paidAtMs = Number(order.paidAtMs ?? order.createdAtMs ?? options.now ?? Date.now())\n const hardwareOrder: PosHardwareOrder = inPersonPosHardwareOrder({\n sellerHostId: config.sellerHostId,\n sellerOrgId: config.sellerOrgId,\n registerOrderId,\n number: Number.isFinite(Number(order.number)) ? Number(order.number) : null,\n registerId: text(order.registerId),\n kiosk: order.posSource === 'kiosk',\n offline: options.offline === true || Boolean((order as { offline?: unknown }).offline),\n share,\n paidAtMs,\n tenders: payments.map((payment) => payment.method),\n paymentLinkSessionId:\n text(payments.find((payment) => payment.checkoutSessionId)?.checkoutSessionId) ?? text(order.checkoutSessionId),\n receiptEmail: text(order.customerEmail)?.toLowerCase() ?? null,\n buyer: order.hardwareBuyer,\n termsAcceptance: order.hardwareTermsAcceptance,\n serials: (Array.isArray(order.hardwareSerials) ? order.hardwareSerials : [])\n .map(normalizePosHardwareSerial)\n .filter(Boolean),\n taxRegion: tax.region,\n ratePct: tax.ratePct,\n stripeAccountId,\n // A card payment says which mode it was in; a cash sale takes the\n // deployment's, so a test deployment's booth is never a real sale.\n livemode: livemodes.length ? livemodes.every(Boolean) : !posStripeTestMode(),\n currency: String((order as { currency?: unknown }).currency ?? 'usd').toLowerCase(),\n })\n\n const { created } = await recordPosHardwareOrder(orderId, hardwareOrder)\n // The mark comes off once the order exists, by this call or an earlier one.\n await orderRef.set(\n { hardwareOrderId: orderId, hardwareSalePending: firebaseAdmin.firestore.FieldValue.delete() },\n { merge: true },\n )\n // A buyer with no account, named at the register while the sale was open,\n // is invited to sign up now that there is an order to point them at.\n if (created && hardwareOrder.attachment?.state === 'pending' && hardwareOrder.attachment.email) {\n await (await import('./pos-hardware-attach')).invitePendingBuyer(orderId, hardwareOrder.orgId, hardwareOrder)\n }\n return {\n outcome: created ? 'recorded' : 'already',\n orderId,\n orgId: hardwareOrder.orgId,\n pending: hardwareOrder.attachment?.state === 'pending',\n }\n}\n\n/**\n * Records every paid sale on the seller store that is still marked, at most\n * {@link IN_PERSON_SWEEP_LIMIT} a time, and drops the mark from a sale that\n * can no longer be paid. Never throws: a sale it cannot record stays marked\n * for the next sweep.\n */\nexport async function sweepInPersonPosHardwareSales(\n config: PosHardwareInPersonConfig | null = posHardwareInPersonConfig(),\n): Promise<{ recorded: number; failed: number }> {\n if (!config) return { recorded: 0, failed: 0 }\n const marked = await firestore()\n .collection('hosts')\n .doc(config.sellerHostId)\n .collection('orders')\n .where('hardwareSalePending', '==', true)\n .limit(IN_PERSON_SWEEP_LIMIT)\n .get()\n let recorded = 0\n let failed = 0\n for (const doc of marked.docs as Array<{ id: string; ref: any; get: (field: string) => unknown }>) {\n const status = String(doc.get('status') ?? '')\n try {\n if (NEVER_PAID.has(status)) {\n await doc.ref.set({ hardwareSalePending: firebaseAdmin.firestore.FieldValue.delete() }, { merge: true })\n continue\n }\n if (status !== 'paid') continue\n const outcome = await recordInPersonPosHardwareSale(config.sellerHostId, String(doc.id), { config })\n if (outcome.outcome === 'recorded') recorded += 1\n } catch (error) {\n failed += 1\n console.error('[pos-hardware-in-person] a marked sale could not be recorded', doc.id, error)\n }\n }\n return { recorded, failed }\n}\n\n/** The \"To attach\" list: the selling workspace's pending in-person orders, newest first. */\nexport async function pendingInPersonPosHardwareOrders(\n config: PosHardwareInPersonConfig,\n limit = 50,\n): Promise<Array<{ id: string; order: PosHardwareOrder }>> {\n const snapshot = await hardwareOrdersRef(config.sellerOrgId)\n .where('attachment.state', '==', 'pending')\n .orderBy('createdAtMs', 'desc')\n .limit(limit)\n .get()\n return snapshot.docs.map((doc: any) => ({ id: String(doc.id), order: doc.data() as PosHardwareOrder }))\n}\n\n/**\n * What the completion listener runs for a sale on the seller store. Never\n * throws into a sale: a failure is logged and the sale stays marked for the\n * sweep.\n */\nexport async function recordCompletedSaleHardware(event: {\n hostId: string\n orderId: string\n offline?: boolean\n}): Promise<void> {\n try {\n await recordInPersonPosHardwareSale(event.hostId, event.orderId, { offline: event.offline === true })\n } catch (error) {\n console.error('[pos-hardware-in-person] sale not recorded; the sweep will', event.orderId, error)\n }\n}\n"],"names":["firebaseAdmin","getOrgForHost","CommerceModel","isPosHardwareSkuId","normalizePosHardwareSerial","inPersonPosHardwareOrder","posHardwareRegisterShare","hardwareOrdersRef","posHardwareInPersonConfig","posHardwareInPersonOrderId","recordPosHardwareOrder","posStripeTestMode","IN_PERSON_SWEEP_LIMIT","NEVER_PAID","Set","text","value","trim","firestore","app","registerOrderRef","hostId","orderId","collection","doc","storeTax","settings","tax","get","origin","country","toUpperCase","rate","resolveTaxRate","region","state","postalCode","ratePct","Number","isFinite","pct","storeStripeAccount","owner","catch","ownerUid","org","profile","recordInPersonPosHardwareSale","registerOrderId","options","order","payments","hardwareOrder","config","undefined","outcome","sellerHostId","orderRef","snapshot","exists","data","status","lineItems","Array","isArray","productIds","map","line","String","productId","filter","Boolean","products","Map","Promise","all","id","lines","sku","hardwareSku","quantity","unitAmountCents","share","discountCents","totals","taxCents","hardwareSalePending","set","FieldValue","delete","merge","orderPayments","payment","livemodes","livemode","mode","stripeAccountId","paidAtMs","createdAtMs","now","Date","sellerOrgId","number","registerId","kiosk","posSource","offline","tenders","method","paymentLinkSessionId","find","checkoutSessionId","receiptEmail","customerEmail","toLowerCase","buyer","hardwareBuyer","termsAcceptance","hardwareTermsAcceptance","serials","hardwareSerials","taxRegion","length","every","currency","created","hardwareOrderId","attachment","email","invitePendingBuyer","orgId","pending","sweepInPersonPosHardwareSales","recorded","failed","marked","where","limit","docs","has","ref","error","console","pendingInPersonPosHardwareOrders","orderBy","recordCompletedSaleHardware","event"],"mappings":"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"}
|
|
@@ -15,13 +15,51 @@
|
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/
|
|
17
17
|
import { POS_HARDWARE_EMAIL_KEYS } from '@aglyn/shared-util-email';
|
|
18
|
-
import { type PosHardwareOrder } from '../model/pos-hardware';
|
|
18
|
+
import { type PosHardwareCancelReason, type PosHardwareOrder } from '../model/pos-hardware';
|
|
19
19
|
export type PosHardwareEmailKind = keyof typeof POS_HARDWARE_EMAIL_KEYS;
|
|
20
20
|
/** The merge values for one order's emails. Exported for the render spec. */
|
|
21
21
|
export declare function posHardwareEmailMerge(orderId: string, order: PosHardwareOrder, names: {
|
|
22
22
|
site: string;
|
|
23
23
|
org: string;
|
|
24
24
|
}): Promise<Record<string, string>>;
|
|
25
|
-
|
|
25
|
+
/** What became of one email. */
|
|
26
|
+
export type PosHardwareEmailOutcome =
|
|
27
|
+
/** Sent. */
|
|
28
|
+
'sent'
|
|
29
|
+
/** Nobody to send it to: no address, suppressed, or the account is banned. */
|
|
30
|
+
| 'skipped'
|
|
31
|
+
/** The send failed, and may be tried again. */
|
|
32
|
+
| 'failed';
|
|
33
|
+
export declare function sendPosHardwareEmail(kind: PosHardwareEmailKind, orderId: string, order: PosHardwareOrder): Promise<PosHardwareEmailOutcome>;
|
|
34
|
+
/**
|
|
35
|
+
* Sends one email for an order ONCE, under `key` (the kind by default; one
|
|
36
|
+
* per refund for a refund in parts). The claim is a field on the order,
|
|
37
|
+
* `buyerEmails.{key}`, taken in a transaction before the send, so the staff
|
|
38
|
+
* page and a closure, a retried press or two staff at once, send it once
|
|
39
|
+
* between them. A send that failed can be claimed again; one that found
|
|
40
|
+
* nobody to send to is not tried again. Never throws.
|
|
41
|
+
*/
|
|
42
|
+
export declare function sendPosHardwareEmailOnce(kind: PosHardwareEmailKind, orderId: string, order: PosHardwareOrder, key?: string): Promise<PosHardwareEmailOutcome | 'already'>;
|
|
43
|
+
/**
|
|
44
|
+
* The invitation to sign up (AGL-4038), for someone who bought a card reader
|
|
45
|
+
* in person at the platform's own store with no account yet: create the
|
|
46
|
+
* account with this address and the order joins their workspace on its own.
|
|
47
|
+
* Sent in the selling workspace's brand, which is the platform's. Never
|
|
48
|
+
* throws; the caller has already claimed the send.
|
|
49
|
+
*/
|
|
50
|
+
/** The invitation's merge values. Exported for the render spec. */
|
|
51
|
+
export declare function posHardwareInviteMerge(orderId: string, order: PosHardwareOrder): Record<string, string>;
|
|
52
|
+
export declare function sendPosHardwareInvite(orderId: string, order: PosHardwareOrder): Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* A closure canceled an order staff had already placed with Stripe: the
|
|
55
|
+
* merchant is refunded, and Stripe will still ship it unless someone cancels
|
|
56
|
+
* it there. Once per order.
|
|
57
|
+
*/
|
|
58
|
+
export declare function raisePosHardwareCanceledAfterOrderingAlert(orderId: string, order: PosHardwareOrder, reason: PosHardwareCancelReason): Promise<void>;
|
|
59
|
+
/**
|
|
60
|
+
* Stripe refused a closure's refund, and the closure went ahead without it.
|
|
61
|
+
* Carries the payment to refund by hand, never the buyer.
|
|
62
|
+
*/
|
|
63
|
+
export declare function raisePosHardwareRefundFailedAlert(orderId: string, order: PosHardwareOrder, reason: PosHardwareCancelReason, error: string): Promise<void>;
|
|
26
64
|
/** "New hardware order", once per order. */
|
|
27
65
|
export declare function raisePosHardwareOrderAlert(orderId: string, order: PosHardwareOrder): Promise<void>;
|
|
@@ -17,13 +17,14 @@ import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
|
17
17
|
*/ import { formatOperatorAlertAmount } from "@aglyn/aglyn/app-utils/operator-alerts";
|
|
18
18
|
import { isAccountBanLockdownReason, normalizeOrgLockdown } from "@aglyn/aglyn/app-utils/lockdown";
|
|
19
19
|
import { POS_HARDWARE_EMAIL_KEYS, sendEmail } from "@aglyn/shared-util-email";
|
|
20
|
+
import { platformConsoleOrigin } from "@aglyn/aglyn/app-utils/platform-brand";
|
|
20
21
|
import { firebaseAdmin, hostDisplayName, meterPlatformEmail, raiseOperatorAlert } from "@aglyn/tenant-data-admin";
|
|
21
22
|
import { filterSuppressedEmails } from "@aglyn/tenant-data-admin/server/email-suppression";
|
|
22
23
|
import { orgSystemEmailBrand, renderSystemEmailContent } from "@aglyn/tenant-data-admin/server/render-system-email";
|
|
23
|
-
import { COMMERCE_POS_HARDWARE_ORDER } from "../constants/operator-alerts.js";
|
|
24
|
+
import { COMMERCE_POS_HARDWARE_CANCELED_AFTER_ORDERING, COMMERCE_POS_HARDWARE_ORDER, COMMERCE_POS_HARDWARE_REFUND_FAILED } from "../constants/operator-alerts.js";
|
|
24
25
|
import { carrierLabelFor } from "../model/tracking-url.js";
|
|
25
26
|
import { formatPosHardwareCents, POS_HARDWARE_ANCHOR } from "../model/pos-hardware.js";
|
|
26
|
-
import { posHardwareOrderNumber, posSettingsUrl } from "./pos-hardware.js";
|
|
27
|
+
import { hardwareOrdersRef, posHardwareOrderNumber, posSettingsUrl } from "./pos-hardware.js";
|
|
27
28
|
/** The lines as the emails list them, one per item. */ function itemsText(order) {
|
|
28
29
|
var _order_lines;
|
|
29
30
|
return ((_order_lines = order.lines) != null ? _order_lines : []).map((line)=>`${line.name} × ${line.quantity}`).join('\n');
|
|
@@ -55,18 +56,38 @@ async function siteAndOrgNames(order) {
|
|
|
55
56
|
const lock = normalizeOrgLockdown(org == null ? void 0 : org.data());
|
|
56
57
|
return {
|
|
57
58
|
site: (host == null ? void 0 : host.exists) ? hostDisplayName(host.data(), order.hostId) : 'your site',
|
|
58
|
-
org: String((_ref = org == null ? void 0 : org.get('name')) != null ? _ref : '').trim() ||
|
|
59
|
+
org: String((_ref = org == null ? void 0 : org.get('name')) != null ? _ref : '').trim() || UNNAMED_WORKSPACE,
|
|
59
60
|
ban: Boolean(lock && isAccountBanLockdownReason(lock.reason))
|
|
60
61
|
};
|
|
61
62
|
}
|
|
62
63
|
/** The fallback subject and first line, when no design renders. */ const FALLBACK = {
|
|
63
64
|
received: (number)=>`We have your card reader order ${number}`,
|
|
64
65
|
shipped: (number)=>`Your card reader order ${number} has shipped`,
|
|
65
|
-
delivered: (number)=>`Your card reader order ${number} was delivered
|
|
66
|
+
delivered: (number)=>`Your card reader order ${number} was delivered`,
|
|
67
|
+
canceled: (number)=>`Your card reader order ${number} was canceled and refunded`,
|
|
68
|
+
refunded: (number)=>`Your refund for card reader order ${number}`,
|
|
69
|
+
invited: (number)=>`Your card reader order ${number} is waiting for your account`,
|
|
70
|
+
returnRefunded: (number)=>`We refunded your returned card reader order ${number}`
|
|
66
71
|
};
|
|
72
|
+
/** The fallback a workspace with no name gets in a sentence. */ const UNNAMED_WORKSPACE = 'your workspace';
|
|
73
|
+
/**
|
|
74
|
+
* Who canceled the order and why, as the email's first sentence; the
|
|
75
|
+
* template goes on "It had not shipped yet, so we refunded …".
|
|
76
|
+
*/ function cancelReasonText(reason, org) {
|
|
77
|
+
if (reason === 'workspace-closed') {
|
|
78
|
+
return org && org !== UNNAMED_WORKSPACE ? `We canceled your order because the ${org} workspace was deleted.` : 'We canceled your order because your workspace was deleted.';
|
|
79
|
+
}
|
|
80
|
+
if (reason === 'account-closed') return 'We canceled your order because the account that placed it was closed.';
|
|
81
|
+
return 'Our team canceled your order.';
|
|
82
|
+
}
|
|
83
|
+
/** Why, for staff: the closure that canceled it, never who the buyer was. */ function staffReasonText(reason, orgId) {
|
|
84
|
+
if (reason === 'workspace-closed') return `its workspace ${orgId} was deleted`;
|
|
85
|
+
if (reason === 'account-closed') return 'the account that placed it was closed';
|
|
86
|
+
return 'staff canceled it';
|
|
87
|
+
}
|
|
67
88
|
/** The merge values for one order's emails. Exported for the render spec. */ export async function posHardwareEmailMerge(orderId, order, names) {
|
|
68
|
-
var _order_totalCents, _ref, _ref1, _ref2;
|
|
69
|
-
var _order_shipping, _order_tracking, _order_tracking1, _order_tracking2;
|
|
89
|
+
var _order_totalCents, _ref, _ref1, _ref2, _ref3, _order_refundedCents, _ref4, _ref5, _ref6, _order_refunds, _order_totalCents1, _order_refundedCents1;
|
|
90
|
+
var _order_shipping, _order_tracking, _order_tracking1, _order_tracking2, _slice_;
|
|
70
91
|
const base = await posSettingsUrl(order.hostId);
|
|
71
92
|
const [path] = base.split('#');
|
|
72
93
|
const ordersUrl = `${path}#${POS_HARDWARE_ANCHOR}`;
|
|
@@ -83,27 +104,40 @@ async function siteAndOrgNames(order) {
|
|
|
83
104
|
// An unknown carrier has no tracker to link; the card shows the number.
|
|
84
105
|
'order.trackingUrl': (_ref2 = (_order_tracking2 = order.tracking) == null ? void 0 : _order_tracking2.url) != null ? _ref2 : ordersUrl,
|
|
85
106
|
'order.ordersUrl': ordersUrl,
|
|
86
|
-
'order.setupUrl': `${path}#pos-devices
|
|
107
|
+
'order.setupUrl': `${path}#pos-devices`,
|
|
108
|
+
// What Stripe reported refunding, or the whole charge where it has not.
|
|
109
|
+
'order.refunded': formatPosHardwareCents((_ref3 = (_order_refundedCents = order.refundedCents) != null ? _order_refundedCents : order.totalCents) != null ? _ref3 : 0),
|
|
110
|
+
// This refund alone, for an order refunded in parts; the whole of it otherwise.
|
|
111
|
+
'order.refundedNow': formatPosHardwareCents((_ref4 = (_ref5 = (_ref6 = (_slice_ = ((_order_refunds = order.refunds) != null ? _order_refunds : []).slice(-1)[0]) == null ? void 0 : _slice_.cents) != null ? _ref6 : order.refundedCents) != null ? _ref5 : order.totalCents) != null ? _ref4 : 0),
|
|
112
|
+
'order.cancelReason': cancelReasonText(order.cancelReason, names.org),
|
|
113
|
+
// What a return kept back: the original shipping and any restocking fee.
|
|
114
|
+
'order.kept': formatPosHardwareCents(Math.max(0, ((_order_totalCents1 = order.totalCents) != null ? _order_totalCents1 : 0) - ((_order_refundedCents1 = order.refundedCents) != null ? _order_refundedCents1 : 0)))
|
|
87
115
|
};
|
|
88
116
|
}
|
|
89
117
|
export async function sendPosHardwareEmail(kind, orderId, order) {
|
|
90
118
|
try {
|
|
91
|
-
var _order_contactEmail;
|
|
119
|
+
var _order_contactEmail, _ref;
|
|
120
|
+
var _order_posSale;
|
|
92
121
|
const to = String((_order_contactEmail = order.contactEmail) != null ? _order_contactEmail : '').trim();
|
|
93
|
-
if (!to) return;
|
|
122
|
+
if (!to) return 'skipped';
|
|
94
123
|
const names = await siteAndOrgNames(order);
|
|
95
124
|
// A ban is a ban (AGL-3420): after its notice the account is sent nothing.
|
|
96
|
-
if (names.ban) return;
|
|
125
|
+
if (names.ban) return 'skipped';
|
|
97
126
|
const [recipient] = await filterSuppressedEmails([
|
|
98
127
|
to
|
|
99
128
|
]);
|
|
100
|
-
if (!recipient) return;
|
|
129
|
+
if (!recipient) return 'skipped';
|
|
101
130
|
const merge = await posHardwareEmailMerge(orderId, order, names);
|
|
102
131
|
const subject = FALLBACK[kind](merge['order.number']);
|
|
103
|
-
|
|
132
|
+
// A refund in person is in the selling workspace's brand, as its
|
|
133
|
+
// invitation is; the rest in the buyer's.
|
|
134
|
+
const brand = await orgSystemEmailBrand(kind === 'refunded' ? (_ref = (_order_posSale = order.posSale) == null ? void 0 : _order_posSale.orgId) != null ? _ref : order.orgId : order.orgId);
|
|
135
|
+
// A canceled order's workspace may be gone, so its fallback names the
|
|
136
|
+
// refund rather than linking a card that no longer opens.
|
|
137
|
+
const last = kind === 'canceled' ? `Refunded: ${merge['order.refunded']}` : kind === 'refunded' ? `Refunded now: ${merge['order.refundedNow']}` : merge['order.ordersUrl'];
|
|
104
138
|
const content = await renderSystemEmailContent(POS_HARDWARE_EMAIL_KEYS[kind], merge, brand, {
|
|
105
139
|
subject,
|
|
106
|
-
text: `${subject}\n\n${merge['order.items']}\n\n${
|
|
140
|
+
text: `${subject}\n\n${merge['order.items']}\n\n${last}`
|
|
107
141
|
});
|
|
108
142
|
const result = await sendEmail(_extends({
|
|
109
143
|
to: recipient
|
|
@@ -112,9 +146,156 @@ export async function sendPosHardwareEmail(kind, orderId, order) {
|
|
|
112
146
|
} : {}, {
|
|
113
147
|
context: POS_HARDWARE_EMAIL_KEYS[kind]
|
|
114
148
|
}));
|
|
115
|
-
if (result.sent)
|
|
149
|
+
if (!result.sent) return 'failed';
|
|
150
|
+
await meterPlatformEmail(1);
|
|
151
|
+
return 'sent';
|
|
116
152
|
} catch (error) {
|
|
117
153
|
console.error('[pos-hardware] email failed', kind, orderId, error);
|
|
154
|
+
return 'failed';
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/** How long a claimed send that never finished holds the next one back. */ const EMAIL_CLAIM_STALE_MS = 10 * 60 * 1000;
|
|
158
|
+
/**
|
|
159
|
+
* Sends one email for an order ONCE, under `key` (the kind by default; one
|
|
160
|
+
* per refund for a refund in parts). The claim is a field on the order,
|
|
161
|
+
* `buyerEmails.{key}`, taken in a transaction before the send, so the staff
|
|
162
|
+
* page and a closure, a retried press or two staff at once, send it once
|
|
163
|
+
* between them. A send that failed can be claimed again; one that found
|
|
164
|
+
* nobody to send to is not tried again. Never throws.
|
|
165
|
+
*/ export async function sendPosHardwareEmailOnce(kind, orderId, order, key = kind) {
|
|
166
|
+
try {
|
|
167
|
+
const firestore = firebaseAdmin.app().firestore();
|
|
168
|
+
const ref = hardwareOrdersRef(order.orgId).doc(orderId);
|
|
169
|
+
const claimed = await firestore.runTransaction(async (transaction)=>{
|
|
170
|
+
var _ref, _held_atMs;
|
|
171
|
+
var _snapshot_data;
|
|
172
|
+
const snapshot = await transaction.get(ref);
|
|
173
|
+
if (!snapshot.exists) return false;
|
|
174
|
+
const held = ((_ref = (_snapshot_data = snapshot.data()) == null ? void 0 : _snapshot_data.buyerEmails) != null ? _ref : {})[key];
|
|
175
|
+
const now = Date.now();
|
|
176
|
+
if ((held == null ? void 0 : held.state) === 'sent' || (held == null ? void 0 : held.state) === 'skipped') return false;
|
|
177
|
+
if ((held == null ? void 0 : held.state) === 'sending' && now - Number((_held_atMs = held.atMs) != null ? _held_atMs : 0) < EMAIL_CLAIM_STALE_MS) return false;
|
|
178
|
+
transaction.set(ref, {
|
|
179
|
+
buyerEmails: {
|
|
180
|
+
[key]: {
|
|
181
|
+
state: 'sending',
|
|
182
|
+
atMs: now
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}, {
|
|
186
|
+
merge: true
|
|
187
|
+
});
|
|
188
|
+
return true;
|
|
189
|
+
});
|
|
190
|
+
if (!claimed) return 'already';
|
|
191
|
+
const outcome = await sendPosHardwareEmail(kind, orderId, order);
|
|
192
|
+
await ref.set({
|
|
193
|
+
buyerEmails: {
|
|
194
|
+
[key]: {
|
|
195
|
+
state: outcome === 'sent' ? 'sent' : outcome,
|
|
196
|
+
atMs: Date.now()
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}, {
|
|
200
|
+
merge: true
|
|
201
|
+
}).catch((error)=>console.error('[pos-hardware] email claim not settled', kind, orderId, error));
|
|
202
|
+
return outcome;
|
|
203
|
+
} catch (error) {
|
|
204
|
+
console.error('[pos-hardware] email claim failed', kind, orderId, error);
|
|
205
|
+
return 'failed';
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* The invitation to sign up (AGL-4038), for someone who bought a card reader
|
|
210
|
+
* in person at the platform's own store with no account yet: create the
|
|
211
|
+
* account with this address and the order joins their workspace on its own.
|
|
212
|
+
* Sent in the selling workspace's brand, which is the platform's. Never
|
|
213
|
+
* throws; the caller has already claimed the send.
|
|
214
|
+
*/ /** The invitation's merge values. Exported for the render spec. */ export function posHardwareInviteMerge(orderId, order) {
|
|
215
|
+
var _order_totalCents;
|
|
216
|
+
return {
|
|
217
|
+
'order.number': posHardwareOrderNumber(orderId),
|
|
218
|
+
'order.items': itemsText(order),
|
|
219
|
+
'order.total': formatPosHardwareCents((_order_totalCents = order.totalCents) != null ? _order_totalCents : 0),
|
|
220
|
+
'order.signUpUrl': `${platformConsoleOrigin()}/signup`
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
export async function sendPosHardwareInvite(orderId, order) {
|
|
224
|
+
try {
|
|
225
|
+
var _ref, _ref1;
|
|
226
|
+
var _order_attachment, _order_posSale;
|
|
227
|
+
const to = String((_ref = (_order_attachment = order.attachment) == null ? void 0 : _order_attachment.email) != null ? _ref : '').trim();
|
|
228
|
+
if (!to) return;
|
|
229
|
+
const [recipient] = await filterSuppressedEmails([
|
|
230
|
+
to
|
|
231
|
+
]);
|
|
232
|
+
if (!recipient) return;
|
|
233
|
+
const merge = posHardwareInviteMerge(orderId, order);
|
|
234
|
+
const signUpUrl = merge['order.signUpUrl'];
|
|
235
|
+
const subject = FALLBACK.invited(merge['order.number']);
|
|
236
|
+
const brand = await orgSystemEmailBrand((_ref1 = (_order_posSale = order.posSale) == null ? void 0 : _order_posSale.orgId) != null ? _ref1 : order.orgId);
|
|
237
|
+
const content = await renderSystemEmailContent(POS_HARDWARE_EMAIL_KEYS.invited, merge, brand, {
|
|
238
|
+
subject,
|
|
239
|
+
text: `${subject}\n\n${merge['order.items']}\n\nCreate your account with this email address: ${signUpUrl}`
|
|
240
|
+
});
|
|
241
|
+
const result = await sendEmail(_extends({
|
|
242
|
+
to: recipient
|
|
243
|
+
}, content, brand.fromName ? {
|
|
244
|
+
fromName: brand.fromName
|
|
245
|
+
} : {}, {
|
|
246
|
+
context: POS_HARDWARE_EMAIL_KEYS.invited
|
|
247
|
+
}));
|
|
248
|
+
if (result.sent) await meterPlatformEmail(1);
|
|
249
|
+
} catch (error) {
|
|
250
|
+
console.error('[pos-hardware] invitation failed', orderId, error);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* A closure canceled an order staff had already placed with Stripe: the
|
|
255
|
+
* merchant is refunded, and Stripe will still ship it unless someone cancels
|
|
256
|
+
* it there. Once per order.
|
|
257
|
+
*/ export async function raisePosHardwareCanceledAfterOrderingAlert(orderId, order, reason) {
|
|
258
|
+
try {
|
|
259
|
+
var _order_stripeHardwareOrderId, _order_totalCents, _order_lines;
|
|
260
|
+
const stripeOrderId = String((_order_stripeHardwareOrderId = order.stripeHardwareOrderId) != null ? _order_stripeHardwareOrderId : '').trim();
|
|
261
|
+
await raiseOperatorAlert(COMMERCE_POS_HARDWARE_CANCELED_AFTER_ORDERING, {
|
|
262
|
+
dedupeKey: orderId,
|
|
263
|
+
orgId: order.orgId,
|
|
264
|
+
hostId: order.hostId,
|
|
265
|
+
context: {
|
|
266
|
+
orderNumber: posHardwareOrderNumber(orderId),
|
|
267
|
+
amount: formatOperatorAlertAmount((_order_totalCents = order.totalCents) != null ? _order_totalCents : 0),
|
|
268
|
+
items: ((_order_lines = order.lines) != null ? _order_lines : []).map((line)=>`${line.quantity} × ${line.name}`).join(', '),
|
|
269
|
+
reason: staffReasonText(reason, order.orgId),
|
|
270
|
+
stripeOrder: stripeOrderId ? ` (Stripe order ${stripeOrderId})` : ''
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
} catch (error) {
|
|
274
|
+
console.error('[pos-hardware] canceled-after-ordering alert failed', orderId, error);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Stripe refused a closure's refund, and the closure went ahead without it.
|
|
279
|
+
* Carries the payment to refund by hand, never the buyer.
|
|
280
|
+
*/ export async function raisePosHardwareRefundFailedAlert(orderId, order, reason, error) {
|
|
281
|
+
try {
|
|
282
|
+
var _order_stripeHardwareOrderId, _order_totalCents, _order_stripePaymentIntentId;
|
|
283
|
+
const stripeOrderId = String((_order_stripeHardwareOrderId = order.stripeHardwareOrderId) != null ? _order_stripeHardwareOrderId : '').trim();
|
|
284
|
+
await raiseOperatorAlert(COMMERCE_POS_HARDWARE_REFUND_FAILED, {
|
|
285
|
+
dedupeKey: orderId,
|
|
286
|
+
orgId: order.orgId,
|
|
287
|
+
hostId: order.hostId,
|
|
288
|
+
context: {
|
|
289
|
+
orderNumber: posHardwareOrderNumber(orderId),
|
|
290
|
+
amount: formatOperatorAlertAmount((_order_totalCents = order.totalCents) != null ? _order_totalCents : 0),
|
|
291
|
+
reason: staffReasonText(reason, order.orgId),
|
|
292
|
+
error: error || 'no reason given',
|
|
293
|
+
paymentIntentId: (_order_stripePaymentIntentId = order.stripePaymentIntentId) != null ? _order_stripePaymentIntentId : 'for this order (no payment id is recorded on it)',
|
|
294
|
+
orderedNote: order.status === 'ordered' ? `. It had already been placed with Stripe${stripeOrderId ? ` as ${stripeOrderId}` : ''}, so cancel it there too before it ships` : ''
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
} catch (failure) {
|
|
298
|
+
console.error('[pos-hardware] refund-failed alert failed', orderId, failure);
|
|
118
299
|
}
|
|
119
300
|
}
|
|
120
301
|
/** "New hardware order", once per order. */ export async function raisePosHardwareOrderAlert(orderId, order) {
|