import { formatFrappeApiError } from '../utils/frappeErrorMessage'; const RESOURCE = 'Purchase%20Order'; export interface PurchaseOrderItem { name?: string; item_code?: string; item_name?: string; description?: string; qty?: number; rate?: number; amount?: number; uom?: string; idx?: number; [key: string]: any; } export interface PurchaseTaxCharge { name?: string; charge_type?: string; account_head?: string; tax_amount?: number; rate?: number; idx?: number; [key: string]: any; } export interface PurchaseOrder { name: string; docstatus?: number; status?: string; supplier?: string; supplier_name?: string; transaction_date?: string; schedule_date?: string; company?: string; currency?: string; grand_total?: number; net_total?: number; total_taxes_and_charges?: number; items?: PurchaseOrderItem[]; taxes?: PurchaseTaxCharge[]; owner?: string; creation?: string; modified?: string; [key: string]: any; } class PurchaseOrderService { private async getCSRFToken(): Promise { if (typeof window === 'undefined') return null; if ((window as any).csrf_token) return (window as any).csrf_token; if ((window as any).frappe?.csrf_token) return (window as any).frappe.csrf_token; try { const res = await fetch('/api/method/frappe.sessions.get_csrf_token', { credentials: 'include' }); if (res.ok) { const json = await res.json(); if (json.message) { (window as any).csrf_token = json.message; return json.message; } } } catch { /* ignore */ } return null; } private async getHeaders(): Promise> { const h: Record = { 'Content-Type': 'application/json', Accept: 'application/json' }; const csrf = await this.getCSRFToken(); if (csrf) h['X-Frappe-CSRF-Token'] = csrf; return h; } private async fetchJson(url: string, opts: RequestInit = {}): Promise { const headers = await this.getHeaders(); const r = await fetch(url, { credentials: 'include', headers, ...opts }); const body = await r.json().catch(() => ({})); if (!r.ok) throw new Error(formatFrappeApiError(body) || body?.message || `HTTP ${r.status}`); if (body.exc) throw new Error(formatFrappeApiError(body) || 'Request failed'); return body; } async getPurchaseOrders( params: { filters?: any[]; limit_start?: number; limit_page_length?: number; order_by?: string } = {}, ): Promise { const q = new URLSearchParams(); const fields = [ 'name', 'supplier', 'supplier_name', 'transaction_date', 'schedule_date', 'status', 'grand_total', 'currency', 'docstatus', 'company', 'creation', 'modified', ]; q.set('fields', JSON.stringify(fields)); if (params.filters?.length) q.set('filters', JSON.stringify(params.filters)); q.set('limit_start', String(params.limit_start ?? 0)); q.set('limit_page_length', String(params.limit_page_length ?? 20)); q.set('order_by', params.order_by ?? 'creation desc'); const body = await this.fetchJson(`/api/resource/${RESOURCE}?${q}`); return body.data || []; } async getPurchaseOrderCount(filters: any[] = []): Promise { const q = new URLSearchParams(); q.set('fields', JSON.stringify(['count(name) as count'])); if (filters.length) q.set('filters', JSON.stringify(filters)); try { const body = await this.fetchJson(`/api/resource/${RESOURCE}?${q}`); return body.data?.[0]?.count ?? 0; } catch { return 0; } } async getPurchaseOrder(name: string): Promise { const body = await this.fetchJson(`/api/resource/${RESOURCE}/${encodeURIComponent(name)}`); return body.data; } async createPurchaseOrder(data: Partial): Promise { const body = await this.fetchJson(`/api/resource/${RESOURCE}`, { method: 'POST', body: JSON.stringify(data), }); return body.data; } async updatePurchaseOrder(name: string, data: Partial): Promise { const body = await this.fetchJson(`/api/resource/${RESOURCE}/${encodeURIComponent(name)}`, { method: 'PUT', body: JSON.stringify(data), }); return body.data; } async submitPurchaseOrder(name: string): Promise { const body = await this.fetchJson(`/api/resource/${RESOURCE}/${encodeURIComponent(name)}`, { method: 'PUT', body: JSON.stringify({ docstatus: 1 }), }); return body.data; } } const purchaseOrderService = new PurchaseOrderService(); export default purchaseOrderService;