@aglyn/plugins-commerce 1.0.0-beta.278 → 1.0.0-beta.283
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 +17 -14
- package/src/lib/components/commerce-console-page.js +33 -1
- package/src/lib/components/commerce-console-page.js.map +1 -1
- package/src/lib/components/console/payments-settings-card.component.js +1 -1
- package/src/lib/components/console/payments-settings-card.component.js.map +1 -1
- package/src/lib/components/console/pos/pos-hardware-api.d.ts +122 -0
- package/src/lib/components/console/pos/pos-hardware-api.js +90 -0
- package/src/lib/components/console/pos/pos-hardware-api.js.map +1 -0
- package/src/lib/components/console/pos/pos-reader-splash-api.d.ts +58 -0
- package/src/lib/components/console/pos/pos-reader-splash-api.js +101 -0
- package/src/lib/components/console/pos/pos-reader-splash-api.js.map +1 -0
- package/src/lib/components/console/pos-devices-card.component.js +5 -0
- package/src/lib/components/console/pos-devices-card.component.js.map +1 -1
- package/src/lib/components/console/pos-hardware-card.component.d.ts +26 -0
- package/src/lib/components/console/pos-hardware-card.component.js +456 -0
- package/src/lib/components/console/pos-hardware-card.component.js.map +1 -0
- package/src/lib/components/console/pos-hardware-orders-staff-page.component.d.ts +14 -0
- package/src/lib/components/console/pos-hardware-orders-staff-page.component.js +519 -0
- package/src/lib/components/console/pos-hardware-orders-staff-page.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-check-in-dialog.component.d.ts +27 -0
- package/src/lib/components/console/pos-ops/pos-check-in-dialog.component.js +444 -0
- package/src/lib/components/console/pos-ops/pos-check-in-dialog.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-check-in-zone.component.d.ts +9 -0
- package/src/lib/components/console/pos-ops/pos-check-in-zone.component.js +37 -0
- package/src/lib/components/console/pos-ops/pos-check-in-zone.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-check-ins-card.component.d.ts +24 -0
- package/src/lib/components/console/pos-ops/pos-check-ins-card.component.js +346 -0
- package/src/lib/components/console/pos-ops/pos-check-ins-card.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-customer-lookup.component.d.ts +5 -1
- package/src/lib/components/console/pos-ops/pos-customer-lookup.component.js +83 -4
- package/src/lib/components/console/pos-ops/pos-customer-lookup.component.js.map +1 -1
- package/src/lib/components/console/pos-ops/pos-day-totals-card.component.d.ts +35 -0
- package/src/lib/components/console/pos-ops/pos-day-totals-card.component.js +546 -0
- package/src/lib/components/console/pos-ops/pos-day-totals-card.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-operations-bar.component.d.ts +2 -1
- package/src/lib/components/console/pos-ops/pos-operations-bar.component.js +20 -1
- package/src/lib/components/console/pos-ops/pos-operations-bar.component.js.map +1 -1
- package/src/lib/components/console/pos-ops/pos-ops-api.d.ts +1 -1
- package/src/lib/components/console/pos-ops/pos-ops-api.js.map +1 -1
- package/src/lib/components/console/pos-page.component.js +6 -3
- package/src/lib/components/console/pos-page.component.js.map +1 -1
- package/src/lib/components/console/pos-reader-splash-setting.component.d.ts +22 -0
- package/src/lib/components/console/pos-reader-splash-setting.component.js +275 -0
- package/src/lib/components/console/pos-reader-splash-setting.component.js.map +1 -0
- package/src/lib/components/console/pos-reader-splash-staff-page.component.d.ts +14 -0
- package/src/lib/components/console/pos-reader-splash-staff-page.component.js +301 -0
- package/src/lib/components/console/pos-reader-splash-staff-page.component.js.map +1 -0
- package/src/lib/components/console/pos-zones.d.ts +37 -3
- package/src/lib/components/console/pos-zones.js +11 -1
- package/src/lib/components/console/pos-zones.js.map +1 -1
- package/src/lib/components/console/product-check-in-fields.component.d.ts +20 -0
- package/src/lib/components/console/product-check-in-fields.component.js +172 -0
- package/src/lib/components/console/product-check-in-fields.component.js.map +1 -0
- package/src/lib/components/console/product-editor-dialog.component.js +48 -9
- package/src/lib/components/console/product-editor-dialog.component.js.map +1 -1
- package/src/lib/components/console/product-register-fields.component.d.ts +12 -0
- package/src/lib/components/console/product-register-fields.component.js +39 -1
- package/src/lib/components/console/product-register-fields.component.js.map +1 -1
- package/src/lib/components/console/products-hub-card.component.js +21 -6
- package/src/lib/components/console/products-hub-card.component.js.map +1 -1
- package/src/lib/components/console/reservations-card.component.js +239 -70
- package/src/lib/components/console/reservations-card.component.js.map +1 -1
- package/src/lib/components/reservation-widget.js +16 -0
- package/src/lib/components/reservation-widget.js.map +1 -1
- package/src/lib/constants/operator-alerts.d.ts +6 -0
- package/src/lib/constants/operator-alerts.js +20 -1
- package/src/lib/constants/operator-alerts.js.map +1 -1
- package/src/lib/declarations.console-server.js +7 -0
- package/src/lib/declarations.console-server.js.map +1 -1
- package/src/lib/declarations.d.ts +26 -0
- package/src/lib/declarations.js +34 -0
- package/src/lib/declarations.js.map +1 -0
- package/src/lib/model/commerce-check-in-product.d.ts +37 -0
- package/src/lib/model/commerce-check-in-product.js +49 -0
- package/src/lib/model/commerce-check-in-product.js.map +1 -0
- package/src/lib/model/commerce-check-in.d.ts +187 -0
- package/src/lib/model/commerce-check-in.js +468 -0
- package/src/lib/model/commerce-check-in.js.map +1 -0
- package/src/lib/model/commerce-pos-day-report.d.ts +209 -0
- package/src/lib/model/commerce-pos-day-report.js +572 -0
- package/src/lib/model/commerce-pos-day-report.js.map +1 -0
- package/src/lib/model/commerce-pos-offline.d.ts +65 -3
- package/src/lib/model/commerce-pos-offline.js +104 -7
- package/src/lib/model/commerce-pos-offline.js.map +1 -1
- package/src/lib/model/commerce-pos-ops.d.ts +3 -0
- package/src/lib/model/commerce-pos-ops.js +1 -0
- package/src/lib/model/commerce-pos-ops.js.map +1 -1
- package/src/lib/model/commerce-pos.d.ts +43 -3
- package/src/lib/model/commerce-pos.js +73 -5
- package/src/lib/model/commerce-pos.js.map +1 -1
- package/src/lib/model/commerce-reservations.d.ts +73 -7
- package/src/lib/model/commerce-reservations.js +90 -10
- package/src/lib/model/commerce-reservations.js.map +1 -1
- package/src/lib/model/commerce.d.ts +40 -0
- package/src/lib/model/commerce.js +22 -4
- package/src/lib/model/commerce.js.map +1 -1
- package/src/lib/model/index.d.ts +1 -0
- package/src/lib/model/index.js +1 -0
- package/src/lib/model/index.js.map +1 -1
- package/src/lib/model/plugin-permissions.d.ts +1 -1
- package/src/lib/model/plugin-permissions.js +2 -1
- package/src/lib/model/plugin-permissions.js.map +1 -1
- package/src/lib/model/pos-hardware.d.ts +288 -0
- package/src/lib/model/pos-hardware.js +499 -0
- package/src/lib/model/pos-hardware.js.map +1 -0
- package/src/lib/model/pos-offline-card-limits.d.ts +20 -0
- package/src/lib/model/pos-offline-card-limits.js +28 -0
- package/src/lib/model/pos-offline-card-limits.js.map +1 -0
- package/src/lib/model/pos-reader-splash.d.ts +114 -0
- package/src/lib/model/pos-reader-splash.js +141 -0
- package/src/lib/model/pos-reader-splash.js.map +1 -0
- package/src/lib/model/product-write.d.ts +6 -0
- package/src/lib/plugin-config.d.ts +10 -0
- package/src/lib/plugin-config.js +40 -0
- package/src/lib/plugin-config.js.map +1 -1
- package/src/lib/plugin.js +28 -0
- package/src/lib/plugin.js.map +1 -1
- package/src/lib/server/cart-checkout.js +3 -1
- package/src/lib/server/cart-checkout.js.map +1 -1
- package/src/lib/server/cart.js +12 -1
- package/src/lib/server/cart.js.map +1 -1
- package/src/lib/server/catalog.js +49 -12
- package/src/lib/server/catalog.js.map +1 -1
- package/src/lib/server/checkout-extras.js +1 -1
- package/src/lib/server/checkout-extras.js.map +1 -1
- package/src/lib/server/checkout.js +7 -0
- package/src/lib/server/checkout.js.map +1 -1
- package/src/lib/server/person-eraser.d.ts +8 -1
- package/src/lib/server/person-eraser.js +23 -1
- package/src/lib/server/person-eraser.js.map +1 -1
- package/src/lib/server/pos-check-in.d.ts +49 -0
- package/src/lib/server/pos-check-in.js +652 -0
- package/src/lib/server/pos-check-in.js.map +1 -0
- package/src/lib/server/pos-day-report.d.ts +46 -0
- package/src/lib/server/pos-day-report.js +299 -0
- package/src/lib/server/pos-day-report.js.map +1 -0
- package/src/lib/server/pos-hardware-admin.d.ts +50 -0
- package/src/lib/server/pos-hardware-admin.js +366 -0
- package/src/lib/server/pos-hardware-admin.js.map +1 -0
- package/src/lib/server/pos-hardware-notify.d.ts +27 -0
- package/src/lib/server/pos-hardware-notify.js +142 -0
- package/src/lib/server/pos-hardware-notify.js.map +1 -0
- package/src/lib/server/pos-hardware-user-eraser.d.ts +26 -0
- package/src/lib/server/pos-hardware-user-eraser.js +67 -0
- package/src/lib/server/pos-hardware-user-eraser.js.map +1 -0
- package/src/lib/server/pos-hardware-webhook.d.ts +31 -0
- package/src/lib/server/pos-hardware-webhook.js +176 -0
- package/src/lib/server/pos-hardware-webhook.js.map +1 -0
- package/src/lib/server/pos-hardware.d.ts +58 -0
- package/src/lib/server/pos-hardware.js +234 -0
- package/src/lib/server/pos-hardware.js.map +1 -0
- package/src/lib/server/pos-offline-card-reconcile.d.ts +38 -0
- package/src/lib/server/pos-offline-card-reconcile.js +58 -0
- package/src/lib/server/pos-offline-card-reconcile.js.map +1 -0
- package/src/lib/server/pos-offline-sync.d.ts +32 -0
- package/src/lib/server/pos-offline-sync.js +191 -15
- package/src/lib/server/pos-offline-sync.js.map +1 -1
- package/src/lib/server/pos-ops-routes.d.ts +4 -2
- package/src/lib/server/pos-ops-routes.js +14 -2
- package/src/lib/server/pos-ops-routes.js.map +1 -1
- package/src/lib/server/pos-order.js +39 -51
- package/src/lib/server/pos-order.js.map +1 -1
- package/src/lib/server/pos-payment.js +8 -4
- package/src/lib/server/pos-payment.js.map +1 -1
- package/src/lib/server/pos-reader-splash-admin.d.ts +36 -0
- package/src/lib/server/pos-reader-splash-admin.js +295 -0
- package/src/lib/server/pos-reader-splash-admin.js.map +1 -0
- package/src/lib/server/pos-reader-splash-render.d.ts +40 -0
- package/src/lib/server/pos-reader-splash-render.js +138 -0
- package/src/lib/server/pos-reader-splash-render.js.map +1 -0
- package/src/lib/server/pos-reader-splash-server.d.ts +32 -0
- package/src/lib/server/pos-reader-splash-server.js +32 -0
- package/src/lib/server/pos-reader-splash-server.js.map +1 -0
- package/src/lib/server/pos-reader-splash.d.ts +105 -0
- package/src/lib/server/pos-reader-splash.js +548 -0
- package/src/lib/server/pos-reader-splash.js.map +1 -0
- package/src/lib/server/pos-sale.d.ts +2 -1
- package/src/lib/server/pos-sale.js +3 -1
- package/src/lib/server/pos-sale.js.map +1 -1
- package/src/lib/server/pos-terminal.d.ts +67 -4
- package/src/lib/server/pos-terminal.js +239 -32
- package/src/lib/server/pos-terminal.js.map +1 -1
- package/src/lib/server/process-restock.js +4 -0
- package/src/lib/server/process-restock.js.map +1 -1
- package/src/lib/server/product-card.js +2 -2
- package/src/lib/server/product-card.js.map +1 -1
- package/src/lib/server/product-catalog.d.ts +2 -0
- package/src/lib/server/product-catalog.js +11 -4
- package/src/lib/server/product-catalog.js.map +1 -1
- package/src/lib/server/product.js +3 -1
- package/src/lib/server/product.js.map +1 -1
- package/src/lib/server/related.js +8 -1
- package/src/lib/server/related.js.map +1 -1
- package/src/lib/server/reservation-availability-query.d.ts +35 -0
- package/src/lib/server/reservation-availability-query.js +34 -0
- package/src/lib/server/reservation-availability-query.js.map +1 -0
- package/src/lib/server/reservation-availability.d.ts +21 -0
- package/src/lib/server/reservation-availability.js +64 -10
- package/src/lib/server/reservation-availability.js.map +1 -1
- package/src/lib/server/reservation-walk-in.d.ts +28 -0
- package/src/lib/server/reservation-walk-in.js +166 -0
- package/src/lib/server/reservation-walk-in.js.map +1 -0
- package/src/lib/server/reserve.js +13 -10
- package/src/lib/server/reserve.js.map +1 -1
- package/src/lib/server/reviews.js +3 -1
- package/src/lib/server/reviews.js.map +1 -1
- package/src/lib/server/site-page-resolver.js +5 -2
- package/src/lib/server/site-page-resolver.js.map +1 -1
- package/src/lib/server.js +26 -0
- package/src/lib/server.js.map +1 -1
- package/src/lib/testing/fake-firestore.js +72 -0
- package/src/lib/testing/fake-firestore.js.map +1 -1
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
2
|
+
/**
|
|
3
|
+
* @license
|
|
4
|
+
* Copyright 2026 Aglyn LLC
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*/ import { normalizeProductCheckIn } from "./commerce-check-in-product.js";
|
|
18
|
+
import { emailSearchTokens } from "@aglyn/aglyn/app-utils/email-search";
|
|
19
|
+
import { nameSearchKey, nameSearchToken, nameSearchTokens } from "@aglyn/aglyn/app-utils/name-search";
|
|
20
|
+
import { formatOrderNumber } from "./commerce-orders.js";
|
|
21
|
+
import { posCsvCell } from "./commerce-pos-ops.js";
|
|
22
|
+
import { orderLabelTokens } from "./order-list-fields.js";
|
|
23
|
+
// The product setting lives in a pure module the native contracts read (AGL-4043).
|
|
24
|
+
export { CHECK_IN_MAX_HEADCOUNT, normalizeProductCheckIn, productCheckInProblem } from "./commerce-check-in-product.js";
|
|
25
|
+
/*==========================================
|
|
26
|
+
* CHECK-IN AT THE WINDOW (AGL-4043).
|
|
27
|
+
*
|
|
28
|
+
* A rider who bought a day pass online walks up to the window, is looked up
|
|
29
|
+
* by name, checked in and handed a wristband. So is somebody who bought a
|
|
30
|
+
* pass at the register, and a guest whose stay covers today.
|
|
31
|
+
*
|
|
32
|
+
* WHAT IS DUE ON A DAY
|
|
33
|
+
* - An order's lines whose product (or variant) "Needs check-in", on the
|
|
34
|
+
* day the order was placed, in the site's time zone. Products have no
|
|
35
|
+
* service date of their own, so the purchase day is the day the pass is
|
|
36
|
+
* for. A paid order only: `paid`, `partially_fulfilled`, `fulfilled` or
|
|
37
|
+
* `delivered`. A line refunded by name is not due.
|
|
38
|
+
* - Each unit is a person: quantity × the product's "people per item"
|
|
39
|
+
* (`headcount`, default 1), so three passes are three check-ins.
|
|
40
|
+
* - A reservation that is `confirmed` or `checked_in` and whose stay
|
|
41
|
+
* covers the day: one check-in per day of the stay.
|
|
42
|
+
*
|
|
43
|
+
* Every due unit is a document, `hosts/{hostId}/checkIns/{id}`, written by
|
|
44
|
+
* the server only. Its id is the unit's identity (order, line, unit; or
|
|
45
|
+
* stay, day), so writing what is due twice writes it once, and a check-in
|
|
46
|
+
* is a transaction on that one document.
|
|
47
|
+
*
|
|
48
|
+
* POST /api/commerce/pos-check-in { hostId, action, … }
|
|
49
|
+
* GET /api/commerce/pos-check-in?hostId=…&day=YYYY-MM-DD[&format=csv]
|
|
50
|
+
*
|
|
51
|
+
* The native register mirrors these types.
|
|
52
|
+
*=========================================*/ export const POS_CHECK_IN_ROUTE = '/api/commerce/pos-check-in';
|
|
53
|
+
/** The most check-ins one order line makes, whatever its quantity. */ export const CHECK_IN_MAX_UNITS_PER_LINE = 200;
|
|
54
|
+
/** The most check-ins, orders or stays one day reads. */ export const CHECK_IN_DAY_CEILING = 3000;
|
|
55
|
+
/** The most check-in rows one search reads. */ export const CHECK_IN_SEARCH_ROWS = 100;
|
|
56
|
+
/** The most customers one search answers. */ export const CHECK_IN_SEARCH_CUSTOMERS = 20;
|
|
57
|
+
/** The most check-ins one tap records. */ export const CHECK_IN_BATCH_MAX = 50;
|
|
58
|
+
/** A wristband's number or color, at most this many characters. */ export const CHECK_IN_WRISTBAND_MAX = 24;
|
|
59
|
+
/** Colors offered as quick picks for a wristband. Any word is accepted. */ export const CHECK_IN_WRISTBAND_COLORS = [
|
|
60
|
+
'Red',
|
|
61
|
+
'Orange',
|
|
62
|
+
'Yellow',
|
|
63
|
+
'Green',
|
|
64
|
+
'Blue',
|
|
65
|
+
'Purple',
|
|
66
|
+
'Pink',
|
|
67
|
+
'White',
|
|
68
|
+
'Black'
|
|
69
|
+
];
|
|
70
|
+
/** The order statuses whose check-in lines are due. */ export const CHECK_IN_ORDER_STATUSES = [
|
|
71
|
+
'paid',
|
|
72
|
+
'partially_fulfilled',
|
|
73
|
+
'fulfilled',
|
|
74
|
+
'delivered'
|
|
75
|
+
];
|
|
76
|
+
/** The stay statuses whose days are due. */ export const CHECK_IN_RESERVATION_STATUSES = [
|
|
77
|
+
'confirmed',
|
|
78
|
+
'checked_in'
|
|
79
|
+
];
|
|
80
|
+
/*==========================================
|
|
81
|
+
* THE PRODUCT SETTING
|
|
82
|
+
*=========================================*/ /**
|
|
83
|
+
* Whether one variant of a product needs check-in, and for how many people
|
|
84
|
+
* per item: the variant's own setting, else the product's; `null` when not.
|
|
85
|
+
*/ export function productCheckInFor(product, variantId) {
|
|
86
|
+
var _product_variants, _normalizeProductCheckIn, _setting_headcount;
|
|
87
|
+
if (!product) return null;
|
|
88
|
+
const variant = ((_product_variants = product.variants) != null ? _product_variants : []).find((one)=>one.id === (variantId || 'default'));
|
|
89
|
+
const setting = (_normalizeProductCheckIn = normalizeProductCheckIn(variant == null ? void 0 : variant.checkIn)) != null ? _normalizeProductCheckIn : normalizeProductCheckIn(product.checkIn);
|
|
90
|
+
return (setting == null ? void 0 : setting.enabled) ? {
|
|
91
|
+
headcount: (_setting_headcount = setting.headcount) != null ? _setting_headcount : 1
|
|
92
|
+
} : null;
|
|
93
|
+
}
|
|
94
|
+
/** Whether any variant of a product needs check-in. */ export function productNeedsCheckIn(product) {
|
|
95
|
+
var _product_variants;
|
|
96
|
+
if (!product) return false;
|
|
97
|
+
const variants = ((_product_variants = product.variants) == null ? void 0 : _product_variants.length) ? product.variants : [
|
|
98
|
+
{
|
|
99
|
+
id: 'default'
|
|
100
|
+
}
|
|
101
|
+
];
|
|
102
|
+
return variants.some((variant)=>productCheckInFor(product, variant.id) !== null);
|
|
103
|
+
}
|
|
104
|
+
/*==========================================
|
|
105
|
+
* WHAT IS DUE
|
|
106
|
+
*=========================================*/ const text = (value)=>typeof value === 'string' ? value.trim() : '';
|
|
107
|
+
/** The digits of a phone number, without a leading US/Canada 1 when it has eleven. */ export function checkInPhoneDigits(phone) {
|
|
108
|
+
const digits = String(phone != null ? phone : '').replace(/\D+/g, '');
|
|
109
|
+
return digits.length === 11 && digits.startsWith('1') ? digits.slice(1) : digits;
|
|
110
|
+
}
|
|
111
|
+
/** The search prefixes of a phone number: its digits from three on, and its last four. */ function phoneTokens(phone) {
|
|
112
|
+
const digits = checkInPhoneDigits(phone).slice(0, 15);
|
|
113
|
+
const tokens = [];
|
|
114
|
+
for(let at = 3; at <= digits.length; at += 1)tokens.push(digits.slice(0, at));
|
|
115
|
+
// The last four, which is what a rider reads out at the window.
|
|
116
|
+
if (digits.length >= 7) tokens.push(digits.slice(-4));
|
|
117
|
+
return tokens;
|
|
118
|
+
}
|
|
119
|
+
/** The tokens a check-in is found by. */ export function checkInSearchTokens(input) {
|
|
120
|
+
var _input_name, _input_email, _input_orderNumber;
|
|
121
|
+
return [
|
|
122
|
+
...new Set([
|
|
123
|
+
...nameSearchTokens((_input_name = input.name) != null ? _input_name : ''),
|
|
124
|
+
...emailSearchTokens((_input_email = input.email) != null ? _input_email : ''),
|
|
125
|
+
...phoneTokens(input.phone),
|
|
126
|
+
...input.orderId ? orderLabelTokens({
|
|
127
|
+
number: (_input_orderNumber = input.orderNumber) != null ? _input_orderNumber : undefined
|
|
128
|
+
}, input.orderId) : []
|
|
129
|
+
])
|
|
130
|
+
].slice(0, 200);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* What a typed search asks the index for: the phone's digits when it is a
|
|
134
|
+
* number, else the first word's prefix (a name, an address, `#1042`).
|
|
135
|
+
*/ export function checkInSearchToken(typed) {
|
|
136
|
+
const value = String(typed != null ? typed : '').trim();
|
|
137
|
+
if (!value) return '';
|
|
138
|
+
if (/^[\d\s()+.-]+$/.test(value) && !value.startsWith('#')) {
|
|
139
|
+
const digits = checkInPhoneDigits(value);
|
|
140
|
+
return digits.length >= 3 ? digits.slice(0, 15) : '';
|
|
141
|
+
}
|
|
142
|
+
return nameSearchToken(value);
|
|
143
|
+
}
|
|
144
|
+
/** One key per customer: the address, else the contact, else the name, else the source. */ export function checkInCustomerKey(input) {
|
|
145
|
+
var _input_name;
|
|
146
|
+
const email = text(input.email).toLowerCase();
|
|
147
|
+
if (email) return `email:${email}`;
|
|
148
|
+
if (input.contactId) return `contact:${input.contactId}`;
|
|
149
|
+
const name = nameSearchKey((_input_name = input.name) != null ? _input_name : '');
|
|
150
|
+
if (name) return `name:${name}`;
|
|
151
|
+
return input.fallback;
|
|
152
|
+
}
|
|
153
|
+
/** A check-in's document id, from its unit's identity. */ export function orderCheckInId(orderId, lineIndex, unitIndex) {
|
|
154
|
+
return `o_${orderId}_${lineIndex}_${unitIndex}`;
|
|
155
|
+
}
|
|
156
|
+
export function reservationCheckInId(reservationId, dayKey, unitIndex = 0) {
|
|
157
|
+
return `r_${reservationId}_${dayKey}_${unitIndex}`;
|
|
158
|
+
}
|
|
159
|
+
/** The customer fields a due check-in copies from its source, which a later read may refresh. */ export const CHECK_IN_CUSTOMER_FIELDS = [
|
|
160
|
+
'customerKey',
|
|
161
|
+
'customerName',
|
|
162
|
+
'customerEmail',
|
|
163
|
+
'customerEmailLower',
|
|
164
|
+
'customerPhone',
|
|
165
|
+
'contactId',
|
|
166
|
+
'searchTokens'
|
|
167
|
+
];
|
|
168
|
+
/** Whether an order's lines are due at all. */ export function orderIsDueForCheckIn(order) {
|
|
169
|
+
var _order_status;
|
|
170
|
+
return Boolean(order && CHECK_IN_ORDER_STATUSES.includes(String((_order_status = order.status) != null ? _order_status : '')));
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* The check-ins an order makes on its day, keyed by document id. `products`
|
|
174
|
+
* holds the products its lines name, as stored now: the setting is read at
|
|
175
|
+
* the window, so turning it on covers passes already sold today.
|
|
176
|
+
*/ export function dueCheckInsForOrder(input) {
|
|
177
|
+
var _order_number;
|
|
178
|
+
var _order_customerRecord;
|
|
179
|
+
const { orderId, order, dayKey } = input;
|
|
180
|
+
const due = new Map();
|
|
181
|
+
if (!orderIsDueForCheckIn(order)) return due;
|
|
182
|
+
const refunded = new Set(Array.isArray(order.refundedLineItemIds) ? order.refundedLineItemIds : []);
|
|
183
|
+
const contactId = ((_order_customerRecord = order.customerRecord) == null ? void 0 : _order_customerRecord.kind) === 'contact' && order.customerRecord.id ? order.customerRecord.id : null;
|
|
184
|
+
const name = text(order.customerName) || null;
|
|
185
|
+
const email = text(order.customerEmail) || null;
|
|
186
|
+
const phone = text(order.customerPhone) || null;
|
|
187
|
+
const customerKey = checkInCustomerKey({
|
|
188
|
+
email,
|
|
189
|
+
contactId,
|
|
190
|
+
name,
|
|
191
|
+
fallback: `order:${orderId}`
|
|
192
|
+
});
|
|
193
|
+
const searchTokens = checkInSearchTokens({
|
|
194
|
+
name,
|
|
195
|
+
email,
|
|
196
|
+
phone,
|
|
197
|
+
orderNumber: (_order_number = order.number) != null ? _order_number : null,
|
|
198
|
+
orderId
|
|
199
|
+
});
|
|
200
|
+
const lines = Array.isArray(order.lineItems) ? order.lineItems : [];
|
|
201
|
+
lines.forEach((line, lineIndex)=>{
|
|
202
|
+
var _input_products_get;
|
|
203
|
+
if (!line || refunded.has(lineIndex)) return;
|
|
204
|
+
const setting = productCheckInFor((_input_products_get = input.products.get(line.productId)) != null ? _input_products_get : null, line.variantId);
|
|
205
|
+
if (!setting) return;
|
|
206
|
+
const quantity = Math.max(0, Math.round(Number(line.quantity) || 0));
|
|
207
|
+
const unitCount = Math.min(quantity * setting.headcount, CHECK_IN_MAX_UNITS_PER_LINE);
|
|
208
|
+
for(let unitIndex = 0; unitIndex < unitCount; unitIndex += 1){
|
|
209
|
+
var _order_channel, _line_productId, _line_variantId;
|
|
210
|
+
due.set(orderCheckInId(orderId, lineIndex, unitIndex), {
|
|
211
|
+
source: 'order',
|
|
212
|
+
orderId,
|
|
213
|
+
orderLabel: formatOrderNumber({
|
|
214
|
+
number: order.number
|
|
215
|
+
}, orderId),
|
|
216
|
+
channel: (_order_channel = order.channel) != null ? _order_channel : 'online',
|
|
217
|
+
reservationId: null,
|
|
218
|
+
lineIndex,
|
|
219
|
+
unitIndex,
|
|
220
|
+
unitCount,
|
|
221
|
+
productId: (_line_productId = line.productId) != null ? _line_productId : null,
|
|
222
|
+
variantId: (_line_variantId = line.variantId) != null ? _line_variantId : null,
|
|
223
|
+
itemName: text(line.name) || 'Item',
|
|
224
|
+
variantLabel: text(line.variantLabel) || null,
|
|
225
|
+
dayKey,
|
|
226
|
+
customerKey,
|
|
227
|
+
customerName: name,
|
|
228
|
+
customerEmail: email,
|
|
229
|
+
customerEmailLower: email ? email.toLowerCase() : null,
|
|
230
|
+
customerPhone: phone,
|
|
231
|
+
contactId,
|
|
232
|
+
searchTokens
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
return due;
|
|
237
|
+
}
|
|
238
|
+
/** UTC midnight of a `YYYY-MM-DD` day, as a stay's days are stored. */ export function checkInDayMs(dayKey) {
|
|
239
|
+
const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(dayKey);
|
|
240
|
+
if (!match) return null;
|
|
241
|
+
const ms = Date.UTC(Number(match[1]), Number(match[2]) - 1, Number(match[3]));
|
|
242
|
+
const check = new Date(ms);
|
|
243
|
+
return check.getUTCDate() === Number(match[3]) && check.getUTCMonth() === Number(match[2]) - 1 ? ms : null;
|
|
244
|
+
}
|
|
245
|
+
/** The check-in a stay makes on a day it covers; empty on any other day. */ export function dueCheckInsForReservation(input) {
|
|
246
|
+
var _reservation_status;
|
|
247
|
+
const { reservationId, reservation, dayKey } = input;
|
|
248
|
+
const due = new Map();
|
|
249
|
+
const dayMs = checkInDayMs(dayKey);
|
|
250
|
+
if (dayMs === null || !CHECK_IN_RESERVATION_STATUSES.includes(String((_reservation_status = reservation.status) != null ? _reservation_status : '')) || !(Number(reservation.checkInDayMs) <= dayMs && dayMs < Number(reservation.checkOutDayMs))) {
|
|
251
|
+
return due;
|
|
252
|
+
}
|
|
253
|
+
const name = text(reservation.guestName) || null;
|
|
254
|
+
const email = text(reservation.guestEmail) || null;
|
|
255
|
+
due.set(reservationCheckInId(reservationId, dayKey), {
|
|
256
|
+
source: 'reservation',
|
|
257
|
+
orderId: null,
|
|
258
|
+
orderLabel: null,
|
|
259
|
+
channel: 'reservation',
|
|
260
|
+
reservationId,
|
|
261
|
+
lineIndex: null,
|
|
262
|
+
unitIndex: 0,
|
|
263
|
+
unitCount: 1,
|
|
264
|
+
productId: null,
|
|
265
|
+
variantId: null,
|
|
266
|
+
itemName: text(input.resourceName) || 'Stay',
|
|
267
|
+
variantLabel: null,
|
|
268
|
+
dayKey,
|
|
269
|
+
customerKey: checkInCustomerKey({
|
|
270
|
+
email,
|
|
271
|
+
name,
|
|
272
|
+
fallback: `reservation:${reservationId}`
|
|
273
|
+
}),
|
|
274
|
+
customerName: name,
|
|
275
|
+
customerEmail: email,
|
|
276
|
+
customerEmailLower: email ? email.toLowerCase() : null,
|
|
277
|
+
customerPhone: null,
|
|
278
|
+
contactId: null,
|
|
279
|
+
searchTokens: checkInSearchTokens({
|
|
280
|
+
name,
|
|
281
|
+
email
|
|
282
|
+
})
|
|
283
|
+
});
|
|
284
|
+
return due;
|
|
285
|
+
}
|
|
286
|
+
/** A due check-in as first written. */ export function newCheckInDocument(due, nowMs) {
|
|
287
|
+
return _extends({}, due, {
|
|
288
|
+
status: 'expected',
|
|
289
|
+
checkedInAtMs: null,
|
|
290
|
+
checkedInBy: null,
|
|
291
|
+
checkedInByName: null,
|
|
292
|
+
wristband: null,
|
|
293
|
+
checkInAttempt: null,
|
|
294
|
+
undoneAtMs: null,
|
|
295
|
+
undoneBy: null,
|
|
296
|
+
createdAtMs: nowMs,
|
|
297
|
+
updatedAtMs: nowMs
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
/** The customer fields of a stored check-in that its source now says otherwise. */ export function changedCheckInCustomerFields(stored, due) {
|
|
301
|
+
const patch = {};
|
|
302
|
+
for (const field of CHECK_IN_CUSTOMER_FIELDS){
|
|
303
|
+
var _stored_field, _due_field;
|
|
304
|
+
if (JSON.stringify((_stored_field = stored[field]) != null ? _stored_field : null) !== JSON.stringify((_due_field = due[field]) != null ? _due_field : null)) patch[field] = due[field];
|
|
305
|
+
}
|
|
306
|
+
return Object.keys(patch).length ? patch : null;
|
|
307
|
+
}
|
|
308
|
+
/*==========================================
|
|
309
|
+
* WRISTBANDS, CUSTOMERS AND THE DAY
|
|
310
|
+
*=========================================*/ /**
|
|
311
|
+
* A wristband as typed, made safe: a number (letters, digits, a dash) and a
|
|
312
|
+
* color word, each optional. `null` with neither; an error for junk.
|
|
313
|
+
*/ export function normalizeWristband(value) {
|
|
314
|
+
var _raw_number, _raw_color;
|
|
315
|
+
if (value === undefined || value === null || value === '') return {
|
|
316
|
+
ok: true,
|
|
317
|
+
wristband: null
|
|
318
|
+
};
|
|
319
|
+
if (typeof value !== 'object') return {
|
|
320
|
+
ok: false,
|
|
321
|
+
error: 'That is not a wristband.'
|
|
322
|
+
};
|
|
323
|
+
const raw = value;
|
|
324
|
+
const number = String((_raw_number = raw['number']) != null ? _raw_number : '').trim();
|
|
325
|
+
const color = String((_raw_color = raw['color']) != null ? _raw_color : '').trim();
|
|
326
|
+
if (number.length > CHECK_IN_WRISTBAND_MAX || color.length > CHECK_IN_WRISTBAND_MAX) {
|
|
327
|
+
return {
|
|
328
|
+
ok: false,
|
|
329
|
+
error: `A wristband number or color is ${CHECK_IN_WRISTBAND_MAX} characters at most.`
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
if (number && !/^[A-Za-z0-9#-]+$/.test(number)) {
|
|
333
|
+
return {
|
|
334
|
+
ok: false,
|
|
335
|
+
error: 'A wristband number is letters, digits and dashes.'
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
if (color && !RegExp("^[\\u0041-\\u005A\\u0061-\\u007A\\u00AA\\u00B5\\u00BA\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376-\\u0377\\u037A-\\u037D\\u037F\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u052F\\u0531-\\u0556\\u0559\\u0560-\\u0588\\u05D0-\\u05EA\\u05EF-\\u05F2\\u0620-\\u064A\\u066E-\\u066F\\u0671-\\u06D3\\u06D5\\u06E5-\\u06E6\\u06EE-\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4-\\u07F5\\u07FA\\u0800-\\u0815\\u081A\\u0824\\u0828\\u0840-\\u0858\\u0860-\\u086A\\u0870-\\u0887\\u0889-\\u088F\\u08A0-\\u08C9\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971-\\u0980\\u0985-\\u098C\\u098F-\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC-\\u09DD\\u09DF-\\u09E1\\u09F0-\\u09F1\\u09FC\\u0A05-\\u0A0A\\u0A0F-\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32-\\u0A33\\u0A35-\\u0A36\\u0A38-\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2-\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0-\\u0AE1\\u0AF9\\u0B05-\\u0B0C\\u0B0F-\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32-\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C-\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99-\\u0B9A\\u0B9C\\u0B9E-\\u0B9F\\u0BA3-\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C39\\u0C3D\\u0C58-\\u0C5A\\u0C5C-\\u0C5D\\u0C60-\\u0C61\\u0C80\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDC-\\u0CDE\\u0CE0-\\u0CE1\\u0CF1-\\u0CF2\\u0D04-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D\\u0D4E\\u0D54-\\u0D56\\u0D5F-\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32-\\u0E33\\u0E40-\\u0E46\\u0E81-\\u0E82\\u0E84\\u0E86-\\u0E8A\\u0E8C-\\u0EA3\\u0EA5\\u0EA7-\\u0EB0\\u0EB2-\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC-\\u0EDF\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8C\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065-\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F5\\u13F8-\\u13FD\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16F1-\\u16F8\\u1700-\\u1711\\u171F-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1878\\u1880-\\u1884\\u1887-\\u18A8\\u18AA\\u18B0-\\u18F5\\u1900-\\u191E\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19B0-\\u19C9\\u1A00-\\u1A16\\u1A20-\\u1A54\\u1AA7\\u1B05-\\u1B33\\u1B45-\\u1B4C\\u1B83-\\u1BA0\\u1BAE-\\u1BAF\\u1BBA-\\u1BE5\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1C80-\\u1C8A\\u1C90-\\u1CBA\\u1CBD-\\u1CBF\\u1CE9-\\u1CEC\\u1CEE-\\u1CF3\\u1CF5-\\u1CF6\\u1CFA\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u209C\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2183-\\u2184\\u2C00-\\u2CE4\\u2CEB-\\u2CEE\\u2CF2-\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005-\\u3006\\u3031-\\u3035\\u303B-\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312F\\u3131-\\u318E\\u31A0-\\u31BF\\u31F0-\\u31FF\\u3400-\\u4DBF\\u4E00-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A-\\uA62B\\uA640-\\uA66E\\uA67F-\\uA69D\\uA6A0-\\uA6E5\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA7DC\\uA7F1-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA8F2-\\uA8F7\\uA8FB\\uA8FD-\\uA8FE\\uA90A-\\uA925\\uA930-\\uA946\\uA960-\\uA97C\\uA984-\\uA9B2\\uA9CF\\uA9E0-\\uA9E4\\uA9E6-\\uA9EF\\uA9FA-\\uA9FE\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAA60-\\uAA76\\uAA7A\\uAA7E-\\uAAAF\\uAAB1\\uAAB5-\\uAAB6\\uAAB9-\\uAABD\\uAAC0\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEA\\uAAF2-\\uAAF4\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uAB30-\\uAB5A\\uAB5C-\\uAB69\\uAB70-\\uABE2\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40-\\uFB41\\uFB43-\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC\\u{10000}-\\u{1000B}\\u{1000D}-\\u{10026}\\u{10028}-\\u{1003A}\\u{1003C}-\\u{1003D}\\u{1003F}-\\u{1004D}\\u{10050}-\\u{1005D}\\u{10080}-\\u{100FA}\\u{10280}-\\u{1029C}\\u{102A0}-\\u{102D0}\\u{10300}-\\u{1031F}\\u{1032D}-\\u{10340}\\u{10342}-\\u{10349}\\u{10350}-\\u{10375}\\u{10380}-\\u{1039D}\\u{103A0}-\\u{103C3}\\u{103C8}-\\u{103CF}\\u{10400}-\\u{1049D}\\u{104B0}-\\u{104D3}\\u{104D8}-\\u{104FB}\\u{10500}-\\u{10527}\\u{10530}-\\u{10563}\\u{10570}-\\u{1057A}\\u{1057C}-\\u{1058A}\\u{1058C}-\\u{10592}\\u{10594}-\\u{10595}\\u{10597}-\\u{105A1}\\u{105A3}-\\u{105B1}\\u{105B3}-\\u{105B9}\\u{105BB}-\\u{105BC}\\u{105C0}-\\u{105F3}\\u{10600}-\\u{10736}\\u{10740}-\\u{10755}\\u{10760}-\\u{10767}\\u{10780}-\\u{10785}\\u{10787}-\\u{107B0}\\u{107B2}-\\u{107BA}\\u{10800}-\\u{10805}\\u{10808}\\u{1080A}-\\u{10835}\\u{10837}-\\u{10838}\\u{1083C}\\u{1083F}-\\u{10855}\\u{10860}-\\u{10876}\\u{10880}-\\u{1089E}\\u{108E0}-\\u{108F2}\\u{108F4}-\\u{108F5}\\u{10900}-\\u{10915}\\u{10920}-\\u{10939}\\u{10940}-\\u{10959}\\u{10980}-\\u{109B7}\\u{109BE}-\\u{109BF}\\u{10A00}\\u{10A10}-\\u{10A13}\\u{10A15}-\\u{10A17}\\u{10A19}-\\u{10A35}\\u{10A60}-\\u{10A7C}\\u{10A80}-\\u{10A9C}\\u{10AC0}-\\u{10AC7}\\u{10AC9}-\\u{10AE4}\\u{10B00}-\\u{10B35}\\u{10B40}-\\u{10B55}\\u{10B60}-\\u{10B72}\\u{10B80}-\\u{10B91}\\u{10C00}-\\u{10C48}\\u{10C80}-\\u{10CB2}\\u{10CC0}-\\u{10CF2}\\u{10D00}-\\u{10D23}\\u{10D4A}-\\u{10D65}\\u{10D6F}-\\u{10D85}\\u{10E80}-\\u{10EA9}\\u{10EB0}-\\u{10EB1}\\u{10EC2}-\\u{10EC7}\\u{10F00}-\\u{10F1C}\\u{10F27}\\u{10F30}-\\u{10F45}\\u{10F70}-\\u{10F81}\\u{10FB0}-\\u{10FC4}\\u{10FE0}-\\u{10FF6}\\u{11003}-\\u{11037}\\u{11071}-\\u{11072}\\u{11075}\\u{11083}-\\u{110AF}\\u{110D0}-\\u{110E8}\\u{11103}-\\u{11126}\\u{11144}\\u{11147}\\u{11150}-\\u{11172}\\u{11176}\\u{11183}-\\u{111B2}\\u{111C1}-\\u{111C4}\\u{111DA}\\u{111DC}\\u{11200}-\\u{11211}\\u{11213}-\\u{1122B}\\u{1123F}-\\u{11240}\\u{11280}-\\u{11286}\\u{11288}\\u{1128A}-\\u{1128D}\\u{1128F}-\\u{1129D}\\u{1129F}-\\u{112A8}\\u{112B0}-\\u{112DE}\\u{11305}-\\u{1130C}\\u{1130F}-\\u{11310}\\u{11313}-\\u{11328}\\u{1132A}-\\u{11330}\\u{11332}-\\u{11333}\\u{11335}-\\u{11339}\\u{1133D}\\u{11350}\\u{1135D}-\\u{11361}\\u{11380}-\\u{11389}\\u{1138B}\\u{1138E}\\u{11390}-\\u{113B5}\\u{113B7}\\u{113D1}\\u{113D3}\\u{11400}-\\u{11434}\\u{11447}-\\u{1144A}\\u{1145F}-\\u{11461}\\u{11480}-\\u{114AF}\\u{114C4}-\\u{114C5}\\u{114C7}\\u{11580}-\\u{115AE}\\u{115D8}-\\u{115DB}\\u{11600}-\\u{1162F}\\u{11644}\\u{11680}-\\u{116AA}\\u{116B8}\\u{11700}-\\u{1171A}\\u{11740}-\\u{11746}\\u{11800}-\\u{1182B}\\u{118A0}-\\u{118DF}\\u{118FF}-\\u{11906}\\u{11909}\\u{1190C}-\\u{11913}\\u{11915}-\\u{11916}\\u{11918}-\\u{1192F}\\u{1193F}\\u{11941}\\u{119A0}-\\u{119A7}\\u{119AA}-\\u{119D0}\\u{119E1}\\u{119E3}\\u{11A00}\\u{11A0B}-\\u{11A32}\\u{11A3A}\\u{11A50}\\u{11A5C}-\\u{11A89}\\u{11A9D}\\u{11AB0}-\\u{11AF8}\\u{11BC0}-\\u{11BE0}\\u{11C00}-\\u{11C08}\\u{11C0A}-\\u{11C2E}\\u{11C40}\\u{11C72}-\\u{11C8F}\\u{11D00}-\\u{11D06}\\u{11D08}-\\u{11D09}\\u{11D0B}-\\u{11D30}\\u{11D46}\\u{11D60}-\\u{11D65}\\u{11D67}-\\u{11D68}\\u{11D6A}-\\u{11D89}\\u{11D98}\\u{11DB0}-\\u{11DDB}\\u{11EE0}-\\u{11EF2}\\u{11F02}\\u{11F04}-\\u{11F10}\\u{11F12}-\\u{11F33}\\u{11FB0}\\u{12000}-\\u{12399}\\u{12480}-\\u{12543}\\u{12F90}-\\u{12FF0}\\u{13000}-\\u{1342F}\\u{13441}-\\u{13446}\\u{13460}-\\u{143FA}\\u{14400}-\\u{14646}\\u{16100}-\\u{1611D}\\u{16800}-\\u{16A38}\\u{16A40}-\\u{16A5E}\\u{16A70}-\\u{16ABE}\\u{16AD0}-\\u{16AED}\\u{16B00}-\\u{16B2F}\\u{16B40}-\\u{16B43}\\u{16B63}-\\u{16B77}\\u{16B7D}-\\u{16B8F}\\u{16D40}-\\u{16D6C}\\u{16E40}-\\u{16E7F}\\u{16EA0}-\\u{16EB8}\\u{16EBB}-\\u{16ED3}\\u{16F00}-\\u{16F4A}\\u{16F50}\\u{16F93}-\\u{16F9F}\\u{16FE0}-\\u{16FE1}\\u{16FE3}\\u{16FF2}-\\u{16FF3}\\u{17000}-\\u{18CD5}\\u{18CFF}-\\u{18D1E}\\u{18D80}-\\u{18DF2}\\u{1AFF0}-\\u{1AFF3}\\u{1AFF5}-\\u{1AFFB}\\u{1AFFD}-\\u{1AFFE}\\u{1B000}-\\u{1B122}\\u{1B132}\\u{1B150}-\\u{1B152}\\u{1B155}\\u{1B164}-\\u{1B167}\\u{1B170}-\\u{1B2FB}\\u{1BC00}-\\u{1BC6A}\\u{1BC70}-\\u{1BC7C}\\u{1BC80}-\\u{1BC88}\\u{1BC90}-\\u{1BC99}\\u{1D400}-\\u{1D454}\\u{1D456}-\\u{1D49C}\\u{1D49E}-\\u{1D49F}\\u{1D4A2}\\u{1D4A5}-\\u{1D4A6}\\u{1D4A9}-\\u{1D4AC}\\u{1D4AE}-\\u{1D4B9}\\u{1D4BB}\\u{1D4BD}-\\u{1D4C3}\\u{1D4C5}-\\u{1D505}\\u{1D507}-\\u{1D50A}\\u{1D50D}-\\u{1D514}\\u{1D516}-\\u{1D51C}\\u{1D51E}-\\u{1D539}\\u{1D53B}-\\u{1D53E}\\u{1D540}-\\u{1D544}\\u{1D546}\\u{1D54A}-\\u{1D550}\\u{1D552}-\\u{1D6A5}\\u{1D6A8}-\\u{1D6C0}\\u{1D6C2}-\\u{1D6DA}\\u{1D6DC}-\\u{1D6FA}\\u{1D6FC}-\\u{1D714}\\u{1D716}-\\u{1D734}\\u{1D736}-\\u{1D74E}\\u{1D750}-\\u{1D76E}\\u{1D770}-\\u{1D788}\\u{1D78A}-\\u{1D7A8}\\u{1D7AA}-\\u{1D7C2}\\u{1D7C4}-\\u{1D7CB}\\u{1DF00}-\\u{1DF1E}\\u{1DF25}-\\u{1DF2A}\\u{1E030}-\\u{1E06D}\\u{1E100}-\\u{1E12C}\\u{1E137}-\\u{1E13D}\\u{1E14E}\\u{1E290}-\\u{1E2AD}\\u{1E2C0}-\\u{1E2EB}\\u{1E4D0}-\\u{1E4EB}\\u{1E5D0}-\\u{1E5ED}\\u{1E5F0}\\u{1E6C0}-\\u{1E6DE}\\u{1E6E0}-\\u{1E6E2}\\u{1E6E4}-\\u{1E6E5}\\u{1E6E7}-\\u{1E6ED}\\u{1E6F0}-\\u{1E6F4}\\u{1E6FE}-\\u{1E6FF}\\u{1E7E0}-\\u{1E7E6}\\u{1E7E8}-\\u{1E7EB}\\u{1E7ED}-\\u{1E7EE}\\u{1E7F0}-\\u{1E7FE}\\u{1E800}-\\u{1E8C4}\\u{1E900}-\\u{1E943}\\u{1E94B}\\u{1EE00}-\\u{1EE03}\\u{1EE05}-\\u{1EE1F}\\u{1EE21}-\\u{1EE22}\\u{1EE24}\\u{1EE27}\\u{1EE29}-\\u{1EE32}\\u{1EE34}-\\u{1EE37}\\u{1EE39}\\u{1EE3B}\\u{1EE42}\\u{1EE47}\\u{1EE49}\\u{1EE4B}\\u{1EE4D}-\\u{1EE4F}\\u{1EE51}-\\u{1EE52}\\u{1EE54}\\u{1EE57}\\u{1EE59}\\u{1EE5B}\\u{1EE5D}\\u{1EE5F}\\u{1EE61}-\\u{1EE62}\\u{1EE64}\\u{1EE67}-\\u{1EE6A}\\u{1EE6C}-\\u{1EE72}\\u{1EE74}-\\u{1EE77}\\u{1EE79}-\\u{1EE7C}\\u{1EE7E}\\u{1EE80}-\\u{1EE89}\\u{1EE8B}-\\u{1EE9B}\\u{1EEA1}-\\u{1EEA3}\\u{1EEA5}-\\u{1EEA9}\\u{1EEAB}-\\u{1EEBB}\\u{20000}-\\u{2A6DF}\\u{2A700}-\\u{2B81D}\\u{2B820}-\\u{2CEAD}\\u{2CEB0}-\\u{2EBE0}\\u{2EBF0}-\\u{2EE5D}\\u{2F800}-\\u{2FA1D}\\u{30000}-\\u{3134A}\\u{31350}-\\u{33479} -]+$", "u").test(color)) {
|
|
339
|
+
return {
|
|
340
|
+
ok: false,
|
|
341
|
+
error: 'A wristband color is a word, such as Blue.'
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
if (!number && !color) return {
|
|
345
|
+
ok: true,
|
|
346
|
+
wristband: null
|
|
347
|
+
};
|
|
348
|
+
return {
|
|
349
|
+
ok: true,
|
|
350
|
+
wristband: {
|
|
351
|
+
number: number || null,
|
|
352
|
+
color: color || null
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
/** A wristband as one line: "Blue #214". */ export function describeWristband(wristband) {
|
|
357
|
+
if (!wristband) return '';
|
|
358
|
+
return [
|
|
359
|
+
wristband.color,
|
|
360
|
+
wristband.number ? `#${wristband.number.replace(/^#/, '')}` : null
|
|
361
|
+
].filter(Boolean).join(' ');
|
|
362
|
+
}
|
|
363
|
+
/** The customers a set of check-ins is for, most due first, then by name. */ export function checkInCustomers(rows) {
|
|
364
|
+
const byKey = new Map();
|
|
365
|
+
for (const row of rows){
|
|
366
|
+
var _customer, _customer1, _customer2, _customer3;
|
|
367
|
+
const found = byKey.get(row.customerKey);
|
|
368
|
+
const customer = found != null ? found : {
|
|
369
|
+
customerKey: row.customerKey,
|
|
370
|
+
name: row.customerName,
|
|
371
|
+
email: row.customerEmail,
|
|
372
|
+
phone: row.customerPhone,
|
|
373
|
+
contactId: row.contactId,
|
|
374
|
+
unitsDue: 0,
|
|
375
|
+
unitsCheckedIn: 0,
|
|
376
|
+
items: []
|
|
377
|
+
};
|
|
378
|
+
customer.unitsDue += 1;
|
|
379
|
+
if (row.status === 'checked_in') customer.unitsCheckedIn += 1;
|
|
380
|
+
(_customer = customer).name || (_customer.name = row.customerName);
|
|
381
|
+
(_customer1 = customer).email || (_customer1.email = row.customerEmail);
|
|
382
|
+
(_customer2 = customer).phone || (_customer2.phone = row.customerPhone);
|
|
383
|
+
(_customer3 = customer).contactId || (_customer3.contactId = row.contactId);
|
|
384
|
+
if (!customer.items.includes(row.itemName)) customer.items.push(row.itemName);
|
|
385
|
+
byKey.set(row.customerKey, customer);
|
|
386
|
+
}
|
|
387
|
+
return [
|
|
388
|
+
...byKey.values()
|
|
389
|
+
].sort((a, b)=>{
|
|
390
|
+
var _ref, _a_name, _ref1, _b_name;
|
|
391
|
+
return b.unitsDue - b.unitsCheckedIn - (a.unitsDue - a.unitsCheckedIn) || String((_ref = (_a_name = a.name) != null ? _a_name : a.email) != null ? _ref : '').localeCompare(String((_ref1 = (_b_name = b.name) != null ? _b_name : b.email) != null ? _ref1 : ''));
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
/** A day's check-ins in the order the window reads them: by name, then item, then unit. */ export function sortCheckInRows(rows) {
|
|
395
|
+
return [
|
|
396
|
+
...rows
|
|
397
|
+
].sort((a, b)=>{
|
|
398
|
+
var _ref, _a_customerName, _ref1, _b_customerName;
|
|
399
|
+
return String((_ref = (_a_customerName = a.customerName) != null ? _a_customerName : a.customerEmail) != null ? _ref : '').localeCompare(String((_ref1 = (_b_customerName = b.customerName) != null ? _b_customerName : b.customerEmail) != null ? _ref1 : '')) || a.itemName.localeCompare(b.itemName) || a.unitIndex - b.unitIndex || a.id.localeCompare(b.id);
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
export function checkInDayTotals(rows) {
|
|
403
|
+
return {
|
|
404
|
+
expected: rows.length,
|
|
405
|
+
checkedIn: rows.filter((row)=>row.status === 'checked_in').length
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
/** A time on the site's clock: "9:14 AM". */ export function checkInTimeLabel(ms, timeZone) {
|
|
409
|
+
if (!ms) return '';
|
|
410
|
+
try {
|
|
411
|
+
return new Intl.DateTimeFormat('en-US', {
|
|
412
|
+
hour: 'numeric',
|
|
413
|
+
minute: '2-digit',
|
|
414
|
+
timeZone
|
|
415
|
+
}).format(new Date(ms));
|
|
416
|
+
} catch (unused) {
|
|
417
|
+
return new Intl.DateTimeFormat('en-US', {
|
|
418
|
+
hour: 'numeric',
|
|
419
|
+
minute: '2-digit'
|
|
420
|
+
}).format(new Date(ms));
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
/** "Already checked in at 9:14 AM by Sam". */ export function alreadyCheckedInLabel(row, timeZone) {
|
|
424
|
+
const at = checkInTimeLabel(row.checkedInAtMs, timeZone);
|
|
425
|
+
return `Already checked in${at ? ` at ${at}` : ''}${row.checkedInByName ? ` by ${row.checkedInByName}` : ''}`;
|
|
426
|
+
}
|
|
427
|
+
/** One person's line, as the list and the spreadsheet name it: "Day pass · Adult (2 of 3)". */ export function checkInItemLabel(row) {
|
|
428
|
+
const item = row.variantLabel ? `${row.itemName} · ${row.variantLabel}` : row.itemName;
|
|
429
|
+
return row.unitCount > 1 ? `${item} (${row.unitIndex + 1} of ${row.unitCount})` : item;
|
|
430
|
+
}
|
|
431
|
+
/** The day's check-ins as a spreadsheet, one row per person. */ export function checkInDayCsv(rows, timeZone) {
|
|
432
|
+
const header = [
|
|
433
|
+
'Day',
|
|
434
|
+
'Name',
|
|
435
|
+
'Email',
|
|
436
|
+
'Phone',
|
|
437
|
+
'Item',
|
|
438
|
+
'Order',
|
|
439
|
+
'Status',
|
|
440
|
+
'Checked in at',
|
|
441
|
+
'Checked in by',
|
|
442
|
+
'Wristband number',
|
|
443
|
+
'Wristband color'
|
|
444
|
+
];
|
|
445
|
+
const lines = sortCheckInRows(rows).map((row)=>{
|
|
446
|
+
var _row_customerName, _row_customerEmail, _row_customerPhone, _row_orderLabel, _row_checkedInByName, _ref, _ref1;
|
|
447
|
+
var _row_wristband, _row_wristband1;
|
|
448
|
+
return [
|
|
449
|
+
row.dayKey,
|
|
450
|
+
(_row_customerName = row.customerName) != null ? _row_customerName : '',
|
|
451
|
+
(_row_customerEmail = row.customerEmail) != null ? _row_customerEmail : '',
|
|
452
|
+
(_row_customerPhone = row.customerPhone) != null ? _row_customerPhone : '',
|
|
453
|
+
checkInItemLabel(row),
|
|
454
|
+
(_row_orderLabel = row.orderLabel) != null ? _row_orderLabel : row.source === 'reservation' ? 'Stay' : '',
|
|
455
|
+
row.status === 'checked_in' ? 'Checked in' : 'Expected',
|
|
456
|
+
checkInTimeLabel(row.checkedInAtMs, timeZone),
|
|
457
|
+
(_row_checkedInByName = row.checkedInByName) != null ? _row_checkedInByName : '',
|
|
458
|
+
(_ref = (_row_wristband = row.wristband) == null ? void 0 : _row_wristband.number) != null ? _ref : '',
|
|
459
|
+
(_ref1 = (_row_wristband1 = row.wristband) == null ? void 0 : _row_wristband1.color) != null ? _ref1 : ''
|
|
460
|
+
].map(posCsvCell).join(',');
|
|
461
|
+
});
|
|
462
|
+
return [
|
|
463
|
+
header.map(posCsvCell).join(','),
|
|
464
|
+
...lines
|
|
465
|
+
].join('\n') + '\n';
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
//# sourceMappingURL=commerce-check-in.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/model/commerce-check-in.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 */\nimport {\n CHECK_IN_MAX_HEADCOUNT,\n normalizeProductCheckIn,\n productCheckInProblem,\n type ProductCheckIn,\n} from './commerce-check-in-product'\nimport { emailSearchTokens } from '@aglyn/aglyn/app-utils/email-search'\nimport {\n nameSearchKey,\n nameSearchToken,\n nameSearchTokens,\n} from '@aglyn/aglyn/app-utils/name-search'\nimport type { ProductVariant } from './commerce'\nimport {\n formatOrderNumber,\n type HostOrder,\n type OrderChannel,\n} from './commerce-orders'\nimport type { HostReservation } from './commerce-reservations'\nimport { posCsvCell } from './commerce-pos-ops'\nimport { orderLabelTokens } from './order-list-fields'\n\n// The product setting lives in a pure module the native contracts read (AGL-4043).\nexport {\n CHECK_IN_MAX_HEADCOUNT,\n normalizeProductCheckIn,\n productCheckInProblem,\n type ProductCheckIn,\n} from './commerce-check-in-product'\n\n/*==========================================\n * CHECK-IN AT THE WINDOW (AGL-4043).\n *\n * A rider who bought a day pass online walks up to the window, is looked up\n * by name, checked in and handed a wristband. So is somebody who bought a\n * pass at the register, and a guest whose stay covers today.\n *\n * WHAT IS DUE ON A DAY\n * - An order's lines whose product (or variant) \"Needs check-in\", on the\n * day the order was placed, in the site's time zone. Products have no\n * service date of their own, so the purchase day is the day the pass is\n * for. A paid order only: `paid`, `partially_fulfilled`, `fulfilled` or\n * `delivered`. A line refunded by name is not due.\n * - Each unit is a person: quantity × the product's \"people per item\"\n * (`headcount`, default 1), so three passes are three check-ins.\n * - A reservation that is `confirmed` or `checked_in` and whose stay\n * covers the day: one check-in per day of the stay.\n *\n * Every due unit is a document, `hosts/{hostId}/checkIns/{id}`, written by\n * the server only. Its id is the unit's identity (order, line, unit; or\n * stay, day), so writing what is due twice writes it once, and a check-in\n * is a transaction on that one document.\n *\n * POST /api/commerce/pos-check-in { hostId, action, … }\n * GET /api/commerce/pos-check-in?hostId=…&day=YYYY-MM-DD[&format=csv]\n *\n * The native register mirrors these types.\n *=========================================*/\n\nexport const POS_CHECK_IN_ROUTE = '/api/commerce/pos-check-in'\n\n/** The most check-ins one order line makes, whatever its quantity. */\nexport const CHECK_IN_MAX_UNITS_PER_LINE = 200\n\n/** The most check-ins, orders or stays one day reads. */\nexport const CHECK_IN_DAY_CEILING = 3000\n\n/** The most check-in rows one search reads. */\nexport const CHECK_IN_SEARCH_ROWS = 100\n\n/** The most customers one search answers. */\nexport const CHECK_IN_SEARCH_CUSTOMERS = 20\n\n/** The most check-ins one tap records. */\nexport const CHECK_IN_BATCH_MAX = 50\n\n/** A wristband's number or color, at most this many characters. */\nexport const CHECK_IN_WRISTBAND_MAX = 24\n\n/** Colors offered as quick picks for a wristband. Any word is accepted. */\nexport const CHECK_IN_WRISTBAND_COLORS = [\n 'Red',\n 'Orange',\n 'Yellow',\n 'Green',\n 'Blue',\n 'Purple',\n 'Pink',\n 'White',\n 'Black',\n] as const\n\n/** The order statuses whose check-in lines are due. */\nexport const CHECK_IN_ORDER_STATUSES = ['paid', 'partially_fulfilled', 'fulfilled', 'delivered'] as const\n\n/** The stay statuses whose days are due. */\nexport const CHECK_IN_RESERVATION_STATUSES = ['confirmed', 'checked_in'] as const\n\nexport type CheckInStatus = 'expected' | 'checked_in'\n\nexport interface CheckInWristband {\n number: string | null\n color: string | null\n}\n\n/** `hosts/{hostId}/checkIns/{id}`: one person due on one day. Server-written only. */\nexport interface HostCheckIn {\n source: 'order' | 'reservation'\n orderId: string | null\n /** The order's number as the console shows it (`#1042`), or null for a stay. */\n orderLabel: string | null\n /** Where the order was sold, or `reservation`. */\n channel: OrderChannel | 'reservation'\n reservationId: string | null\n lineIndex: number | null\n /** This person's place among the line's or stay's check-ins, from 0. */\n unitIndex: number\n /** How many check-ins the line or stay makes that day. */\n unitCount: number\n productId: string | null\n variantId: string | null\n itemName: string\n variantLabel: string | null\n /** The day, `YYYY-MM-DD` in the site's time zone. */\n dayKey: string\n /** Who the check-in is for, as one key: the address, else the contact, else the name, else the order. */\n customerKey: string\n customerName: string | null\n customerEmail: string | null\n customerEmailLower: string | null\n customerPhone: string | null\n /** The contact the register attached to the sale, when it was one. */\n contactId: string | null\n /** The name's, the address's, the phone's and the order number's search prefixes. */\n searchTokens: string[]\n status: CheckInStatus\n checkedInAtMs: number | null\n checkedInBy: string | null\n checkedInByName: string | null\n wristband: CheckInWristband | null\n /** The attempt that checked this person in, so a retried tap is not \"already checked in\". */\n checkInAttempt: string | null\n /** The last undo, kept so a reversed check-in still says who reversed it. */\n undoneAtMs: number | null\n undoneBy: string | null\n createdAtMs: number\n updatedAtMs: number\n}\n\n/** One check-in as the routes answer it. */\nexport type CheckInRow = HostCheckIn & { id: string }\n\n/** A customer with something due on a day, as the search lists them. */\nexport interface CheckInCustomer {\n customerKey: string\n name: string | null\n email: string | null\n phone: string | null\n contactId: string | null\n /** Every check-in the customer has on the day. */\n unitsDue: number\n unitsCheckedIn: number\n /** What the check-ins are for, item names once each. */\n items: string[]\n}\n\n/*==========================================\n * THE PRODUCT SETTING\n *=========================================*/\n\n/**\n * Whether one variant of a product needs check-in, and for how many people\n * per item: the variant's own setting, else the product's; `null` when not.\n */\nexport function productCheckInFor(\n product: { checkIn?: unknown; variants?: ReadonlyArray<Pick<ProductVariant, 'id'> & { checkIn?: unknown }> } | null | undefined,\n variantId: string | null | undefined,\n): { headcount: number } | null {\n if (!product) return null\n const variant = (product.variants ?? []).find((one) => one.id === (variantId || 'default'))\n const setting = normalizeProductCheckIn(variant?.checkIn) ?? normalizeProductCheckIn(product.checkIn)\n return setting?.enabled ? { headcount: setting.headcount ?? 1 } : null\n}\n\n/** Whether any variant of a product needs check-in. */\nexport function productNeedsCheckIn(\n product: Parameters<typeof productCheckInFor>[0],\n): boolean {\n if (!product) return false\n const variants = product.variants?.length ? product.variants : [{ id: 'default' }]\n return variants.some((variant) => productCheckInFor(product, variant.id) !== null)\n}\n\n/*==========================================\n * WHAT IS DUE\n *=========================================*/\n\nconst text = (value: unknown): string => (typeof value === 'string' ? value.trim() : '')\n\n/** The digits of a phone number, without a leading US/Canada 1 when it has eleven. */\nexport function checkInPhoneDigits(phone: string | null | undefined): string {\n const digits = String(phone ?? '').replace(/\\D+/g, '')\n return digits.length === 11 && digits.startsWith('1') ? digits.slice(1) : digits\n}\n\n/** The search prefixes of a phone number: its digits from three on, and its last four. */\nfunction phoneTokens(phone: string | null | undefined): string[] {\n const digits = checkInPhoneDigits(phone).slice(0, 15)\n const tokens: string[] = []\n for (let at = 3; at <= digits.length; at += 1) tokens.push(digits.slice(0, at))\n // The last four, which is what a rider reads out at the window.\n if (digits.length >= 7) tokens.push(digits.slice(-4))\n return tokens\n}\n\n/** The tokens a check-in is found by. */\nexport function checkInSearchTokens(input: {\n name?: string | null\n email?: string | null\n phone?: string | null\n orderNumber?: number | null\n orderId?: string | null\n}): string[] {\n return [\n ...new Set([\n ...nameSearchTokens(input.name ?? ''),\n ...emailSearchTokens(input.email ?? ''),\n ...phoneTokens(input.phone),\n ...(input.orderId ? orderLabelTokens({ number: input.orderNumber ?? undefined }, input.orderId) : []),\n ]),\n ].slice(0, 200)\n}\n\n/**\n * What a typed search asks the index for: the phone's digits when it is a\n * number, else the first word's prefix (a name, an address, `#1042`).\n */\nexport function checkInSearchToken(typed: string): string {\n const value = String(typed ?? '').trim()\n if (!value) return ''\n if (/^[\\d\\s()+.-]+$/.test(value) && !value.startsWith('#')) {\n const digits = checkInPhoneDigits(value)\n return digits.length >= 3 ? digits.slice(0, 15) : ''\n }\n return nameSearchToken(value)\n}\n\n/** One key per customer: the address, else the contact, else the name, else the source. */\nexport function checkInCustomerKey(input: {\n email?: string | null\n contactId?: string | null\n name?: string | null\n fallback: string\n}): string {\n const email = text(input.email).toLowerCase()\n if (email) return `email:${email}`\n if (input.contactId) return `contact:${input.contactId}`\n const name = nameSearchKey(input.name ?? '')\n if (name) return `name:${name}`\n return input.fallback\n}\n\n/** A check-in's document id, from its unit's identity. */\nexport function orderCheckInId(orderId: string, lineIndex: number, unitIndex: number): string {\n return `o_${orderId}_${lineIndex}_${unitIndex}`\n}\n\nexport function reservationCheckInId(reservationId: string, dayKey: string, unitIndex = 0): string {\n return `r_${reservationId}_${dayKey}_${unitIndex}`\n}\n\n/** A due check-in before the server stamps its times and status. */\nexport type DueCheckIn = Omit<\n HostCheckIn,\n | 'status'\n | 'checkedInAtMs'\n | 'checkedInBy'\n | 'checkedInByName'\n | 'wristband'\n | 'checkInAttempt'\n | 'undoneAtMs'\n | 'undoneBy'\n | 'createdAtMs'\n | 'updatedAtMs'\n>\n\n/** The customer fields a due check-in copies from its source, which a later read may refresh. */\nexport const CHECK_IN_CUSTOMER_FIELDS = [\n 'customerKey',\n 'customerName',\n 'customerEmail',\n 'customerEmailLower',\n 'customerPhone',\n 'contactId',\n 'searchTokens',\n] as const\n\n/** Whether an order's lines are due at all. */\nexport function orderIsDueForCheckIn(order: Pick<HostOrder, 'status'> | null | undefined): boolean {\n return Boolean(order && (CHECK_IN_ORDER_STATUSES as readonly string[]).includes(String(order.status ?? '')))\n}\n\n/**\n * The check-ins an order makes on its day, keyed by document id. `products`\n * holds the products its lines name, as stored now: the setting is read at\n * the window, so turning it on covers passes already sold today.\n */\nexport function dueCheckInsForOrder(input: {\n orderId: string\n order: Partial<HostOrder>\n products: ReadonlyMap<string, Parameters<typeof productCheckInFor>[0]>\n dayKey: string\n}): Map<string, DueCheckIn> {\n const { orderId, order, dayKey } = input\n const due = new Map<string, DueCheckIn>()\n if (!orderIsDueForCheckIn(order as HostOrder)) return due\n const refunded = new Set(Array.isArray(order.refundedLineItemIds) ? order.refundedLineItemIds : [])\n const contactId =\n order.customerRecord?.kind === 'contact' && order.customerRecord.id ? order.customerRecord.id : null\n const name = text(order.customerName) || null\n const email = text(order.customerEmail) || null\n const phone = text(order.customerPhone) || null\n const customerKey = checkInCustomerKey({ email, contactId, name, fallback: `order:${orderId}` })\n const searchTokens = checkInSearchTokens({ name, email, phone, orderNumber: order.number ?? null, orderId })\n const lines = Array.isArray(order.lineItems) ? order.lineItems : []\n lines.forEach((line, lineIndex) => {\n if (!line || refunded.has(lineIndex)) return\n const setting = productCheckInFor(input.products.get(line.productId) ?? null, line.variantId)\n if (!setting) return\n const quantity = Math.max(0, Math.round(Number(line.quantity) || 0))\n const unitCount = Math.min(quantity * setting.headcount, CHECK_IN_MAX_UNITS_PER_LINE)\n for (let unitIndex = 0; unitIndex < unitCount; unitIndex += 1) {\n due.set(orderCheckInId(orderId, lineIndex, unitIndex), {\n source: 'order',\n orderId,\n orderLabel: formatOrderNumber({ number: order.number }, orderId),\n channel: (order.channel ?? 'online') as OrderChannel,\n reservationId: null,\n lineIndex,\n unitIndex,\n unitCount,\n productId: line.productId ?? null,\n variantId: line.variantId ?? null,\n itemName: text(line.name) || 'Item',\n variantLabel: text(line.variantLabel) || null,\n dayKey,\n customerKey,\n customerName: name,\n customerEmail: email,\n customerEmailLower: email ? email.toLowerCase() : null,\n customerPhone: phone,\n contactId,\n searchTokens,\n })\n }\n })\n return due\n}\n\n/** UTC midnight of a `YYYY-MM-DD` day, as a stay's days are stored. */\nexport function checkInDayMs(dayKey: string): number | null {\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(dayKey)\n if (!match) return null\n const ms = Date.UTC(Number(match[1]), Number(match[2]) - 1, Number(match[3]))\n const check = new Date(ms)\n return check.getUTCDate() === Number(match[3]) && check.getUTCMonth() === Number(match[2]) - 1 ? ms : null\n}\n\n/** The check-in a stay makes on a day it covers; empty on any other day. */\nexport function dueCheckInsForReservation(input: {\n reservationId: string\n reservation: Partial<HostReservation>\n resourceName: string | null\n dayKey: string\n}): Map<string, DueCheckIn> {\n const { reservationId, reservation, dayKey } = input\n const due = new Map<string, DueCheckIn>()\n const dayMs = checkInDayMs(dayKey)\n if (\n dayMs === null ||\n !(CHECK_IN_RESERVATION_STATUSES as readonly string[]).includes(String(reservation.status ?? '')) ||\n !(Number(reservation.checkInDayMs) <= dayMs && dayMs < Number(reservation.checkOutDayMs))\n ) {\n return due\n }\n const name = text(reservation.guestName) || null\n const email = text(reservation.guestEmail) || null\n due.set(reservationCheckInId(reservationId, dayKey), {\n source: 'reservation',\n orderId: null,\n orderLabel: null,\n channel: 'reservation',\n reservationId,\n lineIndex: null,\n unitIndex: 0,\n unitCount: 1,\n productId: null,\n variantId: null,\n itemName: text(input.resourceName) || 'Stay',\n variantLabel: null,\n dayKey,\n customerKey: checkInCustomerKey({ email, name, fallback: `reservation:${reservationId}` }),\n customerName: name,\n customerEmail: email,\n customerEmailLower: email ? email.toLowerCase() : null,\n customerPhone: null,\n contactId: null,\n searchTokens: checkInSearchTokens({ name, email }),\n })\n return due\n}\n\n/** A due check-in as first written. */\nexport function newCheckInDocument(due: DueCheckIn, nowMs: number): HostCheckIn {\n return {\n ...due,\n status: 'expected',\n checkedInAtMs: null,\n checkedInBy: null,\n checkedInByName: null,\n wristband: null,\n checkInAttempt: null,\n undoneAtMs: null,\n undoneBy: null,\n createdAtMs: nowMs,\n updatedAtMs: nowMs,\n }\n}\n\n/** The customer fields of a stored check-in that its source now says otherwise. */\nexport function changedCheckInCustomerFields(\n stored: Partial<HostCheckIn>,\n due: DueCheckIn,\n): Partial<DueCheckIn> | null {\n const patch: Record<string, unknown> = {}\n for (const field of CHECK_IN_CUSTOMER_FIELDS) {\n if (JSON.stringify(stored[field] ?? null) !== JSON.stringify(due[field] ?? null)) patch[field] = due[field]\n }\n return Object.keys(patch).length ? (patch as Partial<DueCheckIn>) : null\n}\n\n/*==========================================\n * WRISTBANDS, CUSTOMERS AND THE DAY\n *=========================================*/\n\n/**\n * A wristband as typed, made safe: a number (letters, digits, a dash) and a\n * color word, each optional. `null` with neither; an error for junk.\n */\nexport function normalizeWristband(\n value: unknown,\n): { ok: true; wristband: CheckInWristband | null } | { ok: false; error: string } {\n if (value === undefined || value === null || value === '') return { ok: true, wristband: null }\n if (typeof value !== 'object') return { ok: false, error: 'That is not a wristband.' }\n const raw = value as Record<string, unknown>\n const number = String(raw['number'] ?? '').trim()\n const color = String(raw['color'] ?? '').trim()\n if (number.length > CHECK_IN_WRISTBAND_MAX || color.length > CHECK_IN_WRISTBAND_MAX) {\n return { ok: false, error: `A wristband number or color is ${CHECK_IN_WRISTBAND_MAX} characters at most.` }\n }\n if (number && !/^[A-Za-z0-9#-]+$/.test(number)) {\n return { ok: false, error: 'A wristband number is letters, digits and dashes.' }\n }\n if (color && !/^[\\p{L} -]+$/u.test(color)) {\n return { ok: false, error: 'A wristband color is a word, such as Blue.' }\n }\n if (!number && !color) return { ok: true, wristband: null }\n return { ok: true, wristband: { number: number || null, color: color || null } }\n}\n\n/** A wristband as one line: \"Blue #214\". */\nexport function describeWristband(wristband: CheckInWristband | null | undefined): string {\n if (!wristband) return ''\n return [wristband.color, wristband.number ? `#${wristband.number.replace(/^#/, '')}` : null]\n .filter(Boolean)\n .join(' ')\n}\n\n/** The customers a set of check-ins is for, most due first, then by name. */\nexport function checkInCustomers(rows: ReadonlyArray<CheckInRow>): CheckInCustomer[] {\n const byKey = new Map<string, CheckInCustomer>()\n for (const row of rows) {\n const found = byKey.get(row.customerKey)\n const customer: CheckInCustomer = found ?? {\n customerKey: row.customerKey,\n name: row.customerName,\n email: row.customerEmail,\n phone: row.customerPhone,\n contactId: row.contactId,\n unitsDue: 0,\n unitsCheckedIn: 0,\n items: [],\n }\n customer.unitsDue += 1\n if (row.status === 'checked_in') customer.unitsCheckedIn += 1\n customer.name ||= row.customerName\n customer.email ||= row.customerEmail\n customer.phone ||= row.customerPhone\n customer.contactId ||= row.contactId\n if (!customer.items.includes(row.itemName)) customer.items.push(row.itemName)\n byKey.set(row.customerKey, customer)\n }\n return [...byKey.values()].sort(\n (a, b) =>\n b.unitsDue - b.unitsCheckedIn - (a.unitsDue - a.unitsCheckedIn) ||\n String(a.name ?? a.email ?? '').localeCompare(String(b.name ?? b.email ?? '')),\n )\n}\n\n/** A day's check-ins in the order the window reads them: by name, then item, then unit. */\nexport function sortCheckInRows<T extends Pick<CheckInRow, 'customerName' | 'customerEmail' | 'itemName' | 'unitIndex' | 'id'>>(\n rows: ReadonlyArray<T>,\n): T[] {\n return [...rows].sort(\n (a, b) =>\n String(a.customerName ?? a.customerEmail ?? '').localeCompare(String(b.customerName ?? b.customerEmail ?? '')) ||\n a.itemName.localeCompare(b.itemName) ||\n a.unitIndex - b.unitIndex ||\n a.id.localeCompare(b.id),\n )\n}\n\nexport interface CheckInDayTotals {\n expected: number\n checkedIn: number\n}\n\nexport function checkInDayTotals(rows: ReadonlyArray<Pick<CheckInRow, 'status'>>): CheckInDayTotals {\n return {\n expected: rows.length,\n checkedIn: rows.filter((row) => row.status === 'checked_in').length,\n }\n}\n\n/** A time on the site's clock: \"9:14 AM\". */\nexport function checkInTimeLabel(ms: number | null | undefined, timeZone: string): string {\n if (!ms) return ''\n try {\n return new Intl.DateTimeFormat('en-US', { hour: 'numeric', minute: '2-digit', timeZone }).format(new Date(ms))\n } catch {\n return new Intl.DateTimeFormat('en-US', { hour: 'numeric', minute: '2-digit' }).format(new Date(ms))\n }\n}\n\n/** \"Already checked in at 9:14 AM by Sam\". */\nexport function alreadyCheckedInLabel(row: Pick<CheckInRow, 'checkedInAtMs' | 'checkedInByName'>, timeZone: string): string {\n const at = checkInTimeLabel(row.checkedInAtMs, timeZone)\n return `Already checked in${at ? ` at ${at}` : ''}${row.checkedInByName ? ` by ${row.checkedInByName}` : ''}`\n}\n\n/** One person's line, as the list and the spreadsheet name it: \"Day pass · Adult (2 of 3)\". */\nexport function checkInItemLabel(row: Pick<CheckInRow, 'itemName' | 'variantLabel' | 'unitIndex' | 'unitCount'>): string {\n const item = row.variantLabel ? `${row.itemName} · ${row.variantLabel}` : row.itemName\n return row.unitCount > 1 ? `${item} (${row.unitIndex + 1} of ${row.unitCount})` : item\n}\n\n/** The day's check-ins as a spreadsheet, one row per person. */\nexport function checkInDayCsv(rows: ReadonlyArray<CheckInRow>, timeZone: string): string {\n const header = [\n 'Day',\n 'Name',\n 'Email',\n 'Phone',\n 'Item',\n 'Order',\n 'Status',\n 'Checked in at',\n 'Checked in by',\n 'Wristband number',\n 'Wristband color',\n ]\n const lines = sortCheckInRows(rows).map((row) =>\n [\n row.dayKey,\n row.customerName ?? '',\n row.customerEmail ?? '',\n row.customerPhone ?? '',\n checkInItemLabel(row),\n row.orderLabel ?? (row.source === 'reservation' ? 'Stay' : ''),\n row.status === 'checked_in' ? 'Checked in' : 'Expected',\n checkInTimeLabel(row.checkedInAtMs, timeZone),\n row.checkedInByName ?? '',\n row.wristband?.number ?? '',\n row.wristband?.color ?? '',\n ]\n .map(posCsvCell)\n .join(','),\n )\n return [header.map(posCsvCell).join(','), ...lines].join('\\n') + '\\n'\n}\n"],"names":["normalizeProductCheckIn","emailSearchTokens","nameSearchKey","nameSearchToken","nameSearchTokens","formatOrderNumber","posCsvCell","orderLabelTokens","CHECK_IN_MAX_HEADCOUNT","productCheckInProblem","POS_CHECK_IN_ROUTE","CHECK_IN_MAX_UNITS_PER_LINE","CHECK_IN_DAY_CEILING","CHECK_IN_SEARCH_ROWS","CHECK_IN_SEARCH_CUSTOMERS","CHECK_IN_BATCH_MAX","CHECK_IN_WRISTBAND_MAX","CHECK_IN_WRISTBAND_COLORS","CHECK_IN_ORDER_STATUSES","CHECK_IN_RESERVATION_STATUSES","productCheckInFor","product","variantId","setting","variant","variants","find","one","id","checkIn","enabled","headcount","productNeedsCheckIn","length","some","text","value","trim","checkInPhoneDigits","phone","digits","String","replace","startsWith","slice","phoneTokens","tokens","at","push","checkInSearchTokens","input","Set","name","email","orderId","number","orderNumber","undefined","checkInSearchToken","typed","test","checkInCustomerKey","toLowerCase","contactId","fallback","orderCheckInId","lineIndex","unitIndex","reservationCheckInId","reservationId","dayKey","CHECK_IN_CUSTOMER_FIELDS","orderIsDueForCheckIn","order","Boolean","includes","status","dueCheckInsForOrder","due","Map","refunded","Array","isArray","refundedLineItemIds","customerRecord","kind","customerName","customerEmail","customerPhone","customerKey","searchTokens","lines","lineItems","forEach","line","has","products","get","productId","quantity","Math","max","round","Number","unitCount","min","set","source","orderLabel","channel","itemName","variantLabel","customerEmailLower","checkInDayMs","match","exec","ms","Date","UTC","check","getUTCDate","getUTCMonth","dueCheckInsForReservation","reservation","dayMs","checkOutDayMs","guestName","guestEmail","resourceName","newCheckInDocument","nowMs","checkedInAtMs","checkedInBy","checkedInByName","wristband","checkInAttempt","undoneAtMs","undoneBy","createdAtMs","updatedAtMs","changedCheckInCustomerFields","stored","patch","field","JSON","stringify","Object","keys","normalizeWristband","raw","ok","error","color","describeWristband","filter","join","checkInCustomers","rows","byKey","row","customer","found","unitsDue","unitsCheckedIn","items","values","sort","a","b","localeCompare","sortCheckInRows","checkInDayTotals","expected","checkedIn","checkInTimeLabel","timeZone","Intl","DateTimeFormat","hour","minute","format","alreadyCheckedInLabel","checkInItemLabel","item","checkInDayCsv","header","map"],"mappings":"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"}
|