@openrails/billing-ui 0.247.0 → 0.248.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## Entitlements read
4
+
5
+ - `getEntitlements()` lists the entitlement keys the customer holds
6
+ (`GET /me/entitlements`), so a host can gate access right after a purchase.
7
+
8
+ ## Every payment belongs to its order
9
+
10
+ - Breaking: `Payment` no longer carries `price` or `product`; `order_id` names
11
+ the bill it settles, whose frozen `lines` say what was bought.
12
+ - `listOrders({ ids })` reads exactly the orders a page of payments settles.
13
+ - `PaymentHistory` and `usePayments` name each payment from its order's lines
14
+ (and one recurring line's cadence) in one extra read per page; `usePayments`
15
+ returns those orders as `orders`.
16
+
3
17
  ## Low-balance lines
4
18
 
5
19
  - `getAccount()` answers `low_balance_lines`: the line each balance is judged
@@ -1,4 +1,4 @@
1
- import { CardSummary, CurrencyScales, Payment, Price, Subscription } from '../client/types';
1
+ import { CardSummary, CurrencyScales, Order, Payment, Price, Subscription } from '../client/types';
2
2
  import { Translator } from '../i18n/messages';
3
3
  export declare function formatDate(value: string | null | undefined, locale?: string): string | null;
4
4
  /** Exact money, or null while the currency's scale is unknown. */
@@ -6,8 +6,11 @@ export declare function formatMoney(amount: string | null | undefined, currency:
6
6
  /** "every 30 days", "30 days of access" or "one-time". */
7
7
  export declare function intervalLabel(price: Pick<Price, "access_duration_hours" | "billing_interval_hours"> | null | undefined, m: Translator): string | null;
8
8
  export declare function subscriptionName(s: Subscription, { t }: Translator): string;
9
- /** What a payment bought: the product's name, else its kind, plus its cadence. */
10
- export declare function paymentItem(p: Payment, m: Translator): {
9
+ /**
10
+ * What a payment bought, from the frozen lines of the order it settles: their
11
+ * names and, for one recurring line, its cadence. Without its order, the kind.
12
+ */
13
+ export declare function paymentItem(p: Payment, order: Order | undefined, m: Translator): {
11
14
  name: string;
12
15
  detail: string | null;
13
16
  };
@@ -295,17 +295,17 @@ export declare function createAdminServices(options: AdminClientOptions): {
295
295
  queryFn?: import('@tanstack/react-query').QueryFunction<import('../client/generated/wire').Payment, readonly [...string[], "payments", string], never> | undefined;
296
296
  } & import('@tanstack/react-query').QueryKeyWithDataTag<readonly [...string[], "payments", string], import('../client/generated/wire').Payment, Error>;
297
297
  attempts: (filters: import('./lib/api/endpoints').AttemptFilters, limit: number, cursor?: string) => import('@tanstack/react-query').OmitKeyof<import('@tanstack/react-query').UseQueryOptions<import('./lib/api/credit-types').ListPage<import('../client/generated/wire').PaymentAttempt>, Error, import('./lib/api/credit-types').ListPage<import('../client/generated/wire').PaymentAttempt>, (string | {
298
- filters: Partial<Record<"psp_id" | "source" | "order_id" | "reason" | "subscription_id" | "customer_id" | "payment_id" | "kind" | "owner" | "category" | "response_code" | "card_entry" | "observed_via" | "avs_result" | "cvv_result" | "cycle_id" | "since" | "until", string>>;
298
+ filters: Partial<Record<"psp_id" | "source" | "order_id" | "reason" | "subscription_id" | "customer_id" | "kind" | "payment_id" | "owner" | "category" | "response_code" | "card_entry" | "observed_via" | "avs_result" | "cvv_result" | "cycle_id" | "since" | "until", string>>;
299
299
  limit: number;
300
300
  cursor: string | undefined;
301
301
  })[]>, "queryFn"> & {
302
302
  queryFn?: import('@tanstack/react-query').QueryFunction<import('./lib/api/credit-types').ListPage<import('../client/generated/wire').PaymentAttempt>, (string | {
303
- filters: Partial<Record<"psp_id" | "source" | "order_id" | "reason" | "subscription_id" | "customer_id" | "payment_id" | "kind" | "owner" | "category" | "response_code" | "card_entry" | "observed_via" | "avs_result" | "cvv_result" | "cycle_id" | "since" | "until", string>>;
303
+ filters: Partial<Record<"psp_id" | "source" | "order_id" | "reason" | "subscription_id" | "customer_id" | "kind" | "payment_id" | "owner" | "category" | "response_code" | "card_entry" | "observed_via" | "avs_result" | "cvv_result" | "cycle_id" | "since" | "until", string>>;
304
304
  limit: number;
305
305
  cursor: string | undefined;
306
306
  })[], never> | undefined;
307
307
  } & import('@tanstack/react-query').QueryKeyWithDataTag<(string | {
308
- filters: Partial<Record<"psp_id" | "source" | "order_id" | "reason" | "subscription_id" | "customer_id" | "payment_id" | "kind" | "owner" | "category" | "response_code" | "card_entry" | "observed_via" | "avs_result" | "cvv_result" | "cycle_id" | "since" | "until", string>>;
308
+ filters: Partial<Record<"psp_id" | "source" | "order_id" | "reason" | "subscription_id" | "customer_id" | "kind" | "payment_id" | "owner" | "category" | "response_code" | "card_entry" | "observed_via" | "avs_result" | "cvv_result" | "cycle_id" | "since" | "until", string>>;
309
309
  limit: number;
310
310
  cursor: string | undefined;
311
311
  })[], import('./lib/api/credit-types').ListPage<import('../client/generated/wire').PaymentAttempt>, Error>;
@@ -895,17 +895,17 @@ export declare const useAdminServices: () => {
895
895
  queryFn?: import('@tanstack/react-query').QueryFunction<import('../client/generated/wire').Payment, readonly [...string[], "payments", string], never> | undefined;
896
896
  } & import('@tanstack/react-query').QueryKeyWithDataTag<readonly [...string[], "payments", string], import('../client/generated/wire').Payment, Error>;
897
897
  attempts: (filters: import('./lib/api/endpoints').AttemptFilters, limit: number, cursor?: string) => import('@tanstack/react-query').OmitKeyof<import('@tanstack/react-query').UseQueryOptions<import('./lib/api/credit-types').ListPage<import('../client/generated/wire').PaymentAttempt>, Error, import('./lib/api/credit-types').ListPage<import('../client/generated/wire').PaymentAttempt>, (string | {
898
- filters: Partial<Record<"psp_id" | "source" | "order_id" | "reason" | "subscription_id" | "customer_id" | "payment_id" | "kind" | "owner" | "category" | "response_code" | "card_entry" | "observed_via" | "avs_result" | "cvv_result" | "cycle_id" | "since" | "until", string>>;
898
+ filters: Partial<Record<"psp_id" | "source" | "order_id" | "reason" | "subscription_id" | "customer_id" | "kind" | "payment_id" | "owner" | "category" | "response_code" | "card_entry" | "observed_via" | "avs_result" | "cvv_result" | "cycle_id" | "since" | "until", string>>;
899
899
  limit: number;
900
900
  cursor: string | undefined;
901
901
  })[]>, "queryFn"> & {
902
902
  queryFn?: import('@tanstack/react-query').QueryFunction<import('./lib/api/credit-types').ListPage<import('../client/generated/wire').PaymentAttempt>, (string | {
903
- filters: Partial<Record<"psp_id" | "source" | "order_id" | "reason" | "subscription_id" | "customer_id" | "payment_id" | "kind" | "owner" | "category" | "response_code" | "card_entry" | "observed_via" | "avs_result" | "cvv_result" | "cycle_id" | "since" | "until", string>>;
903
+ filters: Partial<Record<"psp_id" | "source" | "order_id" | "reason" | "subscription_id" | "customer_id" | "kind" | "payment_id" | "owner" | "category" | "response_code" | "card_entry" | "observed_via" | "avs_result" | "cvv_result" | "cycle_id" | "since" | "until", string>>;
904
904
  limit: number;
905
905
  cursor: string | undefined;
906
906
  })[], never> | undefined;
907
907
  } & import('@tanstack/react-query').QueryKeyWithDataTag<(string | {
908
- filters: Partial<Record<"psp_id" | "source" | "order_id" | "reason" | "subscription_id" | "customer_id" | "payment_id" | "kind" | "owner" | "category" | "response_code" | "card_entry" | "observed_via" | "avs_result" | "cvv_result" | "cycle_id" | "since" | "until", string>>;
908
+ filters: Partial<Record<"psp_id" | "source" | "order_id" | "reason" | "subscription_id" | "customer_id" | "kind" | "payment_id" | "owner" | "category" | "response_code" | "card_entry" | "observed_via" | "avs_result" | "cvv_result" | "cycle_id" | "since" | "until", string>>;
909
909
  limit: number;
910
910
  cursor: string | undefined;
911
911
  })[], import('./lib/api/credit-types').ListPage<import('../client/generated/wire').PaymentAttempt>, Error>;
@@ -168,17 +168,17 @@ export declare function createQueries(client: AdminClient, api: AdminAPI): {
168
168
  queryFn?: import('@tanstack/react-query').QueryFunction<import('../../client/generated/wire').Payment, readonly [...string[], "payments", string], never> | undefined;
169
169
  } & import('@tanstack/react-query').QueryKeyWithDataTag<readonly [...string[], "payments", string], import('../../client/generated/wire').Payment, Error>;
170
170
  attempts: (filters: AttemptFilters, limit: number, cursor?: string) => import('@tanstack/react-query').OmitKeyof<import('@tanstack/react-query').UseQueryOptions<ListPage<import('../../client/generated/wire').PaymentAttempt>, Error, ListPage<import('../../client/generated/wire').PaymentAttempt>, (string | {
171
- filters: Partial<Record<"psp_id" | "source" | "order_id" | "reason" | "subscription_id" | "customer_id" | "payment_id" | "kind" | "owner" | "category" | "response_code" | "card_entry" | "observed_via" | "avs_result" | "cvv_result" | "cycle_id" | "since" | "until", string>>;
171
+ filters: Partial<Record<"psp_id" | "source" | "order_id" | "reason" | "subscription_id" | "customer_id" | "kind" | "payment_id" | "owner" | "category" | "response_code" | "card_entry" | "observed_via" | "avs_result" | "cvv_result" | "cycle_id" | "since" | "until", string>>;
172
172
  limit: number;
173
173
  cursor: string | undefined;
174
174
  })[]>, "queryFn"> & {
175
175
  queryFn?: import('@tanstack/react-query').QueryFunction<ListPage<import('../../client/generated/wire').PaymentAttempt>, (string | {
176
- filters: Partial<Record<"psp_id" | "source" | "order_id" | "reason" | "subscription_id" | "customer_id" | "payment_id" | "kind" | "owner" | "category" | "response_code" | "card_entry" | "observed_via" | "avs_result" | "cvv_result" | "cycle_id" | "since" | "until", string>>;
176
+ filters: Partial<Record<"psp_id" | "source" | "order_id" | "reason" | "subscription_id" | "customer_id" | "kind" | "payment_id" | "owner" | "category" | "response_code" | "card_entry" | "observed_via" | "avs_result" | "cvv_result" | "cycle_id" | "since" | "until", string>>;
177
177
  limit: number;
178
178
  cursor: string | undefined;
179
179
  })[], never> | undefined;
180
180
  } & import('@tanstack/react-query').QueryKeyWithDataTag<(string | {
181
- filters: Partial<Record<"psp_id" | "source" | "order_id" | "reason" | "subscription_id" | "customer_id" | "payment_id" | "kind" | "owner" | "category" | "response_code" | "card_entry" | "observed_via" | "avs_result" | "cvv_result" | "cycle_id" | "since" | "until", string>>;
181
+ filters: Partial<Record<"psp_id" | "source" | "order_id" | "reason" | "subscription_id" | "customer_id" | "kind" | "payment_id" | "owner" | "category" | "response_code" | "card_entry" | "observed_via" | "avs_result" | "cvv_result" | "cycle_id" | "since" | "until", string>>;
182
182
  limit: number;
183
183
  cursor: string | undefined;
184
184
  })[], ListPage<import('../../client/generated/wire').PaymentAttempt>, Error>;
@@ -25,7 +25,7 @@ var I = {
25
25
  };
26
26
  function R(e) {
27
27
  let t = e.usage;
28
- if (!t || BigInt(t.amount_due) <= 0n) return [];
28
+ if (e.collection_owner !== "engine" || !t || BigInt(t.amount_due) <= 0n) return [];
29
29
  switch (e.status) {
30
30
  case "open": return [
31
31
  "record_payment",
@@ -176,6 +176,8 @@ function U({ order: e }) {
176
176
  className: "space-y-3 text-sm",
177
177
  children: [
178
178
  /* @__PURE__ */ F("p", { children: [/* @__PURE__ */ P(i, { id: "Status: " }), /* @__PURE__ */ P(h, { status: e.payment.status })] }),
179
+ e.collection_owner !== "engine" && /* @__PURE__ */ P("p", { children: e.collection_owner === "nmi_schedule" ? "Collection follows the NMI schedule. Recovery is coordinated through the subscription." : "The payment provider collects this bill. Payment activity appears in the history below." }),
180
+ e.provider_bills.map((e, t) => /* @__PURE__ */ F("p", { children: [e.reference || e.kind, e.settled_at ? ` · Settled via ${e.settlement_source} · ${l(e.settled_at)}` : " · Settlement not yet verified"] }, `${e.psp_id}:${e.kind}:${e.reference}:${t}`)),
179
181
  s && /* @__PURE__ */ F("p", { children: [/* @__PURE__ */ P(i, { id: "Last failure: " }), s.message] }),
180
182
  e.usage && /* @__PURE__ */ P(G, { order: e })
181
183
  ]
@@ -339,4 +341,4 @@ function G({ order: t }) {
339
341
  //#endregion
340
342
  export { H as OrderDetailPage };
341
343
 
342
- //# sourceMappingURL=admin-detail-7p684Uyc.js.map
344
+ //# sourceMappingURL=admin-detail-BHe51ma9.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin-detail-BHe51ma9.js","names":[],"sources":["../src/admin/pages/orders/model.ts","../src/admin/pages/orders/detail.tsx"],"sourcesContent":["import type { Order, Payment } from \"#orck/client/generated/wire\"\nimport type { UsageAction } from \"#orck/admin/lib/api/order-endpoints\"\nimport { amountFromInput } from \"#orck/admin/lib/format\"\n\nexport const usageActionLabels: Record<UsageAction, string> = {\n waive_balance: \"Waive balance\",\n mark_uncollectible: \"Mark uncollectible\",\n record_payment: \"Record payment\",\n}\nexport const usageActionDescriptions: Record<UsageAction, string> = {\n waive_balance:\n \"Forgive the remaining debt. Existing payments stay recorded and are not refunded.\",\n mark_uncollectible:\n \"Stop scheduled collection. What the order owes remains owed; collecting it again reopens it.\",\n record_payment:\n \"Record money already received outside automatic collection. This does not charge a payment method.\",\n}\n// usageActions are what staff who may change billing can do to a usage\n// order in its state: none while a collection is in progress.\nexport function usageActions(order: Order): UsageAction[] {\n const usage = order.usage\n if (order.collection_owner !== \"engine\" || !usage || BigInt(usage.amount_due) <= 0n) return []\n switch (order.status) {\n case \"open\":\n return [\"record_payment\", \"mark_uncollectible\", \"waive_balance\"]\n case \"uncollectible\":\n return [\"record_payment\", \"waive_balance\"]\n }\n return []\n}\nexport function usageResultMessage(result: Order | Payment) {\n if (\"kind\" in result) return \"Payment recorded.\"\n if (result.status === \"complete\") return \"Order paid.\"\n if (result.status === \"processing\")\n return \"Collection is pending verification. No new collection should be started.\"\n return \"Order updated.\"\n}\nexport function usagePaymentAmount(\n input: string,\n amountDue: string,\n decimals: number\n) {\n const amount = amountFromInput(input.trim(), decimals)\n if (amount === null)\n throw new Error(\n `Enter a positive amount with up to ${decimals} decimal places.`\n )\n if (BigInt(amount) <= 0n || BigInt(amount) > BigInt(amountDue))\n throw new Error(\n \"Payment must be positive and no greater than what the order owes.\"\n )\n return amount\n}\n","import { AdminMessage, useAdminUI } from \"#orck/admin/ui-context\"\nimport { useAdminServices } from \"#orck/admin/context\"\nimport { useState } from \"react\"\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\"\nimport { Link, useParams } from \"#orck/admin/router\"\nimport type { ColumnDef } from \"@tanstack/react-table\"\n\nimport { CursorPager } from \"#orck/admin/components/cursor-pager\"\nimport { DataTable } from \"#orck/admin/components/data-table\"\nimport { StatusBadge } from \"#orck/admin/components/status-badge\"\nimport { Button } from \"#orck/admin/components/ui/button\"\nimport { Input } from \"#orck/admin/components/ui/input\"\nimport { Label } from \"#orck/admin/components/ui/label\"\nimport {\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n} from \"#orck/admin/components/ui/card\"\nimport {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogDescription,\n DialogFooter,\n} from \"#orck/admin/components/ui/dialog\"\nimport { useCursorPages } from \"#orck/admin/lib/cursor-pages\"\nimport type { Order, OrderUsage, Payment } from \"#orck/client/generated/wire\"\nimport type { UsageAction } from \"#orck/admin/lib/api/order-endpoints\"\n\nimport { useAdminUpdates } from \"#orck/admin/lib/capabilities\"\nimport {\n currencyScale,\n formatDate,\n formatNativeAmount,\n shortId,\n} from \"#orck/admin/lib/format\"\nimport { taxDisplay } from \"../customers/invoice-profile-model\"\nimport {\n usageActionDescriptions,\n usageActionLabels,\n usageActions,\n usagePaymentAmount,\n usageResultMessage,\n} from \"./model\"\n\nconst historyColumns: ColumnDef<Payment, unknown>[] = [\n {\n header: \"Paid\",\n cell: ({ row }) => formatDate(row.original.created_at),\n },\n {\n header: \"Amount\",\n cell: ({ row }) =>\n formatNativeAmount(row.original.amount, row.original.currency),\n },\n {\n header: \"Status\",\n cell: ({ row }) => <StatusBadge status={row.original.status} />,\n },\n {\n header: \"Method\",\n cell: ({ row }) => row.original.rail ?? row.original.channel,\n },\n {\n header: \"Reference\",\n cell: ({ row }) => row.original.transaction_id || shortId(row.original.id),\n },\n]\nexport function OrderDetailPage() {\n const { orderQueries } = useAdminServices()\n\n const { id = \"\" } = useParams()\n const { data: order, isPending, error } = useQuery(orderQueries.detail(id))\n if (isPending)\n return (\n <p>\n <AdminMessage id={\"Loading order…\"} />\n </p>\n )\n if (error)\n return (\n <p role=\"alert\" className=\"text-destructive\">\n {error.message}\n </p>\n )\n if (!order)\n return (\n <p>\n <AdminMessage id={\"Order not found.\"} />\n </p>\n )\n return <OrderDetail key={order.id} order={order} />\n}\nexport function OrderDetail({ order }: { order: Order }) {\n const { orderQueries } = useAdminServices()\n\n const paging = useCursorPages(order.id, 25)\n const history = useQuery(\n orderQueries.payments(order.id, paging.size, paging.cursor)\n )\n const failure = order.payment.last_payment_error\n return (\n <div className=\"flex flex-col gap-5\">\n <Link to=\"/orders\" className=\"text-sm underline\">\n <AdminMessage id={\"← Orders\"} />\n </Link>\n <div className=\"flex flex-wrap items-center gap-3\">\n <h1 className=\"text-xl font-semibold\">{order.number ?? order.id}</h1>\n <StatusBadge status={order.status} />\n {order.usage?.delinquent && <StatusBadge status=\"delinquent\" />}\n </div>\n <p className=\"text-sm\">\n <AdminMessage id={\"Customer\"} />{\" \"}\n <Link className=\"underline\" to={`/customers/${order.customer_id}`}>\n {order.customer_id}\n </Link>{\" \"}\n · {order.origin} · {order.currency}\n </p>\n <div className=\"grid gap-4 md:grid-cols-3\">\n {[\n [\"Total\", order.total],\n ...(order.usage\n ? [\n [\"Paid\", order.usage.amount_paid],\n [\"Unpaid\", order.usage.amount_due],\n ]\n : []),\n ].map(([label, value]) => (\n <Card key={String(label)}>\n <CardHeader>\n <CardTitle>{label}</CardTitle>\n </CardHeader>\n <CardContent className=\"text-xl\">\n {formatNativeAmount(value, order.currency)}\n </CardContent>\n </Card>\n ))}\n </div>\n {order.usage && <UsageFacts usage={order.usage} />}\n {order.renewal && (\n <Card>\n <CardHeader>\n <CardTitle>\n <AdminMessage id={\"Renewal\"} />\n </CardTitle>\n </CardHeader>\n <CardContent className=\"grid gap-3 text-sm md:grid-cols-2\">\n <p>\n <AdminMessage id={\"Subscription:\"} />{\" \"}\n <Link\n className=\"underline\"\n to={`/subscriptions/${order.renewal.subscription_id}`}\n >\n {shortId(order.renewal.subscription_id)}\n </Link>\n </p>\n <p>\n <AdminMessage id={\"Period: \"} />\n {formatDate(order.renewal.period_starts_at)} –{\" \"}\n {formatDate(order.renewal.period_ends_at)}\n </p>\n <p>\n <AdminMessage id={\"Due: \"} />\n {formatDate(order.renewal.due_at)}\n </p>\n </CardContent>\n </Card>\n )}\n <Card>\n <CardHeader>\n <CardTitle>\n <AdminMessage id={\"Lines\"} />\n </CardTitle>\n </CardHeader>\n <CardContent>\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"text-left\">\n <th>\n <AdminMessage id={\"Description\"} />\n </th>\n <th>\n <AdminMessage id={\"Quantity\"} />\n </th>\n <th className=\"text-right\">\n <AdminMessage id={\"Amount\"} />\n </th>\n </tr>\n </thead>\n <tbody>\n {order.lines.map((line) => (\n <tr key={line.id}>\n <td className=\"py-2\">\n {line.description}\n {line.source && (\n <p className=\"text-xs text-muted-foreground\">\n {line.source}\n </p>\n )}\n </td>\n <td>{line.quantity ?? \"—\"}</td>\n <td className=\"text-right\">\n {formatNativeAmount(line.amount, order.currency)}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n {!order.lines.length && (\n <p>\n <AdminMessage id={\"No lines.\"} />\n </p>\n )}\n </CardContent>\n </Card>\n <Card>\n <CardHeader>\n <CardTitle>\n <AdminMessage id={\"Payment\"} />\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3 text-sm\">\n <p>\n <AdminMessage id={\"Status: \"} />\n <StatusBadge status={order.payment.status} />\n </p>\n {order.collection_owner !== \"engine\" && (\n <p>\n {order.collection_owner === \"nmi_schedule\"\n ? \"Collection follows the NMI schedule. Recovery is coordinated through the subscription.\"\n : \"The payment provider collects this bill. Payment activity appears in the history below.\"}\n </p>\n )}\n {order.provider_bills.map((bill, index) => (\n <p key={`${bill.psp_id}:${bill.kind}:${bill.reference}:${index}`}>\n {bill.reference || bill.kind}\n {bill.settled_at\n ? ` · Settled via ${bill.settlement_source} · ${formatDate(bill.settled_at)}`\n : \" · Settlement not yet verified\"}\n </p>\n ))}\n {failure && (\n <p>\n <AdminMessage id={\"Last failure: \"} />\n {failure.message}\n </p>\n )}\n {order.usage && <UsageActions order={order} />}\n </CardContent>\n </Card>\n <Card>\n <CardHeader>\n <CardTitle>\n <AdminMessage id={\"Payment history\"} />\n </CardTitle>\n </CardHeader>\n <CardContent>\n {history.error ? (\n <p role=\"alert\" className=\"text-destructive\">\n {history.error.message}\n </p>\n ) : (\n <>\n <DataTable\n columns={historyColumns}\n data={history.data?.data ?? []}\n loading={history.isPending}\n emptyMessage=\"No payments recorded.\"\n />\n <CursorPager\n pages={paging}\n rows={history.data?.data?.length ?? 0}\n nextCursor={history.data?.next_cursor}\n busy={history.isFetching}\n />\n </>\n )}\n </CardContent>\n </Card>\n </div>\n )\n}\n\nfunction UsageFacts({ usage }: { usage: OrderUsage }) {\n return (\n <Card>\n <CardHeader>\n <CardTitle>\n <AdminMessage id={\"Usage billed\"} />\n </CardTitle>\n </CardHeader>\n <CardContent className=\"grid gap-3 text-sm md:grid-cols-2\">\n <p>\n <AdminMessage id={\"Period: \"} />\n {formatDate(usage.period_starts_at)} –{\" \"}\n {formatDate(usage.period_ends_at)}\n </p>\n <p>\n <AdminMessage id={\"Due: \"} />\n {formatDate(usage.due_at)}\n </p>\n <p>\n <AdminMessage id={\"Collection:\"} />{\" \"}\n {usage.collection_method === \"send_invoice\"\n ? \"Manual remittance\"\n : \"Saved payment method\"}\n </p>\n <p>\n <AdminMessage id={\"Next attempt: \"} />\n {formatDate(usage.next_collection_attempt_at)}\n </p>\n <p>\n <AdminMessage id={\"Purchase order: \"} />\n {usage.po_number ?? \"—\"}\n </p>\n <p>\n <AdminMessage id={\"Memo: \"} />\n {usage.memo ?? \"—\"}\n </p>\n <div>\n <p className=\"font-medium\">\n <AdminMessage id={\"Billing contacts\"} />\n </p>\n {usage.billing_contacts.length ? (\n usage.billing_contacts.map((c, i) => (\n <p key={i}>\n {c.name ? `${c.name} · ` : \"\"}\n {c.email}\n </p>\n ))\n ) : (\n <p>—</p>\n )}\n </div>\n <div>\n <p className=\"font-medium\">\n <AdminMessage id={\"Tax details\"} />\n </p>\n {Object.entries(usage.tax ?? {}).map(([key, value]) => (\n <p key={key}>\n {key}: {taxDisplay(value)}\n </p>\n ))}\n </div>\n <p className=\"text-muted-foreground md:col-span-2\">\n <AdminMessage\n id={\n \"These are the customer&apos;s invoice profile when the order was billed. Editing the profile affects later orders.\"\n }\n />\n </p>\n </CardContent>\n </Card>\n )\n}\n\nfunction UsageActions({ order }: { order: Order }) {\n const { toast, usageActionMutation } = useAdminServices()\n\n const { id: adminId } = useAdminUI()\n\n const canUpdate = useAdminUpdates()\n const [action, setAction] = useState<UsageAction | null>(null)\n const [amount, setAmount] = useState(\"\")\n const [reference, setReference] = useState(\"\")\n const [error, setError] = useState<string | null>(null)\n const client = useQueryClient()\n const mutation = useMutation(usageActionMutation(client, order.customer_id))\n const actions = canUpdate ? usageActions(order) : []\n async function submit() {\n if (!action || mutation.isPending) return\n setError(null)\n try {\n if (!actions.includes(action))\n throw new Error(\n \"This action is no longer available. Refresh the order before continuing.\"\n )\n if (action === \"record_payment\" && !reference.trim())\n throw new Error(\"Enter the bank or payment reference.\")\n let paid: string | undefined\n if (action === \"record_payment\") {\n const scale = currencyScale(order.currency)\n if (scale === undefined)\n throw new Error(`${order.currency} is not a registered currency.`)\n paid = usagePaymentAmount(amount, order.usage!.amount_due, scale)\n }\n const result = await mutation.mutateAsync({\n id: order.id,\n action,\n amount: paid,\n reference: reference.trim(),\n })\n toast(usageResultMessage(result))\n setAction(null)\n } catch (failure) {\n setError(\n failure instanceof Error ? failure.message : \"Order action failed.\"\n )\n }\n }\n return (\n <>\n {order.status === \"processing\" && (\n <p role=\"status\">\n <AdminMessage\n id={\n \"A collection of this order is in progress. It must finish, or be resolved with \"\n }\n />\n <code>\n <AdminMessage id={\"openrails intents resolve\"} />\n </code>\n <AdminMessage id={\", before another action.\"} />\n </p>\n )}\n <div className=\"flex flex-wrap gap-2\">\n {actions.map((value) => (\n <Button\n key={value}\n variant={value === \"waive_balance\" ? \"destructive\" : \"outline\"}\n onClick={() => {\n setAction(value)\n setError(null)\n }}\n >\n {usageActionLabels[value]}\n </Button>\n ))}\n </div>\n {!actions.length && order.status !== \"processing\" && (\n <p className=\"text-muted-foreground\">\n <AdminMessage\n id={\n \"No actions are available for your permissions and this order&apos;s state.\"\n }\n />\n </p>\n )}\n <Dialog\n open={action !== null}\n onOpenChange={(open) => {\n if (!open && !mutation.isPending) setAction(null)\n }}\n >\n <DialogContent>\n <DialogHeader>\n <DialogTitle>\n {action ? usageActionLabels[action] : \"Order action\"}\n </DialogTitle>\n <DialogDescription>\n {action ? usageActionDescriptions[action] : \"\"}\n </DialogDescription>\n </DialogHeader>\n {action === \"record_payment\" && (\n <div className=\"space-y-3\">\n <div>\n <Label htmlFor={adminId(\"order-payment-amount\")}>\n <AdminMessage id={\"Amount (\"} />\n {order.currency})\n </Label>\n <Input\n id={adminId(\"order-payment-amount\")}\n inputMode=\"decimal\"\n value={amount}\n onChange={(e) => setAmount(e.target.value)}\n />\n </div>\n <div>\n <Label htmlFor={adminId(\"order-payment-reference\")}>\n <AdminMessage id={\"Payment reference\"} />\n </Label>\n <Input\n id={adminId(\"order-payment-reference\")}\n maxLength={255}\n value={reference}\n onChange={(e) => setReference(e.target.value)}\n />\n </div>\n </div>\n )}\n {error && (\n <p role=\"alert\" className=\"text-destructive\">\n {error}\n </p>\n )}\n <DialogFooter>\n <Button\n variant=\"outline\"\n disabled={mutation.isPending}\n onClick={() => setAction(null)}\n >\n <AdminMessage id={\"Cancel\"} />\n </Button>\n <Button\n disabled={\n mutation.isPending || !action || !actions.includes(action)\n }\n onClick={() => void submit()}\n >\n {mutation.isPending ? \"Working…\" : \"Confirm\"}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </>\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAIA,IAAa,IAAiD;CAC5D,eAAe;CACf,oBAAoB;CACpB,gBAAgB;AAClB,GACa,IAAuD;CAClE,eACE;CACF,oBACE;CACF,gBACE;AACJ;AAGA,SAAgB,EAAa,GAA6B;CACxD,IAAM,IAAQ,EAAM;CACpB,IAAI,EAAM,qBAAqB,YAAY,CAAC,KAAS,OAAO,EAAM,UAAU,KAAK,IAAI,OAAO,CAAC;CAC7F,QAAQ,EAAM,QAAd;EACE,KAAK,QACH,OAAO;GAAC;GAAkB;GAAsB;EAAe;EACjE,KAAK,iBACH,OAAO,CAAC,kBAAkB,eAAe;CAC7C;CACA,OAAO,CAAC;AACV;AACA,SAAgB,EAAmB,GAAyB;CAK1D,OAJI,UAAU,IAAe,sBACzB,EAAO,WAAW,aAAmB,gBACrC,EAAO,WAAW,eACb,6EACF;AACT;AACA,SAAgB,EACd,GACA,GACA,GACA;CACA,IAAM,IAAS,EAAgB,EAAM,KAAK,GAAG,CAAQ;CACrD,IAAI,MAAW,MACb,MAAU,MACR,sCAAsC,EAAS,iBACjD;CACF,IAAI,OAAO,CAAM,KAAK,MAAM,OAAO,CAAM,IAAI,OAAO,CAAS,GAC3D,MAAU,MACR,mEACF;CACF,OAAO;AACT;;;ACLA,IAAM,IAAgD;CACpD;EACE,QAAQ;EACR,OAAO,EAAE,aAAU,EAAW,EAAI,SAAS,UAAU;CACvD;CACA;EACE,QAAQ;EACR,OAAO,EAAE,aACP,EAAmB,EAAI,SAAS,QAAQ,EAAI,SAAS,QAAQ;CACjE;CACA;EACE,QAAQ;EACR,OAAO,EAAE,aAAU,kBAAC,GAAD,EAAa,QAAQ,EAAI,SAAS,OAAS,CAAA;CAChE;CACA;EACE,QAAQ;EACR,OAAO,EAAE,aAAU,EAAI,SAAS,QAAQ,EAAI,SAAS;CACvD;CACA;EACE,QAAQ;EACR,OAAO,EAAE,aAAU,EAAI,SAAS,kBAAkB,EAAQ,EAAI,SAAS,EAAE;CAC3E;AACF;AACA,SAAgB,IAAkB;CAChC,IAAM,EAAE,oBAAiB,EAAiB,GAEpC,EAAE,QAAK,OAAO,EAAU,GACxB,EAAE,MAAM,GAAO,cAAW,aAAU,EAAS,EAAa,OAAO,CAAE,CAAC;CAmB1E,OAlBI,IAEA,kBAAC,KAAD,EAAA,UACE,kBAAC,GAAD,EAAc,IAAI,iBAAmB,CAAA,EACpC,CAAA,IAEH,IAEA,kBAAC,KAAD;EAAG,MAAK;EAAQ,WAAU;EACvB,UAAA,EAAM;CACN,CAAA,IAEF,IAME,kBAAC,GAAD,EAAmC,SAAQ,GAAzB,EAAM,EAAmB,IAJ9C,kBAAC,KAAD,EAAA,UACE,kBAAC,GAAD,EAAc,IAAI,mBAAqB,CAAA,EACtC,CAAA;AAGT;AACA,SAAgB,EAAY,EAAE,YAA2B;CACvD,IAAM,EAAE,oBAAiB,EAAiB,GAEpC,IAAS,EAAe,EAAM,IAAI,EAAE,GACpC,IAAU,EACd,EAAa,SAAS,EAAM,IAAI,EAAO,MAAM,EAAO,MAAM,CAC5D,GACM,IAAU,EAAM,QAAQ;CAC9B,OACE,kBAAC,OAAD;EAAK,WAAU;EAAf,UAAA;GACE,kBAAC,GAAD;IAAM,IAAG;IAAU,WAAU;IAC3B,UAAA,kBAAC,GAAD,EAAc,IAAI,WAAa,CAAA;GAC3B,CAAA;GACN,kBAAC,OAAD;IAAK,WAAU;IAAf,UAAA;KACE,kBAAC,MAAD;MAAI,WAAU;MAAyB,UAAA,EAAM,UAAU,EAAM;KAAO,CAAA;KACpE,kBAAC,GAAD,EAAa,QAAQ,EAAM,OAAS,CAAA;KACnC,EAAM,OAAO,cAAc,kBAAC,GAAD,EAAa,QAAO,aAAc,CAAA;IAC3D;;GACL,kBAAC,KAAD;IAAG,WAAU;IAAb,UAAA;KACE,kBAAC,GAAD,EAAc,IAAI,WAAa,CAAA;KAAE;KACjC,kBAAC,GAAD;MAAM,WAAU;MAAY,IAAI,cAAc,EAAM;MACjD,UAAA,EAAM;KACH,CAAA;KAAE;KAAI;KACT,EAAM;KAAO;KAAI,EAAM;IACzB;;GACH,kBAAC,OAAD;IAAK,WAAU;IACZ,UAAA,CACC,CAAC,SAAS,EAAM,KAAK,GACrB,GAAI,EAAM,QACN,CACE,CAAC,QAAQ,EAAM,MAAM,WAAW,GAChC,CAAC,UAAU,EAAM,MAAM,UAAU,CACnC,IACA,CAAC,CACP,CAAC,CAAC,KAAK,CAAC,GAAO,OACb,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UAAY,EAAiB,CAAA,EACnB,CAAA,GACZ,kBAAC,GAAD;KAAa,WAAU;KACpB,UAAA,EAAmB,GAAO,EAAM,QAAQ;IAC9B,CAAA,CACT,EAAA,GAPK,OAAO,CAAK,CAOjB,CACP;GACE,CAAA;GACJ,EAAM,SAAS,kBAAC,GAAD,EAAY,OAAO,EAAM,MAAQ,CAAA;GAChD,EAAM,WACL,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAc,IAAI,UAAY,CAAA,EACrB,CAAA,EACD,CAAA,GACZ,kBAAC,GAAD;IAAa,WAAU;IAAvB,UAAA;KACE,kBAAC,KAAD,EAAA,UAAA;MACE,kBAAC,GAAD,EAAc,IAAI,gBAAkB,CAAA;MAAE;MACtC,kBAAC,GAAD;OACE,WAAU;OACV,IAAI,kBAAkB,EAAM,QAAQ;OAEnC,UAAA,EAAQ,EAAM,QAAQ,eAAe;MAClC,CAAA;KACL,EAAA,CAAA;KACH,kBAAC,KAAD,EAAA,UAAA;MACE,kBAAC,GAAD,EAAc,IAAI,WAAa,CAAA;MAC9B,EAAW,EAAM,QAAQ,gBAAgB;MAAE;MAAG;MAC9C,EAAW,EAAM,QAAQ,cAAc;KACvC,EAAA,CAAA;KACH,kBAAC,KAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAc,IAAI,QAAU,CAAA,GAC3B,EAAW,EAAM,QAAQ,MAAM,CAC/B,EAAA,CAAA;IACQ;GACT,CAAA,CAAA,EAAA,CAAA;GAER,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAc,IAAI,QAAU,CAAA,EACnB,CAAA,EACD,CAAA,GACZ,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,SAAD;IAAO,WAAU;IAAjB,UAAA,CACE,kBAAC,SAAD,EAAA,UACE,kBAAC,MAAD;KAAI,WAAU;KAAd,UAAA;MACE,kBAAC,MAAD,EAAA,UACE,kBAAC,GAAD,EAAc,IAAI,cAAgB,CAAA,EAChC,CAAA;MACJ,kBAAC,MAAD,EAAA,UACE,kBAAC,GAAD,EAAc,IAAI,WAAa,CAAA,EAC7B,CAAA;MACJ,kBAAC,MAAD;OAAI,WAAU;OACZ,UAAA,kBAAC,GAAD,EAAc,IAAI,SAAW,CAAA;MAC3B,CAAA;KACF;IACC,CAAA,EAAA,CAAA,GACP,kBAAC,SAAD,EAAA,UACG,EAAM,MAAM,KAAK,MAChB,kBAAC,MAAD,EAAA,UAAA;KACE,kBAAC,MAAD;MAAI,WAAU;MAAd,UAAA,CACG,EAAK,aACL,EAAK,UACJ,kBAAC,KAAD;OAAG,WAAU;OACV,UAAA,EAAK;MACL,CAAA,CAEH;;KACJ,kBAAC,MAAD,EAAA,UAAK,EAAK,YAAY,IAAQ,CAAA;KAC9B,kBAAC,MAAD;MAAI,WAAU;MACX,UAAA,EAAmB,EAAK,QAAQ,EAAM,QAAQ;KAC7C,CAAA;IACF,EAAA,GAbK,EAAK,EAaV,CACL,EACI,CAAA,CACF;GACN,CAAA,GAAA,CAAC,EAAM,MAAM,UACZ,kBAAC,KAAD,EAAA,UACE,kBAAC,GAAD,EAAc,IAAI,YAAc,CAAA,EAC/B,CAAA,CAEM,EAAA,CAAA,CACT,EAAA,CAAA;GACN,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAc,IAAI,UAAY,CAAA,EACrB,CAAA,EACD,CAAA,GACZ,kBAAC,GAAD;IAAa,WAAU;IAAvB,UAAA;KACE,kBAAC,KAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAc,IAAI,WAAa,CAAA,GAC/B,kBAAC,GAAD,EAAa,QAAQ,EAAM,QAAQ,OAAS,CAAA,CAC3C,EAAA,CAAA;KACF,EAAM,qBAAqB,YAC1B,kBAAC,KAAD,EAAA,UACG,EAAM,qBAAqB,iBACxB,2FACA,0FACH,CAAA;KAEJ,EAAM,eAAe,KAAK,GAAM,MAC/B,kBAAC,KAAD,EAAA,UAAA,CACG,EAAK,aAAa,EAAK,MACvB,EAAK,aACF,kBAAkB,EAAK,kBAAkB,KAAK,EAAW,EAAK,UAAU,MACxE,gCACH,EAAA,GALK,GAAG,EAAK,OAAO,GAAG,EAAK,KAAK,GAAG,EAAK,UAAU,GAAG,GAKtD,CACJ;KACA,KACC,kBAAC,KAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAc,IAAI,iBAAmB,CAAA,GACpC,EAAQ,OACR,EAAA,CAAA;KAEJ,EAAM,SAAS,kBAAC,GAAD,EAAqB,SAAQ,CAAA;IAClC;GACT,CAAA,CAAA,EAAA,CAAA;GACN,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAc,IAAI,kBAAoB,CAAA,EAC7B,CAAA,EACD,CAAA,GACZ,kBAAC,GAAD,EAAA,UACG,EAAQ,QACP,kBAAC,KAAD;IAAG,MAAK;IAAQ,WAAU;IACvB,UAAA,EAAQ,MAAM;GACd,CAAA,IAEH,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;IACE,SAAS;IACT,MAAM,EAAQ,MAAM,QAAQ,CAAC;IAC7B,SAAS,EAAQ;IACjB,cAAa;GACd,CAAA,GACD,kBAAC,GAAD;IACE,OAAO;IACP,MAAM,EAAQ,MAAM,MAAM,UAAU;IACpC,YAAY,EAAQ,MAAM;IAC1B,MAAM,EAAQ;GACf,CAAA,CACD,EAAA,CAAA,EAEO,CAAA,CACT,EAAA,CAAA;EACH;;AAET;AAEA,SAAS,EAAW,EAAE,YAAgC;CACpD,OACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAc,IAAI,eAAiB,CAAA,EAC1B,CAAA,EACD,CAAA,GACZ,kBAAC,GAAD;EAAa,WAAU;EAAvB,UAAA;GACE,kBAAC,KAAD,EAAA,UAAA;IACE,kBAAC,GAAD,EAAc,IAAI,WAAa,CAAA;IAC9B,EAAW,EAAM,gBAAgB;IAAE;IAAG;IACtC,EAAW,EAAM,cAAc;GAC/B,EAAA,CAAA;GACH,kBAAC,KAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAc,IAAI,QAAU,CAAA,GAC3B,EAAW,EAAM,MAAM,CACvB,EAAA,CAAA;GACH,kBAAC,KAAD,EAAA,UAAA;IACE,kBAAC,GAAD,EAAc,IAAI,cAAgB,CAAA;IAAE;IACnC,EAAM,sBAAsB,iBACzB,sBACA;GACH,EAAA,CAAA;GACH,kBAAC,KAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAc,IAAI,iBAAmB,CAAA,GACpC,EAAW,EAAM,0BAA0B,CAC3C,EAAA,CAAA;GACH,kBAAC,KAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAc,IAAI,mBAAqB,CAAA,GACtC,EAAM,aAAa,GACnB,EAAA,CAAA;GACH,kBAAC,KAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAc,IAAI,SAAW,CAAA,GAC5B,EAAM,QAAQ,GACd,EAAA,CAAA;GACH,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;IAAG,WAAU;IACX,UAAA,kBAAC,GAAD,EAAc,IAAI,mBAAqB,CAAA;GACtC,CAAA,GACF,EAAM,iBAAiB,SACtB,EAAM,iBAAiB,KAAK,GAAG,MAC7B,kBAAC,KAAD,EAAA,UAAA,CACG,EAAE,OAAO,GAAG,EAAE,KAAK,OAAO,IAC1B,EAAE,KACF,EAAA,GAHK,CAGL,CACJ,IAED,kBAAC,KAAD,EAAA,UAAG,IAAI,CAAA,CAEN,EAAA,CAAA;GACL,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;IAAG,WAAU;IACX,UAAA,kBAAC,GAAD,EAAc,IAAI,cAAgB,CAAA;GACjC,CAAA,GACF,OAAO,QAAQ,EAAM,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAK,OAC1C,kBAAC,KAAD,EAAA,UAAA;IACG;IAAI;IAAG,EAAW,CAAK;GACvB,EAAA,GAFK,CAEL,CACJ,CACE,EAAA,CAAA;GACL,kBAAC,KAAD;IAAG,WAAU;IACX,UAAA,kBAAC,GAAD,EACE,IACE,qHAEH,CAAA;GACA,CAAA;EACQ;CACT,CAAA,CAAA,EAAA,CAAA;AAEV;AAEA,SAAS,EAAa,EAAE,YAA2B;CACjD,IAAM,EAAE,UAAO,2BAAwB,EAAiB,GAElD,EAAE,IAAI,MAAY,EAAW,GAE7B,IAAY,EAAgB,GAC5B,CAAC,GAAQ,KAAa,EAA6B,IAAI,GACvD,CAAC,GAAQ,KAAa,EAAS,EAAE,GACjC,CAAC,GAAW,KAAgB,EAAS,EAAE,GACvC,CAAC,GAAO,KAAY,EAAwB,IAAI,GAChD,IAAS,EAAe,GACxB,IAAW,EAAY,EAAoB,GAAQ,EAAM,WAAW,CAAC,GACrE,IAAU,IAAY,EAAa,CAAK,IAAI,CAAC;CACnD,eAAe,IAAS;EAClB,OAAC,KAAU,EAAS,YACxB;KAAS,IAAI;GACb,IAAI;IACF,IAAI,CAAC,EAAQ,SAAS,CAAM,GAC1B,MAAU,MACR,0EACF;IACF,IAAI,MAAW,oBAAoB,CAAC,EAAU,KAAK,GACjD,MAAU,MAAM,sCAAsC;IACxD,IAAI;IACJ,IAAI,MAAW,kBAAkB;KAC/B,IAAM,IAAQ,EAAc,EAAM,QAAQ;KAC1C,IAAI,MAAU,KAAA,GACZ,MAAU,MAAM,GAAG,EAAM,SAAS,+BAA+B;KACnE,IAAO,EAAmB,GAAQ,EAAM,MAAO,YAAY,CAAK;IAClE;IACA,IAAM,IAAS,MAAM,EAAS,YAAY;KACxC,IAAI,EAAM;KACV;KACA,QAAQ;KACR,WAAW,EAAU,KAAK;IAC5B,CAAC;IAED,AADA,EAAM,EAAmB,CAAM,CAAC,GAChC,EAAU,IAAI;GAChB,SAAS,GAAS;IAChB,EACE,aAAmB,QAAQ,EAAQ,UAAU,sBAC/C;GACF;EA3Ba;CA4Bf;CACA,OACE,kBAAA,GAAA,EAAA,UAAA;EACG,EAAM,WAAW,gBAChB,kBAAC,KAAD;GAAG,MAAK;GAAR,UAAA;IACE,kBAAC,GAAD,EACE,IACE,kFAEH,CAAA;IACD,kBAAC,QAAD,EAAA,UACE,kBAAC,GAAD,EAAc,IAAI,4BAA8B,CAAA,EAC5C,CAAA;IACN,kBAAC,GAAD,EAAc,IAAI,2BAA6B,CAAA;GAC9C;;EAEL,kBAAC,OAAD;GAAK,WAAU;GACZ,UAAA,EAAQ,KAAK,MACZ,kBAAC,GAAD;IAEE,SAAS,MAAU,kBAAkB,gBAAgB;IACrD,eAAe;KAEb,AADA,EAAU,CAAK,GACf,EAAS,IAAI;IACf;IAEC,UAAA,EAAkB;GACb,GARD,CAQC,CACT;EACE,CAAA;EACJ,CAAC,EAAQ,UAAU,EAAM,WAAW,gBACnC,kBAAC,KAAD;GAAG,WAAU;GACX,UAAA,kBAAC,GAAD,EACE,IACE,6EAEH,CAAA;EACA,CAAA;EAEL,kBAAC,GAAD;GACE,MAAM,MAAW;GACjB,eAAe,MAAS;IACtB,AAAI,CAAC,KAAQ,CAAC,EAAS,aAAW,EAAU,IAAI;GAClD;GAEA,UAAA,kBAAC,GAAD,EAAA,UAAA;IACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACG,IAAS,EAAkB,KAAU,eAC3B,CAAA,GACb,kBAAC,GAAD,EAAA,UACG,IAAS,EAAwB,KAAU,GAC3B,CAAA,CACP,EAAA,CAAA;IACb,MAAW,oBACV,kBAAC,OAAD;KAAK,WAAU;KAAf,UAAA,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,GAAD;MAAO,SAAS,EAAQ,sBAAsB;MAA9C,UAAA;OACE,kBAAC,GAAD,EAAc,IAAI,WAAa,CAAA;OAC9B,EAAM;OAAS;MACX;KACP,CAAA,GAAA,kBAAC,GAAD;MACE,IAAI,EAAQ,sBAAsB;MAClC,WAAU;MACV,OAAO;MACP,WAAW,MAAM,EAAU,EAAE,OAAO,KAAK;KAC1C,CAAA,CACE,EAAA,CAAA,GACL,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,GAAD;MAAO,SAAS,EAAQ,yBAAyB;MAC/C,UAAA,kBAAC,GAAD,EAAc,IAAI,oBAAsB,CAAA;KACnC,CAAA,GACP,kBAAC,GAAD;MACE,IAAI,EAAQ,yBAAyB;MACrC,WAAW;MACX,OAAO;MACP,WAAW,MAAM,EAAa,EAAE,OAAO,KAAK;KAC7C,CAAA,CACE,EAAA,CAAA,CACF;;IAEN,KACC,kBAAC,KAAD;KAAG,MAAK;KAAQ,WAAU;KACvB,UAAA;IACA,CAAA;IAEL,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;KACE,SAAQ;KACR,UAAU,EAAS;KACnB,eAAe,EAAU,IAAI;KAE7B,UAAA,kBAAC,GAAD,EAAc,IAAI,SAAW,CAAA;IACvB,CAAA,GACR,kBAAC,GAAD;KACE,UACE,EAAS,aAAa,CAAC,KAAU,CAAC,EAAQ,SAAS,CAAM;KAE3D,eAAe,KAAK,EAAO;KAE1B,UAAA,EAAS,YAAY,aAAa;IAC7B,CAAA,CACI,EAAA,CAAA;GACD,EAAA,CAAA;EACT,CAAA;CACR,EAAA,CAAA;AAEN"}
@@ -102,8 +102,12 @@ function Y() {
102
102
  }) : "—"
103
103
  }),
104
104
  /* @__PURE__ */ U(L, {
105
- label: c("Product"),
106
- children: T.product?.display_name ?? (T.price_id ? h(T.price_id, 16) : "—")
105
+ label: c("Order"),
106
+ children: T.order_id ? /* @__PURE__ */ U(i, {
107
+ className: A,
108
+ to: `/orders/${T.order_id}`,
109
+ children: h(T.order_id, 16)
110
+ }) : "—"
107
111
  }),
108
112
  /* @__PURE__ */ U(L, {
109
113
  label: c("Card"),
@@ -321,4 +325,4 @@ function X({ payment: t, disabled: n, disabledNote: i }) {
321
325
  //#endregion
322
326
  export { Y as PaymentDetailPage };
323
327
 
324
- //# sourceMappingURL=admin-detail-5aNNvrc0.js.map
328
+ //# sourceMappingURL=admin-detail-X82kR2f7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin-detail-X82kR2f7.js","names":[],"sources":["../src/admin/pages/payments/detail.tsx"],"sourcesContent":["import { AdminMessage, useAdminUI } from \"#orck/admin/ui-context\"\nimport { useAdminServices } from \"#orck/admin/context\"\nimport { HugeiconsIcon } from \"@hugeicons/react\"\nimport { ArrowLeft01Icon, Undo02Icon } from \"@hugeicons/core-free-icons\"\nimport * as React from \"react\"\nimport { Link, useNavigate, useParams } from \"#orck/admin/router\"\n\nimport { useForm } from \"@tanstack/react-form\"\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\"\n\nimport { Fact } from \"#orck/admin/components/fact-card\"\nimport { FormFieldErrors } from \"#orck/admin/components/form-field-errors\"\nimport { StatusBadge } from \"#orck/admin/components/status-badge\"\nimport { Button } from \"#orck/admin/components/ui/button\"\nimport {\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n} from \"#orck/admin/components/ui/card\"\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from \"#orck/admin/components/ui/dialog\"\nimport { Input } from \"#orck/admin/components/ui/input\"\nimport { Label } from \"#orck/admin/components/ui/label\"\nimport { Switch } from \"#orck/admin/components/ui/switch\"\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"#orck/admin/components/ui/table\"\nimport { REFUNDABLE_RAILS } from \"#orck/admin/lib/api/endpoints\"\nimport type { Payment } from \"#orck/client/generated/wire\"\nimport { DIALOG_FORM } from \"#orck/admin/lib/dialog-width\"\nimport {\n formatCard,\n formatNativeAmount,\n formatDate,\n nativeAmountFromInput,\n nativeAmountToInput,\n shortId,\n} from \"#orck/admin/lib/format\"\n\nimport { useAdminUpdates } from \"#orck/admin/lib/capabilities\"\n\nexport function PaymentDetailPage() {\n const { text: adminText } = useAdminUI()\n\n const { adminQueries } = useAdminServices()\n\n const canUpdate = useAdminUpdates()\n const { id = \"\" } = useParams()\n const navigate = useNavigate()\n const { data: payment, isPending: loading } = useQuery(\n adminQueries.payment(id)\n )\n\n if (loading)\n return (\n <p className=\"text-sm text-muted-foreground\">\n <AdminMessage id={\"Loading…\"} />\n </p>\n )\n if (!payment)\n return (\n <p className=\"text-sm text-muted-foreground\">\n <AdminMessage id={\"Payment not found.\"} />\n </p>\n )\n\n const railRefunds = REFUNDABLE_RAILS.includes(payment.rail ?? \"\")\n const refundable =\n payment.kind === \"charge\" &&\n railRefunds &&\n (payment.status === \"succeeded\" || payment.status === \"partially_refunded\")\n const refundNote = !payment.rail\n ? `A ${payment.channel} payment is refunded where it was taken`\n : railRefunds\n ? undefined\n : `Refunds are not supported via the ${payment.rail} rail API`\n const link = \"text-xs underline-offset-2 hover:underline\"\n\n return (\n <div className=\"flex flex-col gap-4\">\n <div className=\"flex items-center gap-3\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => navigate(-1)}\n aria-label={adminText(\"Back\")}\n >\n <HugeiconsIcon icon={ArrowLeft01Icon} className=\"size-4\" />\n </Button>\n <div>\n <h2 className=\"flex items-center gap-2 text-sm\">\n {payment.id} <StatusBadge status={payment.status} />\n </h2>\n <p className=\"text-xs text-muted-foreground\">\n {payment.kind} · {payment.rail ?? payment.channel}\n <AdminMessage id={\" · txn\"} /> {payment.transaction_id || \"—\"}\n </p>\n </div>\n {canUpdate && (\n <div className=\"ml-auto\">\n <RefundDialog\n payment={payment}\n disabled={!refundable}\n disabledNote={refundNote}\n />\n </div>\n )}\n </div>\n\n <div className=\"grid gap-3 sm:grid-cols-2 lg:grid-cols-4\">\n <Fact label={adminText(\"Amount\")}>\n {formatNativeAmount(payment.amount, payment.currency)}\n </Fact>\n <Fact label={adminText(\"Refunded\")}>\n {payment.amount_refunded !== \"0\"\n ? formatNativeAmount(payment.amount_refunded, payment.currency)\n : \"—\"}\n </Fact>\n <Fact label={adminText(\"Customer\")}>\n <Link className={link} to={`/customers/${payment.customer_id}`}>\n {shortId(payment.customer_id, 16)}\n </Link>\n </Fact>\n <Fact label={adminText(\"Subscription\")}>\n {payment.subscription_id ? (\n <Link\n className={link}\n to={`/subscriptions/${payment.subscription_id}`}\n >\n {shortId(payment.subscription_id, 16)}\n </Link>\n ) : (\n \"—\"\n )}\n </Fact>\n <Fact label={adminText(\"Order\")}>\n {payment.order_id ? (\n <Link className={link} to={`/orders/${payment.order_id}`}>\n {shortId(payment.order_id, 16)}\n </Link>\n ) : \"—\"}\n </Fact>\n <Fact label={adminText(\"Card\")}>{formatCard(payment.card)}</Fact>\n <Fact label={adminText(\"Channel\")}>\n {payment.channel}\n {payment.psp_id ? ` · PSP ${shortId(payment.psp_id, 13)}` : \"\"}\n </Fact>\n <Fact label={adminText(\"Created\")}>\n {formatDate(payment.created_at)}\n </Fact>\n {payment.refunded_payment_id ? (\n <Fact label={adminText(\"Reverses\")}>\n <Link\n className={link}\n to={`/payments/${payment.refunded_payment_id}`}\n >\n {shortId(payment.refunded_payment_id, 16)}\n </Link>\n </Fact>\n ) : null}\n {payment.reason ? (\n <Fact label={adminText(\"Reason\")}>{payment.reason}</Fact>\n ) : null}\n {payment.failure ? (\n <Fact label={adminText(\"Failure\")}>\n {payment.failure.message || payment.failure.reason}\n </Fact>\n ) : null}\n </div>\n\n <Card>\n <CardHeader>\n <CardTitle className=\"text-sm\">\n <AdminMessage id={\"Refunds\"} />\n </CardTitle>\n </CardHeader>\n <CardContent>\n {!payment.refunds?.length ? (\n <p className=\"text-sm text-muted-foreground\">\n <AdminMessage id={\"No refunds.\"} />\n </p>\n ) : (\n <Table>\n <TableHeader>\n <TableRow className=\"hover:bg-transparent\">\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Refund\"} />\n </TableHead>\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Status\"} />\n </TableHead>\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Amount\"} />\n </TableHead>\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Created\"} />\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {payment.refunds.map((r) => (\n <TableRow key={r.id}>\n <TableCell className=\"text-xs\">\n <Link className={link} to={`/payments/${r.id}`}>\n {shortId(r.id, 16)}\n </Link>\n </TableCell>\n <TableCell>\n <StatusBadge status={r.status} />\n </TableCell>\n <TableCell>\n {formatNativeAmount(r.amount, r.currency)}\n </TableCell>\n <TableCell>{formatDate(r.created_at)}</TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n )}\n </CardContent>\n </Card>\n </div>\n )\n}\n\nfunction RefundDialog({\n payment,\n disabled,\n disabledNote,\n}: {\n payment: Payment\n disabled: boolean\n disabledNote?: string\n}) {\n const { toast, toastApiError, adminMutations } = useAdminServices()\n\n const { id: adminId } = useAdminUI()\n\n const [open, setOpen] = React.useState(false)\n const remaining = (\n BigInt(payment.amount) - BigInt(payment.amount_refunded)\n ).toString()\n const queryClient = useQueryClient()\n const refund = useMutation(\n adminMutations.refundPayment(\n queryClient,\n payment.id,\n payment.customer_id,\n payment.subscription_id ?? undefined\n )\n )\n const form = useForm({\n defaultValues: {\n amount: nativeAmountToInput(remaining, payment.currency),\n reason: \"\",\n revokeAccess: false,\n },\n onSubmit: async ({ value }) => {\n const amount = nativeAmountFromInput(value.amount, payment.currency)\n if (\n amount === null ||\n BigInt(amount) <= 0n ||\n BigInt(amount) > BigInt(remaining)\n )\n return\n try {\n const result = await refund.mutateAsync({\n amount,\n reason: value.reason,\n revokeAccess: value.revokeAccess,\n })\n toast.success(\n result.status === \"pending\" ? \"Refund submitted\" : \"Refunded\"\n )\n handleOpenChange(false)\n } catch (err) {\n toastApiError(err, \"Refund payment\")\n }\n },\n })\n\n const handleOpenChange = (next: boolean) => {\n setOpen(next)\n if (next) {\n form.reset({\n amount: nativeAmountToInput(remaining, payment.currency),\n reason: \"\",\n revokeAccess: false,\n })\n } else {\n form.reset()\n refund.reset()\n }\n }\n\n return (\n <>\n <Button\n variant=\"destructive\"\n size=\"sm\"\n disabled={disabled}\n title={disabledNote}\n onClick={() => handleOpenChange(true)}\n >\n <HugeiconsIcon icon={Undo02Icon} className=\"size-4\" />\n <AdminMessage id={\" Refund\"} />\n </Button>\n <Dialog open={open} onOpenChange={handleOpenChange}>\n <DialogContent className={DIALOG_FORM}>\n <DialogHeader>\n <DialogTitle>\n <AdminMessage id={\"Refund payment\"} />\n </DialogTitle>\n <DialogDescription>\n <AdminMessage id={\"Executes the refund at the \"} />\n {payment.rail}\n <AdminMessage id={\" rail. Remaining refundable: \"} />\n {formatNativeAmount(remaining, payment.currency)}.\n </DialogDescription>\n </DialogHeader>\n <form\n onSubmit={(event) => {\n event.preventDefault()\n event.stopPropagation()\n void form.handleSubmit()\n }}\n className=\"grid gap-4\"\n >\n <div className=\"grid gap-3\">\n <form.Field\n name=\"amount\"\n validators={{\n onChange: ({ value }) => {\n const amount = nativeAmountFromInput(\n value,\n payment.currency\n )\n if (amount === null || BigInt(amount) <= 0n) {\n return \"Enter an amount greater than zero\"\n }\n return BigInt(amount) > BigInt(remaining)\n ? \"Amount exceeds the remaining refundable balance\"\n : undefined\n },\n }}\n >\n {(field) => (\n <div className=\"grid gap-1.5\">\n <Label htmlFor={adminId(\"refund-amount\")}>\n <AdminMessage id={\"Amount (\"} />\n {payment.currency})\n </Label>\n <Input\n id={adminId(\"refund-amount\")}\n type=\"number\"\n step=\"any\"\n min=\"0\"\n max={nativeAmountToInput(remaining, payment.currency)}\n value={field.state.value}\n onBlur={field.handleBlur}\n onChange={(event) =>\n field.handleChange(event.target.value)\n }\n aria-invalid={field.state.meta.errors.length > 0}\n />\n <FormFieldErrors errors={field.state.meta.errors} />\n </div>\n )}\n </form.Field>\n <form.Field name=\"reason\">\n {(field) => (\n <div className=\"grid gap-1.5\">\n <Label htmlFor={adminId(\"refund-reason\")}>\n <AdminMessage id={\"Reason (optional)\"} />\n </Label>\n <Input\n id={adminId(\"refund-reason\")}\n value={field.state.value}\n onBlur={field.handleBlur}\n onChange={(event) =>\n field.handleChange(event.target.value)\n }\n />\n </div>\n )}\n </form.Field>\n <form.Field name=\"revokeAccess\">\n {(field) => (\n <div className=\"flex items-center gap-2\">\n <Switch\n id={adminId(\"refund-revoke\")}\n checked={field.state.value}\n onCheckedChange={field.handleChange}\n />\n <Label htmlFor={adminId(\"refund-revoke\")}>\n <AdminMessage id={\"Also revoke granted access\"} />\n </Label>\n </div>\n )}\n </form.Field>\n </div>\n <DialogFooter>\n <form.Subscribe\n selector={(state) =>\n [\n state.values.amount,\n state.canSubmit,\n state.isSubmitting,\n ] as const\n }\n >\n {([amountInput, canSubmit, isSubmitting]) => (\n <>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => handleOpenChange(false)}\n disabled={isSubmitting}\n >\n <AdminMessage id={\"Close\"} />\n </Button>\n <Button\n type=\"submit\"\n variant=\"destructive\"\n disabled={\n !nativeAmountFromInput(amountInput, payment.currency) ||\n !canSubmit ||\n isSubmitting\n }\n >\n {isSubmitting ? \"Refunding…\" : \"Refund\"}\n </Button>\n </>\n )}\n </form.Subscribe>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n </>\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAqDA,SAAgB,IAAoB;CAClC,IAAM,EAAE,MAAM,MAAc,EAAW,GAEjC,EAAE,oBAAiB,EAAiB,GAEpC,IAAY,EAAgB,GAC5B,EAAE,QAAK,OAAO,EAAU,GACxB,IAAW,EAAY,GACvB,EAAE,MAAM,GAAS,WAAW,MAAY,EAC5C,EAAa,QAAQ,CAAE,CACzB;CAEA,IAAI,GACF,OACE,kBAAC,KAAD;EAAG,WAAU;EACX,UAAA,kBAAC,GAAD,EAAc,IAAI,WAAa,CAAA;CAC9B,CAAA;CAEP,IAAI,CAAC,GACH,OACE,kBAAC,KAAD;EAAG,WAAU;EACX,UAAA,kBAAC,GAAD,EAAc,IAAI,qBAAuB,CAAA;CACxC,CAAA;CAGP,IAAM,IAAc,EAAiB,SAAS,EAAQ,QAAQ,EAAE,GAC1D,IACJ,EAAQ,SAAS,YACjB,MACC,EAAQ,WAAW,eAAe,EAAQ,WAAW,uBAClD,IAAc,EAAQ,OAExB,IACE,KAAA,IACA,qCAAqC,EAAQ,KAAK,aAHpD,KAAK,EAAQ,QAAQ,0CAInB,IAAO;CAEb,OACE,kBAAC,OAAD;EAAK,WAAU;EAAf,UAAA;GACE,kBAAC,OAAD;IAAK,WAAU;IAAf,UAAA;KACE,kBAAC,GAAD;MACE,SAAQ;MACR,MAAK;MACL,eAAe,EAAS,EAAE;MAC1B,cAAY,EAAU,MAAM;MAE5B,UAAA,kBAAC,GAAD;OAAe,MAAM;OAAiB,WAAU;MAAU,CAAA;KACpD,CAAA;KACR,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;MAAI,WAAU;MAAd,UAAA;OACG,EAAQ;OAAG;OAAC,kBAAC,GAAD,EAAa,QAAQ,EAAQ,OAAS,CAAA;MACjD;KACJ,CAAA,GAAA,kBAAC,KAAD;MAAG,WAAU;MAAb,UAAA;OACG,EAAQ;OAAK;OAAI,EAAQ,QAAQ,EAAQ;OAC1C,kBAAC,GAAD,EAAc,IAAI,SAAW,CAAA;OAAC;OAAE,EAAQ,kBAAkB;MACzD;KACA,CAAA,CAAA,EAAA,CAAA;KACJ,KACC,kBAAC,OAAD;MAAK,WAAU;MACb,UAAA,kBAAC,GAAD;OACW;OACT,UAAU,CAAC;OACX,cAAc;MACf,CAAA;KACE,CAAA;IAEJ;;GAEL,kBAAC,OAAD;IAAK,WAAU;IAAf,UAAA;KACE,kBAAC,GAAD;MAAM,OAAO,EAAU,QAAQ;MAC5B,UAAA,EAAmB,EAAQ,QAAQ,EAAQ,QAAQ;KAChD,CAAA;KACN,kBAAC,GAAD;MAAM,OAAO,EAAU,UAAU;MAC9B,UAAA,EAAQ,oBAAoB,MAEzB,MADA,EAAmB,EAAQ,iBAAiB,EAAQ,QAAQ;KAE5D,CAAA;KACN,kBAAC,GAAD;MAAM,OAAO,EAAU,UAAU;MAC/B,UAAA,kBAAC,GAAD;OAAM,WAAW;OAAM,IAAI,cAAc,EAAQ;OAC9C,UAAA,EAAQ,EAAQ,aAAa,EAAE;MAC5B,CAAA;KACF,CAAA;KACN,kBAAC,GAAD;MAAM,OAAO,EAAU,cAAc;MAClC,UAAA,EAAQ,kBACP,kBAAC,GAAD;OACE,WAAW;OACX,IAAI,kBAAkB,EAAQ;OAE7B,UAAA,EAAQ,EAAQ,iBAAiB,EAAE;MAChC,CAAA,IAEN;KAEE,CAAA;KACN,kBAAC,GAAD;MAAM,OAAO,EAAU,OAAO;MAC3B,UAAA,EAAQ,WACP,kBAAC,GAAD;OAAM,WAAW;OAAM,IAAI,WAAW,EAAQ;OAC3C,UAAA,EAAQ,EAAQ,UAAU,EAAE;MACzB,CAAA,IACJ;KACA,CAAA;KACN,kBAAC,GAAD;MAAM,OAAO,EAAU,MAAM;MAAI,UAAA,EAAW,EAAQ,IAAI;KAAQ,CAAA;KAChE,kBAAC,GAAD;MAAM,OAAO,EAAU,SAAS;MAAhC,UAAA,CACG,EAAQ,SACR,EAAQ,SAAS,UAAU,EAAQ,EAAQ,QAAQ,EAAE,MAAM,EACxD;;KACN,kBAAC,GAAD;MAAM,OAAO,EAAU,SAAS;MAC7B,UAAA,EAAW,EAAQ,UAAU;KAC1B,CAAA;KACL,EAAQ,sBACP,kBAAC,GAAD;MAAM,OAAO,EAAU,UAAU;MAC/B,UAAA,kBAAC,GAAD;OACE,WAAW;OACX,IAAI,aAAa,EAAQ;OAExB,UAAA,EAAQ,EAAQ,qBAAqB,EAAE;MACpC,CAAA;KACF,CAAA,IACJ;KACH,EAAQ,SACP,kBAAC,GAAD;MAAM,OAAO,EAAU,QAAQ;MAAI,UAAA,EAAQ;KAAa,CAAA,IACtD;KACH,EAAQ,UACP,kBAAC,GAAD;MAAM,OAAO,EAAU,SAAS;MAC7B,UAAA,EAAQ,QAAQ,WAAW,EAAQ,QAAQ;KACxC,CAAA,IACJ;IACD;;GAEL,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;IAAW,WAAU;IACnB,UAAA,kBAAC,GAAD,EAAc,IAAI,UAAY,CAAA;GACrB,CAAA,EACD,CAAA,GACZ,kBAAC,GAAD,EAAA,UACI,EAAQ,SAAS,SAKjB,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;IAAU,WAAU;IAApB,UAAA;KACE,kBAAC,GAAD;MAAW,WAAU;MACnB,UAAA,kBAAC,GAAD,EAAc,IAAI,SAAW,CAAA;KACpB,CAAA;KACX,kBAAC,GAAD;MAAW,WAAU;MACnB,UAAA,kBAAC,GAAD,EAAc,IAAI,SAAW,CAAA;KACpB,CAAA;KACX,kBAAC,GAAD;MAAW,WAAU;MACnB,UAAA,kBAAC,GAAD,EAAc,IAAI,SAAW,CAAA;KACpB,CAAA;KACX,kBAAC,GAAD;MAAW,WAAU;MACnB,UAAA,kBAAC,GAAD,EAAc,IAAI,UAAY,CAAA;KACrB,CAAA;IACH;GACC,CAAA,EAAA,CAAA,GACb,kBAAC,GAAD,EAAA,UACG,EAAQ,QAAQ,KAAK,MACpB,kBAAC,GAAD,EAAA,UAAA;IACE,kBAAC,GAAD;KAAW,WAAU;KACnB,UAAA,kBAAC,GAAD;MAAM,WAAW;MAAM,IAAI,aAAa,EAAE;MACvC,UAAA,EAAQ,EAAE,IAAI,EAAE;KACb,CAAA;IACG,CAAA;IACX,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAa,QAAQ,EAAE,OAAS,CAAA,EACvB,CAAA;IACX,kBAAC,GAAD,EAAA,UACG,EAAmB,EAAE,QAAQ,EAAE,QAAQ,EAC/B,CAAA;IACX,kBAAC,GAAD,EAAA,UAAY,EAAW,EAAE,UAAU,EAAa,CAAA;GACxC,EAAA,GAbK,EAAE,EAaP,CACX,EACQ,CAAA,CACN,EAAA,CAAA,IAvCP,kBAAC,KAAD;IAAG,WAAU;IACX,UAAA,kBAAC,GAAD,EAAc,IAAI,cAAgB,CAAA;GACjC,CAAA,EAuCM,CAAA,CACT,EAAA,CAAA;EACH;;AAET;AAEA,SAAS,EAAa,EACpB,YACA,aACA,mBAKC;CACD,IAAM,EAAE,UAAO,kBAAe,sBAAmB,EAAiB,GAE5D,EAAE,IAAI,MAAY,EAAW,GAE7B,CAAC,GAAM,KAAW,EAAM,SAAS,EAAK,GACtC,KACJ,OAAO,EAAQ,MAAM,IAAI,OAAO,EAAQ,eAAe,EAAA,CACvD,SAAS,GACL,IAAc,EAAe,GAC7B,IAAS,EACb,EAAe,cACb,GACA,EAAQ,IACR,EAAQ,aACR,EAAQ,mBAAmB,KAAA,CAC7B,CACF,GACM,IAAO,EAAQ;EACnB,eAAe;GACb,QAAQ,EAAoB,GAAW,EAAQ,QAAQ;GACvD,QAAQ;GACR,cAAc;EAChB;EACA,UAAU,OAAO,EAAE,eAAY;GAC7B,IAAM,IAAS,EAAsB,EAAM,QAAQ,EAAQ,QAAQ;GAEjE,YAAW,QACX,OAAO,CAAM,KAAK,MAClB,OAAO,CAAM,IAAI,OAAO,CAAS,IAGnC,IAAI;IACF,IAAM,IAAS,MAAM,EAAO,YAAY;KACtC;KACA,QAAQ,EAAM;KACd,cAAc,EAAM;IACtB,CAAC;IAID,AAHA,EAAM,QACJ,EAAO,WAAW,YAAY,qBAAqB,UACrD,GACA,EAAiB,EAAK;GACxB,SAAS,GAAK;IACZ,EAAc,GAAK,gBAAgB;GACrC;EACF;CACF,CAAC,GAEK,KAAoB,MAAkB;EAE1C,AADA,EAAQ,CAAI,GACR,IACF,EAAK,MAAM;GACT,QAAQ,EAAoB,GAAW,EAAQ,QAAQ;GACvD,QAAQ;GACR,cAAc;EAChB,CAAC,KAED,EAAK,MAAM,GACX,EAAO,MAAM;CAEjB;CAEA,OACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;EACE,SAAQ;EACR,MAAK;EACK;EACV,OAAO;EACP,eAAe,EAAiB,EAAI;EALtC,UAAA,CAOE,kBAAC,GAAD;GAAe,MAAM;GAAY,WAAU;EAAU,CAAA,GACrD,kBAAC,GAAD,EAAc,IAAI,UAAY,CAAA,CACxB;CACR,CAAA,GAAA,kBAAC,GAAD;EAAc;EAAM,cAAc;EAChC,UAAA,kBAAC,GAAD;GAAe,WAAW;GAA1B,UAAA,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAc,IAAI,iBAAmB,CAAA,EAC1B,CAAA,GACb,kBAAC,GAAD,EAAA,UAAA;IACE,kBAAC,GAAD,EAAc,IAAI,8BAAgC,CAAA;IACjD,EAAQ;IACT,kBAAC,GAAD,EAAc,IAAI,gCAAkC,CAAA;IACnD,EAAmB,GAAW,EAAQ,QAAQ;IAAE;GAChC,EAAA,CAAA,CACP,EAAA,CAAA,GACd,kBAAC,QAAD;IACE,WAAW,MAAU;KAGnB,AAFA,EAAM,eAAe,GACrB,EAAM,gBAAgB,GACtB,EAAU,aAAa;IACzB;IACA,WAAU;IANZ,UAAA,CAQE,kBAAC,OAAD;KAAK,WAAU;KAAf,UAAA;MACE,kBAAC,EAAK,OAAN;OACE,MAAK;OACL,YAAY,EACV,WAAW,EAAE,eAAY;QACvB,IAAM,IAAS,EACb,GACA,EAAQ,QACV;QAIA,OAHI,MAAW,QAAQ,OAAO,CAAM,KAAK,KAChC,sCAEF,OAAO,CAAM,IAAI,OAAO,CAAS,IACpC,oDACA,KAAA;OACN,EACF;OAEE,WAAA,MACA,kBAAC,OAAD;QAAK,WAAU;QAAf,UAAA;SACE,kBAAC,GAAD;UAAO,SAAS,EAAQ,eAAe;UAAvC,UAAA;WACE,kBAAC,GAAD,EAAc,IAAI,WAAa,CAAA;WAC9B,EAAQ;WAAS;UACb;;SACP,kBAAC,GAAD;UACE,IAAI,EAAQ,eAAe;UAC3B,MAAK;UACL,MAAK;UACL,KAAI;UACJ,KAAK,EAAoB,GAAW,EAAQ,QAAQ;UACpD,OAAO,EAAM,MAAM;UACnB,QAAQ,EAAM;UACd,WAAW,MACT,EAAM,aAAa,EAAM,OAAO,KAAK;UAEvC,gBAAc,EAAM,MAAM,KAAK,OAAO,SAAS;SAChD,CAAA;SACD,kBAAC,GAAD,EAAiB,QAAQ,EAAM,MAAM,KAAK,OAAS,CAAA;QAChD;;MAEG,CAAA;MACZ,kBAAC,EAAK,OAAN;OAAY,MAAK;OACb,WAAA,MACA,kBAAC,OAAD;QAAK,WAAU;QAAf,UAAA,CACE,kBAAC,GAAD;SAAO,SAAS,EAAQ,eAAe;SACrC,UAAA,kBAAC,GAAD,EAAc,IAAI,oBAAsB,CAAA;QACnC,CAAA,GACP,kBAAC,GAAD;SACE,IAAI,EAAQ,eAAe;SAC3B,OAAO,EAAM,MAAM;SACnB,QAAQ,EAAM;SACd,WAAW,MACT,EAAM,aAAa,EAAM,OAAO,KAAK;QAExC,CAAA,CACE;;MAEG,CAAA;MACZ,kBAAC,EAAK,OAAN;OAAY,MAAK;OACb,WAAA,MACA,kBAAC,OAAD;QAAK,WAAU;QAAf,UAAA,CACE,kBAAC,GAAD;SACE,IAAI,EAAQ,eAAe;SAC3B,SAAS,EAAM,MAAM;SACrB,iBAAiB,EAAM;QACxB,CAAA,GACD,kBAAC,GAAD;SAAO,SAAS,EAAQ,eAAe;SACrC,UAAA,kBAAC,GAAD,EAAc,IAAI,6BAA+B,CAAA;QAC5C,CAAA,CACJ;;MAEG,CAAA;KACT;IACL,CAAA,GAAA,kBAAC,GAAD,EAAA,UACE,kBAAC,EAAK,WAAN;KACE,WAAW,MACT;MACE,EAAM,OAAO;MACb,EAAM;MACN,EAAM;KACR;KAGA,WAAA,CAAC,GAAa,GAAW,OACzB,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;MACE,MAAK;MACL,SAAQ;MACR,eAAe,EAAiB,EAAK;MACrC,UAAU;MAEV,UAAA,kBAAC,GAAD,EAAc,IAAI,QAAU,CAAA;KACtB,CAAA,GACR,kBAAC,GAAD;MACE,MAAK;MACL,SAAQ;MACR,UACE,CAAC,EAAsB,GAAa,EAAQ,QAAQ,KACpD,CAAC,KACD;MAGD,UAAA,IAAe,eAAe;KACzB,CAAA,CACR,EAAA,CAAA;IAEU,CAAA,EACJ,CAAA,CACV;GACO,CAAA,CAAA;;CACT,CAAA,CACR,EAAA,CAAA;AAEN"}
package/dist/admin.js CHANGED
@@ -132,11 +132,11 @@ var ze = [
132
132
  },
133
133
  {
134
134
  path: "/payments/:id",
135
- Component: A(() => import("./admin-detail-5aNNvrc0.js").then((e) => ({ default: e.PaymentDetailPage })))
135
+ Component: A(() => import("./admin-detail-X82kR2f7.js").then((e) => ({ default: e.PaymentDetailPage })))
136
136
  },
137
137
  {
138
138
  path: "/orders/:id",
139
- Component: A(() => import("./admin-detail-7p684Uyc.js").then((e) => ({ default: e.OrderDetailPage })))
139
+ Component: A(() => import("./admin-detail-BHe51ma9.js").then((e) => ({ default: e.OrderDetailPage })))
140
140
  }
141
141
  ];
142
142
  function Be(e) {
@@ -1,5 +1,5 @@
1
1
  import { BillingError } from './errors';
2
- import { Account, CustomerConfig, CustomerLink, LowBalanceLine, NetworkLinkChallenge, PublicConfig, CurrencyScales, ListPage, NewCard, CardCaptureReference, NextAction, Cart, Order, OrderPaymentInput, Page, Payment, PaymentMethod, Product, Subscription, SubscriptionChange, SubscriptionChangePreview, Usage } from './types';
2
+ import { Account, CustomerConfig, CustomerEntitlement, CustomerLink, LowBalanceLine, NetworkLinkChallenge, PublicConfig, CurrencyScales, ListPage, NewCard, CardCaptureReference, NextAction, Cart, Order, OrderPaymentInput, Page, Payment, PaymentMethod, Product, Subscription, SubscriptionChange, SubscriptionChangePreview, Usage } from './types';
3
3
  export interface BillingClientOptions {
4
4
  /** OpenRails embedded mount. Default "/billing/v1". */
5
5
  baseUrl?: string;
@@ -180,6 +180,8 @@ export declare function createBillingClient(options?: BillingClientOptions): {
180
180
  * orders, `overdue` those still owed past their due date.
181
181
  */
182
182
  listOrders(opts?: CursorOptions & {
183
+ /** Read exactly these orders (at most 100), e.g. a page of payments'. */
184
+ ids?: string[];
183
185
  origin?: string;
184
186
  status?: string;
185
187
  subscriptionId?: string;
@@ -226,6 +228,15 @@ export declare function createBillingClient(options?: BillingClientOptions): {
226
228
  listPayments(opts?: CursorOptions & {
227
229
  rail?: string;
228
230
  }): Promise<ListPage<Payment>>;
231
+ /**
232
+ * One page of the entitlement keys the customer holds (up to 500 by
233
+ * default), by key. `at` reads them as of an RFC 3339 instant; `prefix`
234
+ * keeps the keys that start with it.
235
+ */
236
+ getEntitlements(opts?: CursorOptions & {
237
+ at?: string;
238
+ prefix?: string;
239
+ }): Promise<ListPage<CustomerEntitlement>>;
229
240
  /**
230
241
  * The customer's summary: balance and amount owed per currency, the card
231
242
  * that pays each currency, and the low-balance line of each balance.
@@ -713,6 +713,48 @@ export type DeclaredPaymentMethod = {
713
713
  card?: CardDetails;
714
714
  created_at?: string;
715
715
  };
716
+ export type DeclaredProviderSchedule = {
717
+ source_reference?: string;
718
+ amount?: string;
719
+ currency?: string;
720
+ quantity?: number;
721
+ interval_hours?: number;
722
+ interval_months?: number;
723
+ first_due_at?: string;
724
+ };
725
+ export type DeclaredStripeInvoice = {
726
+ id?: string;
727
+ customer_reference?: string;
728
+ status?: string;
729
+ reason?: string;
730
+ currency?: string;
731
+ total?: string;
732
+ amount_due?: string;
733
+ amount_paid?: string;
734
+ amount_remaining?: string;
735
+ amount_off_stripe?: string;
736
+ starting_balance?: string;
737
+ pre_payment_credit?: string;
738
+ due_at?: string;
739
+ lines?: DeclaredStripeInvoiceLine[];
740
+ payments?: DeclaredStripeInvoicePayment[];
741
+ };
742
+ export type DeclaredStripeInvoiceLine = {
743
+ id?: string;
744
+ price_reference?: string;
745
+ description?: string;
746
+ quantity?: number;
747
+ amount?: string;
748
+ period_start?: string;
749
+ period_end?: string;
750
+ };
751
+ export type DeclaredStripeInvoicePayment = {
752
+ id?: string;
753
+ charge_id?: string;
754
+ payment_intent_id?: string;
755
+ amount?: string;
756
+ paid_at?: string;
757
+ };
716
758
  export type DeclaredSubscription = {
717
759
  source_id?: string;
718
760
  customer?: string;
@@ -725,6 +767,7 @@ export type DeclaredSubscription = {
725
767
  cancel?: CancelEvidence;
726
768
  dunning?: DunningEvidence;
727
769
  payment_method?: PaymentMethodRef;
770
+ accepted_schedule?: DeclaredProviderSchedule;
728
771
  evidence?: unknown;
729
772
  };
730
773
  export type DeclaredTransaction = {
@@ -735,6 +778,8 @@ export type DeclaredTransaction = {
735
778
  amount?: string;
736
779
  currency?: string;
737
780
  occurred_at?: string;
781
+ next_billing_at?: string;
782
+ stripe_invoice?: DeclaredStripeInvoice;
738
783
  };
739
784
  export type DefaultPaymentMethod = {
740
785
  currency: string;
@@ -1135,6 +1180,9 @@ export type Order = {
1135
1180
  customer_id: string;
1136
1181
  origin: "customer" | "merchant" | "subscription" | "usage";
1137
1182
  status: "canceled" | "complete" | "expired" | "open" | "processing" | "uncollectible" | "void";
1183
+ collection_owner: "engine" | "nmi_schedule" | "provider";
1184
+ collection_psp_id: string | null;
1185
+ provider_bills: OrderProviderBill[];
1138
1186
  number: string | null;
1139
1187
  currency: string;
1140
1188
  total: string;
@@ -1241,6 +1289,14 @@ export type OrderPreviewLine = {
1241
1289
  access_duration_hours: number | null;
1242
1290
  refusal: OrderLineRefusal | null;
1243
1291
  };
1292
+ export type OrderProviderBill = {
1293
+ psp_id: string;
1294
+ kind: string;
1295
+ reference: string;
1296
+ settlement_source: string | null;
1297
+ non_cash_amount: string;
1298
+ settled_at: string | null;
1299
+ };
1244
1300
  export type OrderRenewal = {
1245
1301
  subscription_id: string;
1246
1302
  period_starts_at: string;
@@ -1341,9 +1397,6 @@ export type Payment = {
1341
1397
  subscription_id: string | null;
1342
1398
  order_id: string | null;
1343
1399
  quantity: number | null;
1344
- price_id: string | null;
1345
- price: Price | null;
1346
- product: ProductSummary | null;
1347
1400
  channel: "manual" | "rail";
1348
1401
  rail: string | null;
1349
1402
  psp_id: string | null;
@@ -1443,7 +1496,6 @@ export type PaymentSettledEvent = {
1443
1496
  payment_id: string;
1444
1497
  customer_id: string;
1445
1498
  order_id?: string;
1446
- price_id?: string;
1447
1499
  subscription_id?: string;
1448
1500
  amount: string;
1449
1501
  currency: string;
@@ -1,5 +1,5 @@
1
1
  export { CANCEL_REASON_MAX, CANCEL_REASON_MIN, createBillingClient, isWalletAction, isWalletRejection, RETRY_BUDGET_MS, signWalletAction, WalletRejectedError, type BillingClient, type BillingClientOptions, type ListOptions, type OrderResult, type ProductListOptions, type SendSolanaTransaction, type SubscriptionChangeInput, type UsageOptions, } from './client';
2
2
  export { redeemAssertion, tokenSource, type RedeemAssertionOptions, type TokenResponse, type TokenSource, type TokenSourceOptions, } from './token-source';
3
3
  export { BillingError, isBillingError, isServerError, readBillingError, toBillingError, type BillingErrorBody, } from './errors';
4
- export type { Account, Balance, CaptchaConfig, CardSummary, Cart, Currency, CurrencyScales, CustomerConfig, CustomerLink, PaymentConfig, PaymentFailure, PublicConfig, PublicMerchant, ListPage, LowBalanceLine, NetworkLinkChallenge, NewCard, CardCaptureReference, NextAction, Order, OrderLine, OrderLineRefusal, OrderPaymentInput, OrderPreviewLine, Page, Payment, PaymentMethod, PaymentRecovery, Price, Product, Subscription, SubscriptionDunning, SubscriptionProduct, SubscriptionStatus, SubscriptionChange, SubscriptionChangePreview, Usage, UsageRow, } from './types';
4
+ export type { Account, Balance, CaptchaConfig, CardSummary, Cart, Currency, CurrencyScales, CustomerConfig, CustomerEntitlement, CustomerLink, PaymentConfig, PaymentFailure, PublicConfig, PublicMerchant, ListPage, LowBalanceLine, NetworkLinkChallenge, NewCard, CardCaptureReference, NextAction, Order, OrderLine, OrderLineRefusal, OrderPaymentInput, OrderPreviewLine, Page, Payment, PaymentMethod, PaymentRecovery, Price, Product, Subscription, SubscriptionDunning, SubscriptionProduct, SubscriptionStatus, SubscriptionChange, SubscriptionChangePreview, Usage, UsageRow, } from './types';
5
5
  export { amountToDecimal, decimalToAmount, formatAmount, type Amount, } from '../lib/money';
@@ -1,5 +1,6 @@
1
1
  import { z } from 'zod';
2
2
  import { CardEntry } from '../lib/card-entry';
3
+ import type * as wire from "./generated/wire";
3
4
  export declare const pageSchema: <T extends z.ZodType>(item: T) => z.ZodObject<{
4
5
  data: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodArray<T>>>, z.ZodTransform<z.core.output<T>[], z.core.output<T>[] | null | undefined>>;
5
6
  total: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
@@ -349,6 +350,30 @@ export declare const orderSchema: z.ZodObject<{
349
350
  id: z.ZodString;
350
351
  customer_id: z.ZodString;
351
352
  origin: z.ZodString;
353
+ collection_owner: z.ZodOptional<z.ZodNullable<z.ZodString>>;
354
+ collection_psp_id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
355
+ provider_bills: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
356
+ psp_id: z.ZodString;
357
+ kind: z.ZodString;
358
+ reference: z.ZodString;
359
+ settlement_source: z.ZodOptional<z.ZodNullable<z.ZodString>>;
360
+ non_cash_amount: z.ZodString & z.ZodType<string, string, z.core.$ZodTypeInternals<string, string>>;
361
+ settled_at: z.ZodOptional<z.ZodNullable<z.ZodString>>;
362
+ }, z.core.$strip>>>>, z.ZodTransform<{
363
+ psp_id: string;
364
+ kind: string;
365
+ reference: string;
366
+ non_cash_amount: string;
367
+ settlement_source?: string | null | undefined;
368
+ settled_at?: string | null | undefined;
369
+ }[], {
370
+ psp_id: string;
371
+ kind: string;
372
+ reference: string;
373
+ non_cash_amount: string;
374
+ settlement_source?: string | null | undefined;
375
+ settled_at?: string | null | undefined;
376
+ }[] | null | undefined>>;
352
377
  status: z.ZodString;
353
378
  number: z.ZodOptional<z.ZodNullable<z.ZodString>>;
354
379
  currency: z.ZodString;
@@ -624,44 +649,10 @@ export declare const paymentSchema: z.ZodObject<{
624
649
  amount_refunded: z.ZodOptional<z.ZodNullable<z.ZodString & z.ZodType<string, string, z.core.$ZodTypeInternals<string, string>>>>;
625
650
  currency: z.ZodString;
626
651
  subscription_id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
627
- price_id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
652
+ order_id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
628
653
  channel: z.ZodOptional<z.ZodNullable<z.ZodString>>;
629
654
  rail: z.ZodOptional<z.ZodNullable<z.ZodString>>;
630
655
  created_at: z.ZodString;
631
- price: z.ZodOptional<z.ZodNullable<z.ZodObject<{
632
- id: z.ZodString;
633
- key: z.ZodString;
634
- revision: z.ZodOptional<z.ZodNumber>;
635
- version: z.ZodOptional<z.ZodNumber>;
636
- product_id: z.ZodString;
637
- archived: z.ZodBoolean;
638
- unit_amount: z.ZodString & z.ZodType<string, string, z.core.$ZodTypeInternals<string, string>>;
639
- customer_amount: z.ZodOptional<z.ZodNullable<z.ZodObject<{
640
- min_amount: z.ZodString & z.ZodType<string, string, z.core.$ZodTypeInternals<string, string>>;
641
- max_amount: z.ZodString & z.ZodType<string, string, z.core.$ZodTypeInternals<string, string>>;
642
- }, z.core.$strip>>>;
643
- currency: z.ZodString;
644
- access_duration_hours: z.ZodNullable<z.ZodNumber>;
645
- billing_interval_hours: z.ZodNullable<z.ZodNumber>;
646
- trial_unit_amount: z.ZodNullable<z.ZodString & z.ZodType<string, string, z.core.$ZodTypeInternals<string, string>>>;
647
- trial_duration_hours: z.ZodNullable<z.ZodNumber>;
648
- psps: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodObject<{
649
- status: z.ZodString;
650
- ids: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodString>>>;
651
- sync_status: z.ZodOptional<z.ZodNullable<z.ZodString>>;
652
- }, z.core.$strip>>>>;
653
- created_at: z.ZodString;
654
- updated_at: z.ZodString;
655
- }, z.core.$strip>>>;
656
- product: z.ZodOptional<z.ZodNullable<z.ZodObject<{
657
- id: z.ZodString;
658
- key: z.ZodOptional<z.ZodNullable<z.ZodString>>;
659
- revision: z.ZodOptional<z.ZodNumber>;
660
- display_name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
661
- description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
662
- tier_group: z.ZodOptional<z.ZodNullable<z.ZodString>>;
663
- tier_rank: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
664
- }, z.core.$strip>>>;
665
656
  card: z.ZodOptional<z.ZodNullable<z.ZodObject<{
666
657
  brand: z.ZodOptional<z.ZodNullable<z.ZodString>>;
667
658
  last4: z.ZodOptional<z.ZodNullable<z.ZodString>>;
@@ -675,6 +666,12 @@ export declare const paymentSchema: z.ZodObject<{
675
666
  }, z.core.$strip>>>;
676
667
  }, z.core.$strip>;
677
668
  export type Payment = z.infer<typeof paymentSchema>;
669
+ /**
670
+ * An entitlement key the customer holds through a product. `quantity` is the
671
+ * most seats a held per-seat product grants it; null when none is per seat.
672
+ */
673
+ export declare const customerEntitlementSchema: z.ZodType<wire.CustomerEntitlement>;
674
+ export type CustomerEntitlement = wire.CustomerEntitlement;
678
675
  /**
679
676
  * A customer's money in one currency, as of `as_of`. `accrued_amount` is what
680
677
  * its running charges have charged and the ledger does not hold yet, already