108 lines
3.2 KiB
Python
108 lines
3.2 KiB
Python
from fastapi import APIRouter, HTTPException, Query
|
||
from decimal import Decimal
|
||
from app.core.database import get_connection
|
||
|
||
router = APIRouter(
|
||
prefix="/general-ledger",
|
||
tags=["元帳"]
|
||
)
|
||
|
||
|
||
def D(x) -> Decimal:
|
||
return Decimal(str(x or 0))
|
||
|
||
|
||
@router.get("", summary="元帳取得(期首残高対応)")
|
||
def get_general_ledger(
|
||
account_id: int = Query(..., description="科目ID"),
|
||
fiscal_year: int = Query(..., description="会計年度(例:2025)"),
|
||
date_from: str = Query(..., description="YYYY-MM-DD"),
|
||
date_to: str = Query(..., description="YYYY-MM-DD"),
|
||
):
|
||
if date_from > date_to:
|
||
raise HTTPException(status_code=400, detail="期間指定が不正です。")
|
||
|
||
with get_connection() as conn, conn.cursor() as cur:
|
||
|
||
# ----------------------------
|
||
# 科目存在確認
|
||
# ----------------------------
|
||
cur.execute("""
|
||
SELECT account_code, account_name
|
||
FROM accounts
|
||
WHERE account_id = %s
|
||
AND is_active = true
|
||
""", (account_id,))
|
||
acc = cur.fetchone()
|
||
|
||
if not acc:
|
||
raise HTTPException(status_code=400, detail="指定された科目は存在しません。")
|
||
|
||
# ----------------------------
|
||
# 期首残高(opening_balances)
|
||
# ----------------------------
|
||
cur.execute("""
|
||
SELECT
|
||
COALESCE(opening_debit, 0) - COALESCE(opening_credit, 0) AS opening
|
||
FROM opening_balances
|
||
WHERE fiscal_year = %s
|
||
AND account_id = %s
|
||
""", (fiscal_year, account_id))
|
||
|
||
row = cur.fetchone()
|
||
opening_balance = D(row["opening"]) if row else D(0)
|
||
|
||
# ----------------------------
|
||
# 期間内仕訳取得
|
||
# ----------------------------
|
||
cur.execute("""
|
||
SELECT
|
||
j.journal_date,
|
||
j.description,
|
||
l.debit,
|
||
l.credit
|
||
FROM journal_entries j
|
||
JOIN journal_lines l
|
||
ON l.journal_id = j.journal_id
|
||
WHERE l.account_id = %s
|
||
AND j.journal_date BETWEEN %s AND %s
|
||
ORDER BY j.journal_date, l.line_id
|
||
""", (account_id, date_from, date_to))
|
||
|
||
rows = cur.fetchall()
|
||
|
||
# ----------------------------
|
||
# 累計残高計算
|
||
# ----------------------------
|
||
balance = opening_balance
|
||
lines = []
|
||
|
||
for r in rows:
|
||
debit = D(r["debit"])
|
||
credit = D(r["credit"])
|
||
balance += debit - credit
|
||
|
||
lines.append({
|
||
"journal_date": r["journal_date"],
|
||
"description": r["description"],
|
||
"debit": str(debit),
|
||
"credit": str(credit),
|
||
"balance": str(balance),
|
||
})
|
||
|
||
return {
|
||
"account": {
|
||
"account_id": account_id,
|
||
"account_code": acc["account_code"],
|
||
"account_name": acc["account_name"],
|
||
},
|
||
"fiscal_year": fiscal_year,
|
||
"period": {
|
||
"from": date_from,
|
||
"to": date_to
|
||
},
|
||
"opening_balance": str(opening_balance),
|
||
"lines": lines,
|
||
"closing_balance": str(balance),
|
||
}
|