@aglyn/plugins-commerce 1.0.0-beta.232 → 1.0.0-beta.233
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/package.json +13 -13
- package/src/lib/components/cart-extras.d.ts +6 -0
- package/src/lib/components/cart-extras.js +4 -1
- package/src/lib/components/cart-extras.js.map +1 -1
- package/src/lib/components/cart-fulfillment.d.ts +117 -0
- package/src/lib/components/cart-fulfillment.js +367 -0
- package/src/lib/components/cart-fulfillment.js.map +1 -0
- package/src/lib/components/cart.js +52 -10
- package/src/lib/components/cart.js.map +1 -1
- package/src/lib/components/commerce-console-page.js +42 -1
- package/src/lib/components/commerce-console-page.js.map +1 -1
- package/src/lib/components/console/host-orders-card.component.js +38 -10
- package/src/lib/components/console/host-orders-card.component.js.map +1 -1
- package/src/lib/components/console/local-delivery-settings-card.component.d.ts +37 -0
- package/src/lib/components/console/local-delivery-settings-card.component.js +542 -0
- package/src/lib/components/console/local-delivery-settings-card.component.js.map +1 -0
- package/src/lib/components/console/locations-card.component.js +177 -3
- package/src/lib/components/console/locations-card.component.js.map +1 -1
- package/src/lib/components/console/order-detail-dialog.component.js +10 -0
- package/src/lib/components/console/order-detail-dialog.component.js.map +1 -1
- package/src/lib/components/console/order-local-fulfillment-panel.component.d.ts +44 -0
- package/src/lib/components/console/order-local-fulfillment-panel.component.js +265 -0
- package/src/lib/components/console/order-local-fulfillment-panel.component.js.map +1 -0
- package/src/lib/components/console/order-offline-notice.component.d.ts +12 -0
- package/src/lib/components/console/order-offline-notice.component.js +53 -0
- package/src/lib/components/console/order-offline-notice.component.js.map +1 -0
- package/src/lib/components/console/pickup-delivery-queue-card.component.d.ts +35 -0
- package/src/lib/components/console/pickup-delivery-queue-card.component.js +222 -0
- package/src/lib/components/console/pickup-delivery-queue-card.component.js.map +1 -0
- package/src/lib/components/console/pos/pos-api.d.ts +24 -1
- package/src/lib/components/console/pos/pos-api.js +13 -0
- package/src/lib/components/console/pos/pos-api.js.map +1 -1
- package/src/lib/components/console/pos/pos-item-dialog.component.d.ts +12 -0
- package/src/lib/components/console/pos/pos-item-dialog.component.js +10 -8
- package/src/lib/components/console/pos/pos-item-dialog.component.js.map +1 -1
- package/src/lib/components/console/pos/pos-kiosk-queue.component.d.ts +22 -0
- package/src/lib/components/console/pos/pos-kiosk-queue.component.js +168 -0
- package/src/lib/components/console/pos/pos-kiosk-queue.component.js.map +1 -0
- package/src/lib/components/console/pos/pos-tender-dialogs.component.d.ts +18 -0
- package/src/lib/components/console/pos/pos-tender-dialogs.component.js +116 -1
- package/src/lib/components/console/pos/pos-tender-dialogs.component.js.map +1 -1
- package/src/lib/components/console/pos/pos-tender-panel.component.d.ts +8 -0
- package/src/lib/components/console/pos/pos-tender-panel.component.js +77 -18
- package/src/lib/components/console/pos/pos-tender-panel.component.js.map +1 -1
- package/src/lib/components/console/pos/use-pos-display.d.ts +5 -2
- package/src/lib/components/console/pos/use-pos-display.js +3 -2
- package/src/lib/components/console/pos/use-pos-display.js.map +1 -1
- package/src/lib/components/console/pos-devices-card.component.js +2 -2
- package/src/lib/components/console/pos-devices-card.component.js.map +1 -1
- package/src/lib/components/console/pos-display/pairing-screen.d.ts +5 -2
- package/src/lib/components/console/pos-display/pairing-screen.js +7 -5
- package/src/lib/components/console/pos-display/pairing-screen.js.map +1 -1
- package/src/lib/components/console/pos-display/pos-display-api.d.ts +7 -1
- package/src/lib/components/console/pos-display/pos-display-api.js +7 -2
- package/src/lib/components/console/pos-display/pos-display-api.js.map +1 -1
- package/src/lib/components/console/pos-kiosk/kiosk-checkout.d.ts +41 -0
- package/src/lib/components/console/pos-kiosk/kiosk-checkout.js +275 -0
- package/src/lib/components/console/pos-kiosk/kiosk-checkout.js.map +1 -0
- package/src/lib/components/console/pos-kiosk/kiosk-menu.d.ts +32 -0
- package/src/lib/components/console/pos-kiosk/kiosk-menu.js +344 -0
- package/src/lib/components/console/pos-kiosk/kiosk-menu.js.map +1 -0
- package/src/lib/components/console/pos-kiosk/kiosk-staff.d.ts +12 -0
- package/src/lib/components/console/pos-kiosk/kiosk-staff.js +257 -0
- package/src/lib/components/console/pos-kiosk/kiosk-staff.js.map +1 -0
- package/src/lib/components/console/pos-kiosk/pos-kiosk-api.d.ts +114 -0
- package/src/lib/components/console/pos-kiosk/pos-kiosk-api.js +189 -0
- package/src/lib/components/console/pos-kiosk/pos-kiosk-api.js.map +1 -0
- package/src/lib/components/console/pos-kiosk/use-kiosk-idle.d.ts +16 -0
- package/src/lib/components/console/pos-kiosk/use-kiosk-idle.js +80 -0
- package/src/lib/components/console/pos-kiosk/use-kiosk-idle.js.map +1 -0
- package/src/lib/components/console/pos-kiosk-page.component.d.ts +28 -0
- package/src/lib/components/console/pos-kiosk-page.component.js +791 -0
- package/src/lib/components/console/pos-kiosk-page.component.js.map +1 -0
- package/src/lib/components/console/pos-offline/pos-offline-api.d.ts +44 -0
- package/src/lib/components/console/pos-offline/pos-offline-api.js +69 -0
- package/src/lib/components/console/pos-offline/pos-offline-api.js.map +1 -0
- package/src/lib/components/console/pos-offline/pos-offline-banner.component.d.ts +7 -0
- package/src/lib/components/console/pos-offline/pos-offline-banner.component.js +135 -0
- package/src/lib/components/console/pos-offline/pos-offline-banner.component.js.map +1 -0
- package/src/lib/components/console/pos-offline/pos-offline-checkout.component.d.ts +32 -0
- package/src/lib/components/console/pos-offline/pos-offline-checkout.component.js +287 -0
- package/src/lib/components/console/pos-offline/pos-offline-checkout.component.js.map +1 -0
- package/src/lib/components/console/pos-offline/pos-offline-store.d.ts +63 -0
- package/src/lib/components/console/pos-offline/pos-offline-store.js +145 -0
- package/src/lib/components/console/pos-offline/pos-offline-store.js.map +1 -0
- package/src/lib/components/console/pos-offline/register-offline.d.ts +24 -0
- package/src/lib/components/console/pos-offline/register-offline.js +24 -0
- package/src/lib/components/console/pos-offline/register-offline.js.map +1 -0
- package/src/lib/components/console/pos-offline/use-pos-offline.d.ts +85 -0
- package/src/lib/components/console/pos-offline/use-pos-offline.js +542 -0
- package/src/lib/components/console/pos-offline/use-pos-offline.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-shift-history-card.component.js +72 -17
- package/src/lib/components/console/pos-ops/pos-shift-history-card.component.js.map +1 -1
- package/src/lib/components/console/pos-page.component.js +174 -27
- package/src/lib/components/console/pos-page.component.js.map +1 -1
- package/src/lib/components/console/products-hub-card.component.js +35 -10
- package/src/lib/components/console/products-hub-card.component.js.map +1 -1
- package/src/lib/components/console/shipping-settings-card.component.js +1 -1
- package/src/lib/components/console/shipping-settings-card.component.js.map +1 -1
- package/src/lib/components/console/stock-movements-card.component.js +48 -16
- package/src/lib/components/console/stock-movements-card.component.js.map +1 -1
- package/src/lib/components/console/store-zones.d.ts +8 -1
- package/src/lib/components/console/store-zones.js +11 -1
- package/src/lib/components/console/store-zones.js.map +1 -1
- package/src/lib/components/order-status.js +66 -0
- package/src/lib/components/order-status.js.map +1 -1
- package/src/lib/components/product-detail.js +42 -15
- package/src/lib/components/product-detail.js.map +1 -1
- package/src/lib/constants/local-fulfillment-list-query.d.ts +48 -0
- package/src/lib/constants/local-fulfillment-list-query.js +84 -0
- package/src/lib/constants/local-fulfillment-list-query.js.map +1 -0
- package/src/lib/constants/orders-list-query.d.ts +7 -2
- package/src/lib/constants/orders-list-query.js +89 -8
- package/src/lib/constants/orders-list-query.js.map +1 -1
- package/src/lib/constants/pos-shift-list-query.d.ts +22 -0
- package/src/lib/constants/pos-shift-list-query.js +115 -0
- package/src/lib/constants/pos-shift-list-query.js.map +1 -0
- package/src/lib/constants/product-list-query.d.ts +6 -1
- package/src/lib/constants/product-list-query.js +77 -8
- package/src/lib/constants/product-list-query.js.map +1 -1
- package/src/lib/constants/stock-movement-query.d.ts +3 -2
- package/src/lib/constants/stock-movement-query.js +52 -8
- package/src/lib/constants/stock-movement-query.js.map +1 -1
- package/src/lib/model/buyer-notifications.d.ts +5 -3
- package/src/lib/model/buyer-notifications.js +25 -4
- package/src/lib/model/buyer-notifications.js.map +1 -1
- package/src/lib/model/commerce-orders.d.ts +59 -0
- package/src/lib/model/commerce-orders.js.map +1 -1
- package/src/lib/model/commerce-pos-kiosk.d.ts +175 -0
- package/src/lib/model/commerce-pos-kiosk.js +147 -0
- package/src/lib/model/commerce-pos-kiosk.js.map +1 -0
- package/src/lib/model/commerce-pos-offline.d.ts +234 -0
- package/src/lib/model/commerce-pos-offline.js +301 -0
- package/src/lib/model/commerce-pos-offline.js.map +1 -0
- package/src/lib/model/commerce-pos-ops.d.ts +16 -6
- package/src/lib/model/commerce-pos-ops.js +12 -4
- package/src/lib/model/commerce-pos-ops.js.map +1 -1
- package/src/lib/model/commerce-pos.d.ts +13 -1
- package/src/lib/model/commerce-pos.js +5 -4
- package/src/lib/model/commerce-pos.js.map +1 -1
- package/src/lib/model/commerce-stock-holds.d.ts +24 -3
- package/src/lib/model/commerce-stock-holds.js +26 -8
- package/src/lib/model/commerce-stock-holds.js.map +1 -1
- package/src/lib/model/commerce.d.ts +3 -0
- package/src/lib/model/commerce.js.map +1 -1
- package/src/lib/model/index.d.ts +4 -0
- package/src/lib/model/index.js +4 -0
- package/src/lib/model/index.js.map +1 -1
- package/src/lib/model/local-fulfillment-settings.d.ts +178 -0
- package/src/lib/model/local-fulfillment-settings.js +361 -0
- package/src/lib/model/local-fulfillment-settings.js.map +1 -0
- package/src/lib/model/order-list-fields.d.ts +10 -1
- package/src/lib/model/order-list-fields.js +1 -0
- package/src/lib/model/order-list-fields.js.map +1 -1
- package/src/lib/model/order-local-fulfillment.d.ts +131 -0
- package/src/lib/model/order-local-fulfillment.js +125 -0
- package/src/lib/model/order-local-fulfillment.js.map +1 -0
- package/src/lib/model/order-shipping-export.js +4 -0
- package/src/lib/model/order-shipping-export.js.map +1 -1
- package/src/lib/model/order-status-view.d.ts +20 -1
- package/src/lib/model/order-status-view.js +60 -6
- package/src/lib/model/order-status-view.js.map +1 -1
- package/src/lib/plugin-config.js +6 -2
- package/src/lib/plugin-config.js.map +1 -1
- package/src/lib/plugin.js +8 -0
- package/src/lib/plugin.js.map +1 -1
- package/src/lib/pos-kiosk-config.d.ts +26 -0
- package/src/lib/pos-kiosk-config.js +59 -0
- package/src/lib/pos-kiosk-config.js.map +1 -0
- package/src/lib/server/api-v1/openapi.js +8 -0
- package/src/lib/server/api-v1/openapi.js.map +1 -1
- package/src/lib/server/api-v1/order-view.d.ts +19 -0
- package/src/lib/server/api-v1/order-view.js +35 -0
- package/src/lib/server/api-v1/order-view.js.map +1 -1
- package/src/lib/server/billing-webhook.js +238 -87
- package/src/lib/server/billing-webhook.js.map +1 -1
- package/src/lib/server/cart-checkout.d.ts +2 -0
- package/src/lib/server/cart-checkout.js +173 -13
- package/src/lib/server/cart-checkout.js.map +1 -1
- package/src/lib/server/checkout-extras.js +18 -4
- package/src/lib/server/checkout-extras.js.map +1 -1
- package/src/lib/server/checkout.js +71 -14
- package/src/lib/server/checkout.js.map +1 -1
- package/src/lib/server/local-fulfillment-status.d.ts +86 -0
- package/src/lib/server/local-fulfillment-status.js +379 -0
- package/src/lib/server/local-fulfillment-status.js.map +1 -0
- package/src/lib/server/local-fulfillment.d.ts +190 -0
- package/src/lib/server/local-fulfillment.js +580 -0
- package/src/lib/server/local-fulfillment.js.map +1 -0
- package/src/lib/server/membership-register.js +3 -1
- package/src/lib/server/membership-register.js.map +1 -1
- package/src/lib/server/order-notifications.js +61 -0
- package/src/lib/server/order-notifications.js.map +1 -1
- package/src/lib/server/pos-display.d.ts +27 -1
- package/src/lib/server/pos-display.js +50 -9
- package/src/lib/server/pos-display.js.map +1 -1
- package/src/lib/server/pos-kiosk-principal.d.ts +29 -0
- package/src/lib/server/pos-kiosk-principal.js +42 -0
- package/src/lib/server/pos-kiosk-principal.js.map +1 -0
- package/src/lib/server/pos-kiosk.d.ts +54 -0
- package/src/lib/server/pos-kiosk.js +972 -0
- package/src/lib/server/pos-kiosk.js.map +1 -0
- package/src/lib/server/pos-offline-sync.d.ts +85 -0
- package/src/lib/server/pos-offline-sync.js +765 -0
- package/src/lib/server/pos-offline-sync.js.map +1 -0
- package/src/lib/server/pos-order.js +22 -4
- package/src/lib/server/pos-order.js.map +1 -1
- package/src/lib/server/pos-payment.d.ts +6 -0
- package/src/lib/server/pos-payment.js +225 -6
- package/src/lib/server/pos-payment.js.map +1 -1
- package/src/lib/server/pos-print.js +5 -0
- package/src/lib/server/pos-print.js.map +1 -1
- package/src/lib/server/pos-return.js +27 -0
- package/src/lib/server/pos-return.js.map +1 -1
- package/src/lib/server/pos-sale.d.ts +6 -0
- package/src/lib/server/pos-sale.js +2 -0
- package/src/lib/server/pos-sale.js.map +1 -1
- package/src/lib/server/pos-shift.js +8 -1
- package/src/lib/server/pos-shift.js.map +1 -1
- package/src/lib/server/refund.js +3 -0
- package/src/lib/server/refund.js.map +1 -1
- package/src/lib/server/stock-hold.d.ts +9 -1
- package/src/lib/server/stock-hold.js +15 -7
- package/src/lib/server/stock-hold.js.map +1 -1
- package/src/lib/server.js +16 -0
- package/src/lib/server.js.map +1 -1
- package/src/lib/tenant-emails.js +161 -0
- package/src/lib/tenant-emails.js.map +1 -1
|
@@ -15,6 +15,8 @@
|
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/
|
|
17
17
|
import type { PluginApiHandler } from '@aglyn/aglyn/server';
|
|
18
|
+
/** A rewards or credit code no provider on this site takes (AGL-3640). */
|
|
19
|
+
export declare const CHECKOUT_CREDIT_INVALID_MESSAGE = "That rewards code is not valid.";
|
|
18
20
|
/** An option the buyer ticked is no longer offered (AGL-3635). */
|
|
19
21
|
export declare const CHECKOUT_EXTRA_UNAVAILABLE_MESSAGE = "An option you picked is no longer available. Review your cart and try again.";
|
|
20
22
|
/**
|
|
@@ -14,7 +14,8 @@ import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
|
14
14
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
15
|
* See the License for the specific language governing permissions and
|
|
16
16
|
* limitations under the License.
|
|
17
|
-
*/ import {
|
|
17
|
+
*/ import { randomUUID } from "crypto";
|
|
18
|
+
import { readSiteReturnHost, siteReturnUrl } from "@aglyn/aglyn/app-utils/site-return-url";
|
|
18
19
|
import * as Aglyn from "@aglyn/aglyn/server";
|
|
19
20
|
import * as CommerceModel from "../model/index.js";
|
|
20
21
|
import { checkoutRecoveryState } from "../model/checkout-recovery.js";
|
|
@@ -29,11 +30,14 @@ import { allocateCentsByWeight, engineLineTaxPercentages, taxEngineSessionMetada
|
|
|
29
30
|
import { quoteSaleTaxWithEngine } from "./tax-engine-quote.js";
|
|
30
31
|
import { holdPromotionSlot, promotionHoldKey } from "./promotion-hold.js";
|
|
31
32
|
import { holdStock, stockHoldKey } from "./stock-hold.js";
|
|
33
|
+
import { appendLocalFulfillmentMetadata, localFulfillmentLocationId, localStockRefusalMessage, planLocalFulfillment, readLocalFulfillmentRequest, readLocalFulfillmentStore } from "./local-fulfillment.js";
|
|
32
34
|
import { applyNativeCheckoutParams, nativeCheckoutStripeHeaders, readCheckoutSessionPayload, resolveNativeCheckoutMode } from "./native-checkout.js";
|
|
33
35
|
import { ensureCheckoutDomain } from "./payment-method-domains.js";
|
|
34
36
|
import { raiseCheckoutStarted } from "./order-events.js";
|
|
35
37
|
import { checkoutExtrasCents, encodeCheckoutExtrasMetadata, readChosenCheckoutExtras } from "@aglyn/aglyn/plugin-manager/plugin-checkout-extras";
|
|
36
38
|
import { quoteCartExtras } from "./checkout-extras.js";
|
|
39
|
+
import { boundedCreditCents, checkoutCreditProviderForCode, encodeCheckoutCreditMetadata, normalizeCheckoutCreditAccount, normalizeCheckoutCreditCode } from "@aglyn/aglyn/plugin-manager/plugin-checkout-credits";
|
|
40
|
+
/** A rewards or credit code no provider on this site takes (AGL-3640). */ export const CHECKOUT_CREDIT_INVALID_MESSAGE = 'That rewards code is not valid.';
|
|
37
41
|
/** An option the buyer ticked is no longer offered (AGL-3635). */ export const CHECKOUT_EXTRA_UNAVAILABLE_MESSAGE = 'An option you picked is no longer available. Review your cart and try again.';
|
|
38
42
|
/**
|
|
39
43
|
* Cart checkout (AGL-293): the whole cart in one Stripe Checkout
|
|
@@ -59,6 +63,8 @@ import { quoteCartExtras } from "./checkout-extras.js";
|
|
|
59
63
|
const marketingOptIn = Boolean(body.marketingOptIn);
|
|
60
64
|
const giftCardCode = String((_body_giftCardCode = body.giftCardCode) != null ? _body_giftCardCode : '').trim().toUpperCase().slice(0, 24);
|
|
61
65
|
const couponCode = String((_body_couponCode = body.couponCode) != null ? _body_couponCode : '').trim().toUpperCase().slice(0, 40);
|
|
66
|
+
// A rewards or referral code another plugin keeps the account for (AGL-3640).
|
|
67
|
+
const creditCode = normalizeCheckoutCreditCode(body.creditCode);
|
|
62
68
|
if (!hostId) return res.status(400).json({
|
|
63
69
|
error: 'Missing hostId'
|
|
64
70
|
});
|
|
@@ -97,7 +103,7 @@ import { quoteCartExtras } from "./checkout-extras.js";
|
|
|
97
103
|
if (held) await held.release();
|
|
98
104
|
};
|
|
99
105
|
try {
|
|
100
|
-
var _cartSnapshot_data, _ref1, _storeSettings_get, _storeSettings_get1, _req_headers_referer, _req_headers_host,
|
|
106
|
+
var _cartSnapshot_data, _ref1, _ref2, _storeSettings_get, _storeSettings_get1, _req_headers_referer, _req_headers_host, _ref3, _ref4;
|
|
101
107
|
var _ownerOrg_org, _ownerOrg_org1, _ownerOrg_org2, _engineTax_quote;
|
|
102
108
|
const firestore = firebaseAdmin.app().firestore();
|
|
103
109
|
const hostRef = firestore.collection('hosts').doc(hostId);
|
|
@@ -288,7 +294,7 @@ import { quoteCartExtras } from "./checkout-extras.js";
|
|
|
288
294
|
// visitor per day, lower while the workspace is young. Above the claim,
|
|
289
295
|
// like the line refusals, so a refusal keeps the key.
|
|
290
296
|
if (giftCardCents > 0) {
|
|
291
|
-
var
|
|
297
|
+
var _ref5;
|
|
292
298
|
var _req_socket;
|
|
293
299
|
const young = isYoungWorkspace(ownerOrg.org);
|
|
294
300
|
const overCeiling = CommerceModel.giftCardPurchaseRefusal({
|
|
@@ -300,7 +306,7 @@ import { quoteCartExtras } from "./checkout-extras.js";
|
|
|
300
306
|
visible: overCeiling
|
|
301
307
|
});
|
|
302
308
|
}
|
|
303
|
-
const buys = await consumeRateLimit(`giftcard:buy:${hostId}:${String((
|
|
309
|
+
const buys = await consumeRateLimit(`giftcard:buy:${hostId}:${String((_ref5 = (_req_socket = req.socket) == null ? void 0 : _req_socket.remoteAddress) != null ? _ref5 : '') || 'no-address'}`, {
|
|
304
310
|
limit: young ? CommerceModel.GIFT_CARD_PURCHASE_LIMITS.perVisitorDailyYoung : CommerceModel.GIFT_CARD_PURCHASE_LIMITS.perVisitorDaily,
|
|
305
311
|
windowMs: 24 * 60 * 60 * 1000
|
|
306
312
|
});
|
|
@@ -325,10 +331,48 @@ import { quoteCartExtras } from "./checkout-extras.js";
|
|
|
325
331
|
// session byte-identical to today's: no shipping charged, exactly as
|
|
326
332
|
// before. Only a merchant who set rates up starts collecting them.
|
|
327
333
|
const storeSettings = await hostRef.collection('settings').doc('store').get();
|
|
334
|
+
// PICKUP OR THE STORE'S OWN DELIVERY (AGL-3624), declared at the cart and
|
|
335
|
+
// decided here from the store's settings: the location, the zone's fee and
|
|
336
|
+
// minimum, the window. Above the claim, so a refusal keeps the key and the
|
|
337
|
+
// shopper's same button works once they choose again. See
|
|
338
|
+
// `local-fulfillment.ts`.
|
|
339
|
+
const localRequest = readLocalFulfillmentRequest(body.fulfillment);
|
|
340
|
+
const localStore = hasPhysicalLine ? await readLocalFulfillmentStore({
|
|
341
|
+
hostRef,
|
|
342
|
+
storeSettings: (_ref1 = storeSettings.data == null ? void 0 : storeSettings.data.call(storeSettings)) != null ? _ref1 : null,
|
|
343
|
+
org: ownerOrg.org
|
|
344
|
+
}) : null;
|
|
345
|
+
const localPlan = localStore ? await planLocalFulfillment({
|
|
346
|
+
hostId,
|
|
347
|
+
request: localRequest,
|
|
348
|
+
itemsCents,
|
|
349
|
+
hasPhysicalLine,
|
|
350
|
+
store: localStore
|
|
351
|
+
}) : {
|
|
352
|
+
kind: 'shipping'
|
|
353
|
+
};
|
|
354
|
+
if (localPlan.kind === 'refusal') {
|
|
355
|
+
return res.status(localPlan.status).json(_extends({
|
|
356
|
+
error: localPlan.error
|
|
357
|
+
}, localPlan.changed ? {
|
|
358
|
+
fulfillmentChanged: localPlan.changed
|
|
359
|
+
} : {}));
|
|
360
|
+
}
|
|
328
361
|
// A live carrier rate (AGL-3612) is quoted here too, before the session,
|
|
329
362
|
// for the destination the shopper declared; a store with none plans from
|
|
330
363
|
// its table exactly as before. See `carrier-shipping.ts`.
|
|
331
|
-
const shippingPlan =
|
|
364
|
+
const shippingPlan = // Collected: nothing to price, no address to ask for.
|
|
365
|
+
localPlan.kind === 'pickup' ? {
|
|
366
|
+
countries: [],
|
|
367
|
+
options: []
|
|
368
|
+
} : localPlan.kind === 'local_delivery' ? {
|
|
369
|
+
countries: [
|
|
370
|
+
localPlan.country
|
|
371
|
+
],
|
|
372
|
+
options: [
|
|
373
|
+
localPlan.option
|
|
374
|
+
]
|
|
375
|
+
} : hasPhysicalLine ? await planCheckoutShippingWithCarriers({
|
|
332
376
|
hostId,
|
|
333
377
|
settings: storeSettings.get('shipping'),
|
|
334
378
|
cart: {
|
|
@@ -343,6 +387,12 @@ import { quoteCartExtras } from "./checkout-extras.js";
|
|
|
343
387
|
countries: CommerceModel.CHECKOUT_SHIPPING_COUNTRIES,
|
|
344
388
|
options: []
|
|
345
389
|
};
|
|
390
|
+
// A store whose locations offer pickup has the shopper choose WHERE at
|
|
391
|
+
// the cart (AGL-3624); the old unnamed `Local pickup` rate would be a
|
|
392
|
+
// second, unrouted pickup inside a session the shopper chose shipping for.
|
|
393
|
+
if (localPlan.kind === 'shipping' && (localStore == null ? void 0 : localStore.pickupLocations.length)) {
|
|
394
|
+
shippingPlan.options = shippingPlan.options.filter((option)=>option.rateId !== CommerceModel.LOCAL_PICKUP_RATE_ID);
|
|
395
|
+
}
|
|
346
396
|
if (shippingPlan.needsPostalCode) {
|
|
347
397
|
return res.status(400).json({
|
|
348
398
|
error: CARRIER_POSTAL_CODE_MESSAGE,
|
|
@@ -458,7 +508,7 @@ import { quoteCartExtras } from "./checkout-extras.js";
|
|
|
458
508
|
const claimed = await claimAttempt(firestore, {
|
|
459
509
|
kind: 'commerce-cart',
|
|
460
510
|
scopeId: `${hostId}:${cartId}`,
|
|
461
|
-
orgId: String((
|
|
511
|
+
orgId: String((_ref2 = ownerOrg == null ? void 0 : (_ownerOrg_org1 = ownerOrg.org) == null ? void 0 : _ownerOrg_org1.id) != null ? _ref2 : ''),
|
|
462
512
|
key: idempotencyKey,
|
|
463
513
|
busyMessage: 'This checkout is already being processed'
|
|
464
514
|
});
|
|
@@ -499,7 +549,9 @@ import { quoteCartExtras } from "./checkout-extras.js";
|
|
|
499
549
|
hostRef,
|
|
500
550
|
holdKey: stockHoldKey(claimed.claim.stripeKey),
|
|
501
551
|
lines: reserveLines,
|
|
502
|
-
label: `cart ${hostId}/${cartId}
|
|
552
|
+
label: `cart ${hostId}/${cartId}`,
|
|
553
|
+
// At the pickup location, or the one deliveries leave from (AGL-3624).
|
|
554
|
+
locationId: localFulfillmentLocationId(localPlan)
|
|
503
555
|
});
|
|
504
556
|
if (!held.ok) {
|
|
505
557
|
// Nothing has been minted yet, so the key goes back and the same
|
|
@@ -510,7 +562,7 @@ import { quoteCartExtras } from "./checkout-extras.js";
|
|
|
510
562
|
await releaseStock();
|
|
511
563
|
await claim.release();
|
|
512
564
|
return res.status(409).json({
|
|
513
|
-
error: held.reason === 'sold-out' ? held.productName ? `"${held.productName}" — ${CommerceModel.STOCK_HELD_MESSAGE}` : CommerceModel.STOCK_HELD_MESSAGE : 'Your cart is no longer available'
|
|
565
|
+
error: held.reason === 'sold-out-at-location' ? localStockRefusalMessage(localPlan, held.productName) : held.reason === 'sold-out' ? held.productName ? `"${held.productName}" — ${CommerceModel.STOCK_HELD_MESSAGE}` : CommerceModel.STOCK_HELD_MESSAGE : 'Your cart is no longer available'
|
|
514
566
|
});
|
|
515
567
|
}
|
|
516
568
|
if (held.holdKey) {
|
|
@@ -613,11 +665,11 @@ import { quoteCartExtras } from "./checkout-extras.js";
|
|
|
613
665
|
})) : shippingPlan.options;
|
|
614
666
|
// Coupons (AGL-96 semantics): percent off the items total.
|
|
615
667
|
if (couponCode && !resolvedDiscount) {
|
|
616
|
-
var
|
|
668
|
+
var _ref6;
|
|
617
669
|
const couponRef = hostRef.collection('coupons').doc(couponCode);
|
|
618
670
|
const couponSnapshot = await couponRef.get();
|
|
619
671
|
const coupon = couponSnapshot.data();
|
|
620
|
-
const percentOff = Number((
|
|
672
|
+
const percentOff = Number((_ref6 = coupon == null ? void 0 : coupon.percentOff) != null ? _ref6 : 0);
|
|
621
673
|
const expired = (coupon == null ? void 0 : coupon.expiresAtMs) != null && Number(coupon.expiresAtMs) < Date.now();
|
|
622
674
|
if (!coupon || coupon.enabled === false || expired || !(percentOff > 0 && percentOff <= 100)) {
|
|
623
675
|
// Deterministic and retryable — the shopper fixes the code and
|
|
@@ -767,13 +819,98 @@ import { quoteCartExtras } from "./checkout-extras.js";
|
|
|
767
819
|
};
|
|
768
820
|
}
|
|
769
821
|
}
|
|
822
|
+
// STORE CREDIT ANOTHER PLUGIN KEEPS (AGL-3640) — a rewards balance, a
|
|
823
|
+
// friend's referral credit — by its code, through core's checkout-credits
|
|
824
|
+
// seam; this plugin never reads the account. Held exactly like the gift
|
|
825
|
+
// card above: against what is LEFT after every other reduction, BEFORE
|
|
826
|
+
// Stripe is contacted, keyed by this attempt so a retry re-places the same
|
|
827
|
+
// hold. The webhook takes it in the transaction that writes the order, and
|
|
828
|
+
// a session that expires lets it go.
|
|
829
|
+
let releaseCreditHold = async ()=>undefined;
|
|
830
|
+
let creditHeldCents = 0;
|
|
831
|
+
if (creditCode) {
|
|
832
|
+
const refuseCredit = async (status, error)=>{
|
|
833
|
+
await releaseGiftCardHold();
|
|
834
|
+
await releasePromotionHolds();
|
|
835
|
+
await releaseStock();
|
|
836
|
+
await (claim == null ? void 0 : claim.release());
|
|
837
|
+
return res.status(status).json({
|
|
838
|
+
error,
|
|
839
|
+
creditCodeInvalid: true
|
|
840
|
+
});
|
|
841
|
+
};
|
|
842
|
+
const entry = checkoutCreditProviderForCode(creditCode);
|
|
843
|
+
const offered = entry ? await entry.provider.offered({
|
|
844
|
+
hostId,
|
|
845
|
+
channel: 'online'
|
|
846
|
+
}).catch(()=>false) : false;
|
|
847
|
+
if (!entry || !offered) return refuseCredit(400, CHECKOUT_CREDIT_INVALID_MESSAGE);
|
|
848
|
+
const account = normalizeCheckoutCreditAccount(await entry.provider.resolve({
|
|
849
|
+
hostId,
|
|
850
|
+
code: creditCode,
|
|
851
|
+
channel: 'online',
|
|
852
|
+
customerEmail: email || null,
|
|
853
|
+
staff: false
|
|
854
|
+
}).catch((error)=>{
|
|
855
|
+
console.error('Checkout credit resolve failed', entry.providerId, error);
|
|
856
|
+
return null;
|
|
857
|
+
}));
|
|
858
|
+
if ('error' in account) return refuseCredit(account.status, account.error);
|
|
859
|
+
const maxCents = Math.max(0, itemsCents - totalOffCents);
|
|
860
|
+
// The attempt's key, so a retry re-places the same hold; a request
|
|
861
|
+
// that sent none (an older client) still needs a key of its own.
|
|
862
|
+
const holdKey = claim.stripeKey || `cart:${cartId}:${randomUUID()}`;
|
|
863
|
+
const held = await entry.provider.hold({
|
|
864
|
+
hostId,
|
|
865
|
+
reference: account.reference,
|
|
866
|
+
holdKey,
|
|
867
|
+
maxCents,
|
|
868
|
+
currency: 'usd',
|
|
869
|
+
customerEmail: email || null,
|
|
870
|
+
nowMs: Date.now()
|
|
871
|
+
}).catch((error)=>{
|
|
872
|
+
console.error('Checkout credit hold failed', entry.providerId, error);
|
|
873
|
+
return {
|
|
874
|
+
ok: false,
|
|
875
|
+
status: 409,
|
|
876
|
+
error: 'That rewards code cannot be used right now. Try again.'
|
|
877
|
+
};
|
|
878
|
+
});
|
|
879
|
+
if ('error' in held) {
|
|
880
|
+
return refuseCredit(held.status >= 400 && held.status < 500 ? held.status : 409, held.error);
|
|
881
|
+
}
|
|
882
|
+
const release = async ()=>{
|
|
883
|
+
await entry.provider.release({
|
|
884
|
+
hostId,
|
|
885
|
+
reference: account.reference,
|
|
886
|
+
holdKey
|
|
887
|
+
});
|
|
888
|
+
};
|
|
889
|
+
creditHeldCents = boundedCreditCents(held.cents, maxCents);
|
|
890
|
+
if (creditHeldCents > 0) {
|
|
891
|
+
totalOffCents += creditHeldCents;
|
|
892
|
+
for (const [key, value] of Object.entries(encodeCheckoutCreditMetadata({
|
|
893
|
+
providerId: entry.providerId,
|
|
894
|
+
reference: account.reference,
|
|
895
|
+
holdKey,
|
|
896
|
+
amountCents: creditHeldCents,
|
|
897
|
+
label: account.label,
|
|
898
|
+
last4: account.last4
|
|
899
|
+
}))){
|
|
900
|
+
params.set(`metadata[${key}]`, value);
|
|
901
|
+
}
|
|
902
|
+
releaseCreditHold = release;
|
|
903
|
+
} else {
|
|
904
|
+
await release();
|
|
905
|
+
}
|
|
906
|
+
}
|
|
770
907
|
if (totalOffCents > 0) {
|
|
771
908
|
const stripeCoupon = await fetch('https://api.stripe.com/v1/coupons', {
|
|
772
909
|
method: 'POST',
|
|
773
910
|
headers: _extends({
|
|
774
911
|
Authorization: `Bearer ${process.env.STRIPE_SECRET_KEY}`,
|
|
775
912
|
'Content-Type': 'application/x-www-form-urlencoded'
|
|
776
|
-
}, stripeKeyHeader('coupon')),
|
|
913
|
+
}, stripeKeyHeader(creditHeldCents > 0 ? `coupon-c${creditHeldCents}` : 'coupon')),
|
|
777
914
|
body: new URLSearchParams({
|
|
778
915
|
amount_off: String(Math.min(totalOffCents, itemsCents)),
|
|
779
916
|
currency: 'usd',
|
|
@@ -785,6 +922,20 @@ import { quoteCartExtras } from "./checkout-extras.js";
|
|
|
785
922
|
// Scaled ONCE, by the reduction that actually reached the session.
|
|
786
923
|
feeCents = Math.round(feeCents * Math.max(0, itemsCents - totalOffCents) / Math.max(1, itemsCents));
|
|
787
924
|
chargedItemsCents = Math.max(0, itemsCents - totalOffCents);
|
|
925
|
+
} else if (creditHeldCents > 0) {
|
|
926
|
+
// A rewards balance that did not reach the price must not be taken
|
|
927
|
+
// from the member when the session is paid (AGL-3640): refuse, and
|
|
928
|
+
// hand back everything this attempt held, rather than sell at full
|
|
929
|
+
// price with their credit spent.
|
|
930
|
+
console.error('Stripe coupon error', stripeCoupon == null ? void 0 : stripeCoupon.error);
|
|
931
|
+
await releaseGiftCardHold();
|
|
932
|
+
await releaseCreditHold();
|
|
933
|
+
await releasePromotionHolds();
|
|
934
|
+
await releaseStock();
|
|
935
|
+
await claim.release();
|
|
936
|
+
return res.status(502).json({
|
|
937
|
+
error: 'Checkout failed'
|
|
938
|
+
});
|
|
788
939
|
}
|
|
789
940
|
}
|
|
790
941
|
// THE FLOOR (AGL-2232). A rate above zero on goods the shopper actually
|
|
@@ -915,6 +1066,7 @@ import { quoteCartExtras } from "./checkout-extras.js";
|
|
|
915
1066
|
// BELOW the claim on this path, so release it: the merchant fixes the
|
|
916
1067
|
// setting and the shopper retries under the same key (AGL-1697).
|
|
917
1068
|
await releaseGiftCardHold();
|
|
1069
|
+
await releaseCreditHold();
|
|
918
1070
|
await releasePromotionHolds();
|
|
919
1071
|
await releaseStock();
|
|
920
1072
|
await claim.release();
|
|
@@ -930,6 +1082,7 @@ import { quoteCartExtras } from "./checkout-extras.js";
|
|
|
930
1082
|
// the undecided case above.
|
|
931
1083
|
// Below the claim here too, so release it for the same reason.
|
|
932
1084
|
await releaseGiftCardHold();
|
|
1085
|
+
await releaseCreditHold();
|
|
933
1086
|
await releasePromotionHolds();
|
|
934
1087
|
await releaseStock();
|
|
935
1088
|
await claim.release();
|
|
@@ -968,6 +1121,7 @@ import { quoteCartExtras } from "./checkout-extras.js";
|
|
|
968
1121
|
// The same visible refusal as the store's own rate: never an
|
|
969
1122
|
// untaxed session.
|
|
970
1123
|
await releaseGiftCardHold();
|
|
1124
|
+
await releaseCreditHold();
|
|
971
1125
|
await releasePromotionHolds();
|
|
972
1126
|
await releaseStock();
|
|
973
1127
|
await claim.release();
|
|
@@ -1012,6 +1166,7 @@ import { quoteCartExtras } from "./checkout-extras.js";
|
|
|
1012
1166
|
// (AGL-1697); the retry re-derives the same digest, so Stripe
|
|
1013
1167
|
// replays any rate the first run did mint.
|
|
1014
1168
|
await releaseGiftCardHold();
|
|
1169
|
+
await releaseCreditHold();
|
|
1015
1170
|
await releasePromotionHolds();
|
|
1016
1171
|
await releaseStock();
|
|
1017
1172
|
await claim.release();
|
|
@@ -1066,6 +1221,10 @@ import { quoteCartExtras } from "./checkout-extras.js";
|
|
|
1066
1221
|
shippingFloorCents: cartShippingFloorCents
|
|
1067
1222
|
})).forEach(([key, value])=>params.set(key, value));
|
|
1068
1223
|
params.set('metadata[type]', 'commerce-cart');
|
|
1224
|
+
// How the order reaches the buyer (AGL-3624): the webhook routes it.
|
|
1225
|
+
if (localPlan.kind === 'pickup' || localPlan.kind === 'local_delivery') {
|
|
1226
|
+
appendLocalFulfillmentMetadata(params, localPlan.metadata);
|
|
1227
|
+
}
|
|
1069
1228
|
for (const [key, value] of Object.entries(taxEngineSessionMetadata(engineTax.stamp))){
|
|
1070
1229
|
params.set(key, value);
|
|
1071
1230
|
}
|
|
@@ -1112,7 +1271,7 @@ import { quoteCartExtras } from "./checkout-extras.js";
|
|
|
1112
1271
|
// and is identical on both checkout paths. This swaps the redirect's URL
|
|
1113
1272
|
// pair for `ui_mode` + `return_url` and stops. Off unless the flag is on for
|
|
1114
1273
|
// this org AND a publishable key exists; see `resolveNativeCheckoutMode`.
|
|
1115
|
-
const nativeMode = await resolveNativeCheckoutMode(String((
|
|
1274
|
+
const nativeMode = await resolveNativeCheckoutMode(String((_ref3 = ownerOrg == null ? void 0 : (_ownerOrg_org2 = ownerOrg.org) == null ? void 0 : _ownerOrg_org2.id) != null ? _ref3 : ''));
|
|
1116
1275
|
if (nativeMode.native) {
|
|
1117
1276
|
applyNativeCheckoutParams(params, `${backUrl}${separator}order=success&session_id={CHECKOUT_SESSION_ID}`);
|
|
1118
1277
|
}
|
|
@@ -1128,7 +1287,7 @@ import { quoteCartExtras } from "./checkout-extras.js";
|
|
|
1128
1287
|
headers: _extends({
|
|
1129
1288
|
Authorization: `Bearer ${process.env.STRIPE_SECRET_KEY}`,
|
|
1130
1289
|
'Content-Type': 'application/x-www-form-urlencoded'
|
|
1131
|
-
}, stripeKeyHeader(`${engineTax.stamp ? `session-tax-${(
|
|
1290
|
+
}, stripeKeyHeader(`${engineTax.stamp ? `session-tax-${(_ref4 = (_engineTax_quote = engineTax.quote) == null ? void 0 : _engineTax_quote.taxCents) != null ? _ref4 : 'own'}-${engineTax.stamp.status}` : 'session'}${extrasCents > 0 ? `-x${extrasCents}` : ''}${creditHeldCents > 0 ? `-c${creditHeldCents}` : ''}`), nativeCheckoutStripeHeaders(nativeMode)),
|
|
1132
1291
|
body: params.toString()
|
|
1133
1292
|
});
|
|
1134
1293
|
const session = await response.json();
|
|
@@ -1144,6 +1303,7 @@ import { quoteCartExtras } from "./checkout-extras.js";
|
|
|
1144
1303
|
// does not lock this cart out. The retry re-derives the same derived
|
|
1145
1304
|
// keys, so Stripe replays whatever objects the first run did create.
|
|
1146
1305
|
await releaseGiftCardHold();
|
|
1306
|
+
await releaseCreditHold();
|
|
1147
1307
|
await releasePromotionHolds();
|
|
1148
1308
|
await releaseStock();
|
|
1149
1309
|
await claim.release();
|