diff --git a/src/lib/server/order-item-context-service.ts b/src/lib/server/order-item-context-service.ts new file mode 100644 index 0000000..07c105a --- /dev/null +++ b/src/lib/server/order-item-context-service.ts @@ -0,0 +1,101 @@ +/** + * order-item-context-service — deterministic SKU-based context for + * the order-sprint process modal + orders detail page. + * + * Mirrors the shape of `item-history-service.ts` but is anchored on + * `order_items.id` instead of `quote_items.id`. The four rows + * surfaced (last quote, last order, last invoiced, stock) plus a + * supplier/cheapest aggregate give the operator the historical + * record before they pick a supplier and cost. + * + * Pure helpers (`normaliseSkuForHistory`, `findBestDescriptionMatch`, + * `aggregateSuppliers`, `computeCheapest`, `daysAgo`, `isValidPrice`) + * are imported from `item-history-service.ts` — DO NOT duplicate them. + */ + +import { getAdminPocketBase } from "@/lib/server/pocketbase-admin"; +import { + normaliseSkuForHistory, + findBestDescriptionMatch, + aggregateSuppliers, + computeCheapest, + daysAgo, + isValidPrice, +} from "@/lib/server/item-history-service"; +import type { + ItemHistoryMatch, + ItemHistorySupplier, + ItemHistoryCheapest, +} from "@/lib/types"; + +export interface OrderItemLastQuote { + quote_item_id: string; + quote_id: string; + quote_number: string; + customer_name: string; + company: string; + status: string; + cost_price: number; + selling_price: number; + markup_percent: number; + days_ago: number; +} + +export interface OrderItemLastOrder { + order_item_id: string; + order_id: string; + order_number: string; + company: string; + cost_price: number; + selling_price: number; + markup_percent: number; + item_status: string; + updated_at: string; + days_ago: number; +} + +export interface OrderItemLastInvoiced { + order_item_id: string; + order_id: string; + order_number: string; + supplier_invoice_number: string; + customer_invoice_number: string; + invoiced_date: string; + cost_price: number; + quantity: number; + qty_invoiced: number; + days_ago: number; +} + +export interface OrderItemStock { + stock_item_id: string; + name: string; + sku: string; + current_qty: number; + min_qty: number | null; + selling_price: number | null; + markup_percent: number | null; + status: "in_stock" | "low" | "out"; +} + +export interface OrderItemContext { + generated_at: string; + match: ItemHistoryMatch; + last_quote: OrderItemLastQuote | null; + last_order: OrderItemLastOrder | null; + last_invoiced: OrderItemLastInvoiced | null; + stock: OrderItemStock | null; + suppliers: ItemHistorySupplier[]; + cheapest: ItemHistoryCheapest | null; +} + +export interface OrderItemContextResponse extends OrderItemContext { + error?: string; +} + +export async function getOrderItemContext( + orderItemId: string, +): Promise { + // Implementation lands in Task 2. + throw new Error("not implemented"); +}