@aglyn/plugins-commerce 1.0.0-beta.288 → 1.0.0-beta.290
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/package.json +13 -13
- package/src/lib/components/commerce-console-page.js +29 -2
- package/src/lib/components/commerce-console-page.js.map +1 -1
- package/src/lib/components/console/commerce-analytics-card.component.js +4 -2
- package/src/lib/components/console/commerce-analytics-card.component.js.map +1 -1
- package/src/lib/components/console/commerce-pdf-download.d.ts +30 -0
- package/src/lib/components/console/commerce-pdf-download.js +53 -0
- package/src/lib/components/console/commerce-pdf-download.js.map +1 -0
- package/src/lib/components/console/host-orders-card.component.js +5 -1
- package/src/lib/components/console/host-orders-card.component.js.map +1 -1
- package/src/lib/components/console/host-quotes-card.component.d.ts +34 -0
- package/src/lib/components/console/host-quotes-card.component.js +263 -0
- package/src/lib/components/console/host-quotes-card.component.js.map +1 -0
- package/src/lib/components/console/order-invoice.component.d.ts +6 -4
- package/src/lib/components/console/order-invoice.component.js +67 -11
- package/src/lib/components/console/order-invoice.component.js.map +1 -1
- package/src/lib/components/console/pos-ops/pos-check-ins-card.component.js +33 -28
- package/src/lib/components/console/pos-ops/pos-check-ins-card.component.js.map +1 -1
- package/src/lib/components/console/quote-editor-dialog.component.d.ts +45 -0
- package/src/lib/components/console/quote-editor-dialog.component.js +1317 -0
- package/src/lib/components/console/quote-editor-dialog.component.js.map +1 -0
- package/src/lib/components/console/quote-pay-link.component.d.ts +38 -0
- package/src/lib/components/console/quote-pay-link.component.js +213 -0
- package/src/lib/components/console/quote-pay-link.component.js.map +1 -0
- package/src/lib/components/console/quote-proofs.component.d.ts +37 -0
- package/src/lib/components/console/quote-proofs.component.js +626 -0
- package/src/lib/components/console/quote-proofs.component.js.map +1 -0
- package/src/lib/components/console/quote-settings-card.component.d.ts +29 -0
- package/src/lib/components/console/quote-settings-card.component.js +121 -0
- package/src/lib/components/console/quote-settings-card.component.js.map +1 -0
- package/src/lib/components/console/tax-settings-card.component.js +4 -1
- package/src/lib/components/console/tax-settings-card.component.js.map +1 -1
- package/src/lib/components/quote-page-body.d.ts +33 -0
- package/src/lib/components/quote-page-body.js +724 -0
- package/src/lib/components/quote-page-body.js.map +1 -0
- package/src/lib/components/quote-page.d.ts +29 -0
- package/src/lib/components/quote-page.js +96 -0
- package/src/lib/components/quote-page.js.map +1 -0
- package/src/lib/components/quote-proof-panel.d.ts +42 -0
- package/src/lib/components/quote-proof-panel.js +436 -0
- package/src/lib/components/quote-proof-panel.js.map +1 -0
- package/src/lib/components/storefront-payment-element.d.ts +7 -1
- package/src/lib/components/storefront-payment-element.js +8 -3
- package/src/lib/components/storefront-payment-element.js.map +1 -1
- package/src/lib/constants/orders-list-query.js +6 -1
- package/src/lib/constants/orders-list-query.js.map +1 -1
- package/src/lib/constants/quote-page.d.ts +30 -0
- package/src/lib/constants/quote-page.js +35 -0
- package/src/lib/constants/quote-page.js.map +1 -0
- package/src/lib/model/commerce-orders.d.ts +25 -2
- package/src/lib/model/commerce-orders.js +10 -1
- package/src/lib/model/commerce-orders.js.map +1 -1
- package/src/lib/model/commerce-quote-pay.d.ts +256 -0
- package/src/lib/model/commerce-quote-pay.js +426 -0
- package/src/lib/model/commerce-quote-pay.js.map +1 -0
- package/src/lib/model/commerce-quote-proofs.d.ts +159 -0
- package/src/lib/model/commerce-quote-proofs.js +348 -0
- package/src/lib/model/commerce-quote-proofs.js.map +1 -0
- package/src/lib/model/commerce-quotes.d.ts +335 -0
- package/src/lib/model/commerce-quotes.js +522 -0
- package/src/lib/model/commerce-quotes.js.map +1 -0
- package/src/lib/model/index.d.ts +3 -0
- package/src/lib/model/index.js +3 -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 +20 -0
- package/src/lib/model/plugin-permissions.js.map +1 -1
- package/src/lib/server/api-v1/orders-and-products.js +6 -2
- package/src/lib/server/api-v1/orders-and-products.js.map +1 -1
- package/src/lib/server/billing-webhook.js +127 -52
- package/src/lib/server/billing-webhook.js.map +1 -1
- package/src/lib/server/checkout-session-expiry.d.ts +36 -0
- package/src/lib/server/checkout-session-expiry.js +63 -0
- package/src/lib/server/checkout-session-expiry.js.map +1 -0
- package/src/lib/server/commerce-pdf.d.ts +100 -0
- package/src/lib/server/commerce-pdf.js +283 -0
- package/src/lib/server/commerce-pdf.js.map +1 -0
- package/src/lib/server/draft-order.js +16 -8
- package/src/lib/server/draft-order.js.map +1 -1
- package/src/lib/server/order-print.d.ts +6 -0
- package/src/lib/server/order-print.js +22 -5
- package/src/lib/server/order-print.js.map +1 -1
- package/src/lib/server/pdf-response.d.ts +31 -0
- package/src/lib/server/pdf-response.js +30 -0
- package/src/lib/server/pdf-response.js.map +1 -0
- package/src/lib/server/person-eraser.d.ts +7 -0
- package/src/lib/server/person-eraser.js +24 -2
- package/src/lib/server/person-eraser.js.map +1 -1
- package/src/lib/server/pos-reader-splash.d.ts +2 -18
- package/src/lib/server/pos-reader-splash.js +8 -93
- package/src/lib/server/pos-reader-splash.js.map +1 -1
- package/src/lib/server/pos-return.js +3 -1
- package/src/lib/server/pos-return.js.map +1 -1
- package/src/lib/server/quote-link-token.d.ts +39 -0
- package/src/lib/server/quote-link-token.js +97 -0
- package/src/lib/server/quote-link-token.js.map +1 -0
- package/src/lib/server/quote-pay.d.ts +110 -0
- package/src/lib/server/quote-pay.js +606 -0
- package/src/lib/server/quote-pay.js.map +1 -0
- package/src/lib/server/quote-proofs.d.ts +51 -0
- package/src/lib/server/quote-proofs.js +500 -0
- package/src/lib/server/quote-proofs.js.map +1 -0
- package/src/lib/server/quote-uploads.d.ts +33 -0
- package/src/lib/server/quote-uploads.js +29 -0
- package/src/lib/server/quote-uploads.js.map +1 -0
- package/src/lib/server/quote.d.ts +63 -0
- package/src/lib/server/quote.js +846 -0
- package/src/lib/server/quote.js.map +1 -0
- package/src/lib/server/related.js +2 -0
- package/src/lib/server/related.js.map +1 -1
- package/src/lib/server/site-image-source.d.ts +38 -0
- package/src/lib/server/site-image-source.js +130 -0
- package/src/lib/server/site-image-source.js.map +1 -0
- package/src/lib/server/site-page-resolver.d.ts +2 -0
- package/src/lib/server/site-page-resolver.js +75 -0
- package/src/lib/server/site-page-resolver.js.map +1 -1
- package/src/lib/server.js +33 -1
- package/src/lib/server.js.map +1 -1
- package/src/lib/site.js +6 -0
- package/src/lib/site.js.map +1 -1
- package/src/lib/transfer/tracking.server.js +6 -0
- package/src/lib/transfer/tracking.server.js.map +1 -1
- package/src/lib/utils/commerce-document-pdf.d.ts +77 -0
- package/src/lib/utils/commerce-document-pdf.js +608 -0
- package/src/lib/utils/commerce-document-pdf.js.map +1 -0
- package/src/lib/utils/order-invoice.d.ts +52 -3
- package/src/lib/utils/order-invoice.js +116 -64
- package/src/lib/utils/order-invoice.js.map +1 -1
package/src/lib/site.js
CHANGED
|
@@ -29,6 +29,7 @@ import * as ProductDetail from "./components/product-detail.js";
|
|
|
29
29
|
import * as ReservationWidget from "./components/reservation-widget.js";
|
|
30
30
|
import * as ProductGrid from "./components/product-grid.js";
|
|
31
31
|
import * as ProductReviews from "./components/product-reviews.js";
|
|
32
|
+
import * as QuotePage from "./components/quote-page.js";
|
|
32
33
|
import * as RelatedProducts from "./components/related-products.js";
|
|
33
34
|
import * as ReturnRequest from "./components/return-request.js";
|
|
34
35
|
import * as Wishlist from "./components/wishlist.js";
|
|
@@ -125,6 +126,11 @@ import { BUNDLE_ID } from "./constants/bundle-common.js";
|
|
|
125
126
|
component: ReturnRequest.default,
|
|
126
127
|
schema: ReturnRequest.schema,
|
|
127
128
|
presets: ReturnRequest.presets
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
component: QuotePage.default,
|
|
132
|
+
schema: QuotePage.schema,
|
|
133
|
+
presets: QuotePage.presets
|
|
128
134
|
}
|
|
129
135
|
];
|
|
130
136
|
export function registerCommercePlugin() {
|
package/src/lib/site.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../libs/plugins/commerce/src/lib/site.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as Aglyn from '@aglyn/aglyn'\nimport { mdiStorefrontOutline } from '@aglyn/shared-data-mdi'\nimport * as Account from './components/account'\nimport * as Cart from './components/cart'\nimport * as Gate from './components/gate'\nimport * as GatedVideo from './components/gated-video'\nimport * as MemberFeed from './components/member-feed'\nimport * as MemberRecovery from './components/member-recovery'\nimport * as MemberSignin from './components/member-signin'\nimport * as MemberSignup from './components/member-signup'\nimport * as NewsletterSignup from './components/newsletter-signup'\nimport * as OrderStatus from './components/order-status'\nimport * as ProductDetail from './components/product-detail'\nimport * as ReservationWidget from './components/reservation-widget'\nimport * as ProductGrid from './components/product-grid'\nimport * as ProductReviews from './components/product-reviews'\nimport * as RelatedProducts from './components/related-products'\nimport * as ReturnRequest from './components/return-request'\nimport * as Wishlist from './components/wishlist'\nimport { BUNDLE_ID } from './constants/bundle-common'\n\n/**\n * Commerce UI feature plugin (AGL-290): the storefront component set,\n * built on the feature-plugin pattern (AGL-277) — depends on the mui\n * bundle for primitives/theming and registers alongside it in the\n * besigner and the tenant renderer. Components join `COMMERCE_BUNDLE`\n * as they land (PLP AGL-291, PDP AGL-292, cart AGL-293, …); ids are\n * persisted in screen docs and never renamed.\n */\nexport const COMMERCE_BUNDLE: Aglyn.FeatureBundleEntry[] = [\n {\n component: ProductGrid.default,\n schema: ProductGrid.schema,\n presets: ProductGrid.presets,\n },\n {\n component: ProductDetail.default,\n schema: ProductDetail.schema,\n presets: ProductDetail.presets,\n },\n {\n component: Cart.default,\n schema: Cart.schema,\n presets: Cart.presets,\n },\n {\n component: Account.default,\n schema: Account.schema,\n presets: Account.presets,\n },\n {\n component: Wishlist.default,\n schema: Wishlist.schema,\n presets: Wishlist.presets,\n },\n {\n component: NewsletterSignup.default,\n schema: NewsletterSignup.schema,\n presets: NewsletterSignup.presets,\n },\n {\n component: Gate.default,\n schema: Gate.schema,\n presets: Gate.presets,\n },\n {\n component: GatedVideo.default,\n schema: GatedVideo.schema,\n presets: GatedVideo.presets,\n },\n {\n component: MemberFeed.default,\n schema: MemberFeed.schema,\n presets: MemberFeed.presets,\n },\n {\n component: MemberRecovery.default,\n schema: MemberRecovery.schema,\n presets: MemberRecovery.presets,\n },\n {\n component: MemberSignin.default,\n schema: MemberSignin.schema,\n presets: MemberSignin.presets,\n },\n {\n component: MemberSignup.default,\n schema: MemberSignup.schema,\n presets: MemberSignup.presets,\n },\n {\n component: ReservationWidget.default,\n schema: ReservationWidget.schema,\n presets: ReservationWidget.presets,\n },\n {\n component: ProductReviews.default,\n schema: ProductReviews.schema,\n presets: ProductReviews.presets,\n },\n {\n component: RelatedProducts.default,\n schema: RelatedProducts.schema,\n presets: RelatedProducts.presets,\n },\n {\n component: OrderStatus.default,\n schema: OrderStatus.schema,\n presets: OrderStatus.presets,\n },\n {\n component: ReturnRequest.default,\n schema: ReturnRequest.schema,\n presets: ReturnRequest.presets,\n },\n]\n\nexport function registerCommercePlugin(): void {\n // The canvas half only. The console registers the console half through its\n // own `console` surface, and a published page must never load console code\n // (AGL-3116): this runs on every page that places one of these elements.\n if (Aglyn.plugins.getDependency(BUNDLE_ID)) return\n Aglyn.plugins.addDependency(\n Aglyn.defineUiFeatureBundle(\n {\n bundleId: BUNDLE_ID,\n displayName: 'Commerce',\n description: 'Storefront blocks: product grids, detail, cart',\n icon: { path: mdiStorefrontOutline.path },\n components: COMMERCE_BUNDLE,\n },\n Aglyn.components,\n ),\n )\n}\n"],"names":["Aglyn","mdiStorefrontOutline","Account","Cart","Gate","GatedVideo","MemberFeed","MemberRecovery","MemberSignin","MemberSignup","NewsletterSignup","OrderStatus","ProductDetail","ReservationWidget","ProductGrid","ProductReviews","RelatedProducts","ReturnRequest","Wishlist","BUNDLE_ID","COMMERCE_BUNDLE","component","default","schema","presets","registerCommercePlugin","plugins","getDependency","addDependency","defineUiFeatureBundle","bundleId","displayName","description","icon","path","components"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,YAAYA,WAAW,eAAc;AACrC,SAASC,oBAAoB,QAAQ,yBAAwB;AAC7D,YAAYC,aAAa,0BAAsB;AAC/C,YAAYC,UAAU,uBAAmB;AACzC,YAAYC,UAAU,uBAAmB;AACzC,YAAYC,gBAAgB,8BAA0B;AACtD,YAAYC,gBAAgB,8BAA0B;AACtD,YAAYC,oBAAoB,kCAA8B;AAC9D,YAAYC,kBAAkB,gCAA4B;AAC1D,YAAYC,kBAAkB,gCAA4B;AAC1D,YAAYC,sBAAsB,oCAAgC;AAClE,YAAYC,iBAAiB,+BAA2B;AACxD,YAAYC,mBAAmB,iCAA6B;AAC5D,YAAYC,uBAAuB,qCAAiC;AACpE,YAAYC,iBAAiB,+BAA2B;AACxD,YAAYC,oBAAoB,kCAA8B;AAC9D,YAAYC,qBAAqB,mCAA+B;AAChE,YAAYC,mBAAmB,iCAA6B;AAC5D,YAAYC,cAAc,2BAAuB;AACjD,SAASC,SAAS,QAAQ,+BAA2B;AAErD;;;;;;;CAOC,GACD,OAAO,MAAMC,kBAA8C;IACzD;QACEC,
|
|
1
|
+
{"version":3,"sources":["../../../../../../libs/plugins/commerce/src/lib/site.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as Aglyn from '@aglyn/aglyn'\nimport { mdiStorefrontOutline } from '@aglyn/shared-data-mdi'\nimport * as Account from './components/account'\nimport * as Cart from './components/cart'\nimport * as Gate from './components/gate'\nimport * as GatedVideo from './components/gated-video'\nimport * as MemberFeed from './components/member-feed'\nimport * as MemberRecovery from './components/member-recovery'\nimport * as MemberSignin from './components/member-signin'\nimport * as MemberSignup from './components/member-signup'\nimport * as NewsletterSignup from './components/newsletter-signup'\nimport * as OrderStatus from './components/order-status'\nimport * as ProductDetail from './components/product-detail'\nimport * as ReservationWidget from './components/reservation-widget'\nimport * as ProductGrid from './components/product-grid'\nimport * as ProductReviews from './components/product-reviews'\nimport * as QuotePage from './components/quote-page'\nimport * as RelatedProducts from './components/related-products'\nimport * as ReturnRequest from './components/return-request'\nimport * as Wishlist from './components/wishlist'\nimport { BUNDLE_ID } from './constants/bundle-common'\n\n/**\n * Commerce UI feature plugin (AGL-290): the storefront component set,\n * built on the feature-plugin pattern (AGL-277) — depends on the mui\n * bundle for primitives/theming and registers alongside it in the\n * besigner and the tenant renderer. Components join `COMMERCE_BUNDLE`\n * as they land (PLP AGL-291, PDP AGL-292, cart AGL-293, …); ids are\n * persisted in screen docs and never renamed.\n */\nexport const COMMERCE_BUNDLE: Aglyn.FeatureBundleEntry[] = [\n {\n component: ProductGrid.default,\n schema: ProductGrid.schema,\n presets: ProductGrid.presets,\n },\n {\n component: ProductDetail.default,\n schema: ProductDetail.schema,\n presets: ProductDetail.presets,\n },\n {\n component: Cart.default,\n schema: Cart.schema,\n presets: Cart.presets,\n },\n {\n component: Account.default,\n schema: Account.schema,\n presets: Account.presets,\n },\n {\n component: Wishlist.default,\n schema: Wishlist.schema,\n presets: Wishlist.presets,\n },\n {\n component: NewsletterSignup.default,\n schema: NewsletterSignup.schema,\n presets: NewsletterSignup.presets,\n },\n {\n component: Gate.default,\n schema: Gate.schema,\n presets: Gate.presets,\n },\n {\n component: GatedVideo.default,\n schema: GatedVideo.schema,\n presets: GatedVideo.presets,\n },\n {\n component: MemberFeed.default,\n schema: MemberFeed.schema,\n presets: MemberFeed.presets,\n },\n {\n component: MemberRecovery.default,\n schema: MemberRecovery.schema,\n presets: MemberRecovery.presets,\n },\n {\n component: MemberSignin.default,\n schema: MemberSignin.schema,\n presets: MemberSignin.presets,\n },\n {\n component: MemberSignup.default,\n schema: MemberSignup.schema,\n presets: MemberSignup.presets,\n },\n {\n component: ReservationWidget.default,\n schema: ReservationWidget.schema,\n presets: ReservationWidget.presets,\n },\n {\n component: ProductReviews.default,\n schema: ProductReviews.schema,\n presets: ProductReviews.presets,\n },\n {\n component: RelatedProducts.default,\n schema: RelatedProducts.schema,\n presets: RelatedProducts.presets,\n },\n {\n component: OrderStatus.default,\n schema: OrderStatus.schema,\n presets: OrderStatus.presets,\n },\n {\n component: ReturnRequest.default,\n schema: ReturnRequest.schema,\n presets: ReturnRequest.presets,\n },\n {\n component: QuotePage.default,\n schema: QuotePage.schema,\n presets: QuotePage.presets,\n },\n]\n\nexport function registerCommercePlugin(): void {\n // The canvas half only. The console registers the console half through its\n // own `console` surface, and a published page must never load console code\n // (AGL-3116): this runs on every page that places one of these elements.\n if (Aglyn.plugins.getDependency(BUNDLE_ID)) return\n Aglyn.plugins.addDependency(\n Aglyn.defineUiFeatureBundle(\n {\n bundleId: BUNDLE_ID,\n displayName: 'Commerce',\n description: 'Storefront blocks: product grids, detail, cart',\n icon: { path: mdiStorefrontOutline.path },\n components: COMMERCE_BUNDLE,\n },\n Aglyn.components,\n ),\n )\n}\n"],"names":["Aglyn","mdiStorefrontOutline","Account","Cart","Gate","GatedVideo","MemberFeed","MemberRecovery","MemberSignin","MemberSignup","NewsletterSignup","OrderStatus","ProductDetail","ReservationWidget","ProductGrid","ProductReviews","QuotePage","RelatedProducts","ReturnRequest","Wishlist","BUNDLE_ID","COMMERCE_BUNDLE","component","default","schema","presets","registerCommercePlugin","plugins","getDependency","addDependency","defineUiFeatureBundle","bundleId","displayName","description","icon","path","components"],"mappings":"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"}
|
|
@@ -19,6 +19,7 @@ import * as Aglyn from "@aglyn/aglyn/server";
|
|
|
19
19
|
import { firebaseAdmin, getOrgForHost, memberHasPermissionOnHost, resolveOrgMembership } from "@aglyn/tenant-data-admin";
|
|
20
20
|
import { TransferEngineError } from "@aglyn/tenant-data-admin/server/transfer-jobs";
|
|
21
21
|
import { normalizeTrackingNumber, parseShippingOrderRef } from "../model/order-shipping-export.js";
|
|
22
|
+
import { isUnpaidQuote } from "../model/commerce-quotes.js";
|
|
22
23
|
import { commerceSitePermissionRefusal } from "../model/plugin-permissions.js";
|
|
23
24
|
import { cancelOrderFulfillment, recordOrderShipment, updateFulfillmentTracking } from "../server/fulfill-order.js";
|
|
24
25
|
import { NOTHING, ROW_BUDGET_MS, firestoreOf, hostRefOf, readerSeesHost } from "./server-common.js";
|
|
@@ -96,6 +97,11 @@ const ordersOf = (firestore, ctx)=>hostRefOf(firestore, ctx).collection('orders'
|
|
|
96
97
|
if (doc.exists) found.set(doc.id, doc);
|
|
97
98
|
}
|
|
98
99
|
}
|
|
100
|
+
// An unpaid quote holds an order number but is not an order yet (AGL-4093):
|
|
101
|
+
// a file naming that number matches nothing to ship.
|
|
102
|
+
for (const [id, doc] of found){
|
|
103
|
+
if (isUnpaidQuote(doc.data())) found.delete(id);
|
|
104
|
+
}
|
|
99
105
|
return found;
|
|
100
106
|
}
|
|
101
107
|
export async function lookupTrackingOrders(ctx, requests) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/transfer/tracking.server.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 {\n buildMatchLookup,\n type BuildTransferPlanInput,\n type MatchKeySpec,\n type MatchLookupRequest,\n type PlannedTransferRow,\n type TransferChunk,\n type TransferPlan,\n type TransferRowResult,\n type TransferUndoEntry,\n type TransferUndoSnapshot,\n type TransferUndoStep,\n} from '@aglyn/aglyn/data-transfer'\nimport * as Aglyn from '@aglyn/aglyn/server'\nimport type {\n PluginTransferResource,\n TransferApplyResult,\n TransferApplyWriter,\n TransferLookupResult,\n TransferReadOptions,\n TransferReadPage,\n TransferResourceContext,\n TransferRevertDecisions,\n TransferRevertResult,\n} from '@aglyn/aglyn/plugin-manager/plugin-transfer-resources'\nimport { firebaseAdmin, getOrgForHost, memberHasPermissionOnHost, resolveOrgMembership } from '@aglyn/tenant-data-admin'\nimport { TransferEngineError } from '@aglyn/tenant-data-admin/server/transfer-jobs'\nimport { normalizeTrackingNumber, parseShippingOrderRef } from '../model/order-shipping-export'\nimport { commerceSitePermissionRefusal } from '../model/plugin-permissions'\nimport {\n cancelOrderFulfillment,\n recordOrderShipment,\n updateFulfillmentTracking,\n} from '../server/fulfill-order'\nimport { NOTHING, ROW_BUDGET_MS, firestoreOf, hostRefOf, readerSeesHost, type Firestore } from './server-common'\nimport {\n TRACKING_DEFAULT_POLICY,\n TRACKING_MATCH_KEYS,\n matchTrackingRows,\n planTrackingRows,\n trackingExportRows,\n trackingMatchValues,\n trackingRecord,\n type StoredTrackingOrder,\n type TrackingPlannedRow,\n} from './tracking-transfer'\n\n/*\n * THE TRACKING IMPORT'S SERVER HALF (AGL-3613). The plan is\n * `planTrackingRows`; this module reads the orders it plans against, writes\n * each parcel through the order's own shipment paths and undoes them.\n *\n * - WHO: the site's admins and editors — the roles the console's Fulfill\n * button has — on a plan that sells. Asked by the plan, the apply and the\n * undo, each server-side.\n * - HOW: a new parcel through `recordOrderShipment`, keyed by its tracking\n * number, so a retried chunk or a second import of the same file is one\n * parcel; the buyer is emailed as for any shipment. A replaced tracking\n * number through `updateFulfillmentTracking`.\n * - UNDO: a parcel this import recorded is cancelled (its units go back to\n * unfulfilled), and a replaced tracking number is put back — each only\n * while the shipment still holds what the import wrote; otherwise it is a\n * conflict the person decides.\n */\n\nconst IN_MAX = 30\n\n/** Orders a page of the shipments export reads: those that have shipped something. */\nconst SHIPPED_STATUSES = ['partially_fulfilled', 'fulfilled', 'delivered']\n\n/** The member importing, checked for the role and the plan, or the refusal. */\nasync function shipperOf(ctx: TransferResourceContext): Promise<{ hostId: string }> {\n const hostId = ctx.hostId\n if (!hostId) throw new TransferEngineError('invalid', 400, 'Tracking numbers belong to a site; name the site.')\n const uid = ctx.actorUid\n const membership = uid ? await resolveOrgMembership(uid, ctx.orgId) : null\n // \"Manage orders\" (`commerce.orders`, AGL-4047) on this site, resolved fresh\n // from the membership: its preset is the site's Admin and Editor this\n // asked for, then the member's custom role, own permissions and site toggle.\n const allowed =\n !!uid && !!membership?.member &&\n (await memberHasPermissionOnHost(ctx.orgId, hostId, membership.member, 'commerce.orders'))\n if (!allowed) {\n throw new TransferEngineError('forbidden', 403, commerceSitePermissionRefusal('commerce.orders'))\n }\n const owner = await getOrgForHost(hostId).catch(() => null)\n if (!Aglyn.checkEntitlement(owner?.org as never, 'commerce')) {\n throw new TransferEngineError('forbidden', 403, 'This site’s plan does not include selling.')\n }\n return { hostId }\n}\n\nconst ordersOf = (firestore: Firestore, ctx: TransferResourceContext) => hostRefOf(firestore, ctx).collection('orders')\n\n/** Orders by the values a file names them by: numbers through one query per 30, ids directly. */\nasync function findOrders(\n firestore: Firestore,\n ctx: TransferResourceContext,\n requests: readonly MatchLookupRequest[],\n): Promise<Map<string, FirebaseFirestore.DocumentSnapshot>> {\n const collection = ordersOf(firestore, ctx)\n const found = new Map<string, FirebaseFirestore.DocumentSnapshot>()\n const numbers = new Set<number>()\n const ids = new Set<string>()\n for (const request of requests) {\n for (const value of request.values) {\n const ref = request.fieldId === 'id' ? { id: value } : parseShippingOrderRef(value)\n if (!ref) continue\n if (ref.number !== undefined) numbers.add(ref.number)\n if (ref.id && !ref.id.includes('/') && !/^__.*__$/.test(ref.id)) ids.add(ref.id)\n }\n }\n const numberList = [...numbers]\n for (let at = 0; at < numberList.length; at += IN_MAX) {\n const snapshot = await collection.where('number', 'in', numberList.slice(at, at + IN_MAX)).get()\n for (const doc of snapshot.docs) found.set(doc.id, doc)\n }\n const idList = [...ids].filter((id) => !found.has(id))\n for (let at = 0; at < idList.length; at += 100) {\n for (const doc of await firestore.getAll(...idList.slice(at, at + 100).map((id) => collection.doc(id)))) {\n if (doc.exists) found.set(doc.id, doc)\n }\n }\n return found\n}\n\nexport async function lookupTrackingOrders(\n ctx: TransferResourceContext,\n requests: readonly MatchLookupRequest[],\n): Promise<TransferLookupResult> {\n const found = await findOrders(firestoreOf(), ctx, requests)\n const keys: MatchKeySpec[] = requests.map((request) => ({ fieldId: request.fieldId, normalizer: request.normalizer }))\n const records = new Map<string, Readonly<Record<string, unknown>>>()\n const entries: Array<{ id: string; values: Record<string, unknown> }> = []\n for (const doc of found.values()) {\n const data = (doc.data() ?? {}) as StoredTrackingOrder\n records.set(doc.id, trackingRecord(doc.id, data))\n entries.push({ id: doc.id, values: trackingMatchValues(doc.id, data) })\n }\n return { lookup: buildMatchLookup(entries, keys), records }\n}\n\n/**\n * The shipments export: every order that has shipped something, newest\n * first, one row per shipment with a tracking number. The cursor is the last\n * order's `createdAtMs` and id, as the orders export pages.\n */\nexport async function readTrackingPage(\n ctx: TransferResourceContext,\n cursor: string | null,\n fieldIds: readonly string[],\n options?: TransferReadOptions,\n): Promise<TransferReadPage> {\n if (!readerSeesHost(ctx, options)) return NOTHING\n if (options?.filter) throw new Error('Shipments export every shipment, or those of the orders you select.')\n const firestore = firestoreOf()\n const collection = ordersOf(firestore, ctx)\n const pageSize = Math.max(1, Math.min(500, options?.pageSize ?? 200))\n let docs: FirebaseFirestore.DocumentSnapshot[]\n let next: string | null\n if (options?.ids) {\n const offset = cursor ? Number(cursor) : 0\n const ids = options.ids.slice(offset, offset + pageSize)\n docs = ids.length ? (await firestore.getAll(...ids.map((id) => collection.doc(id)))).filter((doc) => doc.exists) : []\n next = offset + ids.length < options.ids.length ? String(offset + ids.length) : null\n } else {\n const query = collection\n .where('status', 'in', SHIPPED_STATUSES)\n .orderBy('createdAtMs', 'desc')\n .orderBy(firebaseAdmin.firestore.FieldPath.documentId(), 'desc')\n const after = cursor ? (JSON.parse(cursor) as unknown[]) : null\n const snapshot = await (after ? query.startAfter(...after) : query).limit(pageSize).get()\n docs = snapshot.docs\n const last = snapshot.docs[snapshot.docs.length - 1]\n next = last && snapshot.docs.length === pageSize ? JSON.stringify([last.get('createdAtMs') ?? null, last.id]) : null\n }\n const rows = docs.flatMap((doc) =>\n trackingExportRows(doc.id, (doc.data() ?? {}) as StoredTrackingOrder).map((record) =>\n Object.fromEntries(fieldIds.map((fieldId) => [fieldId, record[fieldId] ?? null])),\n ),\n )\n return { rows, next }\n}\n\n/** The dry run, against every matched order read once. */\nexport async function planTracking(ctx: TransferResourceContext, input: BuildTransferPlanInput): Promise<TransferPlan> {\n await shipperOf(ctx)\n const firestore = firestoreOf()\n const ids = [\n ...new Set(\n input.matches\n .map((match) => (match.kind === 'matched' ? match.recordId : null))\n .filter((id): id is string => Boolean(id)),\n ),\n ]\n const collection = ordersOf(firestore, ctx)\n const orders = new Map<string, StoredTrackingOrder>()\n for (let at = 0; at < ids.length; at += 100) {\n for (const doc of await firestore.getAll(...ids.slice(at, at + 100).map((id) => collection.doc(id)))) {\n if (doc.exists) orders.set(doc.id, (doc.data() ?? {}) as StoredTrackingOrder)\n }\n }\n return planTrackingRows(input, orders)\n}\n\n/** Records one chunk's parcels, each through the order's own shipment paths. */\nexport async function applyTracking(\n ctx: TransferResourceContext,\n chunk: TransferChunk<PlannedTransferRow>,\n writer: TransferApplyWriter,\n): Promise<TransferApplyResult> {\n const { hostId } = await shipperOf(ctx)\n const results: TransferRowResult[] = []\n const undo: TransferUndoEntry[] = []\n const fail = async (row: number, message: string) => {\n const result: TransferRowResult = { row, outcome: 'failed', reason: 'refusedValue', message }\n results.push(result)\n await writer.markApplied(result)\n }\n for (const row of chunk.rows as TrackingPlannedRow[]) {\n const earlier = await writer.alreadyApplied(row.index)\n if (earlier) {\n results.push(earlier)\n continue\n }\n if (writer.timeLeftMs() < ROW_BUDGET_MS) break\n const decision = row.tracking\n if (row.verdict !== 'update' || !decision) {\n await fail(row.index, 'A tracking file only records parcels for orders it names.')\n continue\n }\n if (decision.action === 'ship') {\n const outcome = await recordOrderShipment({\n hostId,\n orderId: decision.orderId,\n to: 'fulfilled',\n carrier: decision.carrier,\n trackingNumber: decision.trackingNumber,\n ...(decision.trackingUrl ? { trackingUrl: decision.trackingUrl } : {}),\n ...(decision.lineItems ? { lineItems: decision.lineItems } : {}),\n idempotencyKey: `tracking-import:${normalizeTrackingNumber(decision.trackingNumber)}`,\n onceByTracking: true,\n })\n if (outcome.outcome === 'recorded' || (outcome.outcome === 'already' && outcome.fulfillment)) {\n const fulfillment = outcome.fulfillment\n const result: TransferRowResult = {\n row: row.index,\n outcome: outcome.outcome === 'recorded' ? 'updated' : 'unchanged',\n recordId: decision.orderId,\n }\n // Only a parcel THIS import recorded is undone; one found already\n // there was somebody else's.\n const entry: TransferUndoEntry | undefined =\n outcome.outcome === 'recorded' && fulfillment\n ? {\n row: row.index,\n recordId: decision.orderId,\n action: 'updated',\n previous: { fulfillmentId: null },\n written: {\n fulfillmentId: fulfillment.id,\n trackingNumber: fulfillment.trackingNumber ?? null,\n carrier: fulfillment.carrier ?? null,\n },\n }\n : undefined\n results.push(result)\n if (entry) undo.push(entry)\n await writer.markApplied(result, entry)\n continue\n }\n await fail(\n row.index,\n outcome.outcome === 'blocked'\n ? `The order is ${outcome.from.replace(/_/g, ' ')} and cannot be shipped.`\n : outcome.outcome === 'invalid_lines'\n ? outcome.message\n : outcome.outcome === 'no_such_order'\n ? 'The order no longer exists.'\n : 'The order has nothing left to ship.',\n )\n continue\n }\n const outcome = await updateFulfillmentTracking({\n hostId,\n orderId: decision.orderId,\n fulfillmentId: decision.fulfillmentId,\n carrier: decision.carrier,\n trackingNumber: decision.trackingNumber,\n ...(decision.trackingUrl ? { trackingUrl: decision.trackingUrl } : {}),\n })\n if (outcome.outcome === 'updated' || outcome.outcome === 'already') {\n const result: TransferRowResult = {\n row: row.index,\n outcome: outcome.outcome === 'updated' ? 'updated' : 'unchanged',\n recordId: decision.orderId,\n }\n const entry: TransferUndoEntry | undefined =\n outcome.outcome === 'updated'\n ? {\n row: row.index,\n recordId: decision.orderId,\n action: 'updated',\n previous: { fulfillmentId: decision.fulfillmentId, ...decision.previous },\n written: {\n fulfillmentId: decision.fulfillmentId,\n trackingNumber: outcome.fulfillment.trackingNumber ?? null,\n carrier: outcome.fulfillment.carrier ?? null,\n },\n }\n : undefined\n results.push(result)\n if (entry) undo.push(entry)\n await writer.markApplied(result, entry)\n continue\n }\n await fail(\n row.index,\n outcome.outcome === 'locked'\n ? `The order is ${outcome.from.replace(/_/g, ' ')}; its shipments can no longer change.`\n : 'The shipment no longer exists.',\n )\n }\n return { results, undo }\n}\n\n/**\n * Undoes one chunk, newest first: a parcel the import recorded is cancelled\n * and a tracking number it replaced is put back — while the shipment still\n * holds what the import wrote. A shipment edited since is a conflict, done\n * only when the person's decision says `revert`.\n */\nexport async function revertTracking(\n ctx: TransferResourceContext,\n snapshot: TransferUndoSnapshot,\n decisions?: TransferRevertDecisions,\n): Promise<TransferRevertResult> {\n const { hostId } = await shipperOf(ctx)\n const firestore = firestoreOf()\n const collection = ordersOf(firestore, ctx)\n const done: TransferUndoStep[] = []\n const conflicts: TransferUndoStep[] = []\n for (const entry of [...snapshot.entries].reverse()) {\n const fulfillmentId = String(entry.written['fulfillmentId'] ?? '')\n const doc = await collection.doc(entry.recordId).get()\n const order = doc.exists ? ((doc.data() ?? {}) as Record<string, unknown>) : null\n const current = ((order?.['fulfillments'] as Array<Record<string, unknown>> | undefined) ?? []).find(\n (fulfillment) => fulfillment['id'] === fulfillmentId,\n )\n if (!doc.exists || !current || current['status'] === 'cancelled') {\n done.push({ action: 'nothing', recordId: entry.recordId, why: doc.exists ? 'alreadyReverted' : 'gone' })\n continue\n }\n const edited =\n normalizeTrackingNumber(current['trackingNumber']) !== normalizeTrackingNumber(entry.written['trackingNumber'])\n if (edited && decisions?.[entry.recordId] !== 'revert') {\n conflicts.push({\n action: 'conflict',\n recordId: entry.recordId,\n fields: ['trackingNumber'],\n values: { trackingNumber: current['trackingNumber'] ?? null },\n })\n continue\n }\n const recorded = entry.previous?.['fulfillmentId'] === null\n const outcome = recorded\n ? await cancelOrderFulfillment({ hostId, orderId: entry.recordId, fulfillmentId })\n : await updateFulfillmentTracking({\n hostId,\n orderId: entry.recordId,\n fulfillmentId,\n carrier: String(entry.previous?.['carrier'] ?? ''),\n trackingNumber: String(entry.previous?.['trackingNumber'] ?? ''),\n ...(entry.previous?.['trackingUrl'] ? { trackingUrl: String(entry.previous['trackingUrl']) } : {}),\n })\n if (outcome.outcome === 'locked') {\n conflicts.push({\n action: 'conflict',\n recordId: entry.recordId,\n fields: ['status'],\n values: { status: outcome.from },\n })\n continue\n }\n done.push(\n recorded\n ? { action: 'delete', recordId: entry.recordId }\n : {\n action: 'restore',\n recordId: entry.recordId,\n values: { trackingNumber: entry.previous?.['trackingNumber'] ?? null },\n },\n )\n }\n return { done, conflicts }\n}\n\nexport const trackingTransfer: PluginTransferResource = {\n matchKeys: TRACKING_MATCH_KEYS,\n defaultPolicy: TRACKING_DEFAULT_POLICY,\n readPage: (ctx, cursor, fieldIds, options) => readTrackingPage(ctx, cursor, fieldIds, options),\n lookup: (ctx, requests) => lookupTrackingOrders(ctx, requests),\n match: (_ctx, input) => ({ outcomes: matchTrackingRows(input.rows, input.lookup) }),\n plan: (ctx, input) => planTracking(ctx, input),\n apply: (ctx, chunk, writer) => applyTracking(ctx, chunk, writer),\n revert: (ctx, snapshot, decisions) => revertTracking(ctx, snapshot, decisions),\n}\n"],"names":["buildMatchLookup","Aglyn","firebaseAdmin","getOrgForHost","memberHasPermissionOnHost","resolveOrgMembership","TransferEngineError","normalizeTrackingNumber","parseShippingOrderRef","commerceSitePermissionRefusal","cancelOrderFulfillment","recordOrderShipment","updateFulfillmentTracking","NOTHING","ROW_BUDGET_MS","firestoreOf","hostRefOf","readerSeesHost","TRACKING_DEFAULT_POLICY","TRACKING_MATCH_KEYS","matchTrackingRows","planTrackingRows","trackingExportRows","trackingMatchValues","trackingRecord","IN_MAX","SHIPPED_STATUSES","shipperOf","ctx","hostId","uid","actorUid","membership","orgId","allowed","member","owner","catch","checkEntitlement","org","ordersOf","firestore","collection","findOrders","requests","found","Map","numbers","Set","ids","request","value","values","ref","fieldId","id","number","undefined","add","includes","test","numberList","at","length","snapshot","where","slice","get","doc","docs","set","idList","filter","has","getAll","map","exists","lookupTrackingOrders","keys","normalizer","records","entries","data","push","lookup","readTrackingPage","cursor","fieldIds","options","Error","pageSize","Math","max","min","next","offset","Number","String","last","query","orderBy","FieldPath","documentId","after","JSON","parse","startAfter","limit","stringify","rows","flatMap","record","Object","fromEntries","planTracking","input","matches","match","kind","recordId","Boolean","orders","applyTracking","chunk","writer","results","undo","fail","row","message","result","outcome","reason","markApplied","earlier","alreadyApplied","index","timeLeftMs","decision","tracking","verdict","action","orderId","to","carrier","trackingNumber","trackingUrl","lineItems","idempotencyKey","onceByTracking","fulfillment","entry","previous","fulfillmentId","written","from","replace","revertTracking","decisions","done","conflicts","reverse","order","current","find","why","edited","fields","recorded","status","trackingTransfer","matchKeys","defaultPolicy","readPage","_ctx","outcomes","plan","apply","revert"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/transfer/tracking.server.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 {\n buildMatchLookup,\n type BuildTransferPlanInput,\n type MatchKeySpec,\n type MatchLookupRequest,\n type PlannedTransferRow,\n type TransferChunk,\n type TransferPlan,\n type TransferRowResult,\n type TransferUndoEntry,\n type TransferUndoSnapshot,\n type TransferUndoStep,\n} from '@aglyn/aglyn/data-transfer'\nimport * as Aglyn from '@aglyn/aglyn/server'\nimport type {\n PluginTransferResource,\n TransferApplyResult,\n TransferApplyWriter,\n TransferLookupResult,\n TransferReadOptions,\n TransferReadPage,\n TransferResourceContext,\n TransferRevertDecisions,\n TransferRevertResult,\n} from '@aglyn/aglyn/plugin-manager/plugin-transfer-resources'\nimport { firebaseAdmin, getOrgForHost, memberHasPermissionOnHost, resolveOrgMembership } from '@aglyn/tenant-data-admin'\nimport { TransferEngineError } from '@aglyn/tenant-data-admin/server/transfer-jobs'\nimport { normalizeTrackingNumber, parseShippingOrderRef } from '../model/order-shipping-export'\nimport { isUnpaidQuote } from '../model/commerce-quotes'\nimport { commerceSitePermissionRefusal } from '../model/plugin-permissions'\nimport {\n cancelOrderFulfillment,\n recordOrderShipment,\n updateFulfillmentTracking,\n} from '../server/fulfill-order'\nimport { NOTHING, ROW_BUDGET_MS, firestoreOf, hostRefOf, readerSeesHost, type Firestore } from './server-common'\nimport {\n TRACKING_DEFAULT_POLICY,\n TRACKING_MATCH_KEYS,\n matchTrackingRows,\n planTrackingRows,\n trackingExportRows,\n trackingMatchValues,\n trackingRecord,\n type StoredTrackingOrder,\n type TrackingPlannedRow,\n} from './tracking-transfer'\n\n/*\n * THE TRACKING IMPORT'S SERVER HALF (AGL-3613). The plan is\n * `planTrackingRows`; this module reads the orders it plans against, writes\n * each parcel through the order's own shipment paths and undoes them.\n *\n * - WHO: the site's admins and editors — the roles the console's Fulfill\n * button has — on a plan that sells. Asked by the plan, the apply and the\n * undo, each server-side.\n * - HOW: a new parcel through `recordOrderShipment`, keyed by its tracking\n * number, so a retried chunk or a second import of the same file is one\n * parcel; the buyer is emailed as for any shipment. A replaced tracking\n * number through `updateFulfillmentTracking`.\n * - UNDO: a parcel this import recorded is cancelled (its units go back to\n * unfulfilled), and a replaced tracking number is put back — each only\n * while the shipment still holds what the import wrote; otherwise it is a\n * conflict the person decides.\n */\n\nconst IN_MAX = 30\n\n/** Orders a page of the shipments export reads: those that have shipped something. */\nconst SHIPPED_STATUSES = ['partially_fulfilled', 'fulfilled', 'delivered']\n\n/** The member importing, checked for the role and the plan, or the refusal. */\nasync function shipperOf(ctx: TransferResourceContext): Promise<{ hostId: string }> {\n const hostId = ctx.hostId\n if (!hostId) throw new TransferEngineError('invalid', 400, 'Tracking numbers belong to a site; name the site.')\n const uid = ctx.actorUid\n const membership = uid ? await resolveOrgMembership(uid, ctx.orgId) : null\n // \"Manage orders\" (`commerce.orders`, AGL-4047) on this site, resolved fresh\n // from the membership: its preset is the site's Admin and Editor this\n // asked for, then the member's custom role, own permissions and site toggle.\n const allowed =\n !!uid && !!membership?.member &&\n (await memberHasPermissionOnHost(ctx.orgId, hostId, membership.member, 'commerce.orders'))\n if (!allowed) {\n throw new TransferEngineError('forbidden', 403, commerceSitePermissionRefusal('commerce.orders'))\n }\n const owner = await getOrgForHost(hostId).catch(() => null)\n if (!Aglyn.checkEntitlement(owner?.org as never, 'commerce')) {\n throw new TransferEngineError('forbidden', 403, 'This site’s plan does not include selling.')\n }\n return { hostId }\n}\n\nconst ordersOf = (firestore: Firestore, ctx: TransferResourceContext) => hostRefOf(firestore, ctx).collection('orders')\n\n/** Orders by the values a file names them by: numbers through one query per 30, ids directly. */\nasync function findOrders(\n firestore: Firestore,\n ctx: TransferResourceContext,\n requests: readonly MatchLookupRequest[],\n): Promise<Map<string, FirebaseFirestore.DocumentSnapshot>> {\n const collection = ordersOf(firestore, ctx)\n const found = new Map<string, FirebaseFirestore.DocumentSnapshot>()\n const numbers = new Set<number>()\n const ids = new Set<string>()\n for (const request of requests) {\n for (const value of request.values) {\n const ref = request.fieldId === 'id' ? { id: value } : parseShippingOrderRef(value)\n if (!ref) continue\n if (ref.number !== undefined) numbers.add(ref.number)\n if (ref.id && !ref.id.includes('/') && !/^__.*__$/.test(ref.id)) ids.add(ref.id)\n }\n }\n const numberList = [...numbers]\n for (let at = 0; at < numberList.length; at += IN_MAX) {\n const snapshot = await collection.where('number', 'in', numberList.slice(at, at + IN_MAX)).get()\n for (const doc of snapshot.docs) found.set(doc.id, doc)\n }\n const idList = [...ids].filter((id) => !found.has(id))\n for (let at = 0; at < idList.length; at += 100) {\n for (const doc of await firestore.getAll(...idList.slice(at, at + 100).map((id) => collection.doc(id)))) {\n if (doc.exists) found.set(doc.id, doc)\n }\n }\n // An unpaid quote holds an order number but is not an order yet (AGL-4093):\n // a file naming that number matches nothing to ship.\n for (const [id, doc] of found) {\n if (isUnpaidQuote(doc.data())) found.delete(id)\n }\n return found\n}\n\nexport async function lookupTrackingOrders(\n ctx: TransferResourceContext,\n requests: readonly MatchLookupRequest[],\n): Promise<TransferLookupResult> {\n const found = await findOrders(firestoreOf(), ctx, requests)\n const keys: MatchKeySpec[] = requests.map((request) => ({ fieldId: request.fieldId, normalizer: request.normalizer }))\n const records = new Map<string, Readonly<Record<string, unknown>>>()\n const entries: Array<{ id: string; values: Record<string, unknown> }> = []\n for (const doc of found.values()) {\n const data = (doc.data() ?? {}) as StoredTrackingOrder\n records.set(doc.id, trackingRecord(doc.id, data))\n entries.push({ id: doc.id, values: trackingMatchValues(doc.id, data) })\n }\n return { lookup: buildMatchLookup(entries, keys), records }\n}\n\n/**\n * The shipments export: every order that has shipped something, newest\n * first, one row per shipment with a tracking number. The cursor is the last\n * order's `createdAtMs` and id, as the orders export pages.\n */\nexport async function readTrackingPage(\n ctx: TransferResourceContext,\n cursor: string | null,\n fieldIds: readonly string[],\n options?: TransferReadOptions,\n): Promise<TransferReadPage> {\n if (!readerSeesHost(ctx, options)) return NOTHING\n if (options?.filter) throw new Error('Shipments export every shipment, or those of the orders you select.')\n const firestore = firestoreOf()\n const collection = ordersOf(firestore, ctx)\n const pageSize = Math.max(1, Math.min(500, options?.pageSize ?? 200))\n let docs: FirebaseFirestore.DocumentSnapshot[]\n let next: string | null\n if (options?.ids) {\n const offset = cursor ? Number(cursor) : 0\n const ids = options.ids.slice(offset, offset + pageSize)\n docs = ids.length ? (await firestore.getAll(...ids.map((id) => collection.doc(id)))).filter((doc) => doc.exists) : []\n next = offset + ids.length < options.ids.length ? String(offset + ids.length) : null\n } else {\n const query = collection\n .where('status', 'in', SHIPPED_STATUSES)\n .orderBy('createdAtMs', 'desc')\n .orderBy(firebaseAdmin.firestore.FieldPath.documentId(), 'desc')\n const after = cursor ? (JSON.parse(cursor) as unknown[]) : null\n const snapshot = await (after ? query.startAfter(...after) : query).limit(pageSize).get()\n docs = snapshot.docs\n const last = snapshot.docs[snapshot.docs.length - 1]\n next = last && snapshot.docs.length === pageSize ? JSON.stringify([last.get('createdAtMs') ?? null, last.id]) : null\n }\n const rows = docs.flatMap((doc) =>\n trackingExportRows(doc.id, (doc.data() ?? {}) as StoredTrackingOrder).map((record) =>\n Object.fromEntries(fieldIds.map((fieldId) => [fieldId, record[fieldId] ?? null])),\n ),\n )\n return { rows, next }\n}\n\n/** The dry run, against every matched order read once. */\nexport async function planTracking(ctx: TransferResourceContext, input: BuildTransferPlanInput): Promise<TransferPlan> {\n await shipperOf(ctx)\n const firestore = firestoreOf()\n const ids = [\n ...new Set(\n input.matches\n .map((match) => (match.kind === 'matched' ? match.recordId : null))\n .filter((id): id is string => Boolean(id)),\n ),\n ]\n const collection = ordersOf(firestore, ctx)\n const orders = new Map<string, StoredTrackingOrder>()\n for (let at = 0; at < ids.length; at += 100) {\n for (const doc of await firestore.getAll(...ids.slice(at, at + 100).map((id) => collection.doc(id)))) {\n if (doc.exists) orders.set(doc.id, (doc.data() ?? {}) as StoredTrackingOrder)\n }\n }\n return planTrackingRows(input, orders)\n}\n\n/** Records one chunk's parcels, each through the order's own shipment paths. */\nexport async function applyTracking(\n ctx: TransferResourceContext,\n chunk: TransferChunk<PlannedTransferRow>,\n writer: TransferApplyWriter,\n): Promise<TransferApplyResult> {\n const { hostId } = await shipperOf(ctx)\n const results: TransferRowResult[] = []\n const undo: TransferUndoEntry[] = []\n const fail = async (row: number, message: string) => {\n const result: TransferRowResult = { row, outcome: 'failed', reason: 'refusedValue', message }\n results.push(result)\n await writer.markApplied(result)\n }\n for (const row of chunk.rows as TrackingPlannedRow[]) {\n const earlier = await writer.alreadyApplied(row.index)\n if (earlier) {\n results.push(earlier)\n continue\n }\n if (writer.timeLeftMs() < ROW_BUDGET_MS) break\n const decision = row.tracking\n if (row.verdict !== 'update' || !decision) {\n await fail(row.index, 'A tracking file only records parcels for orders it names.')\n continue\n }\n if (decision.action === 'ship') {\n const outcome = await recordOrderShipment({\n hostId,\n orderId: decision.orderId,\n to: 'fulfilled',\n carrier: decision.carrier,\n trackingNumber: decision.trackingNumber,\n ...(decision.trackingUrl ? { trackingUrl: decision.trackingUrl } : {}),\n ...(decision.lineItems ? { lineItems: decision.lineItems } : {}),\n idempotencyKey: `tracking-import:${normalizeTrackingNumber(decision.trackingNumber)}`,\n onceByTracking: true,\n })\n if (outcome.outcome === 'recorded' || (outcome.outcome === 'already' && outcome.fulfillment)) {\n const fulfillment = outcome.fulfillment\n const result: TransferRowResult = {\n row: row.index,\n outcome: outcome.outcome === 'recorded' ? 'updated' : 'unchanged',\n recordId: decision.orderId,\n }\n // Only a parcel THIS import recorded is undone; one found already\n // there was somebody else's.\n const entry: TransferUndoEntry | undefined =\n outcome.outcome === 'recorded' && fulfillment\n ? {\n row: row.index,\n recordId: decision.orderId,\n action: 'updated',\n previous: { fulfillmentId: null },\n written: {\n fulfillmentId: fulfillment.id,\n trackingNumber: fulfillment.trackingNumber ?? null,\n carrier: fulfillment.carrier ?? null,\n },\n }\n : undefined\n results.push(result)\n if (entry) undo.push(entry)\n await writer.markApplied(result, entry)\n continue\n }\n await fail(\n row.index,\n outcome.outcome === 'blocked'\n ? `The order is ${outcome.from.replace(/_/g, ' ')} and cannot be shipped.`\n : outcome.outcome === 'invalid_lines'\n ? outcome.message\n : outcome.outcome === 'no_such_order'\n ? 'The order no longer exists.'\n : 'The order has nothing left to ship.',\n )\n continue\n }\n const outcome = await updateFulfillmentTracking({\n hostId,\n orderId: decision.orderId,\n fulfillmentId: decision.fulfillmentId,\n carrier: decision.carrier,\n trackingNumber: decision.trackingNumber,\n ...(decision.trackingUrl ? { trackingUrl: decision.trackingUrl } : {}),\n })\n if (outcome.outcome === 'updated' || outcome.outcome === 'already') {\n const result: TransferRowResult = {\n row: row.index,\n outcome: outcome.outcome === 'updated' ? 'updated' : 'unchanged',\n recordId: decision.orderId,\n }\n const entry: TransferUndoEntry | undefined =\n outcome.outcome === 'updated'\n ? {\n row: row.index,\n recordId: decision.orderId,\n action: 'updated',\n previous: { fulfillmentId: decision.fulfillmentId, ...decision.previous },\n written: {\n fulfillmentId: decision.fulfillmentId,\n trackingNumber: outcome.fulfillment.trackingNumber ?? null,\n carrier: outcome.fulfillment.carrier ?? null,\n },\n }\n : undefined\n results.push(result)\n if (entry) undo.push(entry)\n await writer.markApplied(result, entry)\n continue\n }\n await fail(\n row.index,\n outcome.outcome === 'locked'\n ? `The order is ${outcome.from.replace(/_/g, ' ')}; its shipments can no longer change.`\n : 'The shipment no longer exists.',\n )\n }\n return { results, undo }\n}\n\n/**\n * Undoes one chunk, newest first: a parcel the import recorded is cancelled\n * and a tracking number it replaced is put back — while the shipment still\n * holds what the import wrote. A shipment edited since is a conflict, done\n * only when the person's decision says `revert`.\n */\nexport async function revertTracking(\n ctx: TransferResourceContext,\n snapshot: TransferUndoSnapshot,\n decisions?: TransferRevertDecisions,\n): Promise<TransferRevertResult> {\n const { hostId } = await shipperOf(ctx)\n const firestore = firestoreOf()\n const collection = ordersOf(firestore, ctx)\n const done: TransferUndoStep[] = []\n const conflicts: TransferUndoStep[] = []\n for (const entry of [...snapshot.entries].reverse()) {\n const fulfillmentId = String(entry.written['fulfillmentId'] ?? '')\n const doc = await collection.doc(entry.recordId).get()\n const order = doc.exists ? ((doc.data() ?? {}) as Record<string, unknown>) : null\n const current = ((order?.['fulfillments'] as Array<Record<string, unknown>> | undefined) ?? []).find(\n (fulfillment) => fulfillment['id'] === fulfillmentId,\n )\n if (!doc.exists || !current || current['status'] === 'cancelled') {\n done.push({ action: 'nothing', recordId: entry.recordId, why: doc.exists ? 'alreadyReverted' : 'gone' })\n continue\n }\n const edited =\n normalizeTrackingNumber(current['trackingNumber']) !== normalizeTrackingNumber(entry.written['trackingNumber'])\n if (edited && decisions?.[entry.recordId] !== 'revert') {\n conflicts.push({\n action: 'conflict',\n recordId: entry.recordId,\n fields: ['trackingNumber'],\n values: { trackingNumber: current['trackingNumber'] ?? null },\n })\n continue\n }\n const recorded = entry.previous?.['fulfillmentId'] === null\n const outcome = recorded\n ? await cancelOrderFulfillment({ hostId, orderId: entry.recordId, fulfillmentId })\n : await updateFulfillmentTracking({\n hostId,\n orderId: entry.recordId,\n fulfillmentId,\n carrier: String(entry.previous?.['carrier'] ?? ''),\n trackingNumber: String(entry.previous?.['trackingNumber'] ?? ''),\n ...(entry.previous?.['trackingUrl'] ? { trackingUrl: String(entry.previous['trackingUrl']) } : {}),\n })\n if (outcome.outcome === 'locked') {\n conflicts.push({\n action: 'conflict',\n recordId: entry.recordId,\n fields: ['status'],\n values: { status: outcome.from },\n })\n continue\n }\n done.push(\n recorded\n ? { action: 'delete', recordId: entry.recordId }\n : {\n action: 'restore',\n recordId: entry.recordId,\n values: { trackingNumber: entry.previous?.['trackingNumber'] ?? null },\n },\n )\n }\n return { done, conflicts }\n}\n\nexport const trackingTransfer: PluginTransferResource = {\n matchKeys: TRACKING_MATCH_KEYS,\n defaultPolicy: TRACKING_DEFAULT_POLICY,\n readPage: (ctx, cursor, fieldIds, options) => readTrackingPage(ctx, cursor, fieldIds, options),\n lookup: (ctx, requests) => lookupTrackingOrders(ctx, requests),\n match: (_ctx, input) => ({ outcomes: matchTrackingRows(input.rows, input.lookup) }),\n plan: (ctx, input) => planTracking(ctx, input),\n apply: (ctx, chunk, writer) => applyTracking(ctx, chunk, writer),\n revert: (ctx, snapshot, decisions) => revertTracking(ctx, snapshot, decisions),\n}\n"],"names":["buildMatchLookup","Aglyn","firebaseAdmin","getOrgForHost","memberHasPermissionOnHost","resolveOrgMembership","TransferEngineError","normalizeTrackingNumber","parseShippingOrderRef","isUnpaidQuote","commerceSitePermissionRefusal","cancelOrderFulfillment","recordOrderShipment","updateFulfillmentTracking","NOTHING","ROW_BUDGET_MS","firestoreOf","hostRefOf","readerSeesHost","TRACKING_DEFAULT_POLICY","TRACKING_MATCH_KEYS","matchTrackingRows","planTrackingRows","trackingExportRows","trackingMatchValues","trackingRecord","IN_MAX","SHIPPED_STATUSES","shipperOf","ctx","hostId","uid","actorUid","membership","orgId","allowed","member","owner","catch","checkEntitlement","org","ordersOf","firestore","collection","findOrders","requests","found","Map","numbers","Set","ids","request","value","values","ref","fieldId","id","number","undefined","add","includes","test","numberList","at","length","snapshot","where","slice","get","doc","docs","set","idList","filter","has","getAll","map","exists","data","delete","lookupTrackingOrders","keys","normalizer","records","entries","push","lookup","readTrackingPage","cursor","fieldIds","options","Error","pageSize","Math","max","min","next","offset","Number","String","last","query","orderBy","FieldPath","documentId","after","JSON","parse","startAfter","limit","stringify","rows","flatMap","record","Object","fromEntries","planTracking","input","matches","match","kind","recordId","Boolean","orders","applyTracking","chunk","writer","results","undo","fail","row","message","result","outcome","reason","markApplied","earlier","alreadyApplied","index","timeLeftMs","decision","tracking","verdict","action","orderId","to","carrier","trackingNumber","trackingUrl","lineItems","idempotencyKey","onceByTracking","fulfillment","entry","previous","fulfillmentId","written","from","replace","revertTracking","decisions","done","conflicts","reverse","order","current","find","why","edited","fields","recorded","status","trackingTransfer","matchKeys","defaultPolicy","readPage","_ctx","outcomes","plan","apply","revert"],"mappings":"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"}
|
|
@@ -0,0 +1,77 @@
|
|
|
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 EmailPalette } from '@aglyn/shared-util-email';
|
|
18
|
+
import type { PdfJpegImage } from '@aglyn/shared-util-tools/pdf/pdf-file';
|
|
19
|
+
import type { QuotePageView } from '../model/commerce-quote-pay';
|
|
20
|
+
import { type InvoiceOrder, type OrderInvoiceStore } from './order-invoice';
|
|
21
|
+
/** The colors a document is drawn in, as `#rrggbb`. */
|
|
22
|
+
export interface CommercePdfColors {
|
|
23
|
+
/** The band, the table's header and the pay button: the site's primary color. */
|
|
24
|
+
accent: string;
|
|
25
|
+
/** Text set on the accent. */
|
|
26
|
+
onAccent: string;
|
|
27
|
+
/** The accent as text on white: the document's name, links. */
|
|
28
|
+
accentText: string;
|
|
29
|
+
/** A wash of the accent, behind the total. */
|
|
30
|
+
tint: string;
|
|
31
|
+
ink: string;
|
|
32
|
+
muted: string;
|
|
33
|
+
rule: string;
|
|
34
|
+
}
|
|
35
|
+
/** Who the document is from. */
|
|
36
|
+
export interface CommercePdfBrand {
|
|
37
|
+
businessName: string;
|
|
38
|
+
/** Address lines, email, phone and web address, in that order. */
|
|
39
|
+
contactLines: readonly string[];
|
|
40
|
+
/** The site's logo as a JPEG; the business name stands alone without one. */
|
|
41
|
+
logo?: PdfJpegImage | null;
|
|
42
|
+
/** The site theme's colors; any left out are the neutral ones. */
|
|
43
|
+
colors?: Partial<CommercePdfColors> | null;
|
|
44
|
+
/** The site's time zone, which dates are given in. */
|
|
45
|
+
timeZone?: string | null;
|
|
46
|
+
}
|
|
47
|
+
/** The colors a document wears where its site's theme gives none: the default site theme's greys. */
|
|
48
|
+
export declare const COMMERCE_PDF_NEUTRAL_COLORS: Readonly<CommercePdfColors>;
|
|
49
|
+
/**
|
|
50
|
+
* A document's colors from a site's resolved palette: the primary color for
|
|
51
|
+
* the accent, the theme's own text and divider colors, and text on the
|
|
52
|
+
* accent that reads at 4.5:1 (the theme's contrast text when it does, else
|
|
53
|
+
* the theme's dark ink or white, whichever reads better).
|
|
54
|
+
*/
|
|
55
|
+
export declare function commercePdfColorsFromPalette(palette: EmailPalette): CommercePdfColors;
|
|
56
|
+
/** A date the American way, in the site's time zone: `October 28, 2026`. */
|
|
57
|
+
export declare function formatPdfDate(ms: number | null | undefined, timeZone?: string | null): string;
|
|
58
|
+
export interface QuotePdfInput {
|
|
59
|
+
brand: CommercePdfBrand;
|
|
60
|
+
/** The quote as its customer may see it: `buildQuotePageView`. */
|
|
61
|
+
view: QuotePageView;
|
|
62
|
+
/** The quote's revision, printed beside its date. */
|
|
63
|
+
revision?: number | null;
|
|
64
|
+
/** The pay link, printed on a quote still to be paid; left off when the reader may not have it. */
|
|
65
|
+
payUrl?: string | null;
|
|
66
|
+
}
|
|
67
|
+
/** The quote as a PDF. */
|
|
68
|
+
export declare function renderQuotePdf(input: QuotePdfInput): Uint8Array;
|
|
69
|
+
export interface OrderInvoicePdfInput {
|
|
70
|
+
brand: CommercePdfBrand;
|
|
71
|
+
order: InvoiceOrder;
|
|
72
|
+
orderId: string;
|
|
73
|
+
/** The store's currency, receipt footer and terms address (`invoiceStoreFrom`). */
|
|
74
|
+
store: OrderInvoiceStore;
|
|
75
|
+
}
|
|
76
|
+
/** Any order's invoice as a PDF, a paid quote's included. */
|
|
77
|
+
export declare function renderOrderInvoicePdf(input: OrderInvoicePdfInput): Uint8Array;
|