This commit is contained in:
FNOS-WIN11ENT\choshoukaku
2025-12-14 21:01:12 +09:00
parent c845373db8
commit 0ebf1321ee
9 changed files with 112 additions and 0 deletions

View File

@@ -42,3 +42,6 @@ app.include_router(ledger_router)
from app.modules.trial_balance.router import router as trial_balance_router from app.modules.trial_balance.router import router as trial_balance_router
app.include_router(trial_balance_router) app.include_router(trial_balance_router)
from app.modules.opening_balances.router import router as opening_router
app.include_router(opening_router)

View File

@@ -0,0 +1,29 @@
# app/modules/journals/schemas.py
from pydantic import BaseModel, field_validator
from typing import List
from decimal import Decimal
from datetime import date
class JournalLineCreate(BaseModel):
account_id: int
debit: Decimal = 0
credit: Decimal = 0
@field_validator("debit", "credit")
@classmethod
def non_negative(cls, v):
if v < 0:
raise ValueError("金額は0以上で入力してください")
return v
class JournalCreate(BaseModel):
journal_date: date
description: str
lines: List[JournalLineCreate]
@field_validator("lines")
@classmethod
def validate_lines(cls, v):
if len(v) < 2:
raise ValueError("仕訳明細は2行以上必要です")
return v

View File

@@ -0,0 +1,55 @@
# 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()

View File

@@ -0,0 +1,25 @@
# backend/app/modules/opening_balances/schema.py
from pydantic import BaseModel, field_validator
class OpeningBalanceCreate(BaseModel):
fiscal_year: int
account_id: int
opening_debit: float = 0
opening_credit: float = 0
@field_validator("fiscal_year")
@classmethod
def validate_year(cls, v: int):
if v < 2000 or v > 2100:
raise ValueError("会计年度不正确")
return v
@field_validator("opening_credit")
@classmethod
def validate_balance(cls, v, info):
debit = info.data.get("opening_debit", 0)
if debit > 0 and v > 0:
raise ValueError("借方和贷方不能同时输入金额")
if debit < 0 or v < 0:
raise ValueError("金额不能为负数")
return v