import { getDb } from "@/lib/db"; import type { AccountBalanceRow, AccountRow, ContactRow, DashboardStats, InvoiceRow, JournalEntryRow, KitRow, LowStockRow, PartRow, PurchaseOrderListRow, SalesOrderListRow, VendorBillRow } from "@/lib/types"; function db() { return getDb(); } export function getDashboardStats(): DashboardStats { const row = db() .prepare( ` SELECT (SELECT COUNT(*) FROM parts WHERE kind = 'part') AS total_parts, (SELECT COUNT(*) FROM parts WHERE kind = 'assembly') AS total_assemblies, (SELECT COUNT(*) FROM customers) AS active_customers, (SELECT COUNT(*) FROM vendors) AS active_vendors, (SELECT COUNT(*) FROM sales_orders WHERE status IN ('draft', 'open', 'partial')) AS open_sales_orders, (SELECT COUNT(*) FROM purchase_orders WHERE status IN ('draft', 'ordered', 'partial')) AS open_purchase_orders, (SELECT COUNT(*) FROM customer_invoices WHERE status IN ('open', 'partial')) AS open_invoices, (SELECT COUNT(*) FROM vendor_bills WHERE status IN ('open', 'partial')) AS open_vendor_bills, ( SELECT COUNT(*) FROM parts p LEFT JOIN inventory_balances ib ON ib.part_id = p.id WHERE ib.quantity_on_hand <= p.reorder_point ) AS low_stock_count, ( SELECT COALESCE(SUM(ib.quantity_on_hand * p.unit_cost), 0) FROM parts p LEFT JOIN inventory_balances ib ON ib.part_id = p.id ) AS inventory_value, ( SELECT COALESCE(SUM(total_amount - paid_amount), 0) FROM customer_invoices WHERE status IN ('open', 'partial') ) AS accounts_receivable, ( SELECT COALESCE(SUM(total_amount - paid_amount), 0) FROM vendor_bills WHERE status IN ('open', 'partial') ) AS accounts_payable ` ) .get() as Record; return { totalParts: row.total_parts ?? 0, totalAssemblies: row.total_assemblies ?? 0, activeCustomers: row.active_customers ?? 0, activeVendors: row.active_vendors ?? 0, openSalesOrders: row.open_sales_orders ?? 0, openPurchaseOrders: row.open_purchase_orders ?? 0, openInvoices: row.open_invoices ?? 0, openVendorBills: row.open_vendor_bills ?? 0, lowStockCount: row.low_stock_count ?? 0, inventoryValue: row.inventory_value ?? 0, accountsReceivable: row.accounts_receivable ?? 0, accountsPayable: row.accounts_payable ?? 0 }; } export function getParts(): PartRow[] { return db() .prepare( ` SELECT p.id, p.sku, p.name, p.kind, p.unit_cost AS unitCost, p.sale_price AS salePrice, p.reorder_point AS reorderPoint, p.unit_of_measure AS unitOfMeasure, COALESCE(ib.quantity_on_hand, 0) AS quantityOnHand FROM parts p LEFT JOIN inventory_balances ib ON ib.part_id = p.id ORDER BY p.kind DESC, p.sku ASC ` ) .all() as PartRow[]; } export function getAssembliesWithComponents(): KitRow[] { return db() .prepare( ` SELECT a.sku AS assemblySku, a.name AS assemblyName, c.sku AS componentSku, c.name AS componentName, kc.quantity FROM kit_components kc INNER JOIN parts a ON a.id = kc.assembly_part_id INNER JOIN parts c ON c.id = kc.component_part_id ORDER BY a.sku, c.sku ` ) .all() as KitRow[]; } export function getCustomers(): ContactRow[] { return db().prepare(`SELECT id, code, name, email, phone FROM customers ORDER BY code`).all() as ContactRow[]; } export function getVendors(): ContactRow[] { return db().prepare(`SELECT id, code, name, email, phone FROM vendors ORDER BY code`).all() as ContactRow[]; } export function getSalesOrders(): SalesOrderListRow[] { return db() .prepare( ` SELECT so.id, so.order_number AS orderNumber, c.name AS customerName, so.status, so.created_at AS createdAt, COALESCE(SUM(sol.quantity * sol.unit_price), 0) AS totalAmount, COALESCE(SUM(sol.quantity), 0) AS orderedQuantity, COALESCE(SUM(sol.shipped_quantity), 0) AS fulfilledQuantity FROM sales_orders so INNER JOIN customers c ON c.id = so.customer_id LEFT JOIN sales_order_lines sol ON sol.sales_order_id = so.id GROUP BY so.id, so.order_number, c.name, so.status, so.created_at ORDER BY so.created_at DESC ` ) .all() as SalesOrderListRow[]; } export function getPurchaseOrders(): PurchaseOrderListRow[] { return db() .prepare( ` SELECT po.id, po.order_number AS orderNumber, v.name AS vendorName, po.status, po.created_at AS createdAt, COALESCE(SUM(pol.quantity * pol.unit_cost), 0) AS totalAmount, COALESCE(SUM(pol.quantity), 0) AS orderedQuantity, COALESCE(SUM(pol.received_quantity), 0) AS fulfilledQuantity FROM purchase_orders po INNER JOIN vendors v ON v.id = po.vendor_id LEFT JOIN purchase_order_lines pol ON pol.purchase_order_id = po.id GROUP BY po.id, po.order_number, v.name, po.status, po.created_at ORDER BY po.created_at DESC ` ) .all() as PurchaseOrderListRow[]; } export function getJournalEntries(): JournalEntryRow[] { const entries = db() .prepare( ` SELECT id, entry_type AS entryType, reference_type AS referenceType, reference_id AS referenceId, description, created_at AS createdAt FROM journal_entries ORDER BY created_at DESC, id DESC ` ) .all() as Array>; const lineStatement = db().prepare( ` SELECT account_code AS accountCode, account_name AS accountName, debit, credit FROM journal_lines WHERE journal_entry_id = ? ORDER BY id ` ); return entries.map((entry) => ({ ...entry, lines: lineStatement.all(entry.id) as JournalEntryRow["lines"] })); } export function getInvoices(): InvoiceRow[] { return db() .prepare( ` SELECT ci.id, ci.invoice_number AS invoiceNumber, ci.sales_order_id AS salesOrderId, c.name AS customerName, ci.status, ci.invoice_date AS invoiceDate, ci.due_date AS dueDate, ci.total_amount AS totalAmount, ci.paid_amount AS paidAmount, ci.total_amount - ci.paid_amount AS balanceDue FROM customer_invoices ci INNER JOIN customers c ON c.id = ci.customer_id ORDER BY ci.invoice_date DESC, ci.id DESC ` ) .all() as InvoiceRow[]; } export function getVendorBills(): VendorBillRow[] { return db() .prepare( ` SELECT vb.id, vb.bill_number AS billNumber, vb.purchase_order_id AS purchaseOrderId, v.name AS vendorName, vb.status, vb.bill_date AS billDate, vb.due_date AS dueDate, vb.total_amount AS totalAmount, vb.paid_amount AS paidAmount, vb.total_amount - vb.paid_amount AS balanceDue FROM vendor_bills vb INNER JOIN vendors v ON v.id = vb.vendor_id ORDER BY vb.bill_date DESC, vb.id DESC ` ) .all() as VendorBillRow[]; } export function getAccounts(): AccountRow[] { return db() .prepare( ` SELECT code, name, category, is_system AS isSystem FROM accounts ORDER BY code ` ) .all() as AccountRow[]; } export function getAccountBalances(): AccountBalanceRow[] { return db() .prepare( ` SELECT a.code, a.name, a.category, COALESCE(SUM(jl.debit), 0) AS debitTotal, COALESCE(SUM(jl.credit), 0) AS creditTotal, CASE WHEN a.category IN ('asset', 'expense') THEN COALESCE(SUM(jl.debit), 0) - COALESCE(SUM(jl.credit), 0) ELSE COALESCE(SUM(jl.credit), 0) - COALESCE(SUM(jl.debit), 0) END AS balance FROM accounts a LEFT JOIN journal_lines jl ON jl.account_code = a.code GROUP BY a.code, a.name, a.category ORDER BY a.code ` ) .all() as AccountBalanceRow[]; } export function getLowStockParts(): LowStockRow[] { return db() .prepare( ` SELECT p.id, p.sku, p.name, p.unit_of_measure AS unitOfMeasure, COALESCE(ib.quantity_on_hand, 0) AS quantityOnHand, p.reorder_point AS reorderPoint, MAX(p.reorder_point - COALESCE(ib.quantity_on_hand, 0), 0) AS suggestedReorderQuantity, ( SELECT v.name FROM purchase_order_lines pol INNER JOIN purchase_orders po ON po.id = pol.purchase_order_id INNER JOIN vendors v ON v.id = po.vendor_id WHERE pol.part_id = p.id ORDER BY po.created_at DESC LIMIT 1 ) AS preferredVendorName FROM parts p LEFT JOIN inventory_balances ib ON ib.part_id = p.id WHERE p.kind = 'part' AND COALESCE(ib.quantity_on_hand, 0) <= p.reorder_point ORDER BY suggestedReorderQuantity DESC, p.sku ASC ` ) .all() as LowStockRow[]; }