Seera-Unified-UI/asm_app/src/services/purchaseOrderService.ts

144 lines
4.6 KiB
TypeScript

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<string | null> {
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<Record<string, string>> {
const h: Record<string, string> = { '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<any> {
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<PurchaseOrder[]> {
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<number> {
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<PurchaseOrder> {
const body = await this.fetchJson(`/api/resource/${RESOURCE}/${encodeURIComponent(name)}`);
return body.data;
}
async createPurchaseOrder(data: Partial<PurchaseOrder>): Promise<PurchaseOrder> {
const body = await this.fetchJson(`/api/resource/${RESOURCE}`, {
method: 'POST',
body: JSON.stringify(data),
});
return body.data;
}
async updatePurchaseOrder(name: string, data: Partial<PurchaseOrder>): Promise<PurchaseOrder> {
const body = await this.fetchJson(`/api/resource/${RESOURCE}/${encodeURIComponent(name)}`, {
method: 'PUT',
body: JSON.stringify(data),
});
return body.data;
}
async submitPurchaseOrder(name: string): Promise<PurchaseOrder> {
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;