@aglyn/plugins-commerce 1.0.0-beta.231 → 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/catalog-organization-card.component.js +1 -0
- package/src/lib/components/console/catalog-organization-card.component.js.map +1 -1
- package/src/lib/components/console/host-orders-card.component.js +42 -11
- 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 +228 -51
- package/src/lib/components/console/pos-page.component.js.map +1 -1
- package/src/lib/components/console/pos-zones.d.ts +23 -0
- package/src/lib/components/console/pos-zones.js +31 -0
- package/src/lib/components/console/pos-zones.js.map +1 -0
- package/src/lib/components/console/product-editor-dialog.component.js +10 -64
- package/src/lib/components/console/product-editor-dialog.component.js.map +1 -1
- package/src/lib/components/console/products-hub-card.component.js +46 -30
- 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/console/storefront-tax-summary-card.component.js +1 -0
- package/src/lib/components/console/storefront-tax-summary-card.component.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/declarations.server.js +21 -0
- package/src/lib/declarations.server.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 +103 -1
- package/src/lib/model/commerce-orders.js +2 -1
- 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 +7 -1
- package/src/lib/model/commerce.js.map +1 -1
- package/src/lib/model/index.d.ts +5 -0
- package/src/lib/model/index.js +5 -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/model/product-write.d.ts +186 -0
- package/src/lib/model/product-write.js +116 -0
- package/src/lib/model/product-write.js.map +1 -0
- package/src/lib/plugin-config.js +6 -2
- package/src/lib/plugin-config.js.map +1 -1
- package/src/lib/plugin.js +11 -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/channel-order-updates.d.ts +50 -0
- package/src/lib/server/channel-order-updates.js +290 -0
- package/src/lib/server/channel-order-updates.js.map +1 -0
- package/src/lib/server/channel-orders.d.ts +85 -0
- package/src/lib/server/channel-orders.js +543 -0
- package/src/lib/server/channel-orders.js.map +1 -0
- 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/product-catalog.js +5 -1
- package/src/lib/server/product-catalog.js.map +1 -1
- package/src/lib/server/product-drafts.d.ts +5 -1
- package/src/lib/server/product-drafts.js +3 -3
- package/src/lib/server/product-drafts.js.map +1 -1
- package/src/lib/server/product-writer.d.ts +19 -0
- package/src/lib/server/product-writer.js +261 -0
- package/src/lib/server/product-writer.js.map +1 -0
- package/src/lib/server/products-write.d.ts +61 -0
- package/src/lib/server/products-write.js +375 -0
- package/src/lib/server/products-write.js.map +1 -0
- 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 +21 -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
- package/src/lib/testing/memory-firestore.d.ts +16 -3
- package/src/lib/testing/memory-firestore.js +11 -3
- package/src/lib/testing/memory-firestore.js.map +1 -1
- package/src/lib/transfer/products.server.d.ts +5 -0
- package/src/lib/transfer/products.server.js +2 -2
- package/src/lib/transfer/products.server.js.map +1 -1
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ 'use client';
|
|
17
|
+
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
18
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
19
|
+
import { Alert, Box, Button, Dialog, DialogActions, DialogContent, DialogTitle, Stack, TextField, Typography } from "@mui/material";
|
|
20
|
+
import { useEffect, useState } from "react";
|
|
21
|
+
import { buildPosReceipt } from "../../../model/commerce-pos-ops.js";
|
|
22
|
+
import { posReceiptLogoUrl, printPosReceipt } from "../pos-ops/pos-receipt.js";
|
|
23
|
+
import { centsFromInput, usd } from "../pos/pos-api.js";
|
|
24
|
+
import { POS_TOUCH_PX } from "../pos/pos-product-grid.component.js";
|
|
25
|
+
/** Prints an offline sale's receipt from what the register queued. */ export function printPosOfflineReceipt(rung, kit, hostId, options = {}) {
|
|
26
|
+
var _ref;
|
|
27
|
+
const logoUrl = posReceiptLogoUrl(kit == null ? void 0 : kit.receipt.logo, hostId, typeof window === 'undefined' ? null : window.location.origin);
|
|
28
|
+
printPosReceipt(buildPosReceipt(_extends({
|
|
29
|
+
orderId: rung.saleKey,
|
|
30
|
+
order: rung.order,
|
|
31
|
+
store: _extends({
|
|
32
|
+
name: (_ref = kit == null ? void 0 : kit.receipt.name) != null ? _ref : 'Receipt'
|
|
33
|
+
}, logoUrl ? {
|
|
34
|
+
logoUrl
|
|
35
|
+
} : {}, (kit == null ? void 0 : kit.receipt.address) ? {
|
|
36
|
+
address: kit.receipt.address
|
|
37
|
+
} : {}, (kit == null ? void 0 : kit.receipt.footer) ? {
|
|
38
|
+
footer: kit.receipt.footer
|
|
39
|
+
} : {}, (kit == null ? void 0 : kit.receipt.returnPolicy) ? {
|
|
40
|
+
returnPolicy: kit.receipt.returnPolicy
|
|
41
|
+
} : {})
|
|
42
|
+
}, options.gift ? {
|
|
43
|
+
gift: true
|
|
44
|
+
} : {}, options.registerName ? {
|
|
45
|
+
registerName: options.registerName
|
|
46
|
+
} : {}, options.cashierName ? {
|
|
47
|
+
cashierName: options.cashierName
|
|
48
|
+
} : {})));
|
|
49
|
+
}
|
|
50
|
+
export function PosOfflineCheckout(props) {
|
|
51
|
+
var _ref, _offline_unavailableReason, _ref1;
|
|
52
|
+
var _rung_sale_customer, _offline_kit;
|
|
53
|
+
const { offline, lines, discountPct } = props;
|
|
54
|
+
const [received, setReceived] = useState('');
|
|
55
|
+
const [busy, setBusy] = useState(false);
|
|
56
|
+
const [failed, setFailed] = useState(false);
|
|
57
|
+
const [rung, setRung] = useState(null);
|
|
58
|
+
useEffect(()=>{
|
|
59
|
+
if (!props.open) {
|
|
60
|
+
setReceived('');
|
|
61
|
+
setFailed(false);
|
|
62
|
+
setRung(null);
|
|
63
|
+
}
|
|
64
|
+
}, [
|
|
65
|
+
props.open
|
|
66
|
+
]);
|
|
67
|
+
const totals = rung ? rung.sale.totals : offline.totalsFor(lines, discountPct);
|
|
68
|
+
const owed = (_ref = totals == null ? void 0 : totals.totalCents) != null ? _ref : 0;
|
|
69
|
+
const tendered = centsFromInput(received);
|
|
70
|
+
const overLimit = Boolean(offline.kit && discountPct > offline.kit.maxDiscountPct);
|
|
71
|
+
const quick = [
|
|
72
|
+
...new Set([
|
|
73
|
+
owed,
|
|
74
|
+
Math.ceil(owed / 500) * 500,
|
|
75
|
+
Math.ceil(owed / 1000) * 1000,
|
|
76
|
+
Math.ceil(owed / 2000) * 2000
|
|
77
|
+
])
|
|
78
|
+
].filter((value)=>value >= owed).slice(0, 4);
|
|
79
|
+
const take = async ()=>{
|
|
80
|
+
if (busy || !totals || tendered < owed) return;
|
|
81
|
+
setBusy(true);
|
|
82
|
+
setFailed(false);
|
|
83
|
+
const result = await offline.ringCashSale(_extends({
|
|
84
|
+
lines,
|
|
85
|
+
discountPct,
|
|
86
|
+
cashTenderedCents: tendered
|
|
87
|
+
}, props.customer ? {
|
|
88
|
+
customer: props.customer
|
|
89
|
+
} : {}));
|
|
90
|
+
setBusy(false);
|
|
91
|
+
if (!result) {
|
|
92
|
+
setFailed(true);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
setRung(result);
|
|
96
|
+
props.onRung(result);
|
|
97
|
+
};
|
|
98
|
+
const print = (gift)=>{
|
|
99
|
+
if (!rung) return;
|
|
100
|
+
printPosOfflineReceipt(rung, offline.kit, props.hostId, _extends({
|
|
101
|
+
gift
|
|
102
|
+
}, props.registerName ? {
|
|
103
|
+
registerName: props.registerName
|
|
104
|
+
} : {}, props.cashierName ? {
|
|
105
|
+
cashierName: props.cashierName
|
|
106
|
+
} : {}));
|
|
107
|
+
};
|
|
108
|
+
const close = ()=>rung ? props.onDone() : props.onClose();
|
|
109
|
+
return /*#__PURE__*/ _jsxs(Dialog, {
|
|
110
|
+
open: props.open,
|
|
111
|
+
onClose: close,
|
|
112
|
+
maxWidth: "xs",
|
|
113
|
+
fullWidth: true,
|
|
114
|
+
children: [
|
|
115
|
+
/*#__PURE__*/ _jsx(DialogTitle, {
|
|
116
|
+
children: rung ? 'Sale saved on this register' : `Cash — ${usd(owed)}`
|
|
117
|
+
}),
|
|
118
|
+
/*#__PURE__*/ _jsxs(DialogContent, {
|
|
119
|
+
sx: {
|
|
120
|
+
display: 'flex',
|
|
121
|
+
flexDirection: 'column',
|
|
122
|
+
gap: 2
|
|
123
|
+
},
|
|
124
|
+
children: [
|
|
125
|
+
!totals ? /*#__PURE__*/ _jsx(Alert, {
|
|
126
|
+
severity: "warning",
|
|
127
|
+
sx: {
|
|
128
|
+
mt: 1
|
|
129
|
+
},
|
|
130
|
+
children: (_offline_unavailableReason = offline.unavailableReason) != null ? _offline_unavailableReason : 'This basket cannot be rung offline.'
|
|
131
|
+
}) : /*#__PURE__*/ _jsxs(Stack, {
|
|
132
|
+
spacing: 0.5,
|
|
133
|
+
sx: {
|
|
134
|
+
mt: 1
|
|
135
|
+
},
|
|
136
|
+
"aria-label": "Offline totals",
|
|
137
|
+
children: [
|
|
138
|
+
/*#__PURE__*/ _jsx(Row, {
|
|
139
|
+
label: "Items",
|
|
140
|
+
value: usd(totals.itemsCents)
|
|
141
|
+
}),
|
|
142
|
+
totals.discountCents > 0 ? /*#__PURE__*/ _jsx(Row, {
|
|
143
|
+
label: "Discount",
|
|
144
|
+
value: `-${usd(totals.discountCents)}`
|
|
145
|
+
}) : null,
|
|
146
|
+
/*#__PURE__*/ _jsx(Row, {
|
|
147
|
+
label: "Tax",
|
|
148
|
+
value: usd(totals.taxCents)
|
|
149
|
+
}),
|
|
150
|
+
/*#__PURE__*/ _jsx(Row, {
|
|
151
|
+
label: "Total",
|
|
152
|
+
value: usd(totals.totalCents),
|
|
153
|
+
strong: true
|
|
154
|
+
})
|
|
155
|
+
]
|
|
156
|
+
}),
|
|
157
|
+
rung ? /*#__PURE__*/ _jsxs(_Fragment, {
|
|
158
|
+
children: [
|
|
159
|
+
/*#__PURE__*/ _jsx(Alert, {
|
|
160
|
+
severity: "success",
|
|
161
|
+
children: rung.sale.changeCents > 0 ? `Change due: ${usd(rung.sale.changeCents)}` : 'No change due.'
|
|
162
|
+
}),
|
|
163
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
164
|
+
variant: "body2",
|
|
165
|
+
color: "text.secondary",
|
|
166
|
+
children: ((_rung_sale_customer = rung.sale.customer) == null ? void 0 : _rung_sale_customer.email) ? 'It syncs when the register is back online, and the emailed receipt goes then.' : 'It syncs when the register is back online.'
|
|
167
|
+
})
|
|
168
|
+
]
|
|
169
|
+
}) : totals ? /*#__PURE__*/ _jsxs(_Fragment, {
|
|
170
|
+
children: [
|
|
171
|
+
overLimit ? /*#__PURE__*/ _jsx(Alert, {
|
|
172
|
+
severity: "error",
|
|
173
|
+
children: `This register may discount up to ${(_ref1 = (_offline_kit = offline.kit) == null ? void 0 : _offline_kit.maxDiscountPct) != null ? _ref1 : 0}%.`
|
|
174
|
+
}) : null,
|
|
175
|
+
/*#__PURE__*/ _jsx(TextField, {
|
|
176
|
+
label: "Cash received ($)",
|
|
177
|
+
value: received,
|
|
178
|
+
onChange: (event)=>setReceived(event.target.value.replace(/[^0-9.]/g, '')),
|
|
179
|
+
autoFocus: true,
|
|
180
|
+
slotProps: {
|
|
181
|
+
htmlInput: {
|
|
182
|
+
inputMode: 'decimal'
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}),
|
|
186
|
+
/*#__PURE__*/ _jsx(Stack, {
|
|
187
|
+
direction: "row",
|
|
188
|
+
spacing: 1,
|
|
189
|
+
sx: {
|
|
190
|
+
flexWrap: 'wrap',
|
|
191
|
+
rowGap: 1
|
|
192
|
+
},
|
|
193
|
+
children: quick.map((cents)=>/*#__PURE__*/ _jsx(Button, {
|
|
194
|
+
variant: "outlined",
|
|
195
|
+
onClick: ()=>setReceived((cents / 100).toFixed(2)),
|
|
196
|
+
sx: {
|
|
197
|
+
minHeight: POS_TOUCH_PX
|
|
198
|
+
},
|
|
199
|
+
children: cents === owed ? 'Exact' : usd(cents)
|
|
200
|
+
}, cents))
|
|
201
|
+
}),
|
|
202
|
+
tendered > 0 && tendered >= owed ? /*#__PURE__*/ _jsx(Alert, {
|
|
203
|
+
severity: "success",
|
|
204
|
+
children: `Change: ${usd(tendered - owed)}`
|
|
205
|
+
}) : tendered > 0 ? /*#__PURE__*/ _jsx(Alert, {
|
|
206
|
+
severity: "info",
|
|
207
|
+
children: `Offline sales take the whole total in cash: ${usd(owed - tendered)} more.`
|
|
208
|
+
}) : null,
|
|
209
|
+
failed ? /*#__PURE__*/ _jsx(Alert, {
|
|
210
|
+
severity: "error",
|
|
211
|
+
children: 'This register could not save the sale. Do not take the cash; try again.'
|
|
212
|
+
}) : null
|
|
213
|
+
]
|
|
214
|
+
}) : null
|
|
215
|
+
]
|
|
216
|
+
}),
|
|
217
|
+
/*#__PURE__*/ _jsx(DialogActions, {
|
|
218
|
+
children: rung ? /*#__PURE__*/ _jsxs(_Fragment, {
|
|
219
|
+
children: [
|
|
220
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
221
|
+
onClick: ()=>print(true),
|
|
222
|
+
sx: {
|
|
223
|
+
minHeight: POS_TOUCH_PX
|
|
224
|
+
},
|
|
225
|
+
children: 'Gift receipt'
|
|
226
|
+
}),
|
|
227
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
228
|
+
onClick: ()=>print(false),
|
|
229
|
+
sx: {
|
|
230
|
+
minHeight: POS_TOUCH_PX
|
|
231
|
+
},
|
|
232
|
+
children: 'Print receipt'
|
|
233
|
+
}),
|
|
234
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
235
|
+
variant: "contained",
|
|
236
|
+
onClick: props.onDone,
|
|
237
|
+
sx: {
|
|
238
|
+
minHeight: POS_TOUCH_PX
|
|
239
|
+
},
|
|
240
|
+
children: 'New sale'
|
|
241
|
+
})
|
|
242
|
+
]
|
|
243
|
+
}) : /*#__PURE__*/ _jsxs(_Fragment, {
|
|
244
|
+
children: [
|
|
245
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
246
|
+
onClick: props.onClose,
|
|
247
|
+
sx: {
|
|
248
|
+
minHeight: POS_TOUCH_PX
|
|
249
|
+
},
|
|
250
|
+
children: 'Cancel'
|
|
251
|
+
}),
|
|
252
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
253
|
+
variant: "contained",
|
|
254
|
+
disabled: busy || !totals || overLimit || tendered < owed,
|
|
255
|
+
onClick: ()=>void take(),
|
|
256
|
+
sx: {
|
|
257
|
+
minHeight: POS_TOUCH_PX
|
|
258
|
+
},
|
|
259
|
+
children: busy ? 'Saving…' : 'Take cash'
|
|
260
|
+
})
|
|
261
|
+
]
|
|
262
|
+
})
|
|
263
|
+
})
|
|
264
|
+
]
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
PosOfflineCheckout.displayName = 'PosOfflineCheckout';
|
|
268
|
+
function Row(props) {
|
|
269
|
+
return /*#__PURE__*/ _jsxs(Box, {
|
|
270
|
+
sx: {
|
|
271
|
+
display: 'flex',
|
|
272
|
+
justifyContent: 'space-between'
|
|
273
|
+
},
|
|
274
|
+
children: [
|
|
275
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
276
|
+
variant: props.strong ? 'subtitle1' : 'body2',
|
|
277
|
+
children: props.label
|
|
278
|
+
}),
|
|
279
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
280
|
+
variant: props.strong ? 'subtitle1' : 'body2',
|
|
281
|
+
children: props.value
|
|
282
|
+
})
|
|
283
|
+
]
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
//# sourceMappingURL=pos-offline-checkout.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../../../libs/plugins/commerce/src/lib/components/console/pos-offline/pos-offline-checkout.component.tsx"],"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'use client'\n\nimport {\n Alert,\n Box,\n Button,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n Stack,\n TextField,\n Typography,\n} from '@mui/material'\nimport { useEffect, useState } from 'react'\nimport type * as CommerceModel from '../../../model'\nimport { buildPosReceipt } from '../../../model/commerce-pos-ops'\nimport { posReceiptLogoUrl, printPosReceipt } from '../pos-ops/pos-receipt'\nimport { centsFromInput, usd } from '../pos/pos-api'\nimport { POS_TOUCH_PX } from '../pos/pos-product-grid.component'\nimport type { PosOfflineRungSale, PosOfflineState } from './use-pos-offline'\nimport type { RegisterLine } from '../pos/pos-cart-panel.component'\n\n/*==========================================\n * AN OFFLINE CASH SALE (AGL-3625): the total the register rings from its\n * cached catalog and the store's rate, the cash handed over, and — once the\n * sale is on the device — the change and the printed receipt. The emailed\n * receipt goes when the sale syncs.\n *=========================================*/\n\nexport interface PosOfflineCheckoutProps {\n open: boolean\n offline: PosOfflineState\n hostId: string\n lines: RegisterLine[]\n discountPct: number\n customer?: { email?: string | null; name?: string | null; kind?: string; id?: string } | null\n registerName?: string\n cashierName?: string\n onClose: () => void\n /** The sale is on the device; the basket can be cleared. */\n onRung: (rung: PosOfflineRungSale) => void\n /** The cashier is done with the receipt step. */\n onDone: () => void\n}\n\n/** Prints an offline sale's receipt from what the register queued. */\nexport function printPosOfflineReceipt(\n rung: PosOfflineRungSale,\n kit: PosOfflineState['kit'],\n hostId: string,\n options: { gift?: boolean; registerName?: string; cashierName?: string } = {},\n): void {\n const logoUrl = posReceiptLogoUrl(\n kit?.receipt.logo,\n hostId,\n typeof window === 'undefined' ? null : window.location.origin,\n )\n printPosReceipt(\n buildPosReceipt({\n orderId: rung.saleKey,\n order: rung.order as never,\n store: {\n name: kit?.receipt.name ?? 'Receipt',\n ...(logoUrl ? { logoUrl } : {}),\n ...(kit?.receipt.address ? { address: kit.receipt.address } : {}),\n ...(kit?.receipt.footer ? { footer: kit.receipt.footer } : {}),\n ...(kit?.receipt.returnPolicy ? { returnPolicy: kit.receipt.returnPolicy } : {}),\n },\n ...(options.gift ? { gift: true } : {}),\n ...(options.registerName ? { registerName: options.registerName } : {}),\n ...(options.cashierName ? { cashierName: options.cashierName } : {}),\n }),\n )\n}\n\nexport function PosOfflineCheckout(props: PosOfflineCheckoutProps) {\n const { offline, lines, discountPct } = props\n const [received, setReceived] = useState('')\n const [busy, setBusy] = useState(false)\n const [failed, setFailed] = useState(false)\n const [rung, setRung] = useState<PosOfflineRungSale | null>(null)\n useEffect(() => {\n if (!props.open) {\n setReceived('')\n setFailed(false)\n setRung(null)\n }\n }, [props.open])\n\n const totals: CommerceModel.OrderTotals | null = rung ? rung.sale.totals : offline.totalsFor(lines, discountPct)\n const owed = totals?.totalCents ?? 0\n const tendered = centsFromInput(received)\n const overLimit = Boolean(offline.kit && discountPct > offline.kit.maxDiscountPct)\n const quick = [\n ...new Set([owed, Math.ceil(owed / 500) * 500, Math.ceil(owed / 1000) * 1000, Math.ceil(owed / 2000) * 2000]),\n ]\n .filter((value) => value >= owed)\n .slice(0, 4)\n\n const take = async () => {\n if (busy || !totals || tendered < owed) return\n setBusy(true)\n setFailed(false)\n const result = await offline.ringCashSale({\n lines,\n discountPct,\n cashTenderedCents: tendered,\n ...(props.customer ? { customer: props.customer } : {}),\n })\n setBusy(false)\n if (!result) {\n setFailed(true)\n return\n }\n setRung(result)\n props.onRung(result)\n }\n\n const print = (gift: boolean) => {\n if (!rung) return\n printPosOfflineReceipt(rung, offline.kit, props.hostId, {\n gift,\n ...(props.registerName ? { registerName: props.registerName } : {}),\n ...(props.cashierName ? { cashierName: props.cashierName } : {}),\n })\n }\n\n const close = () => (rung ? props.onDone() : props.onClose())\n\n return (\n <Dialog open={props.open} onClose={close} maxWidth=\"xs\" fullWidth>\n <DialogTitle>{rung ? 'Sale saved on this register' : `Cash — ${usd(owed)}`}</DialogTitle>\n <DialogContent sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>\n {!totals ? (\n <Alert severity=\"warning\" sx={{ mt: 1 }}>\n {offline.unavailableReason ?? 'This basket cannot be rung offline.'}\n </Alert>\n ) : (\n <Stack spacing={0.5} sx={{ mt: 1 }} aria-label=\"Offline totals\">\n <Row label=\"Items\" value={usd(totals.itemsCents)} />\n {totals.discountCents > 0 ? <Row label=\"Discount\" value={`-${usd(totals.discountCents)}`} /> : null}\n <Row label=\"Tax\" value={usd(totals.taxCents)} />\n <Row label=\"Total\" value={usd(totals.totalCents)} strong />\n </Stack>\n )}\n {rung ? (\n <>\n <Alert severity=\"success\">\n {rung.sale.changeCents > 0 ? `Change due: ${usd(rung.sale.changeCents)}` : 'No change due.'}\n </Alert>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {rung.sale.customer?.email\n ? 'It syncs when the register is back online, and the emailed receipt goes then.'\n : 'It syncs when the register is back online.'}\n </Typography>\n </>\n ) : totals ? (\n <>\n {overLimit ? (\n <Alert severity=\"error\">\n {`This register may discount up to ${offline.kit?.maxDiscountPct ?? 0}%.`}\n </Alert>\n ) : null}\n <TextField\n label=\"Cash received ($)\"\n value={received}\n onChange={(event) => setReceived(event.target.value.replace(/[^0-9.]/g, ''))}\n autoFocus\n slotProps={{ htmlInput: { inputMode: 'decimal' } }}\n />\n <Stack direction=\"row\" spacing={1} sx={{ flexWrap: 'wrap', rowGap: 1 }}>\n {quick.map((cents) => (\n <Button\n key={cents}\n variant=\"outlined\"\n onClick={() => setReceived((cents / 100).toFixed(2))}\n sx={{ minHeight: POS_TOUCH_PX }}\n >\n {cents === owed ? 'Exact' : usd(cents)}\n </Button>\n ))}\n </Stack>\n {tendered > 0 && tendered >= owed ? (\n <Alert severity=\"success\">{`Change: ${usd(tendered - owed)}`}</Alert>\n ) : tendered > 0 ? (\n <Alert severity=\"info\">{`Offline sales take the whole total in cash: ${usd(owed - tendered)} more.`}</Alert>\n ) : null}\n {failed ? (\n <Alert severity=\"error\">\n {'This register could not save the sale. Do not take the cash; try again.'}\n </Alert>\n ) : null}\n </>\n ) : null}\n </DialogContent>\n <DialogActions>\n {rung ? (\n <>\n <Button onClick={() => print(true)} sx={{ minHeight: POS_TOUCH_PX }}>\n {'Gift receipt'}\n </Button>\n <Button onClick={() => print(false)} sx={{ minHeight: POS_TOUCH_PX }}>\n {'Print receipt'}\n </Button>\n <Button variant=\"contained\" onClick={props.onDone} sx={{ minHeight: POS_TOUCH_PX }}>\n {'New sale'}\n </Button>\n </>\n ) : (\n <>\n <Button onClick={props.onClose} sx={{ minHeight: POS_TOUCH_PX }}>\n {'Cancel'}\n </Button>\n <Button\n variant=\"contained\"\n disabled={busy || !totals || overLimit || tendered < owed}\n onClick={() => void take()}\n sx={{ minHeight: POS_TOUCH_PX }}\n >\n {busy ? 'Saving…' : 'Take cash'}\n </Button>\n </>\n )}\n </DialogActions>\n </Dialog>\n )\n}\nPosOfflineCheckout.displayName = 'PosOfflineCheckout'\n\nfunction Row(props: { label: string; value: string; strong?: boolean }) {\n return (\n <Box sx={{ display: 'flex', justifyContent: 'space-between' }}>\n <Typography variant={props.strong ? 'subtitle1' : 'body2'}>{props.label}</Typography>\n <Typography variant={props.strong ? 'subtitle1' : 'body2'}>{props.value}</Typography>\n </Box>\n )\n}\n"],"names":["Alert","Box","Button","Dialog","DialogActions","DialogContent","DialogTitle","Stack","TextField","Typography","useEffect","useState","buildPosReceipt","posReceiptLogoUrl","printPosReceipt","centsFromInput","usd","POS_TOUCH_PX","printPosOfflineReceipt","rung","kit","hostId","options","logoUrl","receipt","logo","window","location","origin","orderId","saleKey","order","store","name","address","footer","returnPolicy","gift","registerName","cashierName","PosOfflineCheckout","props","offline","lines","discountPct","received","setReceived","busy","setBusy","failed","setFailed","setRung","open","totals","sale","totalsFor","owed","totalCents","tendered","overLimit","Boolean","maxDiscountPct","quick","Set","Math","ceil","filter","value","slice","take","result","ringCashSale","cashTenderedCents","customer","onRung","print","close","onDone","onClose","maxWidth","fullWidth","sx","display","flexDirection","gap","severity","mt","unavailableReason","spacing","aria-label","Row","label","itemsCents","discountCents","taxCents","strong","changeCents","variant","color","email","onChange","event","target","replace","autoFocus","slotProps","htmlInput","inputMode","direction","flexWrap","rowGap","map","cents","onClick","toFixed","minHeight","disabled","displayName","justifyContent"],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
import type { PosOfflineKit, PosOfflineRefusal, PosOfflineSale } from '../../../model/commerce-pos-offline';
|
|
18
|
+
/** One product as the offline grid sells it. */
|
|
19
|
+
export type PosOfflineProduct = Record<string, any> & {
|
|
20
|
+
$id: string;
|
|
21
|
+
name?: string;
|
|
22
|
+
};
|
|
23
|
+
/** The kit as the device keeps it: the server's rules and the catalog. */
|
|
24
|
+
export interface PosOfflineDeviceKit {
|
|
25
|
+
scope: string;
|
|
26
|
+
kit: PosOfflineKit | null;
|
|
27
|
+
kitSavedAtMs: number;
|
|
28
|
+
products: PosOfflineProduct[];
|
|
29
|
+
catalogSavedAtMs: number;
|
|
30
|
+
}
|
|
31
|
+
/** A sale on the device, with where it stands. */
|
|
32
|
+
export interface PosOfflineQueuedSale {
|
|
33
|
+
scope: string;
|
|
34
|
+
saleKey: string;
|
|
35
|
+
sale: PosOfflineSale;
|
|
36
|
+
/** `queued` waits for the connection; `refused` waits for the cashier. */
|
|
37
|
+
state: 'queued' | 'refused';
|
|
38
|
+
queuedAtMs: number;
|
|
39
|
+
attempts: number;
|
|
40
|
+
error?: string;
|
|
41
|
+
reason?: PosOfflineRefusal;
|
|
42
|
+
}
|
|
43
|
+
export interface PosOfflineStore {
|
|
44
|
+
readonly scope: string;
|
|
45
|
+
loadKit(): Promise<PosOfflineDeviceKit | null>;
|
|
46
|
+
saveKit(kit: Omit<PosOfflineDeviceKit, 'scope'>): Promise<void>;
|
|
47
|
+
/** Every sale this member queued at this site, oldest first. */
|
|
48
|
+
listSales(): Promise<PosOfflineQueuedSale[]>;
|
|
49
|
+
putSale(sale: Omit<PosOfflineQueuedSale, 'scope'>): Promise<void>;
|
|
50
|
+
removeSale(saleKey: string): Promise<void>;
|
|
51
|
+
}
|
|
52
|
+
/** The scope every key carries: one member at one site. */
|
|
53
|
+
export declare function posOfflineScope(uid: string, hostId: string): string;
|
|
54
|
+
/**
|
|
55
|
+
* The device store for one member at one site, or `null` when this browser
|
|
56
|
+
* will not keep one. Never throws.
|
|
57
|
+
*/
|
|
58
|
+
export declare function openPosOfflineStore(scope: {
|
|
59
|
+
uid: string;
|
|
60
|
+
hostId: string;
|
|
61
|
+
}, factory?: IDBFactory | undefined): Promise<PosOfflineStore | null>;
|
|
62
|
+
/** A product trimmed and made plain for the device. */
|
|
63
|
+
export declare function posOfflineProduct(product: Record<string, any>): PosOfflineProduct | null;
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
17
|
+
import { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_without_properties_loose";
|
|
18
|
+
/*==========================================
|
|
19
|
+
* WHAT THE REGISTER KEEPS ON THE DEVICE (AGL-3625), in IndexedDB.
|
|
20
|
+
*
|
|
21
|
+
* Two things, both scoped to ONE signed-in member at ONE site — the scope is
|
|
22
|
+
* part of every key, so another member on the same tablet, or the same
|
|
23
|
+
* member in another workspace, never reads a sale or a catalog that is not
|
|
24
|
+
* theirs:
|
|
25
|
+
*
|
|
26
|
+
* - the KIT: the server's offline rules for the site plus the catalog the
|
|
27
|
+
* grid sells from, refreshed while online. Products only; nothing about
|
|
28
|
+
* any customer.
|
|
29
|
+
* - the QUEUE: each cash sale rung offline, until the server has recorded
|
|
30
|
+
* it. A sale carries its customer's email and name only when the cashier
|
|
31
|
+
* attached one, because the receipt email is sent on sync; it leaves the
|
|
32
|
+
* device the moment the server answers for it.
|
|
33
|
+
*
|
|
34
|
+
* IndexedDB, not `localStorage`: a queue must survive a reload, and a sale is
|
|
35
|
+
* a structured record written atomically. When the browser refuses storage
|
|
36
|
+
* (a private window, storage blocked, a quota) the store does not open and the
|
|
37
|
+
* register says "offline selling unavailable" — it never crashes the till.
|
|
38
|
+
*=========================================*/ const DB_NAME = 'aglyn-pos-offline';
|
|
39
|
+
const DB_VERSION = 1;
|
|
40
|
+
const KITS = 'kits';
|
|
41
|
+
const SALES = 'sales';
|
|
42
|
+
/** The scope every key carries: one member at one site. */ export function posOfflineScope(uid, hostId) {
|
|
43
|
+
return `${uid}:${hostId}`;
|
|
44
|
+
}
|
|
45
|
+
const request = (req)=>new Promise((resolve, reject)=>{
|
|
46
|
+
req.onsuccess = ()=>resolve(req.result);
|
|
47
|
+
req.onerror = ()=>{
|
|
48
|
+
var _req_error;
|
|
49
|
+
return reject((_req_error = req.error) != null ? _req_error : new Error('IndexedDB request failed'));
|
|
50
|
+
};
|
|
51
|
+
});
|
|
52
|
+
function openDatabase(factory) {
|
|
53
|
+
return new Promise((resolve, reject)=>{
|
|
54
|
+
let opening;
|
|
55
|
+
try {
|
|
56
|
+
opening = factory.open(DB_NAME, DB_VERSION);
|
|
57
|
+
} catch (error) {
|
|
58
|
+
reject(error);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
opening.onupgradeneeded = ()=>{
|
|
62
|
+
const db = opening.result;
|
|
63
|
+
if (!db.objectStoreNames.contains(KITS)) db.createObjectStore(KITS, {
|
|
64
|
+
keyPath: 'scope'
|
|
65
|
+
});
|
|
66
|
+
if (!db.objectStoreNames.contains(SALES)) db.createObjectStore(SALES, {
|
|
67
|
+
keyPath: 'key'
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
opening.onsuccess = ()=>resolve(opening.result);
|
|
71
|
+
opening.onerror = ()=>{
|
|
72
|
+
var _opening_error;
|
|
73
|
+
return reject((_opening_error = opening.error) != null ? _opening_error : new Error('IndexedDB did not open'));
|
|
74
|
+
};
|
|
75
|
+
opening.onblocked = ()=>reject(new Error('IndexedDB is blocked'));
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* The device store for one member at one site, or `null` when this browser
|
|
80
|
+
* will not keep one. Never throws.
|
|
81
|
+
*/ export async function openPosOfflineStore(scope, factory = typeof indexedDB === 'undefined' ? undefined : indexedDB) {
|
|
82
|
+
if (!factory || !scope.uid || !scope.hostId) return null;
|
|
83
|
+
let db;
|
|
84
|
+
try {
|
|
85
|
+
db = await openDatabase(factory);
|
|
86
|
+
} catch (unused) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
const key = posOfflineScope(scope.uid, scope.hostId);
|
|
90
|
+
const store = (name, mode)=>db.transaction(name, mode).objectStore(name);
|
|
91
|
+
const saleId = (saleKey)=>`${key}|${saleKey}`;
|
|
92
|
+
return {
|
|
93
|
+
scope: key,
|
|
94
|
+
loadKit: async ()=>{
|
|
95
|
+
const found = await request(store(KITS, 'readonly').get(key));
|
|
96
|
+
return found != null ? found : null;
|
|
97
|
+
},
|
|
98
|
+
saveKit: async (kit)=>{
|
|
99
|
+
await request(store(KITS, 'readwrite').put(_extends({}, kit, {
|
|
100
|
+
scope: key
|
|
101
|
+
})));
|
|
102
|
+
},
|
|
103
|
+
listSales: async ()=>{
|
|
104
|
+
// This member's keys only, where the browser can range over them; the
|
|
105
|
+
// filter below holds either way.
|
|
106
|
+
const range = typeof IDBKeyRange === 'undefined' ? undefined : IDBKeyRange.bound(`${key}|`, `${key}|\uffff`);
|
|
107
|
+
const all = await request(store(SALES, 'readonly').getAll(range));
|
|
108
|
+
return all.filter((entry)=>entry.scope === key).map((_0)=>{
|
|
109
|
+
let { key: _key } = _0, entry = _object_without_properties_loose(_0, [
|
|
110
|
+
"key"
|
|
111
|
+
]);
|
|
112
|
+
return entry;
|
|
113
|
+
}).sort((a, b)=>a.sale.soldAtMs - b.sale.soldAtMs || a.queuedAtMs - b.queuedAtMs);
|
|
114
|
+
},
|
|
115
|
+
putSale: async (sale)=>{
|
|
116
|
+
await request(store(SALES, 'readwrite').put(_extends({}, sale, {
|
|
117
|
+
scope: key,
|
|
118
|
+
key: saleId(sale.saleKey)
|
|
119
|
+
})));
|
|
120
|
+
},
|
|
121
|
+
removeSale: async (saleKey)=>{
|
|
122
|
+
await request(store(SALES, 'readwrite').delete(saleId(saleKey)));
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
/** The fields a product sells by; its long copy stays on the server. */ const HEAVY_PRODUCT_FIELDS = [
|
|
127
|
+
'description',
|
|
128
|
+
'descriptionHtml',
|
|
129
|
+
'body',
|
|
130
|
+
'seo',
|
|
131
|
+
'longDescription',
|
|
132
|
+
'reviews'
|
|
133
|
+
];
|
|
134
|
+
/** A product trimmed and made plain for the device. */ export function posOfflineProduct(product) {
|
|
135
|
+
var _ref;
|
|
136
|
+
const id = String((_ref = product == null ? void 0 : product['$id']) != null ? _ref : '');
|
|
137
|
+
if (!id) return null;
|
|
138
|
+
const plain = JSON.parse(JSON.stringify(product));
|
|
139
|
+
for (const field of HEAVY_PRODUCT_FIELDS)delete plain[field];
|
|
140
|
+
return _extends({}, plain, {
|
|
141
|
+
$id: id
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
//# sourceMappingURL=pos-offline-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../../../libs/plugins/commerce/src/lib/components/console/pos-offline/pos-offline-store.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { PosOfflineKit, PosOfflineRefusal, PosOfflineSale } from '../../../model/commerce-pos-offline'\n\n/*==========================================\n * WHAT THE REGISTER KEEPS ON THE DEVICE (AGL-3625), in IndexedDB.\n *\n * Two things, both scoped to ONE signed-in member at ONE site — the scope is\n * part of every key, so another member on the same tablet, or the same\n * member in another workspace, never reads a sale or a catalog that is not\n * theirs:\n *\n * - the KIT: the server's offline rules for the site plus the catalog the\n * grid sells from, refreshed while online. Products only; nothing about\n * any customer.\n * - the QUEUE: each cash sale rung offline, until the server has recorded\n * it. A sale carries its customer's email and name only when the cashier\n * attached one, because the receipt email is sent on sync; it leaves the\n * device the moment the server answers for it.\n *\n * IndexedDB, not `localStorage`: a queue must survive a reload, and a sale is\n * a structured record written atomically. When the browser refuses storage\n * (a private window, storage blocked, a quota) the store does not open and the\n * register says \"offline selling unavailable\" — it never crashes the till.\n *=========================================*/\n\nconst DB_NAME = 'aglyn-pos-offline'\nconst DB_VERSION = 1\nconst KITS = 'kits'\nconst SALES = 'sales'\n\n/** One product as the offline grid sells it. */\nexport type PosOfflineProduct = Record<string, any> & { $id: string; name?: string }\n\n/** The kit as the device keeps it: the server's rules and the catalog. */\nexport interface PosOfflineDeviceKit {\n scope: string\n kit: PosOfflineKit | null\n kitSavedAtMs: number\n products: PosOfflineProduct[]\n catalogSavedAtMs: number\n}\n\n/** A sale on the device, with where it stands. */\nexport interface PosOfflineQueuedSale {\n scope: string\n saleKey: string\n sale: PosOfflineSale\n /** `queued` waits for the connection; `refused` waits for the cashier. */\n state: 'queued' | 'refused'\n queuedAtMs: number\n attempts: number\n error?: string\n reason?: PosOfflineRefusal\n}\n\nexport interface PosOfflineStore {\n readonly scope: string\n loadKit(): Promise<PosOfflineDeviceKit | null>\n saveKit(kit: Omit<PosOfflineDeviceKit, 'scope'>): Promise<void>\n /** Every sale this member queued at this site, oldest first. */\n listSales(): Promise<PosOfflineQueuedSale[]>\n putSale(sale: Omit<PosOfflineQueuedSale, 'scope'>): Promise<void>\n removeSale(saleKey: string): Promise<void>\n}\n\n/** The scope every key carries: one member at one site. */\nexport function posOfflineScope(uid: string, hostId: string): string {\n return `${uid}:${hostId}`\n}\n\nconst request = <T>(req: IDBRequest<T>): Promise<T> =>\n new Promise((resolve, reject) => {\n req.onsuccess = () => resolve(req.result)\n req.onerror = () => reject(req.error ?? new Error('IndexedDB request failed'))\n })\n\nfunction openDatabase(factory: IDBFactory): Promise<IDBDatabase> {\n return new Promise((resolve, reject) => {\n let opening: IDBOpenDBRequest\n try {\n opening = factory.open(DB_NAME, DB_VERSION)\n } catch (error) {\n reject(error)\n return\n }\n opening.onupgradeneeded = () => {\n const db = opening.result\n if (!db.objectStoreNames.contains(KITS)) db.createObjectStore(KITS, { keyPath: 'scope' })\n if (!db.objectStoreNames.contains(SALES)) db.createObjectStore(SALES, { keyPath: 'key' })\n }\n opening.onsuccess = () => resolve(opening.result)\n opening.onerror = () => reject(opening.error ?? new Error('IndexedDB did not open'))\n opening.onblocked = () => reject(new Error('IndexedDB is blocked'))\n })\n}\n\n/**\n * The device store for one member at one site, or `null` when this browser\n * will not keep one. Never throws.\n */\nexport async function openPosOfflineStore(\n scope: { uid: string; hostId: string },\n factory: IDBFactory | undefined = typeof indexedDB === 'undefined' ? undefined : indexedDB,\n): Promise<PosOfflineStore | null> {\n if (!factory || !scope.uid || !scope.hostId) return null\n let db: IDBDatabase\n try {\n db = await openDatabase(factory)\n } catch {\n return null\n }\n const key = posOfflineScope(scope.uid, scope.hostId)\n const store = (name: string, mode: IDBTransactionMode) => db.transaction(name, mode).objectStore(name)\n const saleId = (saleKey: string) => `${key}|${saleKey}`\n return {\n scope: key,\n loadKit: async () => {\n const found = (await request(store(KITS, 'readonly').get(key))) as PosOfflineDeviceKit | undefined\n return found ?? null\n },\n saveKit: async (kit) => {\n await request(store(KITS, 'readwrite').put({ ...kit, scope: key }))\n },\n listSales: async () => {\n // This member's keys only, where the browser can range over them; the\n // filter below holds either way.\n const range =\n typeof IDBKeyRange === 'undefined' ? undefined : IDBKeyRange.bound(`${key}|`, `${key}|\\uffff`)\n const all = (await request(store(SALES, 'readonly').getAll(range))) as Array<\n PosOfflineQueuedSale & { key: string }\n >\n return all\n .filter((entry) => entry.scope === key)\n .map(({ key: _key, ...entry }) => entry)\n .sort((a, b) => a.sale.soldAtMs - b.sale.soldAtMs || a.queuedAtMs - b.queuedAtMs)\n },\n putSale: async (sale) => {\n await request(store(SALES, 'readwrite').put({ ...sale, scope: key, key: saleId(sale.saleKey) }))\n },\n removeSale: async (saleKey) => {\n await request(store(SALES, 'readwrite').delete(saleId(saleKey)))\n },\n }\n}\n\n/** The fields a product sells by; its long copy stays on the server. */\nconst HEAVY_PRODUCT_FIELDS = ['description', 'descriptionHtml', 'body', 'seo', 'longDescription', 'reviews']\n\n/** A product trimmed and made plain for the device. */\nexport function posOfflineProduct(product: Record<string, any>): PosOfflineProduct | null {\n const id = String(product?.['$id'] ?? '')\n if (!id) return null\n const plain = JSON.parse(JSON.stringify(product)) as Record<string, any>\n for (const field of HEAVY_PRODUCT_FIELDS) delete plain[field]\n return { ...plain, $id: id }\n}\n"],"names":["DB_NAME","DB_VERSION","KITS","SALES","posOfflineScope","uid","hostId","request","req","Promise","resolve","reject","onsuccess","result","onerror","error","Error","openDatabase","factory","opening","open","onupgradeneeded","db","objectStoreNames","contains","createObjectStore","keyPath","onblocked","openPosOfflineStore","scope","indexedDB","undefined","key","store","name","mode","transaction","objectStore","saleId","saleKey","loadKit","found","get","saveKit","kit","put","listSales","range","IDBKeyRange","bound","all","getAll","filter","entry","map","_key","sort","a","b","sale","soldAtMs","queuedAtMs","putSale","removeSale","delete","HEAVY_PRODUCT_FIELDS","posOfflineProduct","product","id","String","plain","JSON","parse","stringify","field","$id"],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* What the register page takes from the offline register (AGL-3625), in one
|
|
19
|
+
* module: the page's own specs stand it in with one `jest.mock`, and the
|
|
20
|
+
* offline register has specs of its own.
|
|
21
|
+
*/
|
|
22
|
+
export { PosOfflineBanner } from './pos-offline-banner.component';
|
|
23
|
+
export { PosOfflineCheckout } from './pos-offline-checkout.component';
|
|
24
|
+
export { usePosOffline, type PosOfflineState } from './use-pos-offline';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ /**
|
|
17
|
+
* What the register page takes from the offline register (AGL-3625), in one
|
|
18
|
+
* module: the page's own specs stand it in with one `jest.mock`, and the
|
|
19
|
+
* offline register has specs of its own.
|
|
20
|
+
*/ export { PosOfflineBanner } from "./pos-offline-banner.component.js";
|
|
21
|
+
export { PosOfflineCheckout } from "./pos-offline-checkout.component.js";
|
|
22
|
+
export { usePosOffline } from "./use-pos-offline.js";
|
|
23
|
+
|
|
24
|
+
//# sourceMappingURL=register-offline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../../../libs/plugins/commerce/src/lib/components/console/pos-offline/register-offline.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\n/**\n * What the register page takes from the offline register (AGL-3625), in one\n * module: the page's own specs stand it in with one `jest.mock`, and the\n * offline register has specs of its own.\n */\nexport { PosOfflineBanner } from './pos-offline-banner.component'\nexport { PosOfflineCheckout } from './pos-offline-checkout.component'\nexport { usePosOffline, type PosOfflineState } from './use-pos-offline'\n"],"names":["PosOfflineBanner","PosOfflineCheckout","usePosOffline"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;CAIC,GACD,SAASA,gBAAgB,QAAQ,oCAAgC;AACjE,SAASC,kBAAkB,QAAQ,sCAAkC;AACrE,SAASC,aAAa,QAA8B,uBAAmB"}
|