/** * Клиент для общения с HotelSync Agent на localhost:9000 * Все кассовые операции идут напрямую через агент, минуя сервер */ const AGENT_URL = 'http://localhost:9000' const TIMEOUT = 30000 // 30 секунд для кассовых операций async function agentReq( method: 'GET' | 'POST', path: string, body?: object, timeout = TIMEOUT, ): Promise { const res = await fetch(`${AGENT_URL}${path}`, { method, headers: body ? { 'Content-Type': 'application/json' } : undefined, body: body ? JSON.stringify(body) : undefined, signal: AbortSignal.timeout(timeout), }) return res.json() as Promise } // ── Типы ────────────────────────────────────────────────────────────────────── export interface AgentIdentity { agent_id: string workstation_id: string workstation_name: string hostname: string error?: string } export interface ShiftStatus { state: 'closed' | 'open' | 'expired' shift_number: number opened_at?: string duration_min?: number cash_sum?: number receipt_count?: number cashier_name?: string } export interface KktInfo { serial_number: string model: string fn_number: string fn_expires_at?: string ofd_status: 'ok' | 'error' | 'no_connection' version: string } export interface KktStatus { shift?: ShiftStatus info?: KktInfo dto_connected: boolean dto_version?: string } export interface CashierInfo { name: string inn?: string } export interface ReceiptItem { name: string quantity: number price: number vat?: 'none' | 'vat0' | 'vat10' | 'vat20' payment_object?: 'commodity' | 'service' } export interface ReceiptData { type: 'sell' | 'sell_return' items: ReceiptItem[] total: number payment_type: 'cash' | 'card' | 'prepaid' cashier?: CashierInfo customer_email?: string customer_phone?: string tax_system?: number } export interface AgentResult { ok: boolean error?: string receipt_number?: string fiscal_sign?: string shift_number?: number } // ── API ─────────────────────────────────────────────────────────────────────── /** Проверяет что агент запущен и возвращает рабочее место. Timeout 500ms. */ export async function getIdentity(): Promise { try { const data = await agentReq('GET', '/identity', undefined, 500) if (data.error) return null return data } catch { return null } } export const kkt = { status: () => agentReq('GET', '/kkt/status', undefined, 5000), openShift: (cashier: CashierInfo, tax_system = 1) => agentReq('POST', '/kkt/shift/open', { cashier, tax_system }), closeShift: (cashier: CashierInfo) => agentReq('POST', '/kkt/shift/close', { cashier }), xReport: () => agentReq('POST', '/kkt/report/x', {}), cashIn: (amount: number, cashier: CashierInfo) => agentReq('POST', '/kkt/cash-in', { amount, cashier }), cashOut: (amount: number, cashier: CashierInfo) => agentReq('POST', '/kkt/cash-out', { amount, cashier }), printReceipt: (data: ReceiptData) => agentReq('POST', '/kkt/receipt', data), printReturn: (data: ReceiptData) => agentReq('POST', '/kkt/return', data), }