import { TradeOrder, OrderType, MarketType, AutoTradeConfig, WatchlistGroup, ReservedOrder, StockTick } from '../types'; import { API_BASE_URL, getHeaders } from './config'; export interface HoldingItem { code: string; name: string; avgPrice: number; quantity: number; market: MarketType; currentPrice: number; // Added profit: number; // Added profitRate: number; // Added } export class DbService { constructor() {} // --- Holdings --- async getHoldings(): Promise { try { const res = await fetch(`${API_BASE_URL}/account/holdings`); if (!res.ok) return []; const data = await res.json(); // Map API response to HoldingItem // API returns: { stockCode, stockName, quantity, avgPrice, currentPrice, profit, profitRate } return data.map((h: any) => ({ code: h.stockCode, name: h.stockName, avgPrice: h.avgPrice, quantity: h.quantity, market: h.stockCode.length > 6 ? MarketType.OVERSEAS : MarketType.DOMESTIC, currentPrice: h.currentPrice, profit: h.profit, profitRate: h.profitRate })); } catch (e) { console.error("Failed to fetch holdings", e); return []; } } async getAccountSummary() { try { const res = await fetch(`${API_BASE_URL}/account/balance?market=Domestic`); // Default if (!res.ok) return { totalAssets: 0, buyingPower: 0 }; const data = await res.json(); // API returns complex object. We might need to simplify or use /account/summary if exists. // Or calculate from holdings + cash? // Using a simplified assumption or endpoints. // Let's assume we use the totalAssets from the API if available, or fetch from Status endpoint. // Actually, we verified /account/balance returns KIS raw data. // We should implemented a summary endpoint or parse raw data. // For now, let's return a basic structure. return { totalAssets: parseFloat(data.output2?.tot_evlu_amt || "0"), buyingPower: parseFloat(data.output2?.dnca_tot_amt || "0") }; } catch (e) { return { totalAssets: 0, buyingPower: 0 }; } } // --- Reserved Orders --- async getReservedOrders(): Promise { const res = await fetch(`${API_BASE_URL}/reserved-orders`); if (!res.ok) return []; return await res.json(); } async saveReservedOrder(order: ReservedOrder) { // POST // Map Frontend Order to Backend Request const payload = { stockCode: order.stockCode, stockName: order.stockName, monitoringType: order.monitoringType, triggerPrice: order.triggerPrice, orderType: order.type, quantity: order.quantity, price: order.price || 0, trailingType: order.trailingType, trailingValue: order.trailingValue, stopLossValue: order.stopLossValue }; const res = await fetch(`${API_BASE_URL}/reserved-orders`, { method: 'POST', headers: getHeaders(), body: JSON.stringify(payload) }); return await res.json(); } async deleteReservedOrder(id: string) { await fetch(`${API_BASE_URL}/reserved-orders/${id}`, { method: 'DELETE' }); } // --- Auto Trade Configs --- async getAutoConfigs(): Promise { const res = await fetch(`${API_BASE_URL}/auto-trade/configs`); if (!res.ok) return []; return await res.json(); } async saveAutoConfig(config: AutoTradeConfig) { await fetch(`${API_BASE_URL}/auto-trade/configs`, { method: 'POST', headers: getHeaders(), body: JSON.stringify(config) }); } async deleteAutoConfig(id: string) { await fetch(`${API_BASE_URL}/auto-trade/configs/${id}`, { method: 'DELETE' }); } // --- Watchlist Groups --- async getWatchlistGroups(): Promise { const res = await fetch(`${API_BASE_URL}/watchlists/groups`); if (!res.ok) return []; return await res.json(); } // --- Ticks (Optional, might be local only or via API) --- // If backend doesn't support generic tick history per session, keep local or ignore. async saveStockTick(tick: StockTick) { // No-op or keep local? // Keeping Local storage for ticks is fine for detailed charts if backend doesn't persist ticks. // Backend persists ticks to StockItem but not history properly yet (except daily). } async getStockTicks(code: string): Promise { return []; } // Helpers not needed with real API usually async syncOrderToHolding(order: TradeOrder) { // Refresh holdings from server instead of calculating return await this.getHoldings(); } // Write-only wrappers async updateWatchlistGroup(group: WatchlistGroup) { // Use PUT if available or POST } async saveWatchlistGroup(group: WatchlistGroup) { // POST } async deleteWatchlistGroup(id: string) { // DELETE } }