import { queryOptions } from "@tanstack/react-query"; import { jsonQuery, paginatedJsonQuery } from "../apiAdapter"; // Single shared definition (type-only import, erased at compile time) — the // canonical CurrencyAmount lives in offers.ts; re-exported here so existing // importers keep working. import type { CurrencyAmount } from "./offers"; export type { CurrencyAmount }; export interface IssuedOrder { id: number; po_number: string | null; supplier_id: number | null; supplier_name: string | null; status: string; currency: string | null; order_date: string | null; // NET total — issued orders carry no VAT (not tax documents). total: number; } /** Active supplier row from the lightweight PO-picker lookup endpoint. */ export interface Supplier { id: number; name: string; ico: string | null; dic: string | null; street: string | null; city: string | null; postal_code: string | null; country: string | null; } export interface IssuedOrderItem { id?: number; description: string | null; item_description: string | null; quantity: number | string | null; unit: string | null; unit_price: number | string | null; position?: number; } /** Rich-text CZ/EN PDF section (mirrors offers' scope sections). */ export interface IssuedOrderSection { id?: number; title: string | null; title_cz: string | null; content: string | null; position?: number; } export interface IssuedOrderDetail extends IssuedOrder { exchange_rate: number | string | null; delivery_date: string | null; language: string | null; order_text: string | null; internal_notes: string | null; items: IssuedOrderItem[]; sections: IssuedOrderSection[]; supplier: Record | null; valid_transitions: string[]; /** Fresh edit lock held by ANOTHER user (same shape as offers), else null. */ locked_by: { user_id: number; username: string; full_name: string; } | null; } // Suppliers lookup for the PO supplier picker — hits the issued-orders-scoped // endpoint (orders permissions), NOT the warehouse.manage-guarded CRUD list. export const issuedOrderSuppliersOptions = () => queryOptions({ queryKey: ["issued-orders", "suppliers"], queryFn: () => jsonQuery("/api/admin/issued-orders/suppliers"), staleTime: 2 * 60_000, }); export const issuedOrderListOptions = (filters: { search?: string; sort?: string; order?: string; page?: number; perPage?: number; status?: string; supplier_id?: number; month?: number; year?: number; }) => queryOptions({ queryKey: ["issued-orders", "list", filters], queryFn: () => { const params = new URLSearchParams(); if (filters.search) params.set("search", filters.search); if (filters.sort) params.set("sort", filters.sort); if (filters.order) params.set("order", filters.order); if (filters.page) params.set("page", String(filters.page)); if (filters.perPage) params.set("per_page", String(filters.perPage)); if (filters.status) params.set("status", filters.status); if (filters.supplier_id) params.set("supplier_id", String(filters.supplier_id)); if (filters.month) params.set("month", String(filters.month)); if (filters.year) params.set("year", String(filters.year)); const qs = params.toString(); return paginatedJsonQuery( `/api/admin/issued-orders${qs ? `?${qs}` : ""}`, ); }, }); export const issuedOrderStatsOptions = (filters: { search?: string; status?: string; supplier_id?: number; month?: number; year?: number; }) => queryOptions({ queryKey: ["issued-orders", "stats", filters], queryFn: async () => { const params = new URLSearchParams(); if (filters.search) params.set("search", filters.search); if (filters.status) params.set("status", filters.status); if (filters.supplier_id) params.set("supplier_id", String(filters.supplier_id)); if (filters.month) params.set("month", String(filters.month)); if (filters.year) params.set("year", String(filters.year)); const qs = params.toString(); const data = await jsonQuery<{ totals?: CurrencyAmount[] }>( `/api/admin/issued-orders/stats${qs ? `?${qs}` : ""}`, ); return data.totals ?? []; }, }); export const issuedOrderDetailOptions = (id: string | undefined) => queryOptions({ queryKey: ["issued-orders", id], queryFn: () => jsonQuery(`/api/admin/issued-orders/${id}`), enabled: !!id, // 404s (deleted/missing orders) are not transient. Retrying just spams // GETs and keeps the detail page on an infinite spinner. retry: false, }); export const issuedOrderNextNumberOptions = () => queryOptions({ queryKey: ["issued-orders", "next-number"], queryFn: () => jsonQuery<{ next_number?: string; number?: string }>( "/api/admin/issued-orders/next-number", ).then((d) => d?.next_number || d?.number || ""), });