@aglyn/plugins-commerce 1.0.0-beta.220 → 1.0.0-beta.222

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.
Files changed (130) hide show
  1. package/README.md +4 -2
  2. package/package.json +14 -13
  3. package/src/lib/components/console/catalog-organization-card.component.js +9 -0
  4. package/src/lib/components/console/catalog-organization-card.component.js.map +1 -1
  5. package/src/lib/components/console/discounts-card.component.js +8 -0
  6. package/src/lib/components/console/discounts-card.component.js.map +1 -1
  7. package/src/lib/components/console/gift-cards-card.component.js +8 -0
  8. package/src/lib/components/console/gift-cards-card.component.js.map +1 -1
  9. package/src/lib/components/console/host-coupons-card.component.js +8 -0
  10. package/src/lib/components/console/host-coupons-card.component.js.map +1 -1
  11. package/src/lib/components/console/host-orders-card.component.js +34 -70
  12. package/src/lib/components/console/host-orders-card.component.js.map +1 -1
  13. package/src/lib/components/console/product-zones.d.ts +7 -6
  14. package/src/lib/components/console/product-zones.js +5 -4
  15. package/src/lib/components/console/product-zones.js.map +1 -1
  16. package/src/lib/components/console/products-hub-card.component.js +86 -284
  17. package/src/lib/components/console/products-hub-card.component.js.map +1 -1
  18. package/src/lib/declarations.console-server.d.ts +38 -0
  19. package/src/lib/declarations.console-server.js +67 -0
  20. package/src/lib/declarations.console-server.js.map +1 -0
  21. package/src/lib/model/commerce-gift-cards.d.ts +26 -0
  22. package/src/lib/model/commerce-gift-cards.js +42 -0
  23. package/src/lib/model/commerce-gift-cards.js.map +1 -1
  24. package/src/lib/model/commerce-orders.d.ts +0 -57
  25. package/src/lib/model/commerce-orders.js +0 -80
  26. package/src/lib/model/commerce-orders.js.map +1 -1
  27. package/src/lib/model/index.d.ts +0 -1
  28. package/src/lib/model/index.js +0 -1
  29. package/src/lib/model/index.js.map +1 -1
  30. package/src/lib/plugin.js +5 -0
  31. package/src/lib/plugin.js.map +1 -1
  32. package/src/lib/server/api-v1/openapi.d.ts +27 -0
  33. package/src/lib/server/api-v1/openapi.js +219 -0
  34. package/src/lib/server/api-v1/openapi.js.map +1 -0
  35. package/src/lib/server/api-v1/orders-and-products.d.ts +19 -0
  36. package/src/lib/server/api-v1/orders-and-products.js +419 -0
  37. package/src/lib/server/api-v1/orders-and-products.js.map +1 -0
  38. package/src/lib/server/billing-webhook.js +83 -56
  39. package/src/lib/server/billing-webhook.js.map +1 -1
  40. package/src/lib/server/download.js +4 -1
  41. package/src/lib/server/download.js.map +1 -1
  42. package/src/lib/server/fulfill-order.d.ts +52 -11
  43. package/src/lib/server/fulfill-order.js +6 -9
  44. package/src/lib/server/fulfill-order.js.map +1 -1
  45. package/src/lib/server/gift-card-issue.d.ts +57 -0
  46. package/src/lib/server/gift-card-issue.js +155 -0
  47. package/src/lib/server/gift-card-issue.js.map +1 -0
  48. package/src/lib/server/gift-cards.js +25 -84
  49. package/src/lib/server/gift-cards.js.map +1 -1
  50. package/src/lib/server/membership-register.js +9 -8
  51. package/src/lib/server/membership-register.js.map +1 -1
  52. package/src/lib/server/newsletter.js +7 -5
  53. package/src/lib/server/newsletter.js.map +1 -1
  54. package/src/lib/server/paid-media-delivery.d.ts +21 -0
  55. package/src/lib/server/paid-media-delivery.js +23 -5
  56. package/src/lib/server/paid-media-delivery.js.map +1 -1
  57. package/src/lib/server/paid-media-serve-count.d.ts +28 -0
  58. package/src/lib/server/paid-media-serve-count.js +46 -0
  59. package/src/lib/server/paid-media-serve-count.js.map +1 -0
  60. package/src/lib/server/person-eraser.d.ts +45 -0
  61. package/src/lib/server/person-eraser.js +57 -0
  62. package/src/lib/server/person-eraser.js.map +1 -0
  63. package/src/lib/server/pos-order.js +17 -9
  64. package/src/lib/server/pos-order.js.map +1 -1
  65. package/src/lib/server/refund.js +15 -15
  66. package/src/lib/server/refund.js.map +1 -1
  67. package/src/lib/server/restock-flag.d.ts +2 -2
  68. package/src/lib/server/restock-flag.js +1 -1
  69. package/src/lib/server/restock-flag.js.map +1 -1
  70. package/src/lib/server/stream.js +4 -1
  71. package/src/lib/server/stream.js.map +1 -1
  72. package/src/lib/server.js +5 -21
  73. package/src/lib/server.js.map +1 -1
  74. package/src/lib/testing/stand-in-person-records.d.ts +43 -0
  75. package/src/lib/testing/stand-in-person-records.js +63 -0
  76. package/src/lib/testing/stand-in-person-records.js.map +1 -0
  77. package/src/lib/testing/stand-in-record-system.d.ts +11 -2
  78. package/src/lib/testing/stand-in-record-system.js +5 -3
  79. package/src/lib/testing/stand-in-record-system.js.map +1 -1
  80. package/src/lib/transfer/gift-card-confirm-step.component.d.ts +22 -0
  81. package/src/lib/transfer/gift-card-confirm-step.component.js +259 -0
  82. package/src/lib/transfer/gift-card-confirm-step.component.js.map +1 -0
  83. package/src/lib/transfer/gift-cards-plan.d.ts +29 -0
  84. package/src/lib/transfer/gift-cards-plan.js +40 -0
  85. package/src/lib/transfer/gift-cards-plan.js.map +1 -0
  86. package/src/lib/transfer/gift-cards.server.d.ts +34 -0
  87. package/src/lib/transfer/gift-cards.server.js +296 -0
  88. package/src/lib/transfer/gift-cards.server.js.map +1 -0
  89. package/src/lib/transfer/list-filter.d.ts +29 -0
  90. package/src/lib/transfer/list-filter.js +112 -0
  91. package/src/lib/transfer/list-filter.js.map +1 -0
  92. package/src/lib/transfer/product-import-results.d.ts +29 -0
  93. package/src/lib/transfer/product-import-results.js +49 -0
  94. package/src/lib/transfer/product-import-results.js.map +1 -0
  95. package/src/lib/transfer/product-import-step.component.d.ts +30 -0
  96. package/src/lib/transfer/product-import-step.component.js +99 -0
  97. package/src/lib/transfer/product-import-step.component.js.map +1 -0
  98. package/src/lib/transfer/product-transfer.d.ts +211 -0
  99. package/src/lib/transfer/product-transfer.js +1594 -0
  100. package/src/lib/transfer/product-transfer.js.map +1 -0
  101. package/src/lib/transfer/products.server.d.ts +44 -0
  102. package/src/lib/transfer/products.server.js +550 -0
  103. package/src/lib/transfer/products.server.js.map +1 -0
  104. package/src/lib/transfer/records-transfer.d.ts +182 -0
  105. package/src/lib/transfer/records-transfer.js +1153 -0
  106. package/src/lib/transfer/records-transfer.js.map +1 -0
  107. package/src/lib/transfer/records.server.d.ts +68 -0
  108. package/src/lib/transfer/records.server.js +455 -0
  109. package/src/lib/transfer/records.server.js.map +1 -0
  110. package/src/lib/transfer/register-transfer-resources.d.ts +17 -0
  111. package/src/lib/transfer/register-transfer-resources.js +171 -0
  112. package/src/lib/transfer/register-transfer-resources.js.map +1 -0
  113. package/src/lib/transfer/register-transfer-ui.d.ts +23 -0
  114. package/src/lib/transfer/register-transfer-ui.js +78 -0
  115. package/src/lib/transfer/register-transfer-ui.js.map +1 -0
  116. package/src/lib/transfer/server-common.d.ts +76 -0
  117. package/src/lib/transfer/server-common.js +165 -0
  118. package/src/lib/transfer/server-common.js.map +1 -0
  119. package/src/lib/transfer/transfer-header-actions.component.d.ts +39 -0
  120. package/src/lib/transfer/transfer-header-actions.component.js +79 -0
  121. package/src/lib/transfer/transfer-header-actions.component.js.map +1 -0
  122. package/src/lib/transfer/transfer-keys.d.ts +31 -0
  123. package/src/lib/transfer/transfer-keys.js +56 -0
  124. package/src/lib/transfer/transfer-keys.js.map +1 -0
  125. package/src/lib/model/commerce-io.d.ts +0 -36
  126. package/src/lib/model/commerce-io.js +0 -245
  127. package/src/lib/model/commerce-io.js.map +0 -1
  128. package/src/lib/server/contact-refund.d.ts +0 -117
  129. package/src/lib/server/contact-refund.js +0 -196
  130. package/src/lib/server/contact-refund.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/transfer/records-transfer.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 buildTransferPlan,\n isBlankTransferValue,\n TRANSFER_FILE_SAMPLE_ROW,\n TRANSFER_SYSTEM_GROUP,\n type BuildTransferPlanInput,\n type MatchKeySpec,\n type PlannedTransferRow,\n type TransferField,\n type TransferFieldChange,\n type TransferPlan,\n type TransferPlanSummary,\n type TransferWarningSample,\n} from '@aglyn/aglyn/data-transfer'\nimport type { PicklistSpec } from '@aglyn/aglyn/app-utils/picklists'\nimport { commerceSlug } from '../model/commerce'\nimport type { DiscountKind, HostDiscount } from '../model/commerce-discounts'\nimport { GIFT_CARD_CONFIRM_STEP_ID } from './transfer-keys'\nimport {\n GIFT_CARD_CURRENCY,\n giftCardAmountProblem,\n giftCardCodeOf,\n giftCardCodeProblem,\n type HostGiftCard,\n} from '../model/commerce-gift-cards'\nimport {\n ORDER_CHANNEL_LABELS,\n ORDER_STATUS_LABELS,\n liftLegacyOrder,\n type HostOrder,\n type OrderAddress,\n} from '../model/commerce-orders'\n\n/*\n * ORDERS, DISCOUNTS, COUPONS, GIFT CARDS AND CATEGORIES AS FILES (AGL-3531):\n * each resource's fields, and its stored document as the record a file\n * names. Pure — the server half is `records.server.ts`.\n *\n * ## What imports, and why the rest does not\n *\n * - Categories, discounts and coupons import: each is a document a person\n * writes from the console with nothing derived behind it, so a file\n * writes the same fields the console's card does. A discount or coupon\n * created from a file starts SWITCHED OFF unless the file says Active —\n * a promotion going live from a spreadsheet is money leaving the store.\n * How many times one was used is history, exported and never written.\n * - Orders are exported only: an order is the record of a sale, written by\n * checkout, the register or a paid draft.\n * - Gift cards import by ISSUING each card (AGL-3551, below), never by\n * writing a balance: a balance is money a shopper can spend. A gift\n * card's ID is its code, so the file is worth what the cards are.\n */\n\nconst iso = (ms: unknown): string | null => {\n const time =\n typeof ms === 'number'\n ? ms\n : ms && typeof (ms as { toMillis?: () => number }).toMillis === 'function'\n ? (ms as { toMillis: () => number }).toMillis()\n : ms && typeof (ms as { toDate?: () => Date }).toDate === 'function'\n ? ((ms as { toDate: () => Date }).toDate()?.getTime() ?? NaN)\n : NaN\n return Number.isFinite(time) ? new Date(time).toISOString() : null\n}\n\nconst dollars = (cents: unknown): number | null => {\n const value = Number(cents)\n return cents === null || cents === undefined || !Number.isFinite(value) ? null : Math.round(value) / 100\n}\n\nconst text = (value: unknown): string => (value === null || value === undefined ? '' : String(value).trim())\n\n/** A planned row's changes, by field id. */\nexport function rowChanges(row: PlannedTransferRow): Record<string, unknown> {\n return Object.fromEntries(row.diff.map((change) => [change.fieldId, change.after]))\n}\n\n/**\n * The core's plan with the fields a NEW record cannot be made without\n * marked required — never in the catalog, where a required field must be\n * mapped, and a file that only switches discounts off would be refused.\n */\nexport function planWithCreateRequired(input: BuildTransferPlanInput, required: readonly string[]): TransferPlan {\n return buildTransferPlan({\n ...input,\n fields: input.fields.map((field) => (required.includes(field.id) ? { ...field, required: true } : field)),\n })\n}\n\n/*==========================================\n * ORDERS\n *=========================================*/\n\nexport const ORDER_TRANSFER_FIELDS: readonly TransferField[] = [\n { id: 'number', label: 'Order number', group: 'order', type: 'integer', readOnly: true },\n { id: 'date', label: 'Date', group: 'order', type: 'datetime', readOnly: true },\n { id: 'status', label: 'Status', group: 'order', type: 'text', readOnly: true },\n { id: 'channel', label: 'Channel', group: 'order', type: 'text', readOnly: true },\n { id: 'customerEmail', label: 'Customer email', group: 'customer', type: 'email', readOnly: true },\n { id: 'customerName', label: 'Customer name', group: 'customer', type: 'text', readOnly: true },\n {\n id: 'product',\n label: 'Product',\n group: 'items',\n type: 'text',\n readOnly: true,\n description: 'The first line’s product, and how many more the order holds.',\n },\n { id: 'items', label: 'Items', group: 'items', type: 'longText', readOnly: true, description: 'Every line: quantity × name (variant), SKU.' },\n { id: 'itemCount', label: 'Units', group: 'items', type: 'integer', readOnly: true },\n { id: 'subtotal', label: 'Items subtotal', group: 'money', type: 'number', readOnly: true },\n { id: 'shipping', label: 'Shipping', group: 'money', type: 'number', readOnly: true },\n { id: 'tax', label: 'Tax', group: 'money', type: 'number', readOnly: true },\n { id: 'discount', label: 'Discount', group: 'money', type: 'number', readOnly: true },\n { id: 'total', label: 'Total', group: 'money', type: 'number', readOnly: true, description: 'What was charged, in dollars.' },\n { id: 'fee', label: 'Fee', group: 'money', type: 'number', readOnly: true },\n { id: 'refunded', label: 'Refunded', group: 'money', type: 'number', readOnly: true },\n { id: 'net', label: 'Net', group: 'money', type: 'number', readOnly: true, description: 'The total less what was refunded.' },\n { id: 'coupon', label: 'Coupon', group: 'money', type: 'text', readOnly: true },\n { id: 'shippingAddress', label: 'Shipping address', group: 'customer', type: 'text', readOnly: true },\n { id: 'billingAddress', label: 'Billing address', group: 'customer', type: 'text', readOnly: true },\n { id: 'note', label: 'Note', group: 'order', type: 'longText', readOnly: true },\n { id: 'dispute', label: 'Dispute', group: 'order', type: 'text', readOnly: true },\n { id: 'paymentIntentId', label: 'Payment ID', group: TRANSFER_SYSTEM_GROUP.id, type: 'text', system: true },\n]\n\nexport const ORDER_TRANSFER_GROUPS = [\n { id: 'order', label: 'Order' },\n { id: 'customer', label: 'Customer' },\n { id: 'items', label: 'Items' },\n { id: 'money', label: 'Money' },\n]\n\n/** An order as a stored document, with the id the export reads it under. */\nexport type StoredOrder = Partial<HostOrder> & {\n createdAt?: unknown\n createdAtMs?: number\n amountCents?: number\n feeCents?: number\n productId?: string\n}\n\nconst addressLine = (address: OrderAddress | undefined): string | null => {\n if (!address) return null\n const parts = [address.name, address.line1, address.line2, address.city, address.state, address.postalCode, address.country]\n .map(text)\n .filter(Boolean)\n return parts.length ? parts.join(', ') : null\n}\n\n/**\n * One order as a file names it. The money is what was ACTUALLY charged:\n * the order's `totals`, and the legacy flat fields only where a buy-now order\n * of old carries nothing else (AGL-1747) — a POS or draft order has no flat\n * field, and reading those first exported every one of them at $0.00. A\n * legacy row is named from `productNames`, never as \"Product\".\n */\nexport function orderRecord(\n id: string,\n stored: StoredOrder,\n productNames: Readonly<Record<string, string>> = {},\n): Record<string, unknown> {\n const lifted = liftLegacyOrder(stored)\n const lineItems = stored.lineItems ?? []\n const first = lineItems[0]?.name ?? productNames[stored.productId ?? ''] ?? stored.productId ?? ''\n const totals = lifted.totals\n const totalCents = Number(totals?.totalCents ?? stored.amountCents ?? 0)\n const refundedCents = Number(stored.refundedCents ?? 0)\n return {\n id,\n number: typeof stored.number === 'number' ? stored.number : null,\n date: iso(stored.createdAt) ?? iso(stored.createdAtMs),\n status: ORDER_STATUS_LABELS[lifted.status] ?? lifted.status,\n channel: ORDER_CHANNEL_LABELS[lifted.channel ?? 'online'] ?? lifted.channel ?? 'online',\n customerEmail: stored.customerEmail ?? null,\n customerName: stored.customerName ?? null,\n product: lineItems.length > 1 ? `${first} +${lineItems.length - 1} more` : first || null,\n items: lineItems.length\n ? lineItems\n .map(\n (line) =>\n `${line.quantity} × ${line.name}${line.variantLabel ? ` (${line.variantLabel})` : ''}${line.sku ? `, ${line.sku}` : ''}`,\n )\n .join('; ')\n : null,\n itemCount: lineItems.reduce((sum, line) => sum + (Number(line.quantity) || 0), 0),\n subtotal: dollars(totals?.itemsCents),\n shipping: dollars(totals?.shippingCents),\n tax: dollars(totals?.taxCents),\n discount: dollars(totals?.discountCents),\n total: dollars(totalCents),\n fee: dollars(totals?.feeCents ?? stored.feeCents ?? 0),\n refunded: dollars(refundedCents),\n net: dollars(totalCents - refundedCents),\n coupon: stored.couponCode ?? null,\n shippingAddress: addressLine(stored.shippingAddress),\n billingAddress: addressLine(stored.billingAddress),\n note: stored.note ?? null,\n dispute: stored.dispute ? text((stored.dispute as { status?: string }).status) || 'open' : null,\n paymentIntentId: stored.paymentIntentId ?? null,\n }\n}\n\n/*==========================================\n * DISCOUNTS\n *=========================================*/\n\nexport const DISCOUNT_KIND_PICKLIST = 'commerce.discountKind'\n\nconst DISCOUNT_KIND_LABELS: Record<DiscountKind, string> = {\n percent: 'Percent off',\n fixed: 'Amount off',\n free_shipping: 'Free shipping',\n}\n\nexport const DISCOUNT_KIND_SPEC: PicklistSpec = {\n restricted: true,\n standardValues: Object.entries(DISCOUNT_KIND_LABELS).map(([id, label]) => ({ id, label })),\n defaultValueId: 'percent',\n}\n\n/** A discount kind's id from a label or id in any case, or `null`. */\nexport function discountKindOf(value: unknown): DiscountKind | null {\n const key = text(value).toLowerCase()\n const found = Object.entries(DISCOUNT_KIND_LABELS).find(\n ([id, label]) => id === key || label.toLowerCase() === key,\n )\n return found ? (found[0] as DiscountKind) : null\n}\n\nexport const DISCOUNT_TRANSFER_FIELDS: readonly TransferField[] = [\n {\n id: 'code',\n label: 'Code',\n group: 'discount',\n type: 'text',\n aliases: ['discount code', 'promo code', 'coupon code'],\n description: 'What a shopper types; blank for a discount that applies on its own.',\n },\n { id: 'name', label: 'Name', group: 'discount', type: 'text', aliases: ['title', 'discount name'] },\n {\n id: 'kind',\n label: 'Kind',\n group: 'discount',\n type: 'picklist',\n picklistId: DISCOUNT_KIND_PICKLIST,\n aliases: ['type', 'discount type', 'value type'],\n description: 'Percent off, Amount off or Free shipping. Needed for a new discount.',\n },\n { id: 'percentOff', label: 'Percent off', group: 'discount', type: 'integer', aliases: ['percent', 'percentage'] },\n { id: 'amountOff', label: 'Amount off', group: 'discount', type: 'currency', aliases: ['amount', 'value'] },\n {\n id: 'minimumSubtotal',\n label: 'Minimum subtotal',\n group: 'conditions',\n type: 'currency',\n aliases: ['minimum', 'minimum purchase', 'minimum subtotal'],\n },\n {\n id: 'productIds',\n label: 'Product IDs',\n group: 'conditions',\n type: 'text',\n description: 'The products it covers, by their IDs separated by commas; blank covers the whole store.',\n },\n { id: 'maxRedemptions', label: 'Use limit', group: 'conditions', type: 'integer', aliases: ['usage limit', 'max uses'] },\n { id: 'startsAt', label: 'Starts', group: 'conditions', type: 'datetime', aliases: ['start date', 'starts at'] },\n { id: 'endsAt', label: 'Ends', group: 'conditions', type: 'datetime', aliases: ['end date', 'ends at', 'expires'] },\n {\n id: 'active',\n label: 'Active',\n group: 'discount',\n type: 'boolean',\n aliases: ['enabled', 'status'],\n description: 'A new discount starts switched off unless the file says it is active.',\n },\n { id: 'redemptions', label: 'Times used', group: 'conditions', type: 'integer', readOnly: true },\n]\n\nexport const DISCOUNT_MATCH_KEYS: readonly MatchKeySpec[] = [\n { fieldId: 'code', normalizer: 'caseless' },\n { fieldId: 'name', normalizer: 'name' },\n { fieldId: 'id', normalizer: 'aglynId' },\n]\n\n/** A code as the discounts card stores it: upper case, letters, digits, `_` and `-`. */\nexport function promotionCode(value: unknown, max = 40): string {\n return text(value)\n .toUpperCase()\n .replace(/[^A-Z0-9_-]/g, '')\n .slice(0, max)\n}\n\nconst cents = (value: unknown): number | null => {\n if (value === null || value === undefined || value === '') return null\n if (typeof value === 'object' && 'amountMinor' in (value as object)) return Math.round(Number((value as { amountMinor: number }).amountMinor))\n const number = Number(value)\n return Number.isFinite(number) ? Math.round(number * 100) : null\n}\n\nconst msOf = (value: unknown): number | null => {\n if (value === null || value === undefined || value === '') return null\n const time = typeof value === 'number' ? value : Date.parse(String(value))\n return Number.isFinite(time) ? time : null\n}\n\nexport function discountRecord(id: string, stored: Partial<HostDiscount> & { code?: string | null }): Record<string, unknown> {\n return {\n id,\n code: stored.code || null,\n name: stored.name ?? null,\n kind: DISCOUNT_KIND_LABELS[stored.kind as DiscountKind] ?? stored.kind ?? null,\n percentOff: stored.kind === 'percent' ? (stored.valuePct ?? null) : null,\n amountOff: stored.kind === 'fixed' ? dollars(stored.valueCents) : null,\n minimumSubtotal: dollars(stored.minSubtotalCents),\n productIds: stored.productIds?.length ? stored.productIds.join(', ') : null,\n maxRedemptions: stored.maxRedemptions ?? null,\n startsAt: iso(stored.startAtMs),\n endsAt: iso(stored.endAtMs),\n active: stored.enabled !== false,\n redemptions: stored.redemptions ?? 0,\n }\n}\n\n/**\n * The document a discount's changes make, over what it holds: the stored\n * shape the discounts card writes, or the sentence refusing it.\n */\nexport function discountWrite(\n current: (Partial<HostDiscount> & { code?: string | null }) | null,\n changes: Readonly<Record<string, unknown>>,\n): { doc: Record<string, unknown> } | { problem: string } {\n const doc: Record<string, unknown> = current ? { ...current } : { enabled: false, redemptions: 0 }\n const has = (fieldId: string) => fieldId in changes\n if (has('code')) doc['code'] = promotionCode(changes['code']) || null\n if (has('name')) doc['name'] = text(changes['name']).slice(0, 80) || null\n if (has('kind')) doc['kind'] = discountKindOf(changes['kind'])\n if (has('percentOff')) doc['valuePct'] = changes['percentOff'] === null ? null : Math.round(Number(changes['percentOff']))\n if (has('amountOff')) doc['valueCents'] = cents(changes['amountOff'])\n if (has('minimumSubtotal')) doc['minSubtotalCents'] = cents(changes['minimumSubtotal'])\n if (has('productIds')) {\n const ids = text(changes['productIds']).split(/[,;|\\s]+/).map(text).filter(Boolean)\n doc['productIds'] = ids.length ? [...new Set(ids)] : null\n }\n if (has('maxRedemptions')) {\n const limit = Number(changes['maxRedemptions'])\n doc['maxRedemptions'] = changes['maxRedemptions'] === null || !Number.isFinite(limit) ? null : Math.max(1, Math.round(limit))\n }\n if (has('startsAt')) doc['startAtMs'] = msOf(changes['startsAt'])\n if (has('endsAt')) doc['endAtMs'] = msOf(changes['endsAt'])\n if (has('active')) doc['enabled'] = changes['active'] === true\n if (!('code' in doc)) doc['code'] = null\n const kind = doc['kind'] as DiscountKind | null | undefined\n if (!kind) return { problem: 'Say what kind of discount it is: Percent off, Amount off or Free shipping.' }\n if (kind === 'percent') {\n const pct = Number(doc['valuePct'])\n if (!(pct >= 1 && pct <= 100)) return { problem: 'A percent-off discount takes 1 to 100 percent.' }\n }\n if (kind === 'fixed' && !(Number(doc['valueCents']) > 0)) return { problem: 'An amount-off discount needs an amount.' }\n if (!doc['code'] && !text(doc['name'])) return { problem: 'A discount with no code needs a name shoppers see.' }\n const start = doc['startAtMs'] as number | null\n const end = doc['endAtMs'] as number | null\n if (start != null && end != null && end <= start) return { problem: 'A discount ends after it starts.' }\n return { doc }\n}\n\n/*==========================================\n * COUPONS\n *=========================================*/\n\nexport const COUPON_TRANSFER_FIELDS: readonly TransferField[] = [\n {\n id: 'code',\n label: 'Code',\n group: 'coupon',\n type: 'text',\n matchKey: true,\n aliases: ['coupon code', 'promo code', 'discount code'],\n description: 'What a shopper types; a coupon’s code is its ID, so it is never changed.',\n },\n { id: 'percentOff', label: 'Percent off', group: 'coupon', type: 'integer', aliases: ['percent', 'percentage', 'value'] },\n { id: 'maxRedemptions', label: 'Use limit', group: 'coupon', type: 'integer', aliases: ['usage limit', 'max uses'] },\n { id: 'expiresAt', label: 'Expires', group: 'coupon', type: 'datetime', aliases: ['expiry', 'expires at', 'end date'] },\n {\n id: 'active',\n label: 'Active',\n group: 'coupon',\n type: 'boolean',\n aliases: ['enabled', 'status'],\n description: 'A new coupon starts switched off unless the file says it is active.',\n },\n { id: 'redemptions', label: 'Times used', group: 'coupon', type: 'integer', readOnly: true },\n { id: 'createdAt', label: 'Created', group: TRANSFER_SYSTEM_GROUP.id, type: 'datetime', system: true },\n]\n\nexport const COUPON_MATCH_KEYS: readonly MatchKeySpec[] = [\n { fieldId: 'code', normalizer: 'caseless' },\n { fieldId: 'id', normalizer: 'aglynId' },\n]\n\nexport interface StoredCoupon {\n percentOff?: number\n enabled?: boolean\n redemptions?: number\n maxRedemptions?: number\n expiresAtMs?: number\n createdAt?: unknown\n}\n\nexport function couponRecord(id: string, stored: StoredCoupon): Record<string, unknown> {\n return {\n id,\n code: id,\n percentOff: stored.percentOff ?? null,\n maxRedemptions: stored.maxRedemptions ?? null,\n expiresAt: iso(stored.expiresAtMs),\n active: stored.enabled !== false,\n redemptions: stored.redemptions ?? 0,\n createdAt: iso(stored.createdAt),\n }\n}\n\n/** A coupon's document from its changes, as the coupons card writes one, or the refusal. */\nexport function couponWrite(\n current: StoredCoupon | null,\n changes: Readonly<Record<string, unknown>>,\n): { doc: Record<string, unknown> } | { problem: string } {\n const doc: Record<string, unknown> = current ? { ...current } : { enabled: false, redemptions: 0 }\n if ('percentOff' in changes) doc['percentOff'] = Math.round(Number(changes['percentOff']))\n if ('maxRedemptions' in changes) {\n const limit = Number(changes['maxRedemptions'])\n doc['maxRedemptions'] = changes['maxRedemptions'] === null || !Number.isFinite(limit) ? null : Math.max(1, Math.round(limit))\n }\n if ('expiresAt' in changes) doc['expiresAtMs'] = msOf(changes['expiresAt'])\n if ('active' in changes) doc['enabled'] = changes['active'] === true\n const pct = Number(doc['percentOff'])\n if (!(pct > 0 && pct <= 100)) return { problem: 'A coupon takes 1 to 100 percent off.' }\n return { doc }\n}\n\n/*==========================================\n * GIFT CARDS\n *=========================================*/\n\n/*\n * A GIFT CARD IMPORT ISSUES CARDS (AGL-3551). A row is never written as a\n * balance: each one the dry run passes is issued through the same path as\n * the Gift cards card's Issue (`issueGiftCard`), so its amount is bounded,\n * its code is never overwritten and its activity line is written.\n *\n * - The plan mints the code a row will carry — the file's own, a new one for\n * a blank cell, or a new one for a row whose code another card holds and\n * whose Conflicts choice is \"create a new record\" — so the dry run shows\n * every card exactly as it will be issued.\n * - A row whose code another card holds and whose choice is \"update\" is\n * refused: a file never changes a card. \"Skip\" leaves the card as it is.\n * - Every card the dry run passes adds to a total the person types back on\n * the wizard's Confirm step (`GIFT_CARD_CONFIRM_STEP_ID`). The server reads\n * the typed total from `extras` and issues nothing unless it is exactly\n * the total of the cards about to be issued.\n */\n\nexport const GIFT_CARD_TRANSFER_FIELDS: readonly TransferField[] = [\n {\n id: 'code',\n label: 'Code',\n group: 'card',\n type: 'text',\n matchKey: true,\n aliases: ['gift card code', 'card code', 'gift card number', 'card number'],\n description:\n 'The card’s code, which spends its balance: keep the file as safe as the cards. On import, a blank code gets a new one.',\n },\n {\n id: 'balance',\n label: 'Balance',\n group: 'card',\n type: 'currency',\n aliases: ['amount', 'value', 'current balance', 'remaining balance', 'balance remaining'],\n description: 'On import, what the card is issued for, in US dollars — the balance it carries over.',\n },\n {\n id: 'currency',\n label: 'Currency',\n group: 'card',\n type: 'text',\n aliases: ['currency code'],\n description: 'Optional. Cards are held in US dollars; a row in another currency is refused, never converted.',\n },\n { id: 'initial', label: 'Issued for', group: 'card', type: 'number', readOnly: true },\n { id: 'status', label: 'Status', group: 'card', type: 'text', readOnly: true, description: 'Active, Used up, Frozen or Voided.' },\n {\n id: 'recipientEmail',\n label: 'Recipient email',\n group: 'card',\n type: 'email',\n aliases: ['email', 'customer email', 'recipient'],\n },\n { id: 'orderId', label: 'Order ID', group: 'card', type: 'text', readOnly: true, description: 'Blank for a card issued by hand.' },\n { id: 'note', label: 'Note', group: 'card', type: 'text', aliases: ['notes', 'message'] },\n { id: 'issuedAt', label: 'Issued', group: 'card', type: 'datetime', readOnly: true },\n { id: 'lastUsedAt', label: 'Last used', group: 'card', type: 'datetime', readOnly: true },\n]\n\n/** A card is found by its code, which is its ID. */\nexport const GIFT_CARD_MATCH_KEYS: readonly MatchKeySpec[] = [\n { fieldId: 'code', normalizer: 'caseless' },\n { fieldId: 'id', normalizer: 'aglynId' },\n]\n\n/** The fields an issued card's undo entry holds: any of them moving means the card was spent. */\nexport const GIFT_CARD_UNDO_FIELDS = ['balance', 'status', 'lastUsedAt'] as const\n\nexport type StoredGiftCard = HostGiftCard & {\n initialCents?: number\n recipientEmail?: string | null\n orderId?: string | null\n note?: string\n createdAtMs?: number\n lastUsedAtMs?: number\n importJobId?: string\n importRow?: number\n}\n\nexport function giftCardRecord(id: string, stored: StoredGiftCard): Record<string, unknown> {\n const balance = Number(stored.balanceCents ?? 0)\n return {\n id,\n code: id,\n balance: dollars(balance),\n currency: GIFT_CARD_CURRENCY,\n initial: dollars(stored.initialCents),\n status: stored.voidedAtMs ? 'Voided' : stored.frozenAtMs ? 'Frozen' : balance > 0 ? 'Active' : 'Used up',\n recipientEmail: stored.recipientEmail ?? null,\n orderId: stored.orderId ?? null,\n note: stored.note ?? null,\n issuedAt: iso(stored.createdAtMs),\n lastUsedAt: iso(stored.lastUsedAtMs),\n }\n}\n\n/** Dollars and cents as a person reads them: `$1,250.00`. */\nexport function giftCardMoney(amountCents: number): string {\n return `$${(amountCents / 100).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`\n}\n\n/** A total as a person types it (`1250`, `$1,250.00`), in cents; `null` for anything else. */\nexport function typedDollarsToCents(typed: unknown): number | null {\n const body = String(typed ?? '')\n .trim()\n .replace(/^\\$|^usd\\s*/i, '')\n .replace(/\\s*usd$/i, '')\n .replace(/,/g, '')\n .trim()\n if (!/^\\d+(\\.\\d{1,2})?$/.test(body)) return null\n return Math.round(Number(body) * 100)\n}\n\n/** The Confirm step's answer. */\nexport interface GiftCardConfirmation {\n /** The total the person typed, in cents. */\n totalCents: number\n /** Email each card's recipient their code as it is issued. */\n email: boolean\n}\n\n/** The Confirm step's answer from `extras`, or `null` for none: a total is a whole number of cents. */\nexport function readGiftCardConfirmation(\n extras: Readonly<Record<string, unknown>> | undefined,\n): GiftCardConfirmation | null {\n const value = extras?.[GIFT_CARD_CONFIRM_STEP_ID]\n if (!value || typeof value !== 'object') return null\n const totalCents = (value as Record<string, unknown>)['totalCents']\n if (typeof totalCents !== 'number' || !Number.isInteger(totalCents) || totalCents <= 0) return null\n return { totalCents, email: (value as Record<string, unknown>)['email'] === true }\n}\n\n/** The card one planned row issues, as the plan decided it. */\nexport interface GiftCardRowPlan {\n /** The code the card is issued under. */\n code: string\n /** The file's code was taken, and the person chose a new one. */\n newCode: boolean\n /** The file named no code, so one was made. */\n madeCode: boolean\n amountCents: number\n recipientEmail: string | null\n note: string | null\n /** Why the row issues nothing; the `gift-card-issuable` invariant fails it. */\n problem?: string\n /** What every card this import issues adds up to. */\n totalCents: number\n /** Whether the person typed exactly that total on the Confirm step. */\n confirmed: boolean\n}\n\nexport type GiftCardPlannedRow = PlannedTransferRow & { giftCard?: GiftCardRowPlan }\n\n/** A money cell in cents and its currency: the derived amount, or a number as dollars. */\nfunction giftCardAmount(value: unknown): { cents: number; currency: string } | null {\n if (value === null || value === undefined || value === '') return null\n if (typeof value === 'object' && 'amountMinor' in (value as object)) {\n const amount = value as { amountMinor: number; currency?: string }\n return { cents: Math.round(Number(amount.amountMinor)), currency: text(amount.currency).toUpperCase() || GIFT_CARD_CURRENCY }\n }\n const number = Number(value)\n return Number.isFinite(number) ? { cents: Math.round(number * 100), currency: GIFT_CARD_CURRENCY } : null\n}\n\n/** The card a row's changes issue, or the sentence refusing it. */\nexport function giftCardIssueOf(\n changes: Readonly<Record<string, unknown>>,\n code: { value: string; fromFile: boolean },\n): Omit<GiftCardRowPlan, 'newCode' | 'madeCode' | 'totalCents' | 'confirmed'> {\n const recipientEmail = text(changes['recipientEmail']).toLowerCase().slice(0, 200) || null\n const note = text(changes['note']).slice(0, 200) || null\n const base = { code: code.value, amountCents: 0, recipientEmail, note }\n const codeProblem = code.fromFile ? giftCardCodeProblem(code.value) : null\n if (codeProblem) return { ...base, problem: codeProblem }\n const amount = giftCardAmount(changes['balance'])\n if (!amount) return { ...base, problem: 'Say what the card is issued for in the Balance column.' }\n const named = text(changes['currency']).toUpperCase()\n for (const currency of [amount.currency, named].filter(Boolean)) {\n if (currency !== GIFT_CARD_CURRENCY) {\n return { ...base, problem: `Gift cards are held in US dollars; ${currency} is not converted.` }\n }\n }\n const amountProblem = giftCardAmountProblem(amount.cents)\n if (amountProblem) return { ...base, problem: amountProblem }\n return { ...base, amountCents: amount.cents }\n}\n\n/**\n * The core's plan for a gift card file, made into the cards it issues: each\n * create carrying the card it issues ({@link GiftCardRowPlan}), each row\n * that would change an existing card refused, the total of every card\n * counted, and a `screening` warning stating that total — and, when the\n * Confirm step's answer is missing or names another total, that nothing is\n * issued until it is confirmed.\n */\nexport function planGiftCardRows(\n plan: TransferPlan,\n input: {\n confirmation: GiftCardConfirmation | null\n mintCode: () => string\n /** The file's codes a card on the site already holds, however the file spelled them. */\n taken?: ReadonlySet<string>\n },\n): TransferPlan {\n const issuing = new Map<string, number>()\n const rows = plan.rows.map((row): GiftCardPlannedRow => {\n if (row.verdict === 'update' || row.verdict === 'unchanged') {\n const code = row.recordId ?? ''\n return {\n ...row,\n verdict: 'update',\n diff: [],\n giftCard: {\n code,\n newCode: false,\n madeCode: false,\n amountCents: 0,\n recipientEmail: null,\n note: null,\n problem:\n `A gift card with the code ${code} already exists, and a file never changes a card. ` +\n 'On the Conflicts step, skip this row, or create a new record to issue it under a new code.',\n totalCents: 0,\n confirmed: false,\n },\n }\n }\n if (row.verdict !== 'create') return row\n const changes = rowChanges(row)\n const fileCode = giftCardCodeOf(changes['code'])\n // A create for a row that matched a card is the person's \"create a new\n // record\": the card it names keeps its code, and this one gets another.\n const newCode = Boolean(fileCode) && row.match.kind !== 'new'\n const madeCode = !fileCode\n const code = newCode || madeCode ? input.mintCode() : fileCode\n const fromFile = !newCode && !madeCode\n let issue = giftCardIssueOf(changes, { value: code, fromFile })\n const earlier = issuing.get(code)\n if (!issue.problem && fromFile && input.taken?.has(code)) {\n issue = { ...issue, problem: `A gift card with the code ${code} already exists, and a file never changes a card.` }\n } else if (!issue.problem && earlier !== undefined) {\n issue = { ...issue, problem: `Row ${earlier + 1} issues the code ${code} already.` }\n }\n if (!issue.problem) issuing.set(code, row.index)\n const diff: TransferFieldChange[] = [\n ...row.diff.filter((change) => change.fieldId !== 'code'),\n { fieldId: 'code', before: null, after: code, mode: 'overwrite', source: 'default', rule: 'written' },\n ]\n return { ...row, diff, giftCard: { ...issue, newCode, madeCode, totalCents: 0, confirmed: false } }\n })\n\n const issued = rows.filter(\n (row): row is GiftCardPlannedRow & { giftCard: GiftCardRowPlan } =>\n row.verdict === 'create' && Boolean(row.giftCard) && !row.giftCard?.problem,\n )\n const totalCents = issued.reduce((sum, row) => sum + row.giftCard.amountCents, 0)\n const confirmed = input.confirmation?.totalCents === totalCents\n for (const row of rows) {\n if (row.giftCard) row.giftCard = { ...row.giftCard, totalCents, confirmed }\n }\n\n const warnings = plan.warnings.filter((warning) => warning.class !== 'screening')\n if (issued.length) {\n const samples: TransferWarningSample[] = [\n {\n row: TRANSFER_FILE_SAMPLE_ROW,\n fieldId: 'balance',\n value: giftCardMoney(totalCents),\n detail: `Issues ${issued.length.toLocaleString('en-US')} gift card${issued.length === 1 ? '' : 's'} worth ${giftCardMoney(totalCents)} in total.`,\n },\n ]\n if (!confirmed) {\n samples.push({\n row: TRANSFER_FILE_SAMPLE_ROW,\n detail: input.confirmation\n ? `The total confirmed was ${giftCardMoney(input.confirmation.totalCents)}, not ${giftCardMoney(totalCents)}: no card is issued until the total is confirmed again on the Confirm step.`\n : 'The total has not been confirmed: no card is issued until it is typed on the Confirm step.',\n })\n }\n warnings.push({\n class: 'screening',\n count: issued.length,\n rows: issued.length,\n fieldIds: ['balance'],\n samples,\n requiresAcknowledgement: true,\n })\n }\n const summary: TransferPlanSummary = { create: 0, update: 0, unchanged: 0, skip: 0, fail: 0, total: rows.length }\n for (const row of rows) summary[row.verdict] += 1\n return {\n rows,\n summary,\n warnings,\n acknowledgementsRequired: warnings.filter((warning) => warning.requiresAcknowledgement).map((warning) => warning.class),\n }\n}\n\n/*==========================================\n * CATEGORIES\n *=========================================*/\n\nexport const CATEGORY_TRANSFER_FIELDS: readonly TransferField[] = [\n { id: 'name', label: 'Name', group: 'category', type: 'text', aliases: ['category', 'category name', 'title'] },\n {\n id: 'slug',\n label: 'Slug',\n group: 'category',\n type: 'text',\n readOnly: true,\n matchKey: true,\n aliases: ['handle'],\n description: 'Made from the name, as the console makes it; a file finds a category by it.',\n },\n {\n id: 'parent',\n label: 'Parent',\n group: 'category',\n type: 'text',\n aliases: ['parent category', 'parent slug'],\n description: 'The parent category’s slug or name; blank for a top-level category.',\n },\n { id: 'order', label: 'Position', group: 'category', type: 'integer', aliases: ['sort order', 'order'] },\n]\n\nexport const CATEGORY_MATCH_KEYS: readonly MatchKeySpec[] = [\n { fieldId: 'slug', normalizer: 'slug' },\n { fieldId: 'name', normalizer: 'name' },\n { fieldId: 'id', normalizer: 'aglynId' },\n]\n\nexport interface StoredCategory {\n name?: string\n slug?: string\n parentId?: string | null\n order?: number\n}\n\nexport function categoryRecord(\n id: string,\n stored: StoredCategory,\n slugs: ReadonlyMap<string, string> = new Map(),\n): Record<string, unknown> {\n return {\n id,\n name: stored.name ?? null,\n slug: stored.slug ?? null,\n parent: stored.parentId ? (slugs.get(stored.parentId) ?? stored.parentId) : null,\n order: typeof stored.order === 'number' ? stored.order : null,\n }\n}\n\n/** Every category's slug, name and parent, by id: what a parent is resolved against. */\nexport type CategoryIndex = Map<string, StoredCategory>\n\n/** The category a parent cell names — by id, slug, then name — or `null`. */\nexport function resolveCategoryParent(index: CategoryIndex, value: unknown): string | null {\n const wanted = text(value)\n if (!wanted) return null\n if (index.has(wanted)) return wanted\n const slug = commerceSlug(wanted)\n for (const [id, category] of index) if (category.slug === slug) return id\n const name = wanted.toLowerCase()\n for (const [id, category] of index) if (text(category.name).toLowerCase() === name) return id\n return null\n}\n\n/**\n * A category's document from its changes: the name and the slug made from\n * it, the parent resolved — never itself or one of its own descendants —\n * and the position. A parent the site does not have is refused, not\n * guessed.\n */\nexport function categoryWrite(\n id: string,\n current: StoredCategory | null,\n changes: Readonly<Record<string, unknown>>,\n index: CategoryIndex,\n): { doc: Record<string, unknown> } | { problem: string } {\n const doc: Record<string, unknown> = current ? { ...current } : { parentId: null }\n if ('name' in changes) {\n const name = text(changes['name']).slice(0, 80)\n if (!name) return { problem: 'A category needs a name.' }\n doc['name'] = name\n doc['slug'] = commerceSlug(name) || id\n }\n if (!text(doc['name'])) return { problem: 'A category needs a name.' }\n if ('parent' in changes) {\n if (isBlankTransferValue(changes['parent'])) doc['parentId'] = null\n else {\n const parentId = resolveCategoryParent(index, changes['parent'])\n if (!parentId) return { problem: `No category \"${text(changes['parent'])}\" to put it under.` }\n for (let at: string | null = parentId, steps = 0; at && steps < 100; steps += 1) {\n if (at === id) return { problem: 'A category cannot sit under itself or one of its own.' }\n at = index.get(at)?.parentId ?? null\n }\n doc['parentId'] = parentId\n }\n }\n if ('order' in changes) {\n const order = Number(changes['order'])\n doc['order'] = changes['order'] === null || !Number.isFinite(order) ? null : Math.round(order)\n }\n return { doc }\n}\n"],"names":["buildTransferPlan","isBlankTransferValue","TRANSFER_FILE_SAMPLE_ROW","TRANSFER_SYSTEM_GROUP","commerceSlug","GIFT_CARD_CONFIRM_STEP_ID","GIFT_CARD_CURRENCY","giftCardAmountProblem","giftCardCodeOf","giftCardCodeProblem","ORDER_CHANNEL_LABELS","ORDER_STATUS_LABELS","liftLegacyOrder","iso","ms","time","toMillis","toDate","getTime","NaN","Number","isFinite","Date","toISOString","dollars","cents","value","undefined","Math","round","text","String","trim","rowChanges","row","Object","fromEntries","diff","map","change","fieldId","after","planWithCreateRequired","input","required","fields","field","includes","id","ORDER_TRANSFER_FIELDS","label","group","type","readOnly","description","system","ORDER_TRANSFER_GROUPS","addressLine","address","parts","name","line1","line2","city","state","postalCode","country","filter","Boolean","length","join","orderRecord","stored","productNames","lineItems","totals","lifted","first","productId","totalCents","amountCents","refundedCents","number","date","createdAt","createdAtMs","status","channel","customerEmail","customerName","product","items","line","quantity","variantLabel","sku","itemCount","reduce","sum","subtotal","itemsCents","shipping","shippingCents","tax","taxCents","discount","discountCents","total","fee","feeCents","refunded","net","coupon","couponCode","shippingAddress","billingAddress","note","dispute","paymentIntentId","DISCOUNT_KIND_PICKLIST","DISCOUNT_KIND_LABELS","percent","fixed","free_shipping","DISCOUNT_KIND_SPEC","restricted","standardValues","entries","defaultValueId","discountKindOf","key","toLowerCase","found","find","DISCOUNT_TRANSFER_FIELDS","aliases","picklistId","DISCOUNT_MATCH_KEYS","normalizer","promotionCode","max","toUpperCase","replace","slice","amountMinor","msOf","parse","discountRecord","code","kind","percentOff","valuePct","amountOff","valueCents","minimumSubtotal","minSubtotalCents","productIds","maxRedemptions","startsAt","startAtMs","endsAt","endAtMs","active","enabled","redemptions","discountWrite","current","changes","doc","has","ids","split","Set","limit","problem","pct","start","end","COUPON_TRANSFER_FIELDS","matchKey","COUPON_MATCH_KEYS","couponRecord","expiresAt","expiresAtMs","couponWrite","GIFT_CARD_TRANSFER_FIELDS","GIFT_CARD_MATCH_KEYS","GIFT_CARD_UNDO_FIELDS","giftCardRecord","balance","balanceCents","currency","initial","initialCents","voidedAtMs","frozenAtMs","recipientEmail","orderId","issuedAt","lastUsedAt","lastUsedAtMs","giftCardMoney","toLocaleString","minimumFractionDigits","maximumFractionDigits","typedDollarsToCents","typed","body","test","readGiftCardConfirmation","extras","isInteger","email","giftCardAmount","amount","giftCardIssueOf","base","codeProblem","fromFile","named","amountProblem","planGiftCardRows","plan","issuing","Map","rows","verdict","recordId","giftCard","newCode","madeCode","confirmed","fileCode","match","mintCode","issue","earlier","get","taken","set","index","before","mode","source","rule","issued","confirmation","warnings","warning","class","samples","detail","push","count","fieldIds","requiresAcknowledgement","summary","create","update","unchanged","skip","fail","acknowledgementsRequired","CATEGORY_TRANSFER_FIELDS","CATEGORY_MATCH_KEYS","categoryRecord","slugs","slug","parent","parentId","order","resolveCategoryParent","wanted","category","categoryWrite","at","steps"],"mappings":"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"}
@@ -0,0 +1,68 @@
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 PlannedTransferRow, type TransferChunk, type TransferUndoSnapshot } from '@aglyn/aglyn/data-transfer';
18
+ import type { PluginTransferResource, TransferApplyResult, TransferApplyWriter, TransferResourceContext, TransferRevertDecisions, TransferRevertResult } from '@aglyn/aglyn/plugin-manager/plugin-transfer-resources';
19
+ import { type CategoryIndex } from './records-transfer';
20
+ import { type CommerceListSource, type Firestore } from './server-common';
21
+ export type Doc = Record<string, unknown>;
22
+ type Collection = FirebaseFirestore.CollectionReference;
23
+ export interface RecordsSpec {
24
+ collection(firestore: Firestore, ctx: TransferResourceContext): Collection;
25
+ /** The list's query an export may carry a filter of. */
26
+ source?: Omit<CommerceListSource, 'collection'>;
27
+ /** A document as a file names it. */
28
+ record(id: string, data: Doc, extra: RecordsExtra): Record<string, unknown>;
29
+ /** The values a document is found by, per match key. */
30
+ matchValues(id: string, data: Doc): Record<string, unknown>;
31
+ /** What a lookup or export reads once per call, besides the documents. */
32
+ extra?(firestore: Firestore, ctx: TransferResourceContext, docs: readonly FirebaseFirestore.DocumentSnapshot[]): Promise<RecordsExtra>;
33
+ /** Finds documents by a key's values (at most 30); the id key is read directly. */
34
+ find?: Record<string, (collection: Collection, values: string[]) => FirebaseFirestore.Query>;
35
+ }
36
+ export type RecordsExtra = {
37
+ productNames?: Record<string, string>;
38
+ categories?: CategoryIndex;
39
+ };
40
+ /** The reading hooks every records resource shares: count, a page of an export, and the lookup. */
41
+ export declare function readableRecords(spec: RecordsSpec): Pick<PluginTransferResource, 'count' | 'readPage' | 'lookup'>;
42
+ export declare const ordersTransfer: PluginTransferResource;
43
+ interface WritableSpec extends RecordsSpec {
44
+ /** The fields a new record cannot be made without. */
45
+ requiredToCreate: readonly string[];
46
+ /** A new record's id: a fresh one, or what the row names (a coupon's code). */
47
+ newId(row: PlannedTransferRow, changes: Readonly<Record<string, unknown>>): string;
48
+ /** The document a row's changes make, or the refusal. */
49
+ write(id: string, current: Doc | null, changes: Readonly<Record<string, unknown>>, extra: RecordsExtra): {
50
+ doc: Record<string, unknown>;
51
+ } | {
52
+ problem: string;
53
+ };
54
+ /** Stamps a create carries beyond its fields. */
55
+ createStamps?(): Record<string, unknown>;
56
+ /** Values normalized before matching and planning (a code's case). */
57
+ normalize?(values: Record<string, unknown>): Record<string, unknown>;
58
+ /** Called after a record is written, with what the next rows resolve against. */
59
+ afterWrite?(id: string, doc: Doc, extra: RecordsExtra): void;
60
+ }
61
+ /** Writes one chunk of planned rows: each a create or an update of one document. */
62
+ export declare function applyRecords(spec: WritableSpec, ctx: TransferResourceContext, chunk: TransferChunk<PlannedTransferRow>, writer: TransferApplyWriter, firestore: Firestore): Promise<TransferApplyResult>;
63
+ /** Reverses one chunk: a created record deleted, an updated one's fields put back. */
64
+ export declare function revertRecords(spec: WritableSpec, ctx: TransferResourceContext, snapshot: TransferUndoSnapshot, decisions: TransferRevertDecisions | undefined, firestore: Firestore): Promise<TransferRevertResult>;
65
+ export declare const discountsTransfer: PluginTransferResource;
66
+ export declare const couponsTransfer: PluginTransferResource;
67
+ export declare const categoriesTransfer: PluginTransferResource;
68
+ export {};