新規作成
This commit is contained in:
109
backend/app/modules/ledger/router.py
Normal file
109
backend/app/modules/ledger/router.py
Normal file
@@ -0,0 +1,109 @@
|
||||
from fastapi import APIRouter, HTTPException, Query
|
||||
from typing import Optional, List, Dict, Any
|
||||
from decimal import Decimal
|
||||
from datetime import date
|
||||
from app.core.database import get_connection
|
||||
|
||||
router = APIRouter(prefix="/ledger", tags=["元帳"])
|
||||
|
||||
def to_decimal(x) -> Decimal:
|
||||
if isinstance(x, Decimal):
|
||||
return x
|
||||
return Decimal(str(x or 0))
|
||||
|
||||
@router.get("/{account_id}", summary="科目別元帳(残高推移)")
|
||||
def get_ledger(
|
||||
account_id: int,
|
||||
date_from: Optional[str] = Query(None, description="YYYY-MM-DD"),
|
||||
date_to: Optional[str] = Query(None, description="YYYY-MM-DD"),
|
||||
):
|
||||
# 1) 科目存在チェック
|
||||
with get_connection() as conn, conn.cursor() as cur:
|
||||
cur.execute("""
|
||||
SELECT account_id, account_code, account_name, account_type
|
||||
FROM accounts
|
||||
WHERE account_id = %s
|
||||
""", (account_id,))
|
||||
account = cur.fetchone()
|
||||
if not account:
|
||||
raise HTTPException(status_code=404, detail="指定した科目が見つかりません。")
|
||||
|
||||
# 2) 期間デフォルト(最小〜最大)
|
||||
if not date_from:
|
||||
cur.execute("""
|
||||
SELECT MIN(j.journal_date) AS min_d
|
||||
FROM journal_entries j
|
||||
JOIN journal_lines l ON l.journal_id = j.journal_id
|
||||
WHERE l.account_id = %s
|
||||
""", (account_id,))
|
||||
row = cur.fetchone()
|
||||
date_from = (row["min_d"] or date.today()).isoformat()
|
||||
|
||||
if not date_to:
|
||||
cur.execute("""
|
||||
SELECT MAX(j.journal_date) AS max_d
|
||||
FROM journal_entries j
|
||||
JOIN journal_lines l ON l.journal_id = j.journal_id
|
||||
WHERE l.account_id = %s
|
||||
""", (account_id,))
|
||||
row = cur.fetchone()
|
||||
date_to = (row["max_d"] or date.today()).isoformat()
|
||||
|
||||
# 3) 期首残高(date_from より前)
|
||||
cur.execute("""
|
||||
SELECT COALESCE(SUM(l.debit - l.credit), 0) AS opening
|
||||
FROM journal_lines l
|
||||
JOIN journal_entries j ON j.journal_id = l.journal_id
|
||||
WHERE l.account_id = %s
|
||||
AND j.journal_date < %s
|
||||
""", (account_id, date_from))
|
||||
opening = to_decimal(cur.fetchone()["opening"])
|
||||
|
||||
# 4) 期間内明細
|
||||
cur.execute("""
|
||||
SELECT j.journal_date, j.journal_id, j.description,
|
||||
l.debit, l.credit
|
||||
FROM journal_lines l
|
||||
JOIN journal_entries j ON j.journal_id = l.journal_id
|
||||
WHERE l.account_id = %s
|
||||
AND j.journal_date BETWEEN %s AND %s
|
||||
ORDER BY j.journal_date, j.journal_id, l.line_id
|
||||
""", (account_id, date_from, date_to))
|
||||
rows = cur.fetchall()
|
||||
|
||||
# 5) 残高推移の計算(借方−貸方)
|
||||
balance = opening
|
||||
out_rows: List[Dict[str, Any]] = []
|
||||
total_debit = Decimal("0")
|
||||
total_credit = Decimal("0")
|
||||
|
||||
for r in rows:
|
||||
d = to_decimal(r["debit"])
|
||||
c = to_decimal(r["credit"])
|
||||
total_debit += d
|
||||
total_credit += c
|
||||
balance += (d - c)
|
||||
out_rows.append({
|
||||
"date": r["journal_date"].isoformat(),
|
||||
"journal_id": r["journal_id"],
|
||||
"description": r["description"],
|
||||
"debit": str(d),
|
||||
"credit": str(c),
|
||||
"balance": str(balance) # 借方残を正とする(借方−貸方)
|
||||
})
|
||||
|
||||
result = {
|
||||
"account": {
|
||||
"id": account["account_id"],
|
||||
"code": account["account_code"],
|
||||
"name": account["account_name"],
|
||||
"type": account["account_type"],
|
||||
},
|
||||
"period": {"from": date_from, "to": date_to},
|
||||
"opening_balance": str(opening),
|
||||
"total_debit": str(total_debit),
|
||||
"total_credit": str(total_credit),
|
||||
"closing_balance": str(balance),
|
||||
"rows": out_rows
|
||||
}
|
||||
return result
|
||||
Reference in New Issue
Block a user