# backend/app/modules/opening_balances/router.py from fastapi import APIRouter, HTTPException from psycopg.errors import ForeignKeyViolation from app.core.database import get_connection from app.modules.opening_balances.schema import OpeningBalanceCreate router = APIRouter( prefix="/opening-balances", tags=["期首残高"] ) @router.post("/", summary="期首残高 登録/更新") def upsert_opening_balance(data: OpeningBalanceCreate): try: with get_connection() as conn, conn.cursor() as cur: cur.execute(""" INSERT INTO opening_balances (fiscal_year, account_id, opening_debit, opening_credit) VALUES (%s, %s, %s, %s) ON CONFLICT (fiscal_year, account_id) DO UPDATE SET opening_debit = EXCLUDED.opening_debit, opening_credit = EXCLUDED.opening_credit """, ( data.fiscal_year, data.account_id, data.opening_debit, data.opening_credit )) conn.commit() return {"result": "ok"} except ForeignKeyViolation: raise HTTPException( status_code=400, detail="存在しない科目が指定されています" ) @router.get("/{fiscal_year}", summary="期首残高一覧取得") def list_opening_balances(fiscal_year: int): with get_connection() as conn, conn.cursor() as cur: cur.execute(""" SELECT a.account_code, a.account_name, a.account_type, ob.opening_debit, ob.opening_credit FROM opening_balances ob JOIN accounts a ON a.account_id = ob.account_id WHERE ob.fiscal_year = %s ORDER BY a.account_code """, (fiscal_year,)) return cur.fetchall()