from fastapi import APIRouter, Query from datetime import date from app.core.database import get_connection router = APIRouter(prefix="/cash", tags=["资金"]) # ※ 临时方案:资金系科目(现金 / 银行) CASH_ACCOUNT_IDS = [101, 102] # ------------------------- # 资金余额 # ------------------------- @router.get("/balance", summary="资金余额取得") def get_cash_balance(): """ 取得当前资金余额(现金・银行) """ with get_connection() as conn, conn.cursor() as cur: cur.execute(""" SELECT a.account_id, a.account_name, COALESCE(SUM(l.debit), 0) - COALESCE(SUM(l.credit), 0) AS balance FROM accounts a LEFT JOIN journal_lines l ON l.account_id = a.account_id LEFT JOIN journal_entries e ON e.journal_id = l.journal_id AND e.is_deleted = false WHERE a.account_id = ANY(%s) GROUP BY a.account_id, a.account_name ORDER BY a.account_id """, (CASH_ACCOUNT_IDS,)) rows = cur.fetchall() total = sum(r["balance"] for r in rows) return { "items": rows, "total_balance": total } # ------------------------- # 资金流水 # ------------------------- @router.get("/transactions", summary="资金流水取得") def get_cash_transactions( account_id: int = Query(..., description="资金账户ID"), from_date: date | None = Query(None, alias="from"), to_date: date | None = Query(None, alias="to"), ): """ 指定资金账户的资金流水 """ with get_connection() as conn, conn.cursor() as cur: sql = """ SELECT e.journal_date, e.description, l.debit, l.credit, COALESCE(a2.account_name, '(未指定)') AS counter_account FROM journal_lines l JOIN journal_entries e ON e.journal_id = l.journal_id LEFT JOIN journal_lines l2 ON l2.journal_id = l.journal_id AND l2.account_id <> l.account_id LEFT JOIN accounts a2 ON a2.account_id = l2.account_id WHERE l.account_id = %s AND e.is_deleted = false """ params = [account_id] if from_date: sql += " AND e.journal_date >= %s" params.append(from_date) if to_date: sql += " AND e.journal_date <= %s" params.append(to_date) sql += " ORDER BY e.journal_date, e.journal_id" cur.execute(sql, params) rows = cur.fetchall() result = [] for r in rows: amount = r["debit"] - r["credit"] result.append({ "journal_date": r["journal_date"], "description": r["description"], "counter_account": r["counter_account"], "amount": amount, "direction": "in" if amount > 0 else "out" if amount < 0 else "none", }) return result