// ── ERPNext Dispatch resource calls ───────────────────────────────────────── // All ERPNext fetch() calls live here. // Swap BASE_URL in config/erpnext.js to change the target server. // ───────────────────────────────────────────────────────────────────────────── import { BASE_URL } from 'src/config/erpnext' import { authFetch } from './auth' async function apiGet (path) { const res = await authFetch(BASE_URL + path) const data = await res.json() if (data.exc) throw new Error(data.exc) return data } async function apiPut (doctype, name, body) { const res = await authFetch( `${BASE_URL}/api/resource/${encodeURIComponent(doctype)}/${encodeURIComponent(name)}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body), }, ) if (!res.ok) console.error(`[API] PUT ${doctype}/${name} failed:`, res.status, await res.text().catch(() => '')) const data = await res.json() if (data.exc) throw new Error(data.exc) return data } export async function fetchTechnicians () { const list = await apiGet('/api/resource/Dispatch%20Technician?fields=["name"]&limit=100') const names = (list.data || []).map(t => t.name) if (!names.length) return [] const docs = await Promise.all( names.map(n => apiGet(`/api/resource/Dispatch%20Technician/${encodeURIComponent(n)}`).then(d => d.data)) ) return docs } // Fetch all jobs with child tables (assistants) export async function fetchJobs (filters = null) { // Step 1: get job names from list endpoint let url = '/api/resource/Dispatch%20Job?fields=["name"]&limit=200' if (filters) url += '&filters=' + encodeURIComponent(JSON.stringify(filters)) const list = await apiGet(url) const names = (list.data || []).map(j => j.name) if (!names.length) return [] // Step 2: fetch each doc individually (includes child tables) const docs = await Promise.all( names.map(n => apiGet(`/api/resource/Dispatch%20Job/${encodeURIComponent(n)}`).then(d => d.data)) ) return docs } export async function updateJob (name, payload) { return apiPut('Dispatch Job', name, payload) } export async function createJob (payload) { const res = await authFetch( `${BASE_URL}/api/resource/Dispatch%20Job`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload), }, ) const data = await res.json() if (data.exc) throw new Error(data.exc) return data.data } export async function updateTech (name, payload) { return apiPut('Dispatch Technician', name, payload) } export async function createTech (payload) { const res = await authFetch( `${BASE_URL}/api/resource/Dispatch%20Technician`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }, ) const data = await res.json() if (data.exc) throw new Error(data.exc) return data.data } export async function deleteTech (name) { const res = await authFetch( `${BASE_URL}/api/resource/Dispatch%20Technician/${encodeURIComponent(name)}`, { method: 'DELETE' }, ) if (!res.ok) { const data = await res.json().catch(() => ({})) const msg = data._server_messages ? JSON.parse(JSON.parse(data._server_messages)[0]).message : data.exception || 'Delete failed' throw new Error(msg) } } export async function fetchTags () { const data = await apiGet('/api/resource/Dispatch%20Tag?fields=["name","label","color","category"]&limit=200') return data.data || [] } export async function createTag (label, category = 'Custom', color = '#6b7280') { const res = await authFetch( `${BASE_URL}/api/resource/Dispatch%20Tag`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ label, category, color }), }, ) const data = await res.json() if (data.exc) throw new Error(data.exc) return data.data }