@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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/server/returns.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as Aglyn from '@aglyn/aglyn/server'\nimport { createResourceUid } from '@aglyn/aglyn/app-utils/create-resource-uid'\nimport type { PluginApiHandler, PluginApiRequest, PluginApiResponse } from '@aglyn/aglyn/server'\nimport {\n findUserByUidAcrossPools,\n firebaseAdmin,\n getOrgForHost,\n hostSendingIdentity,\n meterHostEmail,\n notifyHostManagers,\n renderHostEmailWithTokens,\n} from '@aglyn/tenant-data-admin'\nimport { hostConsoleUrl } from '@aglyn/tenant-data-admin/server/host-console-link'\nimport { isEmailConfigured, sendEmail } from '@aglyn/shared-util-email'\nimport * as CommerceModel from '../model'\nimport {\n RETURN_APPROVED_EVENT,\n RETURN_DECLINED_EVENT,\n RETURN_RECEIVED_EVENT,\n RETURN_REFUNDED_EVENT,\n RETURN_REQUESTED_EVENT,\n} from '../model/order-events'\nimport { raiseOrderEvent, stageOrderEvent } from './order-events'\nimport { orderStatusUrl, verifyOrderStatusToken } from './order-status-token'\nimport { readActiveMemberSession } from './membership'\nimport { resolveTrackedRestockLines } from './restock-flag'\nimport { refundHandler } from './refund'\n\n/**\n * Returns (RMA, AGL-3611): the buyer's door, the merchant's door, and the\n * writes behind both. The rules — what is returnable, the window, the state\n * machine, what a refund is worth — are the model's (`commerce-returns.ts`);\n * this is where they are re-asked under the write.\n *\n * EVERY WRITE IS A TRANSACTION that reads the return, the order and, when it\n * opens one, every return already on the order — so two requests for the last\n * unit cannot both be granted, and a stale console cannot approve a return a\n * colleague declined a moment ago.\n *\n * THE MONEY MOVES THROUGH THE ORDER'S REFUND ROUTE, never here. A return's\n * refund calls `refund.ts` with the merchant's own credentials and a key\n * derived from the return, so its gates (an admin of the whole workspace,\n * the over-refund cap, the open-dispute block, Stripe's idempotency) are the\n * ones every refund passes, and asking twice refunds once.\n *\n * STOCK COMES BACK WHEN THE PARCEL DOES. Receiving a return puts the units\n * the merchant chose back on the shelf, at the location they chose, with an\n * inventory adjustment row — the products hub's history shows it beside the\n * sale. A refund then answers the order's restock question with what the\n * return already did, so nobody is asked to restock the same units twice.\n */\n\ntype Firestore = FirebaseFirestore.Firestore\n\nconst hostRefFor = (firestore: Firestore, hostId: string) => firestore.collection('hosts').doc(hostId)\n\nconst isId = (value: string) => Boolean(value) && value.length <= 200 && !/^__.*__$/.test(value) && !value.includes('/')\n\n/** The store's settings document and what the return emails need from the host. */\nasync function readStore(firestore: Firestore, hostId: string) {\n const hostRef = hostRefFor(firestore, hostId)\n const [host, store] = await Promise.all([\n hostRef.get().catch(() => null),\n hostRef.collection('settings').doc('store').get().catch(() => null),\n ])\n const settings = (store?.data() ?? {}) as Record<string, unknown>\n return {\n host: (host?.data() ?? {}) as Record<string, unknown>,\n returnSettings: CommerceModel.readReturnSettings(settings['returns']),\n currency: String(settings['currency'] ?? 'USD').toUpperCase(),\n }\n}\n\nfunction money(cents: number, currency: string): string {\n try {\n return new Intl.NumberFormat('en-US', { style: 'currency', currency }).format(cents / 100)\n } catch {\n return `$${(cents / 100).toFixed(2)}`\n }\n}\n\n/** The return as an event carries it. */\nfunction returnEventView(id: string, entry: CommerceModel.HostReturn) {\n return {\n id,\n status: entry.status,\n lines: entry.lines.map((line) => ({ ...line })),\n refundCents: entry.refundCents ?? null,\n restock: entry.restock ? entry.restock.lines.map((line) => ({ ...line })) : null,\n }\n}\n\n/** \"1× House Blend — Arrived damaged\", one per line. */\nfunction returnItemsText(order: CommerceModel.HostOrder, entry: Pick<CommerceModel.HostReturn, 'lines'>): string {\n return entry.lines\n .map(\n (line) =>\n `${line.quantity}× ${order.lineItems?.[line.lineItemId]?.name ?? `line ${line.lineItemId}`} — ${\n CommerceModel.RETURN_REASON_LABELS[line.reason] ?? line.reason\n }`,\n )\n .join('\\n')\n}\n\nexport type OpenReturnOutcome =\n | { outcome: 'created'; returnId: string; entry: CommerceModel.HostReturn; order: CommerceModel.HostOrder }\n | { outcome: 'refused'; message: string }\n | { outcome: 'no_such_order' }\n\n/**\n * Opens a return. A buyer's starts `requested`; a merchant's starts\n * `approved`, since the merchant asking is the approval.\n */\nexport async function openReturn(request: {\n hostId: string\n orderId: string\n lines: ReadonlyArray<{ lineItemId: unknown; quantity: unknown; reason: unknown }>\n note?: string\n by: 'buyer' | 'merchant'\n now?: number\n}): Promise<OpenReturnOutcome> {\n const firestore = firebaseAdmin.app().firestore()\n const hostRef = hostRefFor(firestore, request.hostId)\n const orderRef = hostRef.collection('orders').doc(request.orderId)\n const { returnSettings } = await readStore(firestore, request.hostId)\n const now = request.now ?? Date.now()\n const note = String(request.note ?? '').trim().slice(0, CommerceModel.RETURN_NOTE_MAX)\n return firestore.runTransaction(async (transaction): Promise<OpenReturnOutcome> => {\n const orderSnapshot = await transaction.get(orderRef)\n if (!orderSnapshot.exists) return { outcome: 'no_such_order' }\n const existing = await transaction.get(\n hostRef.collection('returns').where('orderId', '==', request.orderId),\n )\n const order = CommerceModel.liftLegacyOrder((orderSnapshot.data() ?? {}) as never)\n const verdict = CommerceModel.validateReturnRequest({\n order,\n existing: existing.docs.map((entry) => entry.data() as CommerceModel.HostReturn),\n settings: returnSettings,\n lines: request.lines,\n by: request.by,\n now,\n })\n if (!('lines' in verdict)) {\n return { outcome: 'refused', message: CommerceModel.describeReturnRequestProblem(verdict) }\n }\n const status: CommerceModel.ReturnStatus = request.by === 'merchant' ? 'approved' : 'requested'\n const entry: CommerceModel.HostReturn = {\n orderId: request.orderId,\n orderNumber: CommerceModel.returnOrderNumber(order, request.orderId),\n customerEmail: order.customerEmail ?? null,\n customerName: order.customerName ?? null,\n lines: verdict.lines.map((line) => ({\n ...line,\n name: String(order.lineItems?.[line.lineItemId]?.name ?? '').slice(0, 200),\n })),\n status,\n requestedBy: request.by,\n ...(note ? (request.by === 'buyer' ? { customerNote: note } : { merchantNote: note }) : {}),\n timeline: [\n {\n atMs: now,\n event: status,\n detail: `${request.by === 'buyer' ? 'Requested by the buyer' : 'Opened by the store'}: ${CommerceModel.describeReturnLines(order, verdict.lines)}`,\n },\n ],\n createdAtMs: now,\n updatedAtMs: now,\n }\n const returnRef = hostRef.collection('returns').doc(createResourceUid())\n transaction.create(returnRef, entry)\n const orderPatch = {\n timeline: CommerceModel.appendOrderEvent(\n order,\n 'return-requested',\n CommerceModel.describeReturnLines(order, verdict.lines),\n now,\n ),\n }\n transaction.update(orderRef, orderPatch)\n stageOrderEvent(transaction, RETURN_REQUESTED_EVENT, {\n hostId: request.hostId,\n orderId: request.orderId,\n key: `return:${returnRef.id}`,\n order: { ...orderSnapshot.data(), ...orderPatch },\n extra: { return: returnEventView(returnRef.id, entry) },\n })\n // The store opening a return is its approval.\n if (status === 'approved') {\n stageOrderEvent(transaction, RETURN_APPROVED_EVENT, {\n hostId: request.hostId,\n orderId: request.orderId,\n key: `return-approved:${returnRef.id}`,\n order: { ...orderSnapshot.data(), ...orderPatch },\n extra: { return: returnEventView(returnRef.id, entry) },\n })\n }\n return { outcome: 'created', returnId: returnRef.id, entry, order }\n })\n}\n\nexport type ReturnAction = 'approve' | 'decline' | 'close' | 'note' | 'attach-label'\n\nexport type ChangeReturnOutcome =\n | { outcome: 'changed'; entry: CommerceModel.HostReturn; order: CommerceModel.HostOrder | null }\n | { outcome: 'already'; entry: CommerceModel.HostReturn }\n | { outcome: 'refused'; message: string }\n | { outcome: 'no_such_return' }\n\nconst ACTION_TARGET: Partial<Record<ReturnAction, CommerceModel.ReturnStatus>> = {\n approve: 'approved',\n decline: 'declined',\n close: 'closed',\n}\n\n/**\n * Approve, decline, close, a note, or a return label — the writes that move\n * no stock and no money. The transition is re-asked under the write.\n */\nexport async function changeReturn(request: {\n hostId: string\n returnId: string\n action: ReturnAction\n merchantNote?: string\n label?: { carrier: string; trackingNumber: string; labelUrl: string; trackingUrl?: string }\n now?: number\n}): Promise<ChangeReturnOutcome> {\n const firestore = firebaseAdmin.app().firestore()\n const hostRef = hostRefFor(firestore, request.hostId)\n const returnRef = hostRef.collection('returns').doc(request.returnId)\n const now = request.now ?? Date.now()\n const note = request.merchantNote === undefined ? undefined : String(request.merchantNote).trim().slice(0, CommerceModel.RETURN_NOTE_MAX)\n return firestore.runTransaction(async (transaction): Promise<ChangeReturnOutcome> => {\n const snapshot = await transaction.get(returnRef)\n if (!snapshot.exists) return { outcome: 'no_such_return' }\n const entry = snapshot.data() as CommerceModel.HostReturn\n const orderSnapshot = await transaction.get(hostRef.collection('orders').doc(entry.orderId))\n const order = orderSnapshot.exists ? CommerceModel.liftLegacyOrder((orderSnapshot.data() ?? {}) as never) : null\n const target = ACTION_TARGET[request.action]\n let patch: Partial<CommerceModel.HostReturn>\n if (target) {\n if (entry.status === target) return { outcome: 'already', entry }\n if (!CommerceModel.canTransitionReturn(entry.status, target)) {\n return {\n outcome: 'refused',\n message: `A return that is ${CommerceModel.RETURN_STATUS_LABELS[entry.status].toLowerCase()} cannot be ${CommerceModel.RETURN_STATUS_LABELS[target].toLowerCase()}`,\n }\n }\n patch = {\n status: target,\n ...(note !== undefined && note ? { merchantNote: note } : {}),\n timeline: CommerceModel.appendReturnEvent(entry, target, note || undefined, now),\n }\n } else if (request.action === 'attach-label') {\n const label = request.label\n if (!label?.labelUrl || !/^https:\\/\\//i.test(label.labelUrl)) {\n return { outcome: 'refused', message: 'A return label needs an https link' }\n }\n if (!CommerceModel.returnIsOpen(entry) || entry.status === 'refunded') {\n return { outcome: 'refused', message: 'This return is finished; a label can no longer be attached' }\n }\n const carrier = String(label.carrier ?? '').trim().slice(0, 40)\n const trackingNumber = String(label.trackingNumber ?? '').trim().slice(0, 60)\n const trackingUrl =\n (label.trackingUrl && /^https:\\/\\//i.test(label.trackingUrl) ? label.trackingUrl : null) ??\n CommerceModel.trackingUrlFor(carrier, trackingNumber)\n patch = {\n returnLabel: {\n carrier,\n trackingNumber,\n labelUrl: String(label.labelUrl).slice(0, 2048),\n ...(trackingUrl ? { trackingUrl } : {}),\n attachedAtMs: now,\n },\n timeline: CommerceModel.appendReturnEvent(entry, 'label', `${carrier} ${trackingNumber}`.trim() || 'Return label attached', now),\n }\n } else {\n patch = {\n merchantNote: note ?? '',\n timeline: CommerceModel.appendReturnEvent(entry, 'note', note || 'Note cleared', now),\n }\n }\n transaction.update(returnRef, { ...patch, updatedAtMs: now })\n const changed = { ...entry, ...patch, updatedAtMs: now }\n const event = target === 'approved' ? RETURN_APPROVED_EVENT : target === 'declined' ? RETURN_DECLINED_EVENT : null\n if (event && orderSnapshot.exists) {\n stageOrderEvent(transaction, event, {\n hostId: request.hostId,\n orderId: entry.orderId,\n key: `return-${target}:${request.returnId}`,\n order: orderSnapshot.data() ?? {},\n extra: { return: returnEventView(request.returnId, changed) },\n })\n }\n return { outcome: 'changed', entry: changed, order }\n })\n}\n\n/**\n * The parcel arrived: the return is `received`, and the units the merchant\n * chose go back on the shelf, at the location they chose. A unit the sale\n * never took off a tracked count (an untracked variant, a deleted product)\n * has nothing to go back to and is left out, as a cancellation leaves it.\n */\nexport async function receiveReturn(request: {\n hostId: string\n returnId: string\n restock: ReadonlyArray<{ lineItemId: unknown; quantity: unknown }>\n locationId?: string\n now?: number\n}): Promise<ChangeReturnOutcome & { units?: number }> {\n const firestore = firebaseAdmin.app().firestore()\n const hostRef = hostRefFor(firestore, request.hostId)\n const returnRef = hostRef.collection('returns').doc(request.returnId)\n const now = request.now ?? Date.now()\n const locationId = String(request.locationId ?? '').trim().slice(0, 100)\n return firestore.runTransaction(async (transaction) => {\n const snapshot = await transaction.get(returnRef)\n if (!snapshot.exists) return { outcome: 'no_such_return' as const }\n const entry = snapshot.data() as CommerceModel.HostReturn\n if (entry.status === 'received' || entry.restock) return { outcome: 'already' as const, entry }\n if (!CommerceModel.canTransitionReturn(entry.status, 'received')) {\n return {\n outcome: 'refused' as const,\n message: `A return that is ${CommerceModel.RETURN_STATUS_LABELS[entry.status].toLowerCase()} cannot be received`,\n }\n }\n // What may go back: at most what the return covers, per line.\n const covered = new Map(entry.lines.map((line) => [line.lineItemId, line.quantity]))\n const wanted = new Map<number, number>()\n for (const line of request.restock) {\n const lineItemId = Number(line?.lineItemId)\n const quantity = Number(line?.quantity)\n if (!covered.has(lineItemId)) {\n return { outcome: 'refused' as const, message: `Line ${lineItemId} is not part of this return` }\n }\n if (!Number.isInteger(quantity) || quantity < 0) {\n return { outcome: 'refused' as const, message: 'Restock quantities must be whole numbers' }\n }\n const total = (wanted.get(lineItemId) ?? 0) + quantity\n if (total > (covered.get(lineItemId) ?? 0)) {\n return { outcome: 'refused' as const, message: `Only ${covered.get(lineItemId)} of line ${lineItemId} came back` }\n }\n if (quantity > 0) wanted.set(lineItemId, total)\n }\n if (locationId && wanted.size > 0) {\n const location = await transaction.get(hostRef.collection('locations').doc(locationId))\n if (!location.exists) return { outcome: 'refused' as const, message: 'That stock location no longer exists' }\n }\n const orderRef = hostRef.collection('orders').doc(entry.orderId)\n const orderSnapshot = await transaction.get(orderRef)\n const order = orderSnapshot.exists ? CommerceModel.liftLegacyOrder((orderSnapshot.data() ?? {}) as never) : null\n // Every read before any write, as a transaction requires.\n const tracked =\n order && wanted.size > 0\n ? await resolveTrackedRestockLines(hostRef, order, (ref) => transaction.get(ref))\n : { lines: [], products: new Map<string, CommerceModel.HostProduct>() }\n const byProduct = new Map<string, Array<{ variantId: string; quantity: number }>>()\n for (const line of tracked.lines) {\n const quantity = Math.min(line.quantity, wanted.get(line.lineIndex ?? -1) ?? 0)\n if (quantity <= 0) continue\n byProduct.set(line.productId, [...(byProduct.get(line.productId) ?? []), { variantId: line.variantId, quantity }])\n }\n let units = 0\n for (const [productId, lines] of byProduct) {\n const product = tracked.products.get(productId)\n if (!product) continue\n let variants = product.variants\n for (const line of lines) {\n variants = CommerceModel.adjustVariantInventory({ variants }, line.variantId, line.quantity, locationId || undefined)\n }\n transaction.update(hostRef.collection('products').doc(productId), {\n variants,\n ...CommerceModel.productStockFields({ ...product, variants }),\n updatedAtMs: now,\n })\n for (const line of lines) {\n units += line.quantity\n transaction.create(hostRef.collection('inventoryAdjustments').doc(createResourceUid()), {\n productId,\n variantId: line.variantId,\n delta: line.quantity,\n reason: 'restock',\n orderId: entry.orderId,\n ...(locationId ? { locationId } : {}),\n atMs: now,\n } satisfies CommerceModel.InventoryAdjustment)\n }\n }\n const restock: CommerceModel.ReturnRestock = {\n lines: [...wanted.entries()].map(([lineItemId, quantity]) => ({ lineItemId, quantity })),\n ...(locationId ? { locationId } : {}),\n atMs: now,\n }\n const patch = {\n status: 'received' as const,\n restock,\n timeline: CommerceModel.appendReturnEvent(\n entry,\n 'received',\n units > 0 ? `${units} ${units === 1 ? 'unit' : 'units'} back in stock` : 'Nothing restocked',\n now,\n ),\n updatedAtMs: now,\n }\n transaction.update(returnRef, patch)\n const received = { ...entry, ...patch }\n if (order) {\n const orderPatch = {\n timeline: CommerceModel.appendOrderEvent(order, 'return-received', units > 0 ? `${units} restocked` : undefined, now),\n }\n transaction.update(orderRef, orderPatch)\n stageOrderEvent(transaction, RETURN_RECEIVED_EVENT, {\n hostId: request.hostId,\n orderId: entry.orderId,\n key: `return-received:${request.returnId}`,\n order: { ...orderSnapshot.data(), ...orderPatch },\n extra: { return: returnEventView(request.returnId, received) },\n })\n }\n return { outcome: 'changed' as const, entry: received, order, units }\n })\n}\n\n/**\n * Records a refund that went through the order's refund route against the\n * return, and answers the order's restock question with what the return\n * already did, so the merchant is not asked to restock the same units again.\n */\nexport async function markReturnRefunded(request: {\n hostId: string\n returnId: string\n refundCents: number\n uid: string\n now?: number\n}): Promise<ChangeReturnOutcome> {\n const firestore = firebaseAdmin.app().firestore()\n const hostRef = hostRefFor(firestore, request.hostId)\n const returnRef = hostRef.collection('returns').doc(request.returnId)\n const now = request.now ?? Date.now()\n return firestore.runTransaction(async (transaction): Promise<ChangeReturnOutcome> => {\n const snapshot = await transaction.get(returnRef)\n if (!snapshot.exists) return { outcome: 'no_such_return' }\n const entry = snapshot.data() as CommerceModel.HostReturn\n if (entry.status === 'refunded' || entry.refundedAtMs) return { outcome: 'already', entry }\n const orderRef = hostRef.collection('orders').doc(entry.orderId)\n const orderSnapshot = await transaction.get(orderRef)\n const order = orderSnapshot.exists ? CommerceModel.liftLegacyOrder((orderSnapshot.data() ?? {}) as never) : null\n const patch = {\n status: 'refunded' as const,\n refundedAtMs: now,\n refundCents: Math.max(0, Math.round(request.refundCents)),\n timeline: CommerceModel.appendReturnEvent(entry, 'refunded', undefined, now),\n updatedAtMs: now,\n }\n transaction.update(returnRef, patch)\n const check = order?.restockCheck\n if (order && check && !check.resolution && entry.restock) {\n const restocked = entry.restock.lines.some((line) => line.quantity > 0)\n transaction.update(orderRef, {\n restockCheck: {\n ...check,\n resolution: restocked ? 'restocked' : 'dismissed',\n resolvedAtMs: now,\n ...(request.uid ? { resolvedBy: request.uid } : {}),\n } satisfies CommerceModel.OrderRestockCheck,\n timeline: CommerceModel.appendOrderEvent(\n order,\n 'restock-check',\n restocked ? 'answered by the return — restocked' : 'answered by the return — no restock',\n now,\n ),\n })\n }\n return { outcome: 'changed', entry: { ...entry, ...patch }, order }\n })\n}\n\n/** Calls the order's own refund route in-process, with the caller's credentials. */\nasync function callRefundRoute(\n req: PluginApiRequest,\n body: Record<string, unknown>,\n idempotencyKey: string,\n): Promise<{ status: number; body: Record<string, any> }> {\n let status = 200\n let payload: Record<string, any> = {}\n const res = {\n status(code: number) {\n status = code\n return res\n },\n json(value: unknown) {\n payload = (value ?? {}) as Record<string, any>\n return res\n },\n send(value: unknown) {\n payload = { error: String(value ?? '') }\n return res\n },\n setHeader() {\n return res\n },\n end() {\n return res\n },\n } as unknown as PluginApiResponse\n await refundHandler(\n {\n ...req,\n method: 'POST',\n headers: { authorization: String(req.headers.authorization ?? ''), 'idempotency-key': idempotencyKey },\n body,\n } as PluginApiRequest,\n res,\n )\n return { status, body: payload }\n}\n\n// ---------------------------------------------------------------------------\n// Emails\n// ---------------------------------------------------------------------------\n\ntype ReturnEmailKey = 'return-requested' | 'return-approved' | 'return-declined' | 'return-refunded'\n\nasync function sendReturnEmail(\n hostId: string,\n key: ReturnEmailKey,\n to: string,\n tokens: Record<string, string>,\n fallback: { subject: string; text: string },\n): Promise<void> {\n if (!to || !isEmailConfigured()) return\n try {\n const firestore = firebaseAdmin.app().firestore()\n const designed = await renderHostEmailWithTokens(firestore, hostId, key, tokens)\n const org = await getOrgForHost(hostId).catch(() => null)\n await sendEmail({\n to,\n subject: designed?.subject ?? fallback.subject,\n text: designed?.text || fallback.text,\n ...(designed?.html ? { html: designed.html } : {}),\n fromName: Aglyn.resolveBrandingProfile(org?.org as never).fromName,\n sendingIdentity: await hostSendingIdentity(hostId),\n audience: 'tenant',\n context: key,\n // Owed to the recipient by their own order (AGL-3356).\n owedFor: 'order',\n })\n await meterHostEmail(hostId)\n } catch (error) {\n // A return that is recorded is not undone because its email failed.\n console.error(`[returns] ${key} not sent`, hostId, error)\n }\n}\n\n/** Tells the store a buyer asked, in the console and by email to the owner. */\nasync function tellStoreOfRequest(hostId: string, returnId: string, entry: CommerceModel.HostReturn, order: CommerceModel.HostOrder) {\n const items = returnItemsText(order, entry)\n await notifyHostManagers(\n hostId,\n {\n type: 'content.order',\n title: `Return requested for order ${entry.orderNumber}`,\n body: `${entry.customerEmail ?? 'A buyer'} wants to return ${CommerceModel.describeReturnLines(order, entry.lines)} from order ${entry.orderNumber} on {site}.`,\n link: `/${hostId}/products/returns?return=${encodeURIComponent(returnId)}`,\n },\n { skipOwnerEmail: true },\n ).catch(() => undefined)\n const ownerUid = (await getOrgForHost(hostId).catch(() => null))?.org?.ownerUid\n const owner = ownerUid ? (await findUserByUidAcrossPools(ownerUid).catch(() => null))?.record : null\n if (!owner?.email) return\n await sendReturnEmail(\n hostId,\n 'return-requested',\n owner.email,\n {\n 'order.number': entry.orderNumber,\n 'return.items': items,\n 'buyer.email': String(entry.customerEmail ?? ''),\n 'return.customerNote': String(entry.customerNote ?? ''),\n 'return.url': await hostConsoleUrl(\n hostId,\n `/${hostId}/products/returns?return=${encodeURIComponent(returnId)}`,\n ),\n },\n {\n subject: `Return requested for order ${entry.orderNumber}`,\n text:\n `${entry.customerEmail ?? 'A buyer'} wants to return items from order ${entry.orderNumber}.\\n\\n${items}` +\n (entry.customerNote ? `\\n\\n\"${entry.customerNote}\"` : '') +\n `\\n\\nApprove or decline it under Products → Returns.`,\n },\n )\n}\n\n/** Tells the buyer what happened to their return. */\nasync function tellBuyer(\n hostId: string,\n key: Exclude<ReturnEmailKey, 'return-requested'>,\n entry: CommerceModel.HostReturn,\n order: CommerceModel.HostOrder | null,\n): Promise<void> {\n const to = String(entry.customerEmail ?? order?.customerEmail ?? '').trim()\n if (!to || !order) return\n const firestore = firebaseAdmin.app().firestore()\n const store = await readStore(firestore, hostId)\n const statusUrl = orderStatusUrl(store.host as never, hostId, entry.orderId) ?? ''\n const items = returnItemsText(order, entry)\n const label = entry.returnLabel\n ? `Print your return label: ${entry.returnLabel.labelUrl}` +\n (entry.returnLabel.trackingNumber ? ` (${[entry.returnLabel.carrier, entry.returnLabel.trackingNumber].filter(Boolean).join(' ')})` : '')\n : ''\n const refundTotal = money(entry.refundCents ?? 0, store.currency)\n const tokens: Record<string, string> = {\n 'order.number': entry.orderNumber,\n 'return.items': items,\n 'return.note': String(entry.merchantNote ?? ''),\n 'return.label': label,\n 'return.refundTotal': refundTotal,\n 'order.statusUrl': statusUrl,\n }\n const fallback =\n key === 'return-approved'\n ? {\n subject: `Your return for order ${entry.orderNumber} is approved`,\n text: `Your return is approved:\\n\\n${items}` + (entry.merchantNote ? `\\n\\n${entry.merchantNote}` : '') + (label ? `\\n\\n${label}` : ''),\n }\n : key === 'return-declined'\n ? {\n subject: `About your return for order ${entry.orderNumber}`,\n text: `We could not accept the return of:\\n\\n${items}` + (entry.merchantNote ? `\\n\\n${entry.merchantNote}` : ''),\n }\n : {\n subject: `Your refund for order ${entry.orderNumber}`,\n text: `We received your return and refunded ${refundTotal}.\\n\\n${items}`,\n }\n if (statusUrl) fallback.text += `\\n\\nView your order: ${statusUrl}`\n await sendReturnEmail(hostId, key, to, tokens, fallback)\n}\n\n// ---------------------------------------------------------------------------\n// The buyer's door (tenant)\n// ---------------------------------------------------------------------------\n\n/**\n * Whether this request may act for the buyer of this order: the signed-in\n * site member whose email the order carries, or the holder of the order's\n * signed status link. Neither reveals whether the order exists to anyone\n * else — both refusals read the same.\n */\nasync function buyerMayActFor(\n req: PluginApiRequest,\n hostId: string,\n orderId: string,\n token: string,\n order: CommerceModel.HostOrder,\n): Promise<boolean> {\n if (token && verifyOrderStatusToken(hostId, orderId, token)) return true\n const session = await readActiveMemberSession(req, hostId)\n if (session.status !== 'active') return false\n const memberEmail = String(session.member.get('email') ?? '').trim().toLowerCase()\n return Boolean(memberEmail) && memberEmail === String(order.customerEmail ?? '').trim().toLowerCase()\n}\n\n/**\n * `GET /api/commerce/return-request?hostId&orderId&t` — what the buyer may\n * send back and until when, and the returns already open.\n * `POST` with `{ hostId, orderId, t?, lines: [{ lineItemId, quantity, reason }], note? }`\n * opens a return.\n */\nexport const returnRequestHandler: PluginApiHandler = async (req, res) => {\n if (req.method !== 'GET' && req.method !== 'POST') {\n return res.status(405).json({ error: 'Method not allowed' })\n }\n const input = (req.method === 'GET' ? req.query : typeof req.body === 'string' ? JSON.parse(req.body) : req.body) ?? {}\n const hostId = String(input.hostId ?? '')\n const orderId = String(input.orderId ?? input.o ?? '')\n const token = String(input.t ?? input.token ?? '').slice(0, 100)\n if (!isId(hostId) || !isId(orderId)) return res.status(400).json({ error: 'Missing hostId or orderId' })\n try {\n const firestore = firebaseAdmin.app().firestore()\n const hostRef = hostRefFor(firestore, hostId)\n const orderSnapshot = await hostRef.collection('orders').doc(orderId).get()\n const order = orderSnapshot.exists ? CommerceModel.liftLegacyOrder((orderSnapshot.data() ?? {}) as never) : null\n if (!order || !(await buyerMayActFor(req, hostId, orderId, token, order))) {\n return res.status(404).json({ error: 'We could not find that order' })\n }\n if (req.method === 'GET') {\n const [{ returnSettings }, existing] = await Promise.all([\n readStore(firestore, hostId),\n hostRef.collection('returns').where('orderId', '==', orderId).get(),\n ])\n const returns = existing.docs.map((entry) => ({ id: entry.id, ...(entry.data() as CommerceModel.HostReturn) }))\n const endsAt = CommerceModel.returnWindowEndsAtMs(order, returnSettings)\n return res.status(200).json({\n enabled: returnSettings.enabled,\n windowEndsAtMs: endsAt,\n windowOpen: endsAt === null || Date.now() <= endsAt,\n lines: CommerceModel.returnableLines(order, returns, returnSettings),\n reasons: CommerceModel.RETURN_REASONS.map((reason) => ({ value: reason, label: CommerceModel.RETURN_REASON_LABELS[reason] })),\n returns: returns.map((entry) => ({\n id: entry.id,\n status: entry.status,\n lines: entry.lines,\n createdAtMs: entry.createdAtMs,\n ...(entry.returnLabel ? { returnLabel: { labelUrl: entry.returnLabel.labelUrl, carrier: entry.returnLabel.carrier, trackingNumber: entry.returnLabel.trackingNumber } } : {}),\n ...(entry.status === 'declined' && entry.merchantNote ? { merchantNote: entry.merchantNote } : {}),\n })),\n })\n }\n const outcome = await openReturn({\n hostId,\n orderId,\n lines: Array.isArray(input.lines) ? (input.lines as unknown[]).slice(0, 100) as never : [],\n note: String(input.note ?? ''),\n by: 'buyer',\n })\n if (outcome.outcome === 'no_such_order') return res.status(404).json({ error: 'We could not find that order' })\n if (outcome.outcome === 'refused') return res.status(409).json({ error: outcome.message })\n await tellStoreOfRequest(hostId, outcome.returnId, outcome.entry, outcome.order)\n return res.status(200).json({ ok: true, returnId: outcome.returnId, status: outcome.entry.status })\n } catch (error) {\n console.error('return request failed', error)\n return res.status(500).json({ error: 'Your return could not be requested. Please try again.' })\n }\n}\n\n// ---------------------------------------------------------------------------\n// The merchant's door (console)\n// ---------------------------------------------------------------------------\n\nconst MERCHANT_ACTIONS = ['create', 'approve', 'decline', 'close', 'note', 'attach-label', 'receive', 'refund'] as const\ntype MerchantAction = (typeof MERCHANT_ACTIONS)[number]\n\n/**\n * `POST /api/commerce/returns` with `{ hostId, action, … }`. Admins and\n * editors run the return; the refund goes through the order's refund route,\n * which asks for an admin of the whole workspace on its own.\n */\nexport const returnsHandler: PluginApiHandler = async (req, res) => {\n if (req.method !== 'POST') return res.status(405).json({ error: 'Method not allowed' })\n const authorization = String(req.headers.authorization ?? '')\n const idToken = authorization.startsWith('Bearer ') ? authorization.slice('Bearer '.length) : undefined\n if (!idToken) return res.status(401).json({ error: 'Unauthenticated' })\n const body = (typeof req.body === 'string' ? JSON.parse(req.body) : req.body) ?? {}\n const hostId = String(body.hostId ?? '')\n const action = String(body.action ?? '') as MerchantAction\n const returnId = String(body.returnId ?? '')\n if (!isId(hostId)) return res.status(400).json({ error: 'Missing hostId' })\n if (!MERCHANT_ACTIONS.includes(action)) return res.status(400).json({ error: 'Unknown action' })\n if (action !== 'create' && !isId(returnId)) return res.status(400).json({ error: 'Missing returnId' })\n try {\n const decoded = await firebaseAdmin.app().auth().verifyIdToken(idToken)\n const firestore = firebaseAdmin.app().firestore()\n const hostSnapshot = await hostRefFor(firestore, hostId).get()\n if (!hostSnapshot.exists) return res.status(404).json({ error: 'Unknown site' })\n const role = (hostSnapshot.get('memberRoles') ?? {})[decoded.uid]\n if (role !== 'admin' && role !== 'editor') return res.status(403).json({ error: 'Not permitted' })\n\n if (action === 'create') {\n const orderId = String(body.orderId ?? '')\n if (!isId(orderId)) return res.status(400).json({ error: 'Missing orderId' })\n const outcome = await openReturn({\n hostId,\n orderId,\n lines: Array.isArray(body.lines) ? (body.lines as unknown[]).slice(0, 100) as never : [],\n note: String(body.note ?? ''),\n by: 'merchant',\n })\n if (outcome.outcome === 'no_such_order') return res.status(404).json({ error: 'Unknown order' })\n if (outcome.outcome === 'refused') return res.status(409).json({ error: outcome.message })\n if (body.notify !== false) await tellBuyer(hostId, 'return-approved', outcome.entry, outcome.order)\n return res.status(200).json({ ok: true, returnId: outcome.returnId, status: outcome.entry.status })\n }\n\n if (action === 'receive') {\n const outcome = await receiveReturn({\n hostId,\n returnId,\n restock: Array.isArray(body.restock) ? (body.restock as unknown[]).slice(0, 100) as never : [],\n locationId: body.locationId ? String(body.locationId) : undefined,\n })\n if (outcome.outcome === 'no_such_return') return res.status(404).json({ error: 'Unknown return' })\n if (outcome.outcome === 'refused') return res.status(409).json({ error: outcome.message })\n return res.status(200).json({\n ok: true,\n ...(outcome.outcome === 'already' ? { already: true } : { units: outcome.units ?? 0 }),\n status: outcome.entry.status,\n })\n }\n\n if (action === 'refund') {\n const returnSnapshot = await hostRefFor(firestore, hostId).collection('returns').doc(returnId).get()\n if (!returnSnapshot.exists) return res.status(404).json({ error: 'Unknown return' })\n const entry = returnSnapshot.data() as CommerceModel.HostReturn\n if (entry.status === 'refunded' || entry.refundedAtMs) {\n return res.status(200).json({ ok: true, already: true, status: entry.status })\n }\n if (!CommerceModel.canTransitionReturn(entry.status, 'refunded')) {\n return res.status(409).json({ error: `A return that is ${CommerceModel.RETURN_STATUS_LABELS[entry.status].toLowerCase()} cannot be refunded` })\n }\n const orderSnapshot = await hostRefFor(firestore, hostId).collection('orders').doc(entry.orderId).get()\n if (!orderSnapshot.exists) return res.status(404).json({ error: 'The order for this return is gone' })\n const order = CommerceModel.liftLegacyOrder((orderSnapshot.data() ?? {}) as never)\n const suggested = CommerceModel.returnRefundCents(order, entry.lines)\n const amountCents = body.amountCents == null ? suggested : Math.round(Number(body.amountCents))\n if (!Number.isFinite(amountCents) || amountCents <= 0) {\n return res.status(400).json({ error: 'The refund amount must be above zero' })\n }\n const wholeLines = CommerceModel.returnWholeLineIds(order, entry.lines).filter(\n (index) => !CommerceModel.orderLineRefunded(order, index),\n )\n const namedWorth = CommerceModel.orderLineRefundCents(order, wholeLines)\n // Lines are named only when the amount covers them in full, which is\n // what the refund route requires before it withdraws a line's\n // entitlements; a smaller amount refunds by amount alone.\n const refund = await callRefundRoute(\n req,\n {\n hostId,\n orderId: entry.orderId,\n amountCents,\n ...(wholeLines.length > 0 && amountCents >= namedWorth ? { lineItemIds: wholeLines } : {}),\n },\n // One refund per return: asking again replays rather than pays twice.\n `return:${hostId}:${returnId}`,\n )\n if (refund.status !== 200) {\n return res.status(refund.status).json({ error: refund.body?.error ?? 'Refund failed' })\n }\n const marked = await markReturnRefunded({ hostId, returnId, refundCents: amountCents, uid: decoded.uid })\n if (marked.outcome === 'changed') {\n await raiseOrderEvent(RETURN_REFUNDED_EVENT, {\n hostId,\n orderId: entry.orderId,\n key: `return-refunded:${returnId}`,\n extra: { return: returnEventView(returnId, marked.entry) },\n })\n await tellBuyer(hostId, 'return-refunded', marked.entry, marked.order)\n }\n return res.status(200).json({ ok: true, refundCents: amountCents, status: 'refunded' })\n }\n\n const outcome = await changeReturn({\n hostId,\n returnId,\n action: action as ReturnAction,\n ...(body.merchantNote !== undefined ? { merchantNote: String(body.merchantNote) } : {}),\n ...(action === 'attach-label' ? { label: body.label } : {}),\n })\n if (outcome.outcome === 'no_such_return') return res.status(404).json({ error: 'Unknown return' })\n if (outcome.outcome === 'refused') return res.status(409).json({ error: outcome.message })\n if (outcome.outcome === 'changed' && body.notify !== false) {\n if (action === 'approve') await tellBuyer(hostId, 'return-approved', outcome.entry, outcome.order)\n if (action === 'decline') await tellBuyer(hostId, 'return-declined', outcome.entry, outcome.order)\n // A label attached after the approval reaches the buyer the same way,\n // in the approval email, which carries it.\n if (action === 'attach-label' && outcome.entry.status === 'approved') {\n await tellBuyer(hostId, 'return-approved', outcome.entry, outcome.order)\n }\n }\n return res.status(200).json({\n ok: true,\n ...(outcome.outcome === 'already' ? { already: true } : {}),\n status: outcome.entry.status,\n })\n } catch (error) {\n console.error('returns action failed', action, error)\n // Every write here is a transaction or keyed (the refund), so asking\n // again lands once.\n return res.status(500).json({ error: 'The return could not be updated. Retrying is safe.' })\n }\n}\n"],"names":["Aglyn","createResourceUid","findUserByUidAcrossPools","firebaseAdmin","getOrgForHost","hostSendingIdentity","meterHostEmail","notifyHostManagers","renderHostEmailWithTokens","hostConsoleUrl","isEmailConfigured","sendEmail","CommerceModel","RETURN_APPROVED_EVENT","RETURN_DECLINED_EVENT","RETURN_RECEIVED_EVENT","RETURN_REFUNDED_EVENT","RETURN_REQUESTED_EVENT","raiseOrderEvent","stageOrderEvent","orderStatusUrl","verifyOrderStatusToken","readActiveMemberSession","resolveTrackedRestockLines","refundHandler","hostRefFor","firestore","hostId","collection","doc","isId","value","Boolean","length","test","includes","readStore","settings","hostRef","host","store","Promise","all","get","catch","data","returnSettings","readReturnSettings","currency","String","toUpperCase","money","cents","Intl","NumberFormat","style","format","toFixed","returnEventView","id","entry","status","lines","map","line","refundCents","restock","returnItemsText","order","quantity","lineItems","lineItemId","name","RETURN_REASON_LABELS","reason","join","openReturn","request","app","orderRef","orderId","now","Date","note","trim","slice","RETURN_NOTE_MAX","runTransaction","transaction","orderSnapshot","exists","outcome","existing","where","liftLegacyOrder","verdict","validateReturnRequest","docs","by","message","describeReturnRequestProblem","orderNumber","returnOrderNumber","customerEmail","customerName","requestedBy","customerNote","merchantNote","timeline","atMs","event","detail","describeReturnLines","createdAtMs","updatedAtMs","returnRef","create","orderPatch","appendOrderEvent","update","key","extra","return","returnId","ACTION_TARGET","approve","decline","close","changeReturn","undefined","snapshot","target","action","patch","canTransitionReturn","RETURN_STATUS_LABELS","toLowerCase","appendReturnEvent","label","labelUrl","returnIsOpen","carrier","trackingNumber","trackingUrl","trackingUrlFor","returnLabel","attachedAtMs","changed","receiveReturn","locationId","covered","Map","wanted","Number","has","isInteger","total","set","size","location","tracked","ref","products","byProduct","Math","min","lineIndex","productId","variantId","units","product","variants","adjustVariantInventory","productStockFields","delta","entries","received","markReturnRefunded","refundedAtMs","max","round","check","restockCheck","resolution","restocked","some","resolvedAtMs","uid","resolvedBy","callRefundRoute","req","body","idempotencyKey","payload","res","code","json","send","error","setHeader","end","method","headers","authorization","sendReturnEmail","to","tokens","fallback","designed","org","subject","text","html","fromName","resolveBrandingProfile","sendingIdentity","audience","context","owedFor","console","tellStoreOfRequest","items","type","title","link","encodeURIComponent","skipOwnerEmail","ownerUid","owner","record","email","tellBuyer","statusUrl","filter","refundTotal","buyerMayActFor","token","session","memberEmail","member","returnRequestHandler","input","query","JSON","parse","o","t","returns","endsAt","returnWindowEndsAtMs","enabled","windowEndsAtMs","windowOpen","returnableLines","reasons","RETURN_REASONS","Array","isArray","ok","MERCHANT_ACTIONS","returnsHandler","idToken","startsWith","hostSnapshot","decoded","auth","verifyIdToken","role","notify","already","returnSnapshot","suggested","returnRefundCents","amountCents","isFinite","wholeLines","returnWholeLineIds","index","orderLineRefunded","namedWorth","orderLineRefundCents","refund","lineItemIds","marked"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/server/returns.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 { holdsCommerceSiteKey } from './commerce-site-keys'\nimport { commerceSitePermissionRefusal } from '../model/plugin-permissions'\nimport * as Aglyn from '@aglyn/aglyn/server'\nimport { createResourceUid } from '@aglyn/aglyn/app-utils/create-resource-uid'\nimport type { PluginApiHandler, PluginApiRequest, PluginApiResponse } from '@aglyn/aglyn/server'\nimport {\n findUserByUidAcrossPools,\n firebaseAdmin,\n getOrgForHost,\n hostSendingIdentity,\n meterHostEmail,\n notifyHostManagers,\n renderHostEmailWithTokens,\n} from '@aglyn/tenant-data-admin'\nimport { hostConsoleUrl } from '@aglyn/tenant-data-admin/server/host-console-link'\nimport { isEmailConfigured, sendEmail } from '@aglyn/shared-util-email'\nimport * as CommerceModel from '../model'\nimport {\n RETURN_APPROVED_EVENT,\n RETURN_DECLINED_EVENT,\n RETURN_RECEIVED_EVENT,\n RETURN_REFUNDED_EVENT,\n RETURN_REQUESTED_EVENT,\n} from '../model/order-events'\nimport { raiseOrderEvent, stageOrderEvent } from './order-events'\nimport { orderStatusUrl, verifyOrderStatusToken } from './order-status-token'\nimport { readActiveMemberSession } from './membership'\nimport { resolveTrackedRestockLines } from './restock-flag'\nimport { refundHandler } from './refund'\n\n/**\n * Returns (RMA, AGL-3611): the buyer's door, the merchant's door, and the\n * writes behind both. The rules — what is returnable, the window, the state\n * machine, what a refund is worth — are the model's (`commerce-returns.ts`);\n * this is where they are re-asked under the write.\n *\n * EVERY WRITE IS A TRANSACTION that reads the return, the order and, when it\n * opens one, every return already on the order — so two requests for the last\n * unit cannot both be granted, and a stale console cannot approve a return a\n * colleague declined a moment ago.\n *\n * THE MONEY MOVES THROUGH THE ORDER'S REFUND ROUTE, never here. A return's\n * refund calls `refund.ts` with the merchant's own credentials and a key\n * derived from the return, so its gates (an admin of the whole workspace,\n * the over-refund cap, the open-dispute block, Stripe's idempotency) are the\n * ones every refund passes, and asking twice refunds once.\n *\n * STOCK COMES BACK WHEN THE PARCEL DOES. Receiving a return puts the units\n * the merchant chose back on the shelf, at the location they chose, with an\n * inventory adjustment row — the products hub's history shows it beside the\n * sale. A refund then answers the order's restock question with what the\n * return already did, so nobody is asked to restock the same units twice.\n */\n\ntype Firestore = FirebaseFirestore.Firestore\n\nconst hostRefFor = (firestore: Firestore, hostId: string) => firestore.collection('hosts').doc(hostId)\n\nconst isId = (value: string) => Boolean(value) && value.length <= 200 && !/^__.*__$/.test(value) && !value.includes('/')\n\n/** The store's settings document and what the return emails need from the host. */\nasync function readStore(firestore: Firestore, hostId: string) {\n const hostRef = hostRefFor(firestore, hostId)\n const [host, store] = await Promise.all([\n hostRef.get().catch(() => null),\n hostRef.collection('settings').doc('store').get().catch(() => null),\n ])\n const settings = (store?.data() ?? {}) as Record<string, unknown>\n return {\n host: (host?.data() ?? {}) as Record<string, unknown>,\n returnSettings: CommerceModel.readReturnSettings(settings['returns']),\n currency: String(settings['currency'] ?? 'USD').toUpperCase(),\n }\n}\n\nfunction money(cents: number, currency: string): string {\n try {\n return new Intl.NumberFormat('en-US', { style: 'currency', currency }).format(cents / 100)\n } catch {\n return `$${(cents / 100).toFixed(2)}`\n }\n}\n\n/** The return as an event carries it. */\nfunction returnEventView(id: string, entry: CommerceModel.HostReturn) {\n return {\n id,\n status: entry.status,\n lines: entry.lines.map((line) => ({ ...line })),\n refundCents: entry.refundCents ?? null,\n restock: entry.restock ? entry.restock.lines.map((line) => ({ ...line })) : null,\n }\n}\n\n/** \"1× House Blend — Arrived damaged\", one per line. */\nfunction returnItemsText(order: CommerceModel.HostOrder, entry: Pick<CommerceModel.HostReturn, 'lines'>): string {\n return entry.lines\n .map(\n (line) =>\n `${line.quantity}× ${order.lineItems?.[line.lineItemId]?.name ?? `line ${line.lineItemId}`} — ${\n CommerceModel.RETURN_REASON_LABELS[line.reason] ?? line.reason\n }`,\n )\n .join('\\n')\n}\n\nexport type OpenReturnOutcome =\n | { outcome: 'created'; returnId: string; entry: CommerceModel.HostReturn; order: CommerceModel.HostOrder }\n | { outcome: 'refused'; message: string }\n | { outcome: 'no_such_order' }\n\n/**\n * Opens a return. A buyer's starts `requested`; a merchant's starts\n * `approved`, since the merchant asking is the approval.\n */\nexport async function openReturn(request: {\n hostId: string\n orderId: string\n lines: ReadonlyArray<{ lineItemId: unknown; quantity: unknown; reason: unknown }>\n note?: string\n by: 'buyer' | 'merchant'\n now?: number\n}): Promise<OpenReturnOutcome> {\n const firestore = firebaseAdmin.app().firestore()\n const hostRef = hostRefFor(firestore, request.hostId)\n const orderRef = hostRef.collection('orders').doc(request.orderId)\n const { returnSettings } = await readStore(firestore, request.hostId)\n const now = request.now ?? Date.now()\n const note = String(request.note ?? '').trim().slice(0, CommerceModel.RETURN_NOTE_MAX)\n return firestore.runTransaction(async (transaction): Promise<OpenReturnOutcome> => {\n const orderSnapshot = await transaction.get(orderRef)\n if (!orderSnapshot.exists) return { outcome: 'no_such_order' }\n const existing = await transaction.get(\n hostRef.collection('returns').where('orderId', '==', request.orderId),\n )\n const order = CommerceModel.liftLegacyOrder((orderSnapshot.data() ?? {}) as never)\n const verdict = CommerceModel.validateReturnRequest({\n order,\n existing: existing.docs.map((entry) => entry.data() as CommerceModel.HostReturn),\n settings: returnSettings,\n lines: request.lines,\n by: request.by,\n now,\n })\n if (!('lines' in verdict)) {\n return { outcome: 'refused', message: CommerceModel.describeReturnRequestProblem(verdict) }\n }\n const status: CommerceModel.ReturnStatus = request.by === 'merchant' ? 'approved' : 'requested'\n const entry: CommerceModel.HostReturn = {\n orderId: request.orderId,\n orderNumber: CommerceModel.returnOrderNumber(order, request.orderId),\n customerEmail: order.customerEmail ?? null,\n customerName: order.customerName ?? null,\n lines: verdict.lines.map((line) => ({\n ...line,\n name: String(order.lineItems?.[line.lineItemId]?.name ?? '').slice(0, 200),\n })),\n status,\n requestedBy: request.by,\n ...(note ? (request.by === 'buyer' ? { customerNote: note } : { merchantNote: note }) : {}),\n timeline: [\n {\n atMs: now,\n event: status,\n detail: `${request.by === 'buyer' ? 'Requested by the buyer' : 'Opened by the store'}: ${CommerceModel.describeReturnLines(order, verdict.lines)}`,\n },\n ],\n createdAtMs: now,\n updatedAtMs: now,\n }\n const returnRef = hostRef.collection('returns').doc(createResourceUid())\n transaction.create(returnRef, entry)\n const orderPatch = {\n timeline: CommerceModel.appendOrderEvent(\n order,\n 'return-requested',\n CommerceModel.describeReturnLines(order, verdict.lines),\n now,\n ),\n }\n transaction.update(orderRef, orderPatch)\n stageOrderEvent(transaction, RETURN_REQUESTED_EVENT, {\n hostId: request.hostId,\n orderId: request.orderId,\n key: `return:${returnRef.id}`,\n order: { ...orderSnapshot.data(), ...orderPatch },\n extra: { return: returnEventView(returnRef.id, entry) },\n })\n // The store opening a return is its approval.\n if (status === 'approved') {\n stageOrderEvent(transaction, RETURN_APPROVED_EVENT, {\n hostId: request.hostId,\n orderId: request.orderId,\n key: `return-approved:${returnRef.id}`,\n order: { ...orderSnapshot.data(), ...orderPatch },\n extra: { return: returnEventView(returnRef.id, entry) },\n })\n }\n return { outcome: 'created', returnId: returnRef.id, entry, order }\n })\n}\n\nexport type ReturnAction = 'approve' | 'decline' | 'close' | 'note' | 'attach-label'\n\nexport type ChangeReturnOutcome =\n | { outcome: 'changed'; entry: CommerceModel.HostReturn; order: CommerceModel.HostOrder | null }\n | { outcome: 'already'; entry: CommerceModel.HostReturn }\n | { outcome: 'refused'; message: string }\n | { outcome: 'no_such_return' }\n\nconst ACTION_TARGET: Partial<Record<ReturnAction, CommerceModel.ReturnStatus>> = {\n approve: 'approved',\n decline: 'declined',\n close: 'closed',\n}\n\n/**\n * Approve, decline, close, a note, or a return label — the writes that move\n * no stock and no money. The transition is re-asked under the write.\n */\nexport async function changeReturn(request: {\n hostId: string\n returnId: string\n action: ReturnAction\n merchantNote?: string\n label?: { carrier: string; trackingNumber: string; labelUrl: string; trackingUrl?: string }\n now?: number\n}): Promise<ChangeReturnOutcome> {\n const firestore = firebaseAdmin.app().firestore()\n const hostRef = hostRefFor(firestore, request.hostId)\n const returnRef = hostRef.collection('returns').doc(request.returnId)\n const now = request.now ?? Date.now()\n const note = request.merchantNote === undefined ? undefined : String(request.merchantNote).trim().slice(0, CommerceModel.RETURN_NOTE_MAX)\n return firestore.runTransaction(async (transaction): Promise<ChangeReturnOutcome> => {\n const snapshot = await transaction.get(returnRef)\n if (!snapshot.exists) return { outcome: 'no_such_return' }\n const entry = snapshot.data() as CommerceModel.HostReturn\n const orderSnapshot = await transaction.get(hostRef.collection('orders').doc(entry.orderId))\n const order = orderSnapshot.exists ? CommerceModel.liftLegacyOrder((orderSnapshot.data() ?? {}) as never) : null\n const target = ACTION_TARGET[request.action]\n let patch: Partial<CommerceModel.HostReturn>\n if (target) {\n if (entry.status === target) return { outcome: 'already', entry }\n if (!CommerceModel.canTransitionReturn(entry.status, target)) {\n return {\n outcome: 'refused',\n message: `A return that is ${CommerceModel.RETURN_STATUS_LABELS[entry.status].toLowerCase()} cannot be ${CommerceModel.RETURN_STATUS_LABELS[target].toLowerCase()}`,\n }\n }\n patch = {\n status: target,\n ...(note !== undefined && note ? { merchantNote: note } : {}),\n timeline: CommerceModel.appendReturnEvent(entry, target, note || undefined, now),\n }\n } else if (request.action === 'attach-label') {\n const label = request.label\n if (!label?.labelUrl || !/^https:\\/\\//i.test(label.labelUrl)) {\n return { outcome: 'refused', message: 'A return label needs an https link' }\n }\n if (!CommerceModel.returnIsOpen(entry) || entry.status === 'refunded') {\n return { outcome: 'refused', message: 'This return is finished; a label can no longer be attached' }\n }\n const carrier = String(label.carrier ?? '').trim().slice(0, 40)\n const trackingNumber = String(label.trackingNumber ?? '').trim().slice(0, 60)\n const trackingUrl =\n (label.trackingUrl && /^https:\\/\\//i.test(label.trackingUrl) ? label.trackingUrl : null) ??\n CommerceModel.trackingUrlFor(carrier, trackingNumber)\n patch = {\n returnLabel: {\n carrier,\n trackingNumber,\n labelUrl: String(label.labelUrl).slice(0, 2048),\n ...(trackingUrl ? { trackingUrl } : {}),\n attachedAtMs: now,\n },\n timeline: CommerceModel.appendReturnEvent(entry, 'label', `${carrier} ${trackingNumber}`.trim() || 'Return label attached', now),\n }\n } else {\n patch = {\n merchantNote: note ?? '',\n timeline: CommerceModel.appendReturnEvent(entry, 'note', note || 'Note cleared', now),\n }\n }\n transaction.update(returnRef, { ...patch, updatedAtMs: now })\n const changed = { ...entry, ...patch, updatedAtMs: now }\n const event = target === 'approved' ? RETURN_APPROVED_EVENT : target === 'declined' ? RETURN_DECLINED_EVENT : null\n if (event && orderSnapshot.exists) {\n stageOrderEvent(transaction, event, {\n hostId: request.hostId,\n orderId: entry.orderId,\n key: `return-${target}:${request.returnId}`,\n order: orderSnapshot.data() ?? {},\n extra: { return: returnEventView(request.returnId, changed) },\n })\n }\n return { outcome: 'changed', entry: changed, order }\n })\n}\n\n/**\n * The parcel arrived: the return is `received`, and the units the merchant\n * chose go back on the shelf, at the location they chose. A unit the sale\n * never took off a tracked count (an untracked variant, a deleted product)\n * has nothing to go back to and is left out, as a cancellation leaves it.\n */\nexport async function receiveReturn(request: {\n hostId: string\n returnId: string\n restock: ReadonlyArray<{ lineItemId: unknown; quantity: unknown }>\n locationId?: string\n now?: number\n}): Promise<ChangeReturnOutcome & { units?: number }> {\n const firestore = firebaseAdmin.app().firestore()\n const hostRef = hostRefFor(firestore, request.hostId)\n const returnRef = hostRef.collection('returns').doc(request.returnId)\n const now = request.now ?? Date.now()\n const locationId = String(request.locationId ?? '').trim().slice(0, 100)\n return firestore.runTransaction(async (transaction) => {\n const snapshot = await transaction.get(returnRef)\n if (!snapshot.exists) return { outcome: 'no_such_return' as const }\n const entry = snapshot.data() as CommerceModel.HostReturn\n if (entry.status === 'received' || entry.restock) return { outcome: 'already' as const, entry }\n if (!CommerceModel.canTransitionReturn(entry.status, 'received')) {\n return {\n outcome: 'refused' as const,\n message: `A return that is ${CommerceModel.RETURN_STATUS_LABELS[entry.status].toLowerCase()} cannot be received`,\n }\n }\n // What may go back: at most what the return covers, per line.\n const covered = new Map(entry.lines.map((line) => [line.lineItemId, line.quantity]))\n const wanted = new Map<number, number>()\n for (const line of request.restock) {\n const lineItemId = Number(line?.lineItemId)\n const quantity = Number(line?.quantity)\n if (!covered.has(lineItemId)) {\n return { outcome: 'refused' as const, message: `Line ${lineItemId} is not part of this return` }\n }\n if (!Number.isInteger(quantity) || quantity < 0) {\n return { outcome: 'refused' as const, message: 'Restock quantities must be whole numbers' }\n }\n const total = (wanted.get(lineItemId) ?? 0) + quantity\n if (total > (covered.get(lineItemId) ?? 0)) {\n return { outcome: 'refused' as const, message: `Only ${covered.get(lineItemId)} of line ${lineItemId} came back` }\n }\n if (quantity > 0) wanted.set(lineItemId, total)\n }\n if (locationId && wanted.size > 0) {\n const location = await transaction.get(hostRef.collection('locations').doc(locationId))\n if (!location.exists) return { outcome: 'refused' as const, message: 'That stock location no longer exists' }\n }\n const orderRef = hostRef.collection('orders').doc(entry.orderId)\n const orderSnapshot = await transaction.get(orderRef)\n const order = orderSnapshot.exists ? CommerceModel.liftLegacyOrder((orderSnapshot.data() ?? {}) as never) : null\n // Every read before any write, as a transaction requires.\n const tracked =\n order && wanted.size > 0\n ? await resolveTrackedRestockLines(hostRef, order, (ref) => transaction.get(ref))\n : { lines: [], products: new Map<string, CommerceModel.HostProduct>() }\n const byProduct = new Map<string, Array<{ variantId: string; quantity: number }>>()\n for (const line of tracked.lines) {\n const quantity = Math.min(line.quantity, wanted.get(line.lineIndex ?? -1) ?? 0)\n if (quantity <= 0) continue\n byProduct.set(line.productId, [...(byProduct.get(line.productId) ?? []), { variantId: line.variantId, quantity }])\n }\n let units = 0\n for (const [productId, lines] of byProduct) {\n const product = tracked.products.get(productId)\n if (!product) continue\n let variants = product.variants\n for (const line of lines) {\n variants = CommerceModel.adjustVariantInventory({ variants }, line.variantId, line.quantity, locationId || undefined)\n }\n transaction.update(hostRef.collection('products').doc(productId), {\n variants,\n ...CommerceModel.productStockFields({ ...product, variants }),\n updatedAtMs: now,\n })\n for (const line of lines) {\n units += line.quantity\n transaction.create(hostRef.collection('inventoryAdjustments').doc(createResourceUid()), {\n productId,\n variantId: line.variantId,\n delta: line.quantity,\n reason: 'restock',\n orderId: entry.orderId,\n ...(locationId ? { locationId } : {}),\n atMs: now,\n } satisfies CommerceModel.InventoryAdjustment)\n }\n }\n const restock: CommerceModel.ReturnRestock = {\n lines: [...wanted.entries()].map(([lineItemId, quantity]) => ({ lineItemId, quantity })),\n ...(locationId ? { locationId } : {}),\n atMs: now,\n }\n const patch = {\n status: 'received' as const,\n restock,\n timeline: CommerceModel.appendReturnEvent(\n entry,\n 'received',\n units > 0 ? `${units} ${units === 1 ? 'unit' : 'units'} back in stock` : 'Nothing restocked',\n now,\n ),\n updatedAtMs: now,\n }\n transaction.update(returnRef, patch)\n const received = { ...entry, ...patch }\n if (order) {\n const orderPatch = {\n timeline: CommerceModel.appendOrderEvent(order, 'return-received', units > 0 ? `${units} restocked` : undefined, now),\n }\n transaction.update(orderRef, orderPatch)\n stageOrderEvent(transaction, RETURN_RECEIVED_EVENT, {\n hostId: request.hostId,\n orderId: entry.orderId,\n key: `return-received:${request.returnId}`,\n order: { ...orderSnapshot.data(), ...orderPatch },\n extra: { return: returnEventView(request.returnId, received) },\n })\n }\n return { outcome: 'changed' as const, entry: received, order, units }\n })\n}\n\n/**\n * Records a refund that went through the order's refund route against the\n * return, and answers the order's restock question with what the return\n * already did, so the merchant is not asked to restock the same units again.\n */\nexport async function markReturnRefunded(request: {\n hostId: string\n returnId: string\n refundCents: number\n uid: string\n now?: number\n}): Promise<ChangeReturnOutcome> {\n const firestore = firebaseAdmin.app().firestore()\n const hostRef = hostRefFor(firestore, request.hostId)\n const returnRef = hostRef.collection('returns').doc(request.returnId)\n const now = request.now ?? Date.now()\n return firestore.runTransaction(async (transaction): Promise<ChangeReturnOutcome> => {\n const snapshot = await transaction.get(returnRef)\n if (!snapshot.exists) return { outcome: 'no_such_return' }\n const entry = snapshot.data() as CommerceModel.HostReturn\n if (entry.status === 'refunded' || entry.refundedAtMs) return { outcome: 'already', entry }\n const orderRef = hostRef.collection('orders').doc(entry.orderId)\n const orderSnapshot = await transaction.get(orderRef)\n const order = orderSnapshot.exists ? CommerceModel.liftLegacyOrder((orderSnapshot.data() ?? {}) as never) : null\n const patch = {\n status: 'refunded' as const,\n refundedAtMs: now,\n refundCents: Math.max(0, Math.round(request.refundCents)),\n timeline: CommerceModel.appendReturnEvent(entry, 'refunded', undefined, now),\n updatedAtMs: now,\n }\n transaction.update(returnRef, patch)\n const check = order?.restockCheck\n if (order && check && !check.resolution && entry.restock) {\n const restocked = entry.restock.lines.some((line) => line.quantity > 0)\n transaction.update(orderRef, {\n restockCheck: {\n ...check,\n resolution: restocked ? 'restocked' : 'dismissed',\n resolvedAtMs: now,\n ...(request.uid ? { resolvedBy: request.uid } : {}),\n } satisfies CommerceModel.OrderRestockCheck,\n timeline: CommerceModel.appendOrderEvent(\n order,\n 'restock-check',\n restocked ? 'answered by the return — restocked' : 'answered by the return — no restock',\n now,\n ),\n })\n }\n return { outcome: 'changed', entry: { ...entry, ...patch }, order }\n })\n}\n\n/** Calls the order's own refund route in-process, with the caller's credentials. */\nasync function callRefundRoute(\n req: PluginApiRequest,\n body: Record<string, unknown>,\n idempotencyKey: string,\n): Promise<{ status: number; body: Record<string, any> }> {\n let status = 200\n let payload: Record<string, any> = {}\n const res = {\n status(code: number) {\n status = code\n return res\n },\n json(value: unknown) {\n payload = (value ?? {}) as Record<string, any>\n return res\n },\n send(value: unknown) {\n payload = { error: String(value ?? '') }\n return res\n },\n setHeader() {\n return res\n },\n end() {\n return res\n },\n } as unknown as PluginApiResponse\n await refundHandler(\n {\n ...req,\n method: 'POST',\n headers: { authorization: String(req.headers.authorization ?? ''), 'idempotency-key': idempotencyKey },\n body,\n } as PluginApiRequest,\n res,\n )\n return { status, body: payload }\n}\n\n// ---------------------------------------------------------------------------\n// Emails\n// ---------------------------------------------------------------------------\n\ntype ReturnEmailKey = 'return-requested' | 'return-approved' | 'return-declined' | 'return-refunded'\n\nasync function sendReturnEmail(\n hostId: string,\n key: ReturnEmailKey,\n to: string,\n tokens: Record<string, string>,\n fallback: { subject: string; text: string },\n): Promise<void> {\n if (!to || !isEmailConfigured()) return\n try {\n const firestore = firebaseAdmin.app().firestore()\n const designed = await renderHostEmailWithTokens(firestore, hostId, key, tokens)\n const org = await getOrgForHost(hostId).catch(() => null)\n await sendEmail({\n to,\n subject: designed?.subject ?? fallback.subject,\n text: designed?.text || fallback.text,\n ...(designed?.html ? { html: designed.html } : {}),\n fromName: Aglyn.resolveBrandingProfile(org?.org as never).fromName,\n sendingIdentity: await hostSendingIdentity(hostId),\n audience: 'tenant',\n context: key,\n // Owed to the recipient by their own order (AGL-3356).\n owedFor: 'order',\n })\n await meterHostEmail(hostId)\n } catch (error) {\n // A return that is recorded is not undone because its email failed.\n console.error(`[returns] ${key} not sent`, hostId, error)\n }\n}\n\n/** Tells the store a buyer asked, in the console and by email to the owner. */\nasync function tellStoreOfRequest(hostId: string, returnId: string, entry: CommerceModel.HostReturn, order: CommerceModel.HostOrder) {\n const items = returnItemsText(order, entry)\n await notifyHostManagers(\n hostId,\n {\n type: 'content.order',\n title: `Return requested for order ${entry.orderNumber}`,\n body: `${entry.customerEmail ?? 'A buyer'} wants to return ${CommerceModel.describeReturnLines(order, entry.lines)} from order ${entry.orderNumber} on {site}.`,\n link: `/${hostId}/products/returns?return=${encodeURIComponent(returnId)}`,\n },\n { skipOwnerEmail: true },\n ).catch(() => undefined)\n const ownerUid = (await getOrgForHost(hostId).catch(() => null))?.org?.ownerUid\n const owner = ownerUid ? (await findUserByUidAcrossPools(ownerUid).catch(() => null))?.record : null\n if (!owner?.email) return\n await sendReturnEmail(\n hostId,\n 'return-requested',\n owner.email,\n {\n 'order.number': entry.orderNumber,\n 'return.items': items,\n 'buyer.email': String(entry.customerEmail ?? ''),\n 'return.customerNote': String(entry.customerNote ?? ''),\n 'return.url': await hostConsoleUrl(\n hostId,\n `/${hostId}/products/returns?return=${encodeURIComponent(returnId)}`,\n ),\n },\n {\n subject: `Return requested for order ${entry.orderNumber}`,\n text:\n `${entry.customerEmail ?? 'A buyer'} wants to return items from order ${entry.orderNumber}.\\n\\n${items}` +\n (entry.customerNote ? `\\n\\n\"${entry.customerNote}\"` : '') +\n `\\n\\nApprove or decline it under Products → Returns.`,\n },\n )\n}\n\n/** Tells the buyer what happened to their return. */\nasync function tellBuyer(\n hostId: string,\n key: Exclude<ReturnEmailKey, 'return-requested'>,\n entry: CommerceModel.HostReturn,\n order: CommerceModel.HostOrder | null,\n): Promise<void> {\n const to = String(entry.customerEmail ?? order?.customerEmail ?? '').trim()\n if (!to || !order) return\n const firestore = firebaseAdmin.app().firestore()\n const store = await readStore(firestore, hostId)\n const statusUrl = orderStatusUrl(store.host as never, hostId, entry.orderId) ?? ''\n const items = returnItemsText(order, entry)\n const label = entry.returnLabel\n ? `Print your return label: ${entry.returnLabel.labelUrl}` +\n (entry.returnLabel.trackingNumber ? ` (${[entry.returnLabel.carrier, entry.returnLabel.trackingNumber].filter(Boolean).join(' ')})` : '')\n : ''\n const refundTotal = money(entry.refundCents ?? 0, store.currency)\n const tokens: Record<string, string> = {\n 'order.number': entry.orderNumber,\n 'return.items': items,\n 'return.note': String(entry.merchantNote ?? ''),\n 'return.label': label,\n 'return.refundTotal': refundTotal,\n 'order.statusUrl': statusUrl,\n }\n const fallback =\n key === 'return-approved'\n ? {\n subject: `Your return for order ${entry.orderNumber} is approved`,\n text: `Your return is approved:\\n\\n${items}` + (entry.merchantNote ? `\\n\\n${entry.merchantNote}` : '') + (label ? `\\n\\n${label}` : ''),\n }\n : key === 'return-declined'\n ? {\n subject: `About your return for order ${entry.orderNumber}`,\n text: `We could not accept the return of:\\n\\n${items}` + (entry.merchantNote ? `\\n\\n${entry.merchantNote}` : ''),\n }\n : {\n subject: `Your refund for order ${entry.orderNumber}`,\n text: `We received your return and refunded ${refundTotal}.\\n\\n${items}`,\n }\n if (statusUrl) fallback.text += `\\n\\nView your order: ${statusUrl}`\n await sendReturnEmail(hostId, key, to, tokens, fallback)\n}\n\n// ---------------------------------------------------------------------------\n// The buyer's door (tenant)\n// ---------------------------------------------------------------------------\n\n/**\n * Whether this request may act for the buyer of this order: the signed-in\n * site member whose email the order carries, or the holder of the order's\n * signed status link. Neither reveals whether the order exists to anyone\n * else — both refusals read the same.\n */\nasync function buyerMayActFor(\n req: PluginApiRequest,\n hostId: string,\n orderId: string,\n token: string,\n order: CommerceModel.HostOrder,\n): Promise<boolean> {\n if (token && verifyOrderStatusToken(hostId, orderId, token)) return true\n const session = await readActiveMemberSession(req, hostId)\n if (session.status !== 'active') return false\n const memberEmail = String(session.member.get('email') ?? '').trim().toLowerCase()\n return Boolean(memberEmail) && memberEmail === String(order.customerEmail ?? '').trim().toLowerCase()\n}\n\n/**\n * `GET /api/commerce/return-request?hostId&orderId&t` — what the buyer may\n * send back and until when, and the returns already open.\n * `POST` with `{ hostId, orderId, t?, lines: [{ lineItemId, quantity, reason }], note? }`\n * opens a return.\n */\nexport const returnRequestHandler: PluginApiHandler = async (req, res) => {\n if (req.method !== 'GET' && req.method !== 'POST') {\n return res.status(405).json({ error: 'Method not allowed' })\n }\n const input = (req.method === 'GET' ? req.query : typeof req.body === 'string' ? JSON.parse(req.body) : req.body) ?? {}\n const hostId = String(input.hostId ?? '')\n const orderId = String(input.orderId ?? input.o ?? '')\n const token = String(input.t ?? input.token ?? '').slice(0, 100)\n if (!isId(hostId) || !isId(orderId)) return res.status(400).json({ error: 'Missing hostId or orderId' })\n try {\n const firestore = firebaseAdmin.app().firestore()\n const hostRef = hostRefFor(firestore, hostId)\n const orderSnapshot = await hostRef.collection('orders').doc(orderId).get()\n const order = orderSnapshot.exists ? CommerceModel.liftLegacyOrder((orderSnapshot.data() ?? {}) as never) : null\n if (!order || !(await buyerMayActFor(req, hostId, orderId, token, order))) {\n return res.status(404).json({ error: 'We could not find that order' })\n }\n if (req.method === 'GET') {\n const [{ returnSettings }, existing] = await Promise.all([\n readStore(firestore, hostId),\n hostRef.collection('returns').where('orderId', '==', orderId).get(),\n ])\n const returns = existing.docs.map((entry) => ({ id: entry.id, ...(entry.data() as CommerceModel.HostReturn) }))\n const endsAt = CommerceModel.returnWindowEndsAtMs(order, returnSettings)\n return res.status(200).json({\n enabled: returnSettings.enabled,\n windowEndsAtMs: endsAt,\n windowOpen: endsAt === null || Date.now() <= endsAt,\n lines: CommerceModel.returnableLines(order, returns, returnSettings),\n reasons: CommerceModel.RETURN_REASONS.map((reason) => ({ value: reason, label: CommerceModel.RETURN_REASON_LABELS[reason] })),\n returns: returns.map((entry) => ({\n id: entry.id,\n status: entry.status,\n lines: entry.lines,\n createdAtMs: entry.createdAtMs,\n ...(entry.returnLabel ? { returnLabel: { labelUrl: entry.returnLabel.labelUrl, carrier: entry.returnLabel.carrier, trackingNumber: entry.returnLabel.trackingNumber } } : {}),\n ...(entry.status === 'declined' && entry.merchantNote ? { merchantNote: entry.merchantNote } : {}),\n })),\n })\n }\n const outcome = await openReturn({\n hostId,\n orderId,\n lines: Array.isArray(input.lines) ? (input.lines as unknown[]).slice(0, 100) as never : [],\n note: String(input.note ?? ''),\n by: 'buyer',\n })\n if (outcome.outcome === 'no_such_order') return res.status(404).json({ error: 'We could not find that order' })\n if (outcome.outcome === 'refused') return res.status(409).json({ error: outcome.message })\n await tellStoreOfRequest(hostId, outcome.returnId, outcome.entry, outcome.order)\n return res.status(200).json({ ok: true, returnId: outcome.returnId, status: outcome.entry.status })\n } catch (error) {\n console.error('return request failed', error)\n return res.status(500).json({ error: 'Your return could not be requested. Please try again.' })\n }\n}\n\n// ---------------------------------------------------------------------------\n// The merchant's door (console)\n// ---------------------------------------------------------------------------\n\nconst MERCHANT_ACTIONS = ['create', 'approve', 'decline', 'close', 'note', 'attach-label', 'receive', 'refund'] as const\ntype MerchantAction = (typeof MERCHANT_ACTIONS)[number]\n\n/**\n * `POST /api/commerce/returns` with `{ hostId, action, … }`. Admins and\n * editors run the return; the refund goes through the order's refund route,\n * which asks for an admin of the whole workspace on its own.\n */\nexport const returnsHandler: PluginApiHandler = async (req, res) => {\n if (req.method !== 'POST') return res.status(405).json({ error: 'Method not allowed' })\n const authorization = String(req.headers.authorization ?? '')\n const idToken = authorization.startsWith('Bearer ') ? authorization.slice('Bearer '.length) : undefined\n if (!idToken) return res.status(401).json({ error: 'Unauthenticated' })\n const body = (typeof req.body === 'string' ? JSON.parse(req.body) : req.body) ?? {}\n const hostId = String(body.hostId ?? '')\n const action = String(body.action ?? '') as MerchantAction\n const returnId = String(body.returnId ?? '')\n if (!isId(hostId)) return res.status(400).json({ error: 'Missing hostId' })\n if (!MERCHANT_ACTIONS.includes(action)) return res.status(400).json({ error: 'Unknown action' })\n if (action !== 'create' && !isId(returnId)) return res.status(400).json({ error: 'Missing returnId' })\n try {\n const decoded = await firebaseAdmin.app().auth().verifyIdToken(idToken)\n const firestore = firebaseAdmin.app().firestore()\n const hostSnapshot = await hostRefFor(firestore, hostId).get()\n if (!hostSnapshot.exists) return res.status(404).json({ error: 'Unknown site' })\n // \"Manage orders\" (`commerce.orders`, AGL-4047).\n if (!holdsCommerceSiteKey(hostSnapshot, decoded.uid, 'commerce.orders')) {\n return res.status(403).json({ error: commerceSitePermissionRefusal('commerce.orders') })\n }\n\n if (action === 'create') {\n const orderId = String(body.orderId ?? '')\n if (!isId(orderId)) return res.status(400).json({ error: 'Missing orderId' })\n const outcome = await openReturn({\n hostId,\n orderId,\n lines: Array.isArray(body.lines) ? (body.lines as unknown[]).slice(0, 100) as never : [],\n note: String(body.note ?? ''),\n by: 'merchant',\n })\n if (outcome.outcome === 'no_such_order') return res.status(404).json({ error: 'Unknown order' })\n if (outcome.outcome === 'refused') return res.status(409).json({ error: outcome.message })\n if (body.notify !== false) await tellBuyer(hostId, 'return-approved', outcome.entry, outcome.order)\n return res.status(200).json({ ok: true, returnId: outcome.returnId, status: outcome.entry.status })\n }\n\n if (action === 'receive') {\n const outcome = await receiveReturn({\n hostId,\n returnId,\n restock: Array.isArray(body.restock) ? (body.restock as unknown[]).slice(0, 100) as never : [],\n locationId: body.locationId ? String(body.locationId) : undefined,\n })\n if (outcome.outcome === 'no_such_return') return res.status(404).json({ error: 'Unknown return' })\n if (outcome.outcome === 'refused') return res.status(409).json({ error: outcome.message })\n return res.status(200).json({\n ok: true,\n ...(outcome.outcome === 'already' ? { already: true } : { units: outcome.units ?? 0 }),\n status: outcome.entry.status,\n })\n }\n\n if (action === 'refund') {\n const returnSnapshot = await hostRefFor(firestore, hostId).collection('returns').doc(returnId).get()\n if (!returnSnapshot.exists) return res.status(404).json({ error: 'Unknown return' })\n const entry = returnSnapshot.data() as CommerceModel.HostReturn\n if (entry.status === 'refunded' || entry.refundedAtMs) {\n return res.status(200).json({ ok: true, already: true, status: entry.status })\n }\n if (!CommerceModel.canTransitionReturn(entry.status, 'refunded')) {\n return res.status(409).json({ error: `A return that is ${CommerceModel.RETURN_STATUS_LABELS[entry.status].toLowerCase()} cannot be refunded` })\n }\n const orderSnapshot = await hostRefFor(firestore, hostId).collection('orders').doc(entry.orderId).get()\n if (!orderSnapshot.exists) return res.status(404).json({ error: 'The order for this return is gone' })\n const order = CommerceModel.liftLegacyOrder((orderSnapshot.data() ?? {}) as never)\n const suggested = CommerceModel.returnRefundCents(order, entry.lines)\n const amountCents = body.amountCents == null ? suggested : Math.round(Number(body.amountCents))\n if (!Number.isFinite(amountCents) || amountCents <= 0) {\n return res.status(400).json({ error: 'The refund amount must be above zero' })\n }\n const wholeLines = CommerceModel.returnWholeLineIds(order, entry.lines).filter(\n (index) => !CommerceModel.orderLineRefunded(order, index),\n )\n const namedWorth = CommerceModel.orderLineRefundCents(order, wholeLines)\n // Lines are named only when the amount covers them in full, which is\n // what the refund route requires before it withdraws a line's\n // entitlements; a smaller amount refunds by amount alone.\n const refund = await callRefundRoute(\n req,\n {\n hostId,\n orderId: entry.orderId,\n amountCents,\n ...(wholeLines.length > 0 && amountCents >= namedWorth ? { lineItemIds: wholeLines } : {}),\n },\n // One refund per return: asking again replays rather than pays twice.\n `return:${hostId}:${returnId}`,\n )\n if (refund.status !== 200) {\n return res.status(refund.status).json({ error: refund.body?.error ?? 'Refund failed' })\n }\n const marked = await markReturnRefunded({ hostId, returnId, refundCents: amountCents, uid: decoded.uid })\n if (marked.outcome === 'changed') {\n await raiseOrderEvent(RETURN_REFUNDED_EVENT, {\n hostId,\n orderId: entry.orderId,\n key: `return-refunded:${returnId}`,\n extra: { return: returnEventView(returnId, marked.entry) },\n })\n await tellBuyer(hostId, 'return-refunded', marked.entry, marked.order)\n }\n return res.status(200).json({ ok: true, refundCents: amountCents, status: 'refunded' })\n }\n\n const outcome = await changeReturn({\n hostId,\n returnId,\n action: action as ReturnAction,\n ...(body.merchantNote !== undefined ? { merchantNote: String(body.merchantNote) } : {}),\n ...(action === 'attach-label' ? { label: body.label } : {}),\n })\n if (outcome.outcome === 'no_such_return') return res.status(404).json({ error: 'Unknown return' })\n if (outcome.outcome === 'refused') return res.status(409).json({ error: outcome.message })\n if (outcome.outcome === 'changed' && body.notify !== false) {\n if (action === 'approve') await tellBuyer(hostId, 'return-approved', outcome.entry, outcome.order)\n if (action === 'decline') await tellBuyer(hostId, 'return-declined', outcome.entry, outcome.order)\n // A label attached after the approval reaches the buyer the same way,\n // in the approval email, which carries it.\n if (action === 'attach-label' && outcome.entry.status === 'approved') {\n await tellBuyer(hostId, 'return-approved', outcome.entry, outcome.order)\n }\n }\n return res.status(200).json({\n ok: true,\n ...(outcome.outcome === 'already' ? { already: true } : {}),\n status: outcome.entry.status,\n })\n } catch (error) {\n console.error('returns action failed', action, error)\n // Every write here is a transaction or keyed (the refund), so asking\n // again lands once.\n return res.status(500).json({ error: 'The return could not be updated. Retrying is safe.' })\n }\n}\n"],"names":["holdsCommerceSiteKey","commerceSitePermissionRefusal","Aglyn","createResourceUid","findUserByUidAcrossPools","firebaseAdmin","getOrgForHost","hostSendingIdentity","meterHostEmail","notifyHostManagers","renderHostEmailWithTokens","hostConsoleUrl","isEmailConfigured","sendEmail","CommerceModel","RETURN_APPROVED_EVENT","RETURN_DECLINED_EVENT","RETURN_RECEIVED_EVENT","RETURN_REFUNDED_EVENT","RETURN_REQUESTED_EVENT","raiseOrderEvent","stageOrderEvent","orderStatusUrl","verifyOrderStatusToken","readActiveMemberSession","resolveTrackedRestockLines","refundHandler","hostRefFor","firestore","hostId","collection","doc","isId","value","Boolean","length","test","includes","readStore","settings","hostRef","host","store","Promise","all","get","catch","data","returnSettings","readReturnSettings","currency","String","toUpperCase","money","cents","Intl","NumberFormat","style","format","toFixed","returnEventView","id","entry","status","lines","map","line","refundCents","restock","returnItemsText","order","quantity","lineItems","lineItemId","name","RETURN_REASON_LABELS","reason","join","openReturn","request","app","orderRef","orderId","now","Date","note","trim","slice","RETURN_NOTE_MAX","runTransaction","transaction","orderSnapshot","exists","outcome","existing","where","liftLegacyOrder","verdict","validateReturnRequest","docs","by","message","describeReturnRequestProblem","orderNumber","returnOrderNumber","customerEmail","customerName","requestedBy","customerNote","merchantNote","timeline","atMs","event","detail","describeReturnLines","createdAtMs","updatedAtMs","returnRef","create","orderPatch","appendOrderEvent","update","key","extra","return","returnId","ACTION_TARGET","approve","decline","close","changeReturn","undefined","snapshot","target","action","patch","canTransitionReturn","RETURN_STATUS_LABELS","toLowerCase","appendReturnEvent","label","labelUrl","returnIsOpen","carrier","trackingNumber","trackingUrl","trackingUrlFor","returnLabel","attachedAtMs","changed","receiveReturn","locationId","covered","Map","wanted","Number","has","isInteger","total","set","size","location","tracked","ref","products","byProduct","Math","min","lineIndex","productId","variantId","units","product","variants","adjustVariantInventory","productStockFields","delta","entries","received","markReturnRefunded","refundedAtMs","max","round","check","restockCheck","resolution","restocked","some","resolvedAtMs","uid","resolvedBy","callRefundRoute","req","body","idempotencyKey","payload","res","code","json","send","error","setHeader","end","method","headers","authorization","sendReturnEmail","to","tokens","fallback","designed","org","subject","text","html","fromName","resolveBrandingProfile","sendingIdentity","audience","context","owedFor","console","tellStoreOfRequest","items","type","title","link","encodeURIComponent","skipOwnerEmail","ownerUid","owner","record","email","tellBuyer","statusUrl","filter","refundTotal","buyerMayActFor","token","session","memberEmail","member","returnRequestHandler","input","query","JSON","parse","o","t","returns","endsAt","returnWindowEndsAtMs","enabled","windowEndsAtMs","windowOpen","returnableLines","reasons","RETURN_REASONS","Array","isArray","ok","MERCHANT_ACTIONS","returnsHandler","idToken","startsWith","decoded","auth","verifyIdToken","hostSnapshot","notify","already","returnSnapshot","suggested","returnRefundCents","amountCents","isFinite","wholeLines","returnWholeLineIds","index","orderLineRefunded","namedWorth","orderLineRefundCents","refund","lineItemIds","marked"],"mappings":"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"}
|
|
@@ -55,7 +55,13 @@ export interface PublicStoreReview {
|
|
|
55
55
|
createdAtMs: number;
|
|
56
56
|
/** The reviewed product, when it is still on sale. */
|
|
57
57
|
productName?: string;
|
|
58
|
+
/** Its page, when it is sold online; a product sold in person only has none. */
|
|
58
59
|
productSlug?: string;
|
|
60
|
+
/**
|
|
61
|
+
* The product is sold in person only and the store shows its reviews
|
|
62
|
+
* (AGL-4060): the band marks it "Sold in store" and links nowhere.
|
|
63
|
+
*/
|
|
64
|
+
soldInStore?: true;
|
|
59
65
|
}
|
|
60
66
|
/** The most reviews the store-wide list returns. */
|
|
61
67
|
export declare const STORE_REVIEWS_MAX = 12;
|
|
@@ -63,6 +69,14 @@ export declare const STORE_REVIEWS_MAX = 12;
|
|
|
63
69
|
export declare const STORE_REVIEWS_DEFAULT = 6;
|
|
64
70
|
/** "Jane Doe" → "Jane D."; one word stays as it is. */
|
|
65
71
|
export declare function reviewerShortName(name: string): string;
|
|
72
|
+
/** The most products a store may keep its in-store reviews off the site for, read at once. */
|
|
73
|
+
export declare const HIDDEN_REVIEW_PRODUCTS_MAX = 500;
|
|
74
|
+
/**
|
|
75
|
+
* The products sold in person only whose reviews the store keeps off the site
|
|
76
|
+
* (AGL-4060, `inStoreReviews: 'hide'`). Two equalities, which Firestore
|
|
77
|
+
* serves from its automatic single-field indexes.
|
|
78
|
+
*/
|
|
79
|
+
export declare function readHiddenReviewProductIds(hostRef: FirebaseFirestore.DocumentReference): Promise<Set<string>>;
|
|
66
80
|
/**
|
|
67
81
|
* The store's latest APPROVED reviews across every product, newest first, with
|
|
68
82
|
* the aggregate over all of them — the store-wide reviews band a storefront
|
|
@@ -70,10 +84,16 @@ export declare function reviewerShortName(name: string): string;
|
|
|
70
84
|
* page, and nothing here is ever sample text (a published page shows real
|
|
71
85
|
* reviews or none).
|
|
72
86
|
*
|
|
87
|
+
* A product sold in person only (AGL-4060) shows its reviews here by default,
|
|
88
|
+
* named, marked `soldInStore` and never linked, since it has no page; one
|
|
89
|
+
* whose store chose to hide them (`inStoreReviews: 'hide'`) is in neither the
|
|
90
|
+
* list nor the aggregate.
|
|
91
|
+
*
|
|
73
92
|
* The list is `status == approved` ordered by `createdAtMs desc`, served by
|
|
74
93
|
* the COLLECTION composite `reviews (status ASC, createdAtMs DESC)` that the
|
|
75
|
-
* moderation queue already declares
|
|
76
|
-
* over the same equality,
|
|
94
|
+
* moderation queue already declares, read a page at a time past hidden ones;
|
|
95
|
+
* the aggregate is a count and a sum over the same equality, less the hidden
|
|
96
|
+
* products' (`productId in …`, at most 30 at a time).
|
|
77
97
|
*/
|
|
78
98
|
export declare function readStoreReviews(hostId: string, limit?: number): Promise<{
|
|
79
99
|
reviews: PublicStoreReview[];
|
|
@@ -66,6 +66,17 @@ import { inspectReviewToken, redeemReviewTokenIn } from "./review-tokens.js";
|
|
|
66
66
|
const last = others[others.length - 1];
|
|
67
67
|
return last ? `${first} ${last[0].toUpperCase()}.` : first;
|
|
68
68
|
}
|
|
69
|
+
/** The most products a store may keep its in-store reviews off the site for, read at once. */ export const HIDDEN_REVIEW_PRODUCTS_MAX = 500;
|
|
70
|
+
/** How many pages of the newest reviews the band reads to fill itself past hidden ones. */ const STORE_REVIEWS_PAGES = 4;
|
|
71
|
+
/** Firestore's ceiling on the values of one `in` filter. */ const IN_FILTER_MAX = 30;
|
|
72
|
+
/**
|
|
73
|
+
* The products sold in person only whose reviews the store keeps off the site
|
|
74
|
+
* (AGL-4060, `inStoreReviews: 'hide'`). Two equalities, which Firestore
|
|
75
|
+
* serves from its automatic single-field indexes.
|
|
76
|
+
*/ export async function readHiddenReviewProductIds(hostRef) {
|
|
77
|
+
const snapshot = await hostRef.collection('products').where('sellOnline', '==', false).where('inStoreReviews', '==', 'hide').limit(HIDDEN_REVIEW_PRODUCTS_MAX).get();
|
|
78
|
+
return new Set(snapshot.docs.map((doc)=>doc.id));
|
|
79
|
+
}
|
|
69
80
|
/**
|
|
70
81
|
* The store's latest APPROVED reviews across every product, newest first, with
|
|
71
82
|
* the aggregate over all of them — the store-wide reviews band a storefront
|
|
@@ -73,24 +84,50 @@ import { inspectReviewToken, redeemReviewTokenIn } from "./review-tokens.js";
|
|
|
73
84
|
* page, and nothing here is ever sample text (a published page shows real
|
|
74
85
|
* reviews or none).
|
|
75
86
|
*
|
|
87
|
+
* A product sold in person only (AGL-4060) shows its reviews here by default,
|
|
88
|
+
* named, marked `soldInStore` and never linked, since it has no page; one
|
|
89
|
+
* whose store chose to hide them (`inStoreReviews: 'hide'`) is in neither the
|
|
90
|
+
* list nor the aggregate.
|
|
91
|
+
*
|
|
76
92
|
* The list is `status == approved` ordered by `createdAtMs desc`, served by
|
|
77
93
|
* the COLLECTION composite `reviews (status ASC, createdAtMs DESC)` that the
|
|
78
|
-
* moderation queue already declares
|
|
79
|
-
* over the same equality,
|
|
94
|
+
* moderation queue already declares, read a page at a time past hidden ones;
|
|
95
|
+
* the aggregate is a count and a sum over the same equality, less the hidden
|
|
96
|
+
* products' (`productId in …`, at most 30 at a time).
|
|
80
97
|
*/ export async function readStoreReviews(hostId, limit = STORE_REVIEWS_DEFAULT) {
|
|
81
|
-
var _data_count, _data_average;
|
|
82
98
|
const firestore = firebaseAdmin.app().firestore();
|
|
83
99
|
const hostRef = firestore.collection('hosts').doc(hostId);
|
|
84
100
|
const approved = hostRef.collection('reviews').where('status', '==', 'approved');
|
|
85
101
|
const max = Math.min(STORE_REVIEWS_MAX, Math.max(1, Math.floor(Number(limit)) || STORE_REVIEWS_DEFAULT));
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
102
|
+
const hidden = await readHiddenReviewProductIds(hostRef);
|
|
103
|
+
const hiddenIds = [
|
|
104
|
+
...hidden
|
|
105
|
+
];
|
|
106
|
+
const tally = {
|
|
107
|
+
count: AggregateField.count(),
|
|
108
|
+
sum: AggregateField.sum('rating')
|
|
109
|
+
};
|
|
110
|
+
const aggregates = Promise.all([
|
|
111
|
+
approved.aggregate(tally).get(),
|
|
112
|
+
...Array.from({
|
|
113
|
+
length: Math.ceil(hiddenIds.length / IN_FILTER_MAX)
|
|
114
|
+
}, (_, chunk)=>approved.where('productId', 'in', hiddenIds.slice(chunk * IN_FILTER_MAX, (chunk + 1) * IN_FILTER_MAX)).aggregate(tally).get())
|
|
92
115
|
]);
|
|
93
|
-
|
|
116
|
+
// The newest approved reviews, a page at a time, past any the store hides.
|
|
117
|
+
const docs = [];
|
|
118
|
+
let after = null;
|
|
119
|
+
for(let page = 0; page < STORE_REVIEWS_PAGES && docs.length < max; page += 1){
|
|
120
|
+
let query = approved.orderBy('createdAtMs', 'desc');
|
|
121
|
+
if (after) query = query.startAfter(after);
|
|
122
|
+
const snapshot = await query.limit(max).get();
|
|
123
|
+
docs.push(...snapshot.docs.filter((doc)=>{
|
|
124
|
+
var _doc_get;
|
|
125
|
+
return !hidden.has(String((_doc_get = doc.get('productId')) != null ? _doc_get : ''));
|
|
126
|
+
}));
|
|
127
|
+
if (snapshot.docs.length < max || !hidden.size) break;
|
|
128
|
+
after = snapshot.docs[snapshot.docs.length - 1];
|
|
129
|
+
}
|
|
130
|
+
const rows = docs.slice(0, max).map((docSnapshot)=>{
|
|
94
131
|
var _docSnapshot_get, _docSnapshot_get1, _docSnapshot_get2, _docSnapshot_get3, _docSnapshot_get4;
|
|
95
132
|
return {
|
|
96
133
|
id: docSnapshot.id,
|
|
@@ -102,7 +139,7 @@ import { inspectReviewToken, redeemReviewTokenIn } from "./review-tokens.js";
|
|
|
102
139
|
createdAtMs: Number((_docSnapshot_get4 = docSnapshot.get('createdAtMs')) != null ? _docSnapshot_get4 : 0)
|
|
103
140
|
};
|
|
104
141
|
});
|
|
105
|
-
// The reviewed products
|
|
142
|
+
// The reviewed products, in one batched read of at most `max` docs.
|
|
106
143
|
const productIds = [
|
|
107
144
|
...new Set(rows.map((row)=>row.productId).filter(Boolean))
|
|
108
145
|
];
|
|
@@ -112,16 +149,22 @@ import { inspectReviewToken, redeemReviewTokenIn } from "./review-tokens.js";
|
|
|
112
149
|
for (const snapshot of snapshots){
|
|
113
150
|
var _data_name, _data_slug;
|
|
114
151
|
const data = snapshot.exists ? snapshot.data() : null;
|
|
115
|
-
|
|
116
|
-
//
|
|
117
|
-
if (!
|
|
152
|
+
const online = CommerceModel.productReviewsOnline(data);
|
|
153
|
+
// A draft or a deleted product is named nowhere, as before.
|
|
154
|
+
if (!online) continue;
|
|
118
155
|
products.set(snapshot.id, {
|
|
119
156
|
name: String((_data_name = data['name']) != null ? _data_name : ''),
|
|
120
|
-
|
|
157
|
+
// Sold in person only: no page to link to.
|
|
158
|
+
slug: online === 'listed' ? String((_data_slug = data['slug']) != null ? _data_slug : '') : null,
|
|
159
|
+
online
|
|
121
160
|
});
|
|
122
161
|
}
|
|
123
162
|
}
|
|
124
|
-
const reviews = rows.
|
|
163
|
+
const reviews = rows// A product hidden since the list was read is still never shown.
|
|
164
|
+
.filter((row)=>{
|
|
165
|
+
var _products_get;
|
|
166
|
+
return ((_products_get = products.get(row.productId)) == null ? void 0 : _products_get.online) !== 'hidden';
|
|
167
|
+
}).map((_0)=>{
|
|
125
168
|
let { productId } = _0, row = _object_without_properties_loose(_0, [
|
|
126
169
|
"productId"
|
|
127
170
|
]);
|
|
@@ -130,11 +173,26 @@ import { inspectReviewToken, redeemReviewTokenIn } from "./review-tokens.js";
|
|
|
130
173
|
productName: product.name
|
|
131
174
|
} : {}, (product == null ? void 0 : product.slug) ? {
|
|
132
175
|
productSlug: product.slug
|
|
176
|
+
} : {}, (product == null ? void 0 : product.online) === 'sold-in-store' ? {
|
|
177
|
+
soldInStore: true
|
|
133
178
|
} : {});
|
|
134
179
|
});
|
|
135
|
-
const
|
|
136
|
-
const
|
|
137
|
-
|
|
180
|
+
const [all, ...hiddenTallies] = await aggregates;
|
|
181
|
+
const counted = (snapshot)=>{
|
|
182
|
+
var _data_count, _data_sum;
|
|
183
|
+
const data = snapshot.data();
|
|
184
|
+
return {
|
|
185
|
+
count: Number((_data_count = data.count) != null ? _data_count : 0),
|
|
186
|
+
sum: Number((_data_sum = data.sum) != null ? _data_sum : 0)
|
|
187
|
+
};
|
|
188
|
+
};
|
|
189
|
+
const total = counted(all);
|
|
190
|
+
for (const tallied of hiddenTallies.map(counted)){
|
|
191
|
+
total.count -= tallied.count;
|
|
192
|
+
total.sum -= tallied.sum;
|
|
193
|
+
}
|
|
194
|
+
const count = Math.max(0, total.count);
|
|
195
|
+
const average = count ? total.sum / count : 0;
|
|
138
196
|
return {
|
|
139
197
|
reviews,
|
|
140
198
|
aggregate: {
|
|
@@ -315,7 +373,17 @@ async function identifyReviewer(req, hostRef, hostId, productId) {
|
|
|
315
373
|
if (req.query.mode === 'eligibility') {
|
|
316
374
|
return await eligibilityHandler(req, res, hostId, productId);
|
|
317
375
|
}
|
|
318
|
-
|
|
376
|
+
// A product sold in person only whose store hides its reviews from the
|
|
377
|
+
// site (AGL-4060) answers none, here as on every other online surface.
|
|
378
|
+
const product = await firebaseAdmin.app().firestore().collection('hosts').doc(hostId).collection('products').doc(productId).get();
|
|
379
|
+
const hiddenOnline = CommerceModel.productReviewsOnline((product == null ? void 0 : product.exists) ? product.data() : null) === 'hidden';
|
|
380
|
+
const { reviews, aggregate } = hiddenOnline ? {
|
|
381
|
+
reviews: [],
|
|
382
|
+
aggregate: {
|
|
383
|
+
count: 0,
|
|
384
|
+
average: 0
|
|
385
|
+
}
|
|
386
|
+
} : await readProductReviews(hostId, productId);
|
|
319
387
|
res.setHeader('Cache-Control', 'public, s-maxage=120, stale-while-revalidate=300');
|
|
320
388
|
return res.status(200).json({
|
|
321
389
|
reviews,
|