Files
njts-accounting-core/backend/app/modules/opening_balances/router.py
2025-12-14 23:54:48 +09:00

109 lines
3.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from fastapi import APIRouter, HTTPException, Query
from pydantic import BaseModel
from typing import List
from decimal import Decimal
from app.core.database import get_connection
router = APIRouter(prefix="/opening-balances", tags=["期首残高"])
# ---------- Models ----------
class OpeningBalanceItem(BaseModel):
account_id: int
debit: Decimal = Decimal("0")
credit: Decimal = Decimal("0")
class OpeningBalanceRequest(BaseModel):
fiscal_year: int
balances: List[OpeningBalanceItem]
# ---------- GET期首残高取得 ----------
@router.get("", summary="期首残高取得")
def get_opening_balances(
fiscal_year: int = Query(..., description="会計年度2025")
):
with get_connection() as conn, conn.cursor() as cur:
cur.execute("""
SELECT
a.account_id,
a.account_code,
a.account_name,
a.account_type,
COALESCE(o.opening_debit, 0) AS opening_debit,
COALESCE(o.opening_credit, 0) AS opening_credit
FROM accounts a
LEFT JOIN opening_balances o
ON o.account_id = a.account_id
AND o.fiscal_year = %s
WHERE a.is_active = true
ORDER BY a.account_code
""", (fiscal_year,))
return cur.fetchall()
# ---------- POST期首残高保存 ----------
@router.post("", summary="期首残高保存")
def save_opening_balances(req: OpeningBalanceRequest):
# 年度锁定チェック
cur.execute("""
SELECT is_locked
FROM fiscal_year_locks
WHERE fiscal_year = %s
""", (req.fiscal_year,))
row = cur.fetchone()
if row and row["is_locked"]:
raise HTTPException(
status_code=400,
detail="この会計年度の期首残高は既に確定されています。"
)
total_debit = Decimal("0")
total_credit = Decimal("0")
for b in req.balances:
total_debit += b.debit
total_credit += b.credit
if total_debit != total_credit:
raise HTTPException(
status_code=400,
detail="借方合計と貸方合計が一致していません。"
)
with get_connection() as conn, conn.cursor() as cur:
# 既存データ削除(年度単位)
cur.execute("""
DELETE FROM opening_balances
WHERE fiscal_year = %s
""", (req.fiscal_year,))
# 再登録
for b in req.balances:
if b.debit == 0 and b.credit == 0:
continue
cur.execute("""
INSERT INTO opening_balances
(fiscal_year, account_id, opening_debit, opening_credit)
VALUES
(%s, %s, %s, %s)
""", (
req.fiscal_year,
b.account_id,
b.debit,
b.credit
))
conn.commit()
return {"message": "期首残高を保存しました。"}