@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,44 @@
|
|
|
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 { isPosHardwareSkuId, parsePosHardwareInPersonConfig } from "../model/pos-hardware.js";
|
|
17
|
+
/*==========================================
|
|
18
|
+
* THE MARK A REGISTER SALE OF HARDWARE CARRIES (AGL-4038).
|
|
19
|
+
*
|
|
20
|
+
* Every path that writes a register sale — an open sale, a payment link, a
|
|
21
|
+
* cash or room sale, the kiosk's cart, an offline sale synced later — spreads
|
|
22
|
+
* these fields into the order it writes. On the platform's own store, a sale
|
|
23
|
+
* with a line whose product is a hardware item says `hardwareSalePending`
|
|
24
|
+
* from the moment it exists, and the hardware order is recorded when it is
|
|
25
|
+
* paid. The completion listener clears the mark; one it missed is found by
|
|
26
|
+
* the mark and recorded on the next sweep, so a sale is never lost because a
|
|
27
|
+
* listener failed after the money was taken.
|
|
28
|
+
*
|
|
29
|
+
* Read on every sale of every store, so it costs nothing anywhere but the
|
|
30
|
+
* seller: the environment is read first, and the products are the ones the
|
|
31
|
+
* sale already loaded.
|
|
32
|
+
*=========================================*/ export function posHardwareSaleFields(input, env = process.env) {
|
|
33
|
+
const config = parsePosHardwareInPersonConfig(env);
|
|
34
|
+
if (!config || config.sellerHostId !== input.hostId || config.sellerOrgId !== input.orgId) return {};
|
|
35
|
+
const sellsHardware = input.lineItems.some((line)=>{
|
|
36
|
+
var _input_products_get;
|
|
37
|
+
return isPosHardwareSkuId((_input_products_get = input.products.get(line.productId)) == null ? void 0 : _input_products_get.hardwareSku);
|
|
38
|
+
});
|
|
39
|
+
return sellsHardware ? {
|
|
40
|
+
hardwareSalePending: true
|
|
41
|
+
} : {};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
//# sourceMappingURL=pos-hardware-sale-fields.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/server/pos-hardware-sale-fields.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 { isPosHardwareSkuId, parsePosHardwareInPersonConfig } from '../model/pos-hardware'\n\n/*==========================================\n * THE MARK A REGISTER SALE OF HARDWARE CARRIES (AGL-4038).\n *\n * Every path that writes a register sale — an open sale, a payment link, a\n * cash or room sale, the kiosk's cart, an offline sale synced later — spreads\n * these fields into the order it writes. On the platform's own store, a sale\n * with a line whose product is a hardware item says `hardwareSalePending`\n * from the moment it exists, and the hardware order is recorded when it is\n * paid. The completion listener clears the mark; one it missed is found by\n * the mark and recorded on the next sweep, so a sale is never lost because a\n * listener failed after the money was taken.\n *\n * Read on every sale of every store, so it costs nothing anywhere but the\n * seller: the environment is read first, and the products are the ones the\n * sale already loaded.\n *=========================================*/\n\nexport function posHardwareSaleFields(\n input: {\n hostId: string\n orgId: string | null | undefined\n lineItems: ReadonlyArray<{ productId: string }>\n products: ReadonlyMap<string, { hardwareSku?: unknown } | null | undefined>\n },\n env: Record<string, string | undefined> = process.env,\n): { hardwareSalePending?: true } {\n const config = parsePosHardwareInPersonConfig(env)\n if (!config || config.sellerHostId !== input.hostId || config.sellerOrgId !== input.orgId) return {}\n const sellsHardware = input.lineItems.some((line) =>\n isPosHardwareSkuId(input.products.get(line.productId)?.hardwareSku),\n )\n return sellsHardware ? { hardwareSalePending: true } : {}\n}\n"],"names":["isPosHardwareSkuId","parsePosHardwareInPersonConfig","posHardwareSaleFields","input","env","process","config","sellerHostId","hostId","sellerOrgId","orgId","sellsHardware","lineItems","some","line","products","get","productId","hardwareSku","hardwareSalePending"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,SAASA,kBAAkB,EAAEC,8BAA8B,QAAQ,2BAAuB;AAE1F;;;;;;;;;;;;;;;2CAe2C,GAE3C,OAAO,SAASC,sBACdC,KAKC,EACDC,MAA0CC,QAAQD,GAAG;IAErD,MAAME,SAASL,+BAA+BG;IAC9C,IAAI,CAACE,UAAUA,OAAOC,YAAY,KAAKJ,MAAMK,MAAM,IAAIF,OAAOG,WAAW,KAAKN,MAAMO,KAAK,EAAE,OAAO,CAAC;IACnG,MAAMC,gBAAgBR,MAAMS,SAAS,CAACC,IAAI,CAAC,CAACC;YACvBX;eAAnBH,oBAAmBG,sBAAAA,MAAMY,QAAQ,CAACC,GAAG,CAACF,KAAKG,SAAS,sBAAjCd,oBAAoCe,WAAW;;IAEpE,OAAOP,gBAAgB;QAAEQ,qBAAqB;IAAK,IAAI,CAAC;AAC1D"}
|
|
@@ -0,0 +1,54 @@
|
|
|
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
|
+
import { type PosHardwareOrder } from '../model/pos-hardware';
|
|
19
|
+
/** How many lookups one register user makes in ten minutes. */
|
|
20
|
+
export declare const BUYER_LOOKUPS_PER_WINDOW = 30;
|
|
21
|
+
export declare const posHardwareSaleHandler: PluginApiHandler;
|
|
22
|
+
/**
|
|
23
|
+
* A sale on the To attach list, as the register shows it: what was sold and
|
|
24
|
+
* when, the register order it came from, and what is known of the buyer —
|
|
25
|
+
* the receipt address, or the address or account a register user gave.
|
|
26
|
+
*/
|
|
27
|
+
export declare function toAttachView(id: string, order: PosHardwareOrder): {
|
|
28
|
+
id: string;
|
|
29
|
+
number: string;
|
|
30
|
+
registerOrderId: string;
|
|
31
|
+
registerNumber: number;
|
|
32
|
+
kiosk: boolean;
|
|
33
|
+
offline: boolean;
|
|
34
|
+
lines: {
|
|
35
|
+
sku: import("../model/pos-hardware").PosHardwareSkuId;
|
|
36
|
+
name: string;
|
|
37
|
+
quantity: number;
|
|
38
|
+
}[];
|
|
39
|
+
totalCents: number;
|
|
40
|
+
createdAtMs: number;
|
|
41
|
+
contactEmail: string;
|
|
42
|
+
attached: boolean;
|
|
43
|
+
/** Attached with the buyer's store chosen: a reader can be registered to it here. */
|
|
44
|
+
storeChosen: boolean;
|
|
45
|
+
/** Readers on the sale, and how many have a serial or are set up. */
|
|
46
|
+
readers: number;
|
|
47
|
+
serialsTaken: number;
|
|
48
|
+
readersSetUp: number;
|
|
49
|
+
/** A buyer with an account and no workspace yet. */
|
|
50
|
+
awaitingWorkspace: boolean;
|
|
51
|
+
/** A buyer with no account yet, invited to sign up. */
|
|
52
|
+
invited: boolean;
|
|
53
|
+
};
|
|
54
|
+
export type ToAttachView = ReturnType<typeof toAttachView>;
|
|
@@ -0,0 +1,369 @@
|
|
|
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 { _ as _extends } from "@swc/helpers/_/_extends";
|
|
17
|
+
import { consumeRateLimit, firebaseAdmin } from "@aglyn/tenant-data-admin";
|
|
18
|
+
import { addAdminAudit } from "@aglyn/tenant-data-admin/server/admin-audit-write";
|
|
19
|
+
import { maskEmailAddress } from "@aglyn/tenant-data-admin/server/admin-audit";
|
|
20
|
+
import { POS_HARDWARE_SKUS } from "../model/pos-hardware.js";
|
|
21
|
+
import { authorizePosStaff, posIdempotencyKey, posRequestBody } from "./pos-auth.js";
|
|
22
|
+
import { isPosHardwareSellerStore, posHardwareInPersonConfig, posHardwareOrderNumber } from "./pos-hardware.js";
|
|
23
|
+
/** How many lookups one register user makes in ten minutes. */ export const BUYER_LOOKUPS_PER_WINDOW = 30;
|
|
24
|
+
const LOOKUP_WINDOW_MS = 10 * 60 * 1000;
|
|
25
|
+
/*==========================================
|
|
26
|
+
* `POST /api/commerce/pos-hardware-sale` (AGL-4038): selling a card reader in
|
|
27
|
+
* person, at the platform's own store's register, to someone who is not a
|
|
28
|
+
* member of it.
|
|
29
|
+
*
|
|
30
|
+
* status whether this store is the platform's hardware seller, and the
|
|
31
|
+
* hardware items a product of it may be — the product editor's
|
|
32
|
+
* "Point of sale hardware" choice is shown only where it is.
|
|
33
|
+
* pending the "To attach" list: sales of hardware nobody has said whose
|
|
34
|
+
* they are yet (a kiosk or offline sale, a buyer with no account
|
|
35
|
+
* or no workspace yet), newest first. Records any paid sale still
|
|
36
|
+
* waiting to be recorded first (`sweepInPersonPosHardwareSales`).
|
|
37
|
+
* find look the buyer up across the platform by exact email, a
|
|
38
|
+
* person's name or a workspace's name (`pos-hardware-buyer-lookup.ts`):
|
|
39
|
+
* the least that picks the right person, their address in full.
|
|
40
|
+
* Rate-limited per register user and written to the platform's
|
|
41
|
+
* audit log (the address masked there), every time.
|
|
42
|
+
* attach say whose a sale is — by the register sale or the To attach
|
|
43
|
+
* entry — as an account and workspace (and store), an account
|
|
44
|
+
* with no workspace yet, or the address of someone with no
|
|
45
|
+
* account, who is invited to sign up (`pos-hardware-attach.ts`).
|
|
46
|
+
* Idempotency-Key required; audited.
|
|
47
|
+
* detach put an attached sale back on the To attach list. Audited.
|
|
48
|
+
* serials the serial numbers of the sale's readers, scanned or typed at
|
|
49
|
+
* the sale, so the order sets itself up when the buyer registers
|
|
50
|
+
* them (`pos-hardware-readers.ts`).
|
|
51
|
+
* terms the terms of sale the buyer accepts before paying (Terms
|
|
52
|
+
* 4.26–4.32 in short, with the link), and `terms-status` whether
|
|
53
|
+
* they have, for the register waiting on its display.
|
|
54
|
+
* accept-terms the buyer accepted on the register tablet handed to them;
|
|
55
|
+
* `terms-on-display` notes who is putting them on the customer
|
|
56
|
+
* display, before the register shows them there (`pos-hardware-terms.ts`).
|
|
57
|
+
* register-at-booth register a reader to the buyer's chosen store by the
|
|
58
|
+
* code it shows, while they are there, with the store's address
|
|
59
|
+
* when it has no reader Location yet (`address`; refused with
|
|
60
|
+
* `reason: 'needs-address'` without one). Idempotency-Key
|
|
61
|
+
* required; audited.
|
|
62
|
+
*
|
|
63
|
+
* `status` is asked of whoever works the register; everything else needs
|
|
64
|
+
* "Sell at the register" (`posSell`) on the seller store, since it is part
|
|
65
|
+
* of ringing a sale there, and answers 404 on any other store.
|
|
66
|
+
*
|
|
67
|
+
* Gated like the register (`authorizePosStaff`, on a plan with POS). Every
|
|
68
|
+
* answer is about THIS store: on any store but the configured seller it says
|
|
69
|
+
* `seller: false` and nothing else, so no other workspace learns the
|
|
70
|
+
* platform's configuration or is shown a control it cannot use.
|
|
71
|
+
*=========================================*/ export const posHardwareSaleHandler = async (req, res)=>{
|
|
72
|
+
var _body_hostId, _body_action;
|
|
73
|
+
if (req.method !== 'POST') return res.status(405).json({
|
|
74
|
+
error: 'Method not allowed'
|
|
75
|
+
});
|
|
76
|
+
const body = posRequestBody(req);
|
|
77
|
+
const hostId = String((_body_hostId = body['hostId']) != null ? _body_hostId : '');
|
|
78
|
+
const action = String((_body_action = body['action']) != null ? _body_action : '');
|
|
79
|
+
const permission = action === 'status' ? undefined : 'posSell';
|
|
80
|
+
const gate = await authorizePosStaff(req, hostId, permission);
|
|
81
|
+
if ('error' in gate) return res.status(gate.status).json({
|
|
82
|
+
error: gate.error
|
|
83
|
+
});
|
|
84
|
+
const staff = gate.staff;
|
|
85
|
+
const config = posHardwareInPersonConfig();
|
|
86
|
+
const seller = isPosHardwareSellerStore(config, staff.hostId, staff.orgId);
|
|
87
|
+
try {
|
|
88
|
+
if (action === 'status') {
|
|
89
|
+
if (!seller) return res.status(200).json({
|
|
90
|
+
seller: false
|
|
91
|
+
});
|
|
92
|
+
return res.status(200).json({
|
|
93
|
+
seller: true,
|
|
94
|
+
items: POS_HARDWARE_SKUS.map((sku)=>({
|
|
95
|
+
sku: sku.id,
|
|
96
|
+
name: sku.displayName,
|
|
97
|
+
kind: sku.kind
|
|
98
|
+
}))
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
if (!seller) return res.status(404).json({
|
|
102
|
+
error: 'Card reader sales are not available on this store.'
|
|
103
|
+
});
|
|
104
|
+
const inPerson = await import("./pos-hardware-in-person.js");
|
|
105
|
+
switch(action){
|
|
106
|
+
case 'pending':
|
|
107
|
+
{
|
|
108
|
+
await inPerson.sweepInPersonPosHardwareSales(config);
|
|
109
|
+
const pending = await inPerson.pendingInPersonPosHardwareOrders(config);
|
|
110
|
+
return res.status(200).json({
|
|
111
|
+
orders: pending.map(({ id, order })=>toAttachView(id, order))
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
case 'find':
|
|
115
|
+
{
|
|
116
|
+
var _body_query;
|
|
117
|
+
const query = String((_body_query = body['query']) != null ? _body_query : '').trim().slice(0, 120);
|
|
118
|
+
if (query.length < 2) return res.status(400).json({
|
|
119
|
+
error: 'Type at least two letters, or an email address.'
|
|
120
|
+
});
|
|
121
|
+
const rate = await consumeRateLimit(`pos-hardware-lookup:${staff.uid}`, {
|
|
122
|
+
limit: BUYER_LOOKUPS_PER_WINDOW,
|
|
123
|
+
windowMs: LOOKUP_WINDOW_MS
|
|
124
|
+
});
|
|
125
|
+
if (!rate.allowed) return res.status(429).json({
|
|
126
|
+
error: 'Too many lookups. Try again in a few minutes.'
|
|
127
|
+
});
|
|
128
|
+
const found = await (await import("./pos-hardware-buyer-lookup.js")).findHardwareBuyers(query);
|
|
129
|
+
await audit(staff, 'pos-hardware-buyer-lookup', {
|
|
130
|
+
// The audit log keeps an address masked; a name as typed. The
|
|
131
|
+
// register itself is answered in full.
|
|
132
|
+
query: found.kind === 'email' ? maskEmailAddress(query) : query,
|
|
133
|
+
kind: found.kind,
|
|
134
|
+
matched: [
|
|
135
|
+
...found.people.map((person)=>person.uid),
|
|
136
|
+
...found.workspaces.map((workspace)=>`org:${workspace.orgId}`)
|
|
137
|
+
]
|
|
138
|
+
});
|
|
139
|
+
return res.status(200).json(found);
|
|
140
|
+
}
|
|
141
|
+
case 'terms':
|
|
142
|
+
case 'terms-status':
|
|
143
|
+
case 'terms-on-display':
|
|
144
|
+
case 'accept-terms':
|
|
145
|
+
{
|
|
146
|
+
var _body_registerOrderId;
|
|
147
|
+
const terms = await import("./pos-hardware-terms.js");
|
|
148
|
+
const registerOrderId = String((_body_registerOrderId = body['registerOrderId']) != null ? _body_registerOrderId : '');
|
|
149
|
+
try {
|
|
150
|
+
if (action === 'terms') return res.status(200).json(terms.posHardwareTermsView());
|
|
151
|
+
if (action === 'terms-status') {
|
|
152
|
+
return res.status(200).json(await terms.posHardwareTermsStatus(config, registerOrderId));
|
|
153
|
+
}
|
|
154
|
+
if (action === 'terms-on-display') {
|
|
155
|
+
await terms.requestPosHardwareTermsOnDisplay({
|
|
156
|
+
config,
|
|
157
|
+
registerOrderId,
|
|
158
|
+
uid: staff.uid
|
|
159
|
+
});
|
|
160
|
+
return res.status(200).json({
|
|
161
|
+
ok: true
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
const device = terms.posHardwareTermsDevice(req.headers);
|
|
165
|
+
const acceptance = await terms.recordPosHardwareTermsAcceptance(_extends({
|
|
166
|
+
config,
|
|
167
|
+
registerOrderId,
|
|
168
|
+
method: 'tablet',
|
|
169
|
+
staffUid: staff.uid
|
|
170
|
+
}, device));
|
|
171
|
+
await audit(staff, 'pos-hardware-terms-accepted', {
|
|
172
|
+
method: acceptance.method,
|
|
173
|
+
version: acceptance.version,
|
|
174
|
+
registerOrderId
|
|
175
|
+
}, null);
|
|
176
|
+
return res.status(200).json({
|
|
177
|
+
ok: true,
|
|
178
|
+
acceptance
|
|
179
|
+
});
|
|
180
|
+
} catch (error) {
|
|
181
|
+
if (error instanceof terms.PosHardwareTermsRefusal) {
|
|
182
|
+
return res.status(error.status).json({
|
|
183
|
+
error: error.message
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
throw error;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
case 'serials':
|
|
190
|
+
case 'register-at-booth':
|
|
191
|
+
{
|
|
192
|
+
const readers = await import("./pos-hardware-readers.js");
|
|
193
|
+
try {
|
|
194
|
+
var _body_orderId, _storeAddress_state;
|
|
195
|
+
if (action === 'serials') {
|
|
196
|
+
const saved = await readers.recordPosHardwareSerials({
|
|
197
|
+
config,
|
|
198
|
+
registerOrderId: typeof body['registerOrderId'] === 'string' ? body['registerOrderId'] : null,
|
|
199
|
+
orderId: typeof body['orderId'] === 'string' ? body['orderId'] : null,
|
|
200
|
+
serials: body['serials']
|
|
201
|
+
});
|
|
202
|
+
return res.status(200).json({
|
|
203
|
+
ok: true,
|
|
204
|
+
serials: saved.serials,
|
|
205
|
+
recorded: saved.recorded
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
if (!posIdempotencyKey(req)) return res.status(400).json({
|
|
209
|
+
error: 'Missing Idempotency-Key'
|
|
210
|
+
});
|
|
211
|
+
const registerOrderId = typeof body['registerOrderId'] === 'string' ? body['registerOrderId'] : '';
|
|
212
|
+
const orderId = registerOrderId ? (await import("./pos-hardware.js")).posHardwareInPersonOrderId(config.sellerHostId, registerOrderId) : String((_body_orderId = body['orderId']) != null ? _body_orderId : '');
|
|
213
|
+
const { order, readerId, storeAddress } = await readers.registerPosHardwareAtBooth({
|
|
214
|
+
config,
|
|
215
|
+
orderId,
|
|
216
|
+
registrationCode: body['registrationCode'],
|
|
217
|
+
label: body['label'],
|
|
218
|
+
address: body['address'],
|
|
219
|
+
uid: staff.uid
|
|
220
|
+
});
|
|
221
|
+
await audit(staff, 'pos-hardware-register-at-booth', _extends({
|
|
222
|
+
readerId,
|
|
223
|
+
hostId: order.hostId,
|
|
224
|
+
orgId: order.orgId
|
|
225
|
+
}, storeAddress ? {
|
|
226
|
+
storeAddressEntered: {
|
|
227
|
+
city: storeAddress.city,
|
|
228
|
+
state: (_storeAddress_state = storeAddress.state) != null ? _storeAddress_state : null,
|
|
229
|
+
country: storeAddress.country
|
|
230
|
+
}
|
|
231
|
+
} : {}), orderId);
|
|
232
|
+
return res.status(200).json({
|
|
233
|
+
ok: true,
|
|
234
|
+
readerId,
|
|
235
|
+
storeAddressSaved: Boolean(storeAddress),
|
|
236
|
+
order: toAttachView(orderId, order)
|
|
237
|
+
});
|
|
238
|
+
} catch (error) {
|
|
239
|
+
if (error instanceof readers.PosHardwareReaderRefusal) {
|
|
240
|
+
return res.status(error.status).json(_extends({
|
|
241
|
+
error: error.message
|
|
242
|
+
}, error.reason ? {
|
|
243
|
+
reason: error.reason
|
|
244
|
+
} : {}));
|
|
245
|
+
}
|
|
246
|
+
throw error;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
case 'attach':
|
|
250
|
+
case 'detach':
|
|
251
|
+
{
|
|
252
|
+
if (!posIdempotencyKey(req)) return res.status(400).json({
|
|
253
|
+
error: 'Missing Idempotency-Key'
|
|
254
|
+
});
|
|
255
|
+
const attach = await import("./pos-hardware-attach.js");
|
|
256
|
+
try {
|
|
257
|
+
var _body_buyer;
|
|
258
|
+
if (action === 'detach') {
|
|
259
|
+
var _body_orderId1;
|
|
260
|
+
const orderId = String((_body_orderId1 = body['orderId']) != null ? _body_orderId1 : '');
|
|
261
|
+
const { order } = await attach.detachPosHardwareSale({
|
|
262
|
+
config,
|
|
263
|
+
orderId
|
|
264
|
+
});
|
|
265
|
+
await audit(staff, 'pos-hardware-sale-detach', {
|
|
266
|
+
orderId
|
|
267
|
+
}, orderId);
|
|
268
|
+
return res.status(200).json({
|
|
269
|
+
ok: true,
|
|
270
|
+
order: toAttachView(orderId, order)
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
const buyer = await attach.checkHardwareBuyer((_body_buyer = body['buyer']) != null ? _body_buyer : {});
|
|
274
|
+
const outcome = await attach.attachPosHardwareSale({
|
|
275
|
+
config,
|
|
276
|
+
buyer,
|
|
277
|
+
attachedBy: staff.uid,
|
|
278
|
+
registerOrderId: typeof body['registerOrderId'] === 'string' ? body['registerOrderId'] : null,
|
|
279
|
+
orderId: typeof body['orderId'] === 'string' ? body['orderId'] : null
|
|
280
|
+
});
|
|
281
|
+
const target = outcome.outcome === 'waiting' ? null : outcome.orderId;
|
|
282
|
+
await audit(staff, 'pos-hardware-sale-attach', _extends({
|
|
283
|
+
outcome: outcome.outcome,
|
|
284
|
+
uid: buyer.uid,
|
|
285
|
+
orgId: buyer.orgId,
|
|
286
|
+
hostId: buyer.hostId,
|
|
287
|
+
email: buyer.uid ? null : maskEmailAddress(buyer.email)
|
|
288
|
+
}, outcome.outcome === 'waiting' ? {
|
|
289
|
+
registerOrderId: outcome.registerOrderId
|
|
290
|
+
} : {}), target);
|
|
291
|
+
return res.status(200).json(outcome.outcome === 'waiting' ? {
|
|
292
|
+
outcome: 'waiting'
|
|
293
|
+
} : {
|
|
294
|
+
outcome: outcome.outcome,
|
|
295
|
+
order: toAttachView(outcome.orderId, outcome.order)
|
|
296
|
+
});
|
|
297
|
+
} catch (error) {
|
|
298
|
+
if (error instanceof attach.PosHardwareAttachRefusal) {
|
|
299
|
+
return res.status(error.status).json({
|
|
300
|
+
error: error.message
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
throw error;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
default:
|
|
307
|
+
return res.status(400).json({
|
|
308
|
+
error: 'Unknown action'
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
} catch (error) {
|
|
312
|
+
console.error('[pos-hardware-sale]', action, error);
|
|
313
|
+
return res.status(500).json({
|
|
314
|
+
error: 'The card reader sale could not answer'
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
/**
|
|
319
|
+
* A sale on the To attach list, as the register shows it: what was sold and
|
|
320
|
+
* when, the register order it came from, and what is known of the buyer —
|
|
321
|
+
* the receipt address, or the address or account a register user gave.
|
|
322
|
+
*/ export function toAttachView(id, order) {
|
|
323
|
+
var _ref, _ref1, _order_lines, _order_totalCents, _order_createdAtMs, _order_contactEmail, _order_units, _order_units1, _order_units2;
|
|
324
|
+
var _order_posSale, _order_posSale1, _order_posSale2, _order_posSale3, _order_attachment, _order_attachment1, _order_attachment2, _order_attachment3, _order_attachment4;
|
|
325
|
+
return {
|
|
326
|
+
id,
|
|
327
|
+
number: posHardwareOrderNumber(id),
|
|
328
|
+
registerOrderId: (_ref = (_order_posSale = order.posSale) == null ? void 0 : _order_posSale.orderId) != null ? _ref : null,
|
|
329
|
+
registerNumber: (_ref1 = (_order_posSale1 = order.posSale) == null ? void 0 : _order_posSale1.number) != null ? _ref1 : null,
|
|
330
|
+
kiosk: ((_order_posSale2 = order.posSale) == null ? void 0 : _order_posSale2.kiosk) === true,
|
|
331
|
+
offline: ((_order_posSale3 = order.posSale) == null ? void 0 : _order_posSale3.offline) === true,
|
|
332
|
+
lines: ((_order_lines = order.lines) != null ? _order_lines : []).map((line)=>({
|
|
333
|
+
sku: line.sku,
|
|
334
|
+
name: line.name,
|
|
335
|
+
quantity: line.quantity
|
|
336
|
+
})),
|
|
337
|
+
totalCents: (_order_totalCents = order.totalCents) != null ? _order_totalCents : 0,
|
|
338
|
+
createdAtMs: (_order_createdAtMs = order.createdAtMs) != null ? _order_createdAtMs : 0,
|
|
339
|
+
// The buyer's address in full, as the lookup shows it (AGL-4038): the
|
|
340
|
+
// account's, a receipt's, or one typed for a buyer with no account.
|
|
341
|
+
contactEmail: (_order_contactEmail = order.contactEmail) != null ? _order_contactEmail : null,
|
|
342
|
+
attached: ((_order_attachment = order.attachment) == null ? void 0 : _order_attachment.state) === 'attached',
|
|
343
|
+
/** Attached with the buyer's store chosen: a reader can be registered to it here. */ storeChosen: ((_order_attachment1 = order.attachment) == null ? void 0 : _order_attachment1.state) === 'attached' && Boolean(order.hostId),
|
|
344
|
+
/** Readers on the sale, and how many have a serial or are set up. */ readers: ((_order_units = order.units) != null ? _order_units : []).length,
|
|
345
|
+
serialsTaken: ((_order_units1 = order.units) != null ? _order_units1 : []).filter((unit)=>unit.serialNumber).length,
|
|
346
|
+
readersSetUp: ((_order_units2 = order.units) != null ? _order_units2 : []).filter((unit)=>unit.readerId).length,
|
|
347
|
+
/** A buyer with an account and no workspace yet. */ awaitingWorkspace: Boolean((_order_attachment2 = order.attachment) == null ? void 0 : _order_attachment2.uid),
|
|
348
|
+
/** A buyer with no account yet, invited to sign up. */ invited: Boolean(((_order_attachment3 = order.attachment) == null ? void 0 : _order_attachment3.email) && !((_order_attachment4 = order.attachment) == null ? void 0 : _order_attachment4.uid))
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* One row of the platform's audit log for a lookup or an attachment: who on
|
|
353
|
+
* the selling store did it, and what — never the buyer's full address.
|
|
354
|
+
*/ async function audit(staff, action, after, orderId = null) {
|
|
355
|
+
const firestore = firebaseAdmin.app().firestore();
|
|
356
|
+
await addAdminAudit(firestore, {
|
|
357
|
+
action,
|
|
358
|
+
actorUid: staff.uid,
|
|
359
|
+
actorEmail: null,
|
|
360
|
+
scope: 'posHardwareSale',
|
|
361
|
+
target: orderId ? `posHardwareSales/${orderId}` : `hosts/${staff.hostId}`,
|
|
362
|
+
orgId: staff.orgId,
|
|
363
|
+
before: null,
|
|
364
|
+
after,
|
|
365
|
+
at: firebaseAdmin.firestore.FieldValue.serverTimestamp()
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
//# sourceMappingURL=pos-hardware-sale.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/server/pos-hardware-sale.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { PluginApiHandler } from '@aglyn/aglyn/server'\nimport { consumeRateLimit, firebaseAdmin } from '@aglyn/tenant-data-admin'\nimport { addAdminAudit } from '@aglyn/tenant-data-admin/server/admin-audit-write'\nimport { maskEmailAddress } from '@aglyn/tenant-data-admin/server/admin-audit'\nimport { POS_HARDWARE_SKUS, type PosHardwareOrder } from '../model/pos-hardware'\nimport type { PosPermission } from '../model/plugin-permissions'\nimport { authorizePosStaff, posIdempotencyKey, posRequestBody, type PosStaff } from './pos-auth'\nimport { isPosHardwareSellerStore, posHardwareInPersonConfig, posHardwareOrderNumber } from './pos-hardware'\n\n/** How many lookups one register user makes in ten minutes. */\nexport const BUYER_LOOKUPS_PER_WINDOW = 30\nconst LOOKUP_WINDOW_MS = 10 * 60 * 1000\n\n/*==========================================\n * `POST /api/commerce/pos-hardware-sale` (AGL-4038): selling a card reader in\n * person, at the platform's own store's register, to someone who is not a\n * member of it.\n *\n * status whether this store is the platform's hardware seller, and the\n * hardware items a product of it may be — the product editor's\n * \"Point of sale hardware\" choice is shown only where it is.\n * pending the \"To attach\" list: sales of hardware nobody has said whose\n * they are yet (a kiosk or offline sale, a buyer with no account\n * or no workspace yet), newest first. Records any paid sale still\n * waiting to be recorded first (`sweepInPersonPosHardwareSales`).\n * find look the buyer up across the platform by exact email, a\n * person's name or a workspace's name (`pos-hardware-buyer-lookup.ts`):\n * the least that picks the right person, their address in full.\n * Rate-limited per register user and written to the platform's\n * audit log (the address masked there), every time.\n * attach say whose a sale is — by the register sale or the To attach\n * entry — as an account and workspace (and store), an account\n * with no workspace yet, or the address of someone with no\n * account, who is invited to sign up (`pos-hardware-attach.ts`).\n * Idempotency-Key required; audited.\n * detach put an attached sale back on the To attach list. Audited.\n * serials the serial numbers of the sale's readers, scanned or typed at\n * the sale, so the order sets itself up when the buyer registers\n * them (`pos-hardware-readers.ts`).\n * terms the terms of sale the buyer accepts before paying (Terms\n * 4.26–4.32 in short, with the link), and `terms-status` whether\n * they have, for the register waiting on its display.\n * accept-terms the buyer accepted on the register tablet handed to them;\n * `terms-on-display` notes who is putting them on the customer\n * display, before the register shows them there (`pos-hardware-terms.ts`).\n * register-at-booth register a reader to the buyer's chosen store by the\n * code it shows, while they are there, with the store's address\n * when it has no reader Location yet (`address`; refused with\n * `reason: 'needs-address'` without one). Idempotency-Key\n * required; audited.\n *\n * `status` is asked of whoever works the register; everything else needs\n * \"Sell at the register\" (`posSell`) on the seller store, since it is part\n * of ringing a sale there, and answers 404 on any other store.\n *\n * Gated like the register (`authorizePosStaff`, on a plan with POS). Every\n * answer is about THIS store: on any store but the configured seller it says\n * `seller: false` and nothing else, so no other workspace learns the\n * platform's configuration or is shown a control it cannot use.\n *=========================================*/\n\nexport const posHardwareSaleHandler: PluginApiHandler = async (req, res) => {\n if (req.method !== 'POST') return res.status(405).json({ error: 'Method not allowed' })\n const body = posRequestBody(req)\n const hostId = String(body['hostId'] ?? '')\n const action = String(body['action'] ?? '')\n const permission: PosPermission | undefined = action === 'status' ? undefined : 'posSell'\n const gate = await authorizePosStaff(req, hostId, permission)\n if ('error' in gate) return res.status(gate.status).json({ error: gate.error })\n const staff = gate.staff\n const config = posHardwareInPersonConfig()\n const seller = isPosHardwareSellerStore(config, staff.hostId, staff.orgId)\n try {\n if (action === 'status') {\n if (!seller) return res.status(200).json({ seller: false })\n return res.status(200).json({\n seller: true,\n items: POS_HARDWARE_SKUS.map((sku) => ({ sku: sku.id, name: sku.displayName, kind: sku.kind })),\n })\n }\n if (!seller) return res.status(404).json({ error: 'Card reader sales are not available on this store.' })\n const inPerson = await import('./pos-hardware-in-person')\n switch (action) {\n case 'pending': {\n await inPerson.sweepInPersonPosHardwareSales(config)\n const pending = await inPerson.pendingInPersonPosHardwareOrders(config)\n return res.status(200).json({ orders: pending.map(({ id, order }) => toAttachView(id, order)) })\n }\n case 'find': {\n const query = String(body['query'] ?? '').trim().slice(0, 120)\n if (query.length < 2) return res.status(400).json({ error: 'Type at least two letters, or an email address.' })\n const rate = await consumeRateLimit(`pos-hardware-lookup:${staff.uid}`, {\n limit: BUYER_LOOKUPS_PER_WINDOW,\n windowMs: LOOKUP_WINDOW_MS,\n })\n if (!rate.allowed) return res.status(429).json({ error: 'Too many lookups. Try again in a few minutes.' })\n const found = await (await import('./pos-hardware-buyer-lookup')).findHardwareBuyers(query)\n await audit(staff, 'pos-hardware-buyer-lookup', {\n // The audit log keeps an address masked; a name as typed. The\n // register itself is answered in full.\n query: found.kind === 'email' ? maskEmailAddress(query) : query,\n kind: found.kind,\n matched: [\n ...found.people.map((person) => person.uid),\n ...found.workspaces.map((workspace) => `org:${workspace.orgId}`),\n ],\n })\n return res.status(200).json(found)\n }\n case 'terms':\n case 'terms-status':\n case 'terms-on-display':\n case 'accept-terms': {\n const terms = await import('./pos-hardware-terms')\n const registerOrderId = String(body['registerOrderId'] ?? '')\n try {\n if (action === 'terms') return res.status(200).json(terms.posHardwareTermsView())\n if (action === 'terms-status') {\n return res.status(200).json(await terms.posHardwareTermsStatus(config, registerOrderId))\n }\n if (action === 'terms-on-display') {\n await terms.requestPosHardwareTermsOnDisplay({ config, registerOrderId, uid: staff.uid })\n return res.status(200).json({ ok: true })\n }\n const device = terms.posHardwareTermsDevice(req.headers as Record<string, unknown>)\n const acceptance = await terms.recordPosHardwareTermsAcceptance({\n config,\n registerOrderId,\n method: 'tablet',\n staffUid: staff.uid,\n ...device,\n })\n await audit(staff, 'pos-hardware-terms-accepted', { method: acceptance.method, version: acceptance.version, registerOrderId }, null)\n return res.status(200).json({ ok: true, acceptance })\n } catch (error) {\n if (error instanceof terms.PosHardwareTermsRefusal) {\n return res.status(error.status).json({ error: error.message })\n }\n throw error\n }\n }\n case 'serials':\n case 'register-at-booth': {\n const readers = await import('./pos-hardware-readers')\n try {\n if (action === 'serials') {\n const saved = await readers.recordPosHardwareSerials({\n config,\n registerOrderId: typeof body['registerOrderId'] === 'string' ? body['registerOrderId'] : null,\n orderId: typeof body['orderId'] === 'string' ? body['orderId'] : null,\n serials: body['serials'],\n })\n return res.status(200).json({ ok: true, serials: saved.serials, recorded: saved.recorded })\n }\n if (!posIdempotencyKey(req)) return res.status(400).json({ error: 'Missing Idempotency-Key' })\n const registerOrderId = typeof body['registerOrderId'] === 'string' ? body['registerOrderId'] : ''\n const orderId = registerOrderId\n ? (await import('./pos-hardware')).posHardwareInPersonOrderId(config.sellerHostId, registerOrderId)\n : String(body['orderId'] ?? '')\n const { order, readerId, storeAddress } = await readers.registerPosHardwareAtBooth({\n config,\n orderId,\n registrationCode: body['registrationCode'],\n label: body['label'],\n address: body['address'],\n uid: staff.uid,\n })\n await audit(\n staff,\n 'pos-hardware-register-at-booth',\n {\n readerId,\n hostId: order.hostId,\n orgId: order.orgId,\n // That the buyer's store address was typed here, and where:\n // the store's reader Location was made from it. The street\n // stays with the store, never in the audit log.\n ...(storeAddress\n ? {\n storeAddressEntered: {\n city: storeAddress.city,\n state: storeAddress.state ?? null,\n country: storeAddress.country,\n },\n }\n : {}),\n },\n orderId,\n )\n return res.status(200).json({\n ok: true,\n readerId,\n storeAddressSaved: Boolean(storeAddress),\n order: toAttachView(orderId, order),\n })\n } catch (error) {\n if (error instanceof readers.PosHardwareReaderRefusal) {\n return res\n .status(error.status)\n .json({ error: error.message, ...(error.reason ? { reason: error.reason } : {}) })\n }\n throw error\n }\n }\n case 'attach':\n case 'detach': {\n if (!posIdempotencyKey(req)) return res.status(400).json({ error: 'Missing Idempotency-Key' })\n const attach = await import('./pos-hardware-attach')\n try {\n if (action === 'detach') {\n const orderId = String(body['orderId'] ?? '')\n const { order } = await attach.detachPosHardwareSale({ config, orderId })\n await audit(staff, 'pos-hardware-sale-detach', { orderId }, orderId)\n return res.status(200).json({ ok: true, order: toAttachView(orderId, order) })\n }\n const buyer = await attach.checkHardwareBuyer((body['buyer'] ?? {}) as Record<string, unknown>)\n const outcome = await attach.attachPosHardwareSale({\n config,\n buyer,\n attachedBy: staff.uid,\n registerOrderId: typeof body['registerOrderId'] === 'string' ? body['registerOrderId'] : null,\n orderId: typeof body['orderId'] === 'string' ? body['orderId'] : null,\n })\n const target = outcome.outcome === 'waiting' ? null : outcome.orderId\n await audit(\n staff,\n 'pos-hardware-sale-attach',\n {\n outcome: outcome.outcome,\n uid: buyer.uid,\n orgId: buyer.orgId,\n hostId: buyer.hostId,\n email: buyer.uid ? null : maskEmailAddress(buyer.email),\n ...(outcome.outcome === 'waiting' ? { registerOrderId: outcome.registerOrderId } : {}),\n },\n target,\n )\n return res.status(200).json(\n outcome.outcome === 'waiting'\n ? { outcome: 'waiting' }\n : { outcome: outcome.outcome, order: toAttachView(outcome.orderId, outcome.order) },\n )\n } catch (error) {\n if (error instanceof attach.PosHardwareAttachRefusal) {\n return res.status(error.status).json({ error: error.message })\n }\n throw error\n }\n }\n default:\n return res.status(400).json({ error: 'Unknown action' })\n }\n } catch (error) {\n console.error('[pos-hardware-sale]', action, error)\n return res.status(500).json({ error: 'The card reader sale could not answer' })\n }\n}\n\n/**\n * A sale on the To attach list, as the register shows it: what was sold and\n * when, the register order it came from, and what is known of the buyer —\n * the receipt address, or the address or account a register user gave.\n */\nexport function toAttachView(id: string, order: PosHardwareOrder) {\n return {\n id,\n number: posHardwareOrderNumber(id),\n registerOrderId: order.posSale?.orderId ?? null,\n registerNumber: order.posSale?.number ?? null,\n kiosk: order.posSale?.kiosk === true,\n offline: order.posSale?.offline === true,\n lines: (order.lines ?? []).map((line) => ({ sku: line.sku, name: line.name, quantity: line.quantity })),\n totalCents: order.totalCents ?? 0,\n createdAtMs: order.createdAtMs ?? 0,\n // The buyer's address in full, as the lookup shows it (AGL-4038): the\n // account's, a receipt's, or one typed for a buyer with no account.\n contactEmail: order.contactEmail ?? null,\n attached: order.attachment?.state === 'attached',\n /** Attached with the buyer's store chosen: a reader can be registered to it here. */\n storeChosen: order.attachment?.state === 'attached' && Boolean(order.hostId),\n /** Readers on the sale, and how many have a serial or are set up. */\n readers: (order.units ?? []).length,\n serialsTaken: (order.units ?? []).filter((unit) => unit.serialNumber).length,\n readersSetUp: (order.units ?? []).filter((unit) => unit.readerId).length,\n /** A buyer with an account and no workspace yet. */\n awaitingWorkspace: Boolean(order.attachment?.uid),\n /** A buyer with no account yet, invited to sign up. */\n invited: Boolean(order.attachment?.email && !order.attachment?.uid),\n }\n}\n\nexport type ToAttachView = ReturnType<typeof toAttachView>\n\n/**\n * One row of the platform's audit log for a lookup or an attachment: who on\n * the selling store did it, and what — never the buyer's full address.\n */\nasync function audit(\n staff: PosStaff,\n action: string,\n after: Record<string, unknown>,\n orderId: string | null = null,\n): Promise<void> {\n const firestore = firebaseAdmin.app().firestore()\n await addAdminAudit(firestore, {\n action,\n actorUid: staff.uid,\n actorEmail: null,\n scope: 'posHardwareSale',\n target: orderId ? `posHardwareSales/${orderId}` : `hosts/${staff.hostId}`,\n orgId: staff.orgId,\n before: null,\n after,\n at: firebaseAdmin.firestore.FieldValue.serverTimestamp(),\n })\n}\n"],"names":["consumeRateLimit","firebaseAdmin","addAdminAudit","maskEmailAddress","POS_HARDWARE_SKUS","authorizePosStaff","posIdempotencyKey","posRequestBody","isPosHardwareSellerStore","posHardwareInPersonConfig","posHardwareOrderNumber","BUYER_LOOKUPS_PER_WINDOW","LOOKUP_WINDOW_MS","posHardwareSaleHandler","req","res","body","method","status","json","error","hostId","String","action","permission","undefined","gate","staff","config","seller","orgId","items","map","sku","id","name","displayName","kind","inPerson","sweepInPersonPosHardwareSales","pending","pendingInPersonPosHardwareOrders","orders","order","toAttachView","query","trim","slice","length","rate","uid","limit","windowMs","allowed","found","findHardwareBuyers","audit","matched","people","person","workspaces","workspace","terms","registerOrderId","posHardwareTermsView","posHardwareTermsStatus","requestPosHardwareTermsOnDisplay","ok","device","posHardwareTermsDevice","headers","acceptance","recordPosHardwareTermsAcceptance","staffUid","version","PosHardwareTermsRefusal","message","readers","storeAddress","saved","recordPosHardwareSerials","orderId","serials","recorded","posHardwareInPersonOrderId","sellerHostId","readerId","registerPosHardwareAtBooth","registrationCode","label","address","storeAddressEntered","city","state","country","storeAddressSaved","Boolean","PosHardwareReaderRefusal","reason","attach","detachPosHardwareSale","buyer","checkHardwareBuyer","outcome","attachPosHardwareSale","attachedBy","target","email","PosHardwareAttachRefusal","console","number","posSale","registerNumber","kiosk","offline","lines","line","quantity","totalCents","createdAtMs","contactEmail","attached","attachment","storeChosen","units","serialsTaken","filter","unit","serialNumber","readersSetUp","awaitingWorkspace","invited","after","firestore","app","actorUid","actorEmail","scope","before","at","FieldValue","serverTimestamp"],"mappings":"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"}
|
|
@@ -0,0 +1,99 @@
|
|
|
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 { TaxReturnFiling, TaxReturnFinding, TaxReturnOperatorSalesPart, TaxReturnSourceAnswer, TaxReturnSourceRequest } from '@aglyn/aglyn/plugin-manager/plugin-tax-return-sources';
|
|
18
|
+
import { type PosHardwareTaxJurisdiction, type PosHardwareTaxRowInput, type PosHardwareTaxSummary } from '../model/pos-hardware-tax-summary';
|
|
19
|
+
/** The section's id, unique on the return. */
|
|
20
|
+
export declare const POS_HARDWARE_TAX_SECTION_ID = "posHardware";
|
|
21
|
+
/** The part the shop's online sales fold into the filing figures under. */
|
|
22
|
+
export declare const POS_HARDWARE_SHOP_PART_ID = "posHardwareShop";
|
|
23
|
+
/** The part an in-person sale at a store that is not the operator's own folds in under. */
|
|
24
|
+
export declare const POS_HARDWARE_IN_PERSON_PART_ID = "posHardwareInPerson";
|
|
25
|
+
/** Where an order is folded into the filing figures. */
|
|
26
|
+
export type PosHardwareFoldedAs = 'shop' | 'store register sale' | 'in-person record';
|
|
27
|
+
/** Who decides where a record folds in: the operator's own stores, by site id. */
|
|
28
|
+
export interface PosHardwareFoldOptions {
|
|
29
|
+
/** The sites of the operator's own stores, whose register sales the own-stores section folds in. */
|
|
30
|
+
ownHostIds?: ReadonlySet<string>;
|
|
31
|
+
}
|
|
32
|
+
/** Where one retained sale record folds into the filing figures. See the module note. */
|
|
33
|
+
export declare function posHardwareFoldedAs(row: Pick<PosHardwareTaxRowInput, 'source' | 'posHostId'>, options?: PosHardwareFoldOptions): PosHardwareFoldedAs;
|
|
34
|
+
/**
|
|
35
|
+
* The operator's own hardware sales the filing figures fold in from this
|
|
36
|
+
* section: the shop's online sales, and any in-person sale whose store is not
|
|
37
|
+
* the operator's own. Every figure is the summary's own math over that part's
|
|
38
|
+
* records, so the card and the figures cannot disagree.
|
|
39
|
+
*/
|
|
40
|
+
export declare function posHardwareOperatorSales(rows: readonly PosHardwareTaxRowInput[], period: {
|
|
41
|
+
start: Date;
|
|
42
|
+
end: Date;
|
|
43
|
+
}, options?: PosHardwareFoldOptions): TaxReturnOperatorSalesPart[];
|
|
44
|
+
/** One order as the working papers carry it: amounts and the region, no buyer. */
|
|
45
|
+
export interface PosHardwareTaxRow {
|
|
46
|
+
orderId: string;
|
|
47
|
+
paidAt: string | null;
|
|
48
|
+
status: string | null;
|
|
49
|
+
state: string | null;
|
|
50
|
+
country: string | null;
|
|
51
|
+
totalSalesCents: number;
|
|
52
|
+
taxableSalesCents: number | null;
|
|
53
|
+
taxCents: number;
|
|
54
|
+
refundedCents: number;
|
|
55
|
+
refundedAt: string | null;
|
|
56
|
+
/** How the order counts in this period. */
|
|
57
|
+
inPeriodAs: 'sale' | 'refund' | 'sale and refund';
|
|
58
|
+
/** Where it is folded into the filing figures. */
|
|
59
|
+
foldedAs: PosHardwareFoldedAs;
|
|
60
|
+
}
|
|
61
|
+
/** The filing jurisdiction's hardware figures, or zeros when none sold there. */
|
|
62
|
+
export declare function posHardwareFilingFigures(summary: PosHardwareTaxSummary, filing: TaxReturnFiling): PosHardwareTaxJurisdiction;
|
|
63
|
+
/** The section's findings. The platform raises the non-zero ones. */
|
|
64
|
+
export declare function posHardwareTaxFindings(summary: PosHardwareTaxSummary, filing: TaxReturnFiling, operatorSales?: readonly TaxReturnOperatorSalesPart[]): TaxReturnFinding[];
|
|
65
|
+
/** One ship-to state's row, ready to print. */
|
|
66
|
+
export interface PosHardwareJurisdictionRow {
|
|
67
|
+
jurisdiction: string;
|
|
68
|
+
isFilingJurisdiction: boolean;
|
|
69
|
+
orders: number;
|
|
70
|
+
totalSalesCents: number;
|
|
71
|
+
taxableSalesCents: number;
|
|
72
|
+
taxCollectedCents: number;
|
|
73
|
+
refundedOrders: number;
|
|
74
|
+
refundedSalesCents: number;
|
|
75
|
+
refundedTaxCents: number;
|
|
76
|
+
}
|
|
77
|
+
/** Every ship-to state, the filing jurisdiction first, then by sales. */
|
|
78
|
+
export declare function posHardwareJurisdictionRows(summary: PosHardwareTaxSummary, filing: TaxReturnFiling): PosHardwareJurisdictionRow[];
|
|
79
|
+
/**
|
|
80
|
+
* The hardware section for one period, from records already read. Pure, so
|
|
81
|
+
* the section a preparer reads can be proved from fixtures.
|
|
82
|
+
*/
|
|
83
|
+
export declare function posHardwareTaxReturnAnswer(read: {
|
|
84
|
+
rows: readonly PosHardwareTaxRowInput[];
|
|
85
|
+
truncated: boolean;
|
|
86
|
+
undatedRows: number;
|
|
87
|
+
}, request: TaxReturnSourceRequest, options?: PosHardwareFoldOptions): TaxReturnSourceAnswer;
|
|
88
|
+
/**
|
|
89
|
+
* Reads the period's hardware records and answers for them.
|
|
90
|
+
*
|
|
91
|
+
* Three range queries, because a record counts in a period two ways — paid
|
|
92
|
+
* in it, or refunded in it (by the stamp of the status that refunded it) —
|
|
93
|
+
* and a fourth, the honesty check: a range query cannot match a record whose
|
|
94
|
+
* `paidAtMs` is null, so those are counted over all of them and the platform
|
|
95
|
+
* blocks the return on any. Each is a single-field range, served by
|
|
96
|
+
* Firestore's automatic index. A query that reaches the row cap marks the
|
|
97
|
+
* section truncated, and the platform blocks on that too.
|
|
98
|
+
*/
|
|
99
|
+
export declare function readPosHardwareTaxReturn(request: TaxReturnSourceRequest, options?: PosHardwareFoldOptions): Promise<TaxReturnSourceAnswer>;
|