@tokenoftrust/storefront-runner 2.4.51 → 2.4.53
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/apps/storefront/src/lib/admin/orderClient.ts +45 -11
- package/apps/storefront/src/lib/admin/services/mock/fulfillment.ts +10 -53
- package/apps/storefront/src/lib/admin/services/orders.ts +524 -87
- package/apps/storefront/src/lib/admin/viewmodels/fulfillment.ts +1159 -33
- package/apps/storefront/src/lib/admin/viewmodels/orders.ts +37 -1
- package/apps/storefront/src/pages/api/admin/orders/[id].ts +20 -5
- package/apps/storefront/src/pages/api/admin/orders.ts +8 -12
- package/package.json +1 -1
|
@@ -8,6 +8,9 @@
|
|
|
8
8
|
|
|
9
9
|
export type OrderPaymentState = "authorized" | "captured" | "refunded";
|
|
10
10
|
|
|
11
|
+
/** Display risk. `unknown` is absent evidence, not a low-risk clearance. */
|
|
12
|
+
export type OrderRiskLevel = "low" | "medium" | "high" | "unknown";
|
|
13
|
+
|
|
11
14
|
export type OrderShipState = "ready_to_ship" | "hold_review_required" | "unfulfilled" | "completed";
|
|
12
15
|
|
|
13
16
|
/** The exact merchant-facing language the shell contract requires. */
|
|
@@ -54,7 +57,35 @@ export interface OrderRow {
|
|
|
54
57
|
shipState: OrderShipState;
|
|
55
58
|
blocker: string | null;
|
|
56
59
|
nextStep: string;
|
|
57
|
-
riskLevel:
|
|
60
|
+
riskLevel: OrderRiskLevel;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** One independent readiness fact. Source and as-of belong to this column only. */
|
|
64
|
+
export interface OrderReadinessColumn {
|
|
65
|
+
key: "payment" | "tax" | "verification" | "risk" | "stock" | "fulfillment";
|
|
66
|
+
state: string;
|
|
67
|
+
source: string;
|
|
68
|
+
asOf: string | null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** Release is held unless every block is empty. `held` is not inferred from payment capture. */
|
|
72
|
+
export interface OrderRelease {
|
|
73
|
+
state: "held" | "ready";
|
|
74
|
+
ready: boolean;
|
|
75
|
+
blocks: readonly string[];
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** Storewide, filtered, and page money are separate scopes. Refunds are not values. */
|
|
79
|
+
export interface OrderMoneyScope {
|
|
80
|
+
count: number;
|
|
81
|
+
valueMinor: number;
|
|
82
|
+
refundMinor: number;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export interface OrderAccounting {
|
|
86
|
+
storewide: OrderMoneyScope;
|
|
87
|
+
filter: OrderMoneyScope;
|
|
88
|
+
page: OrderMoneyScope;
|
|
58
89
|
}
|
|
59
90
|
|
|
60
91
|
export interface OrderDetail extends OrderRow {
|
|
@@ -64,6 +95,9 @@ export interface OrderDetail extends OrderRow {
|
|
|
64
95
|
shipping: number;
|
|
65
96
|
estimatedTax: number;
|
|
66
97
|
taxesAndFees: number;
|
|
98
|
+
/** Present when the order was assessed. Absent on the mock book. */
|
|
99
|
+
columns?: OrderReadinessColumn[];
|
|
100
|
+
release?: OrderRelease;
|
|
67
101
|
}
|
|
68
102
|
|
|
69
103
|
export type OrderQueueKey = "needs_attention" | "ready_to_ship" | "unfulfilled" | "all" | "completed";
|
|
@@ -89,4 +123,6 @@ export interface OrdersViewModel {
|
|
|
89
123
|
rows: OrderRow[];
|
|
90
124
|
detailsById: Record<string, OrderDetail>;
|
|
91
125
|
today: OrdersTodaySummary;
|
|
126
|
+
/** Set by a scrappy book query. Never copied from the current page alone. */
|
|
127
|
+
accounting?: OrderAccounting;
|
|
92
128
|
}
|
|
@@ -2,18 +2,22 @@
|
|
|
2
2
|
* `GET /api/admin/orders/:id` — one order's full detail for the Orders tab.
|
|
3
3
|
*
|
|
4
4
|
* Server-side proxy to checkout `GET /commerce/orders/:orderId` for the
|
|
5
|
-
* resolved tenant + env. Bearer stays server-side
|
|
6
|
-
*
|
|
7
|
-
* Read-only
|
|
5
|
+
* resolved tenant + env. Bearer stays server-side. Address is included only
|
|
6
|
+
* for an owner of this tenant and stage. Readiness is assessed, not inferred.
|
|
7
|
+
* Read-only.
|
|
8
8
|
*/
|
|
9
9
|
import type { APIContext } from "astro";
|
|
10
10
|
import { readEnv } from "@/lib/env";
|
|
11
11
|
import { requireAdminApiEntry } from "@/lib/auth/adminApiGuard";
|
|
12
12
|
import {
|
|
13
|
+
commerceActorForAdmin,
|
|
14
|
+
commerceStageForCustomization,
|
|
13
15
|
createCheckoutOrderClient,
|
|
14
16
|
orderApiBaseUrl,
|
|
15
17
|
OrderApiError,
|
|
18
|
+
projectCheckoutOrder,
|
|
16
19
|
} from "@/lib/admin/orderClient";
|
|
20
|
+
import { assessCheckoutOrder } from "@/lib/admin/services/orders";
|
|
17
21
|
|
|
18
22
|
export const prerender = false;
|
|
19
23
|
|
|
@@ -49,8 +53,19 @@ export async function GET(context: APIContext): Promise<Response> {
|
|
|
49
53
|
});
|
|
50
54
|
|
|
51
55
|
try {
|
|
52
|
-
const
|
|
53
|
-
|
|
56
|
+
const stage = commerceStageForCustomization(customizationEnv);
|
|
57
|
+
const actor = commerceActorForAdmin({
|
|
58
|
+
tenantId: tenant.appDomain,
|
|
59
|
+
stage,
|
|
60
|
+
owner: access.entry.isOwnerViewer,
|
|
61
|
+
admitted: access.entry.admitted,
|
|
62
|
+
});
|
|
63
|
+
const order = projectCheckoutOrder(await client.getOrder(orderId), actor, {
|
|
64
|
+
tenantId: tenant.appDomain,
|
|
65
|
+
stage,
|
|
66
|
+
});
|
|
67
|
+
const readiness = assessCheckoutOrder(order);
|
|
68
|
+
return new Response(JSON.stringify({ order, readiness }), { headers: JSON_HEADERS });
|
|
54
69
|
} catch (err) {
|
|
55
70
|
if (err instanceof OrderApiError) return jsonError(err.code, err.status);
|
|
56
71
|
return jsonError("unexpected", 500);
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
* host/approver layer) — same posture as `api/evidence.json.ts`; no new gate here.
|
|
11
11
|
*/
|
|
12
12
|
import type { APIContext } from "astro";
|
|
13
|
-
import type { CheckoutOrderListFilters } from "@tot/public-runtime";
|
|
14
13
|
import { readEnv } from "@/lib/env";
|
|
15
14
|
import { requireAdminApiEntry } from "@/lib/auth/adminApiGuard";
|
|
16
15
|
import {
|
|
@@ -18,6 +17,7 @@ import {
|
|
|
18
17
|
orderApiBaseUrl,
|
|
19
18
|
OrderApiError,
|
|
20
19
|
} from "@/lib/admin/orderClient";
|
|
20
|
+
import { assessCheckoutOrder, parseOrderFilters } from "@/lib/admin/services/orders";
|
|
21
21
|
|
|
22
22
|
export const prerender = false;
|
|
23
23
|
|
|
@@ -50,16 +50,8 @@ export async function GET(context: APIContext): Promise<Response> {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
const url = new URL(context.request.url);
|
|
53
|
-
|
|
54
|
-
const
|
|
55
|
-
const filters: CheckoutOrderListFilters = {
|
|
56
|
-
queue: q.get("queue") ?? undefined,
|
|
57
|
-
status: q.get("status") ?? undefined,
|
|
58
|
-
from: q.get("from") ?? undefined,
|
|
59
|
-
to: q.get("to") ?? undefined,
|
|
60
|
-
limit: limitRaw != null ? Number(limitRaw) : undefined,
|
|
61
|
-
cursor: q.get("cursor") ?? undefined,
|
|
62
|
-
};
|
|
53
|
+
// Tenant comes from the host, never from a query parameter.
|
|
54
|
+
const filters = parseOrderFilters(url.searchParams);
|
|
63
55
|
|
|
64
56
|
const client = createCheckoutOrderClient({
|
|
65
57
|
baseUrl: orderApiBaseUrl(customizationEnv),
|
|
@@ -69,7 +61,11 @@ export async function GET(context: APIContext): Promise<Response> {
|
|
|
69
61
|
|
|
70
62
|
try {
|
|
71
63
|
const data = await client.listOrders(filters);
|
|
72
|
-
|
|
64
|
+
const orders = data.orders.map((order) => ({
|
|
65
|
+
...order,
|
|
66
|
+
readiness: assessCheckoutOrder(order),
|
|
67
|
+
}));
|
|
68
|
+
return new Response(JSON.stringify({ ...data, orders }), { headers: JSON_HEADERS });
|
|
73
69
|
} catch (err) {
|
|
74
70
|
if (err instanceof OrderApiError) return jsonError(err.code, err.status);
|
|
75
71
|
return jsonError("unexpected", 500);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tokenoftrust/storefront-runner",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.53",
|
|
4
4
|
"license": "SEE LICENSE IN LICENSE",
|
|
5
5
|
"description": "World-shareable storefront runner: multi-tenant renderer on Astro/Cloudflare. No control plane.",
|
|
6
6
|
"packageManager": "pnpm@11.9.0",
|