CI (SIAX Cloud) / sonar (pull_request) Skipped
CI (SIAX Cloud) / integration (push) Skipped
CI (SIAX Cloud) / sonar (push) Skipped
masterplan-lock / check (pull_request) Successful in 7s
masterplan-lock / check (push) Successful in 8s
CI (SIAX Cloud) / security (pull_request) Successful in 19s
Security Scan (SIAX Cloud) / security (push) Successful in 20s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 23s
CI (SIAX Cloud) / security (push) Successful in 24s
CI (SIAX Cloud) / integration (pull_request) Successful in 31s
CI (SIAX Cloud) / quality (push) Successful in 44s
CI (SIAX Cloud) / quality (pull_request) Successful in 2m13s
Servern projicerar öppna ordrar (draft/quoted/in_production/review) på universal-inbox-konvolverna via createInboxItem (buildOrderInboxItem i lib/order-flow, ADR-0001-mönstret: policy/resolution i serverlagret). Admin renderar InboxList (@siax/ui 0.11.1) ovanpå orderkön — resolve- aktionen gateras genom advance_action-state (available krävs). Terminala statusar ger ingen post. tests/order-flow 6/6; full svit 1144/1144; build ✓.
61 lines
2.4 KiB
TypeScript
61 lines
2.4 KiB
TypeScript
import { createInboxItem, type InboxItem } from "@siax/contracts/inbox";
|
|
import { resolveAction, type ResolvedAction } from "@siax/contracts/authz-ux";
|
|
|
|
/** Kanonisk orderflöde — servern äger resolutionen (ADR-0001), UI renderar. */
|
|
export const NEXT_STATUS: Record<string, string> = {
|
|
draft: "quoted",
|
|
quoted: "in_production",
|
|
in_production: "review",
|
|
review: "accepted",
|
|
accepted: "delivered",
|
|
};
|
|
|
|
/**
|
|
* Server-renderad action-resolution för advance-steget (ADR-0001):
|
|
* ägarskapenforces redan av requireOrderOwner på GET/PATCH; tillståndet
|
|
* avgör read_only. Innan Session/roller finns i 0pt är permission alltid
|
|
* granted för autentiserade ägare — hårdkoda aldrig denna resolve i klienten.
|
|
*/
|
|
export function resolveAdvanceAction(status: string): ResolvedAction {
|
|
if (NEXT_STATUS[status]) {
|
|
return resolveAction({ permission: "granted", entitlement: "active", approval: "not_required", readOnly: false });
|
|
}
|
|
return resolveAction({ permission: "granted", entitlement: "active", approval: "not_required", readOnly: true });
|
|
}
|
|
|
|
/** Orderstatus som utgör en inkorgspost (våg 3.3: orders kö = inbox). */
|
|
const INBOX_ELIGIBLE: Record<string, { kind: "task" | "approval"; priority: "normal" | "high" }> = {
|
|
draft: { kind: "task", priority: "normal" },
|
|
quoted: { kind: "task", priority: "normal" },
|
|
in_production: { kind: "task", priority: "normal" },
|
|
review: { kind: "approval", priority: "high" },
|
|
};
|
|
|
|
/**
|
|
* Server-renderad inkorgspost (ADR-0001-mönstret): en order som väntar på
|
|
* nästa steg projiceras på universal-inbox-konvolverna. Terminala statusar
|
|
* (delivered m.fl.) ger ingen post — inboxen är öppna arbetsobjekt.
|
|
*/
|
|
export function buildOrderInboxItem(order: {
|
|
order_id: string;
|
|
status: string;
|
|
flow: string;
|
|
total_ore?: number | null;
|
|
}): InboxItem | null {
|
|
const eligible = INBOX_ELIGIBLE[order.status];
|
|
if (!eligible) return null;
|
|
return createInboxItem({
|
|
id: `order:${order.order_id}`,
|
|
kind: eligible.kind,
|
|
tenantId: "0pt",
|
|
subject: `Order ${order.order_id.slice(0, 8)} — ${order.status} → ${NEXT_STATUS[order.status] ?? "nästa steg"}`,
|
|
priority: eligible.priority,
|
|
createdAt: new Date().toISOString(),
|
|
source: { system: "0pt", channel: "order-queue" },
|
|
entity: { type: "order", id: order.order_id },
|
|
actions: NEXT_STATUS[order.status]
|
|
? [{ id: "advance", label: `→ ${NEXT_STATUS[order.status]}` }]
|
|
: undefined,
|
|
});
|
|
}
|