67 lines
2.5 KiB
Python
67 lines
2.5 KiB
Python
from fastapi import APIRouter, HTTPException
|
||
from pydantic import BaseModel, field_validator
|
||
from enum import Enum
|
||
from psycopg.errors import UniqueViolation, CheckViolation, StringDataRightTruncation
|
||
from app.core.database import get_connection
|
||
|
||
router = APIRouter(prefix="/accounts", tags=["科目マスタ"])
|
||
|
||
class AccountType(str, Enum):
|
||
asset = "asset"
|
||
liability = "liability"
|
||
equity = "equity"
|
||
revenue = "revenue"
|
||
expense = "expense"
|
||
|
||
class AccountCreate(BaseModel):
|
||
account_code: str
|
||
account_name: str
|
||
account_type: AccountType
|
||
|
||
@field_validator("account_code")
|
||
@classmethod
|
||
def validate_code(cls, v: str):
|
||
if not v.isdigit():
|
||
raise ValueError("科目コードは数字のみで入力してください")
|
||
if len(v) > 20:
|
||
raise ValueError("科目コードが長すぎます(20文字以内)")
|
||
return v
|
||
|
||
@field_validator("account_name")
|
||
@classmethod
|
||
def validate_name(cls, v: str):
|
||
if not v.strip():
|
||
raise ValueError("科目名を入力してください")
|
||
if len(v) > 100:
|
||
raise ValueError("科目名が長すぎます(100文字以内)")
|
||
return v
|
||
|
||
@router.get("/", summary="科目一覧取得")
|
||
def list_accounts():
|
||
with get_connection() as conn, conn.cursor() as cur:
|
||
cur.execute("""
|
||
SELECT account_id, account_code, account_name, account_type, is_active
|
||
FROM accounts ORDER BY account_code
|
||
""")
|
||
return cur.fetchall()
|
||
|
||
@router.post("/", summary="科目登録", status_code=201)
|
||
def create_account(data: AccountCreate):
|
||
try:
|
||
with get_connection() as conn, conn.cursor() as cur:
|
||
cur.execute("""
|
||
INSERT INTO accounts (account_code, account_name, account_type)
|
||
VALUES (%s, %s, %s) RETURNING account_id
|
||
""", (data.account_code, data.account_name, data.account_type.value))
|
||
new_id = cur.fetchone()["account_id"]
|
||
conn.commit()
|
||
return {"account_id": new_id}
|
||
|
||
except UniqueViolation:
|
||
# 409 也行;这里按你的要求统一 400
|
||
raise HTTPException(status_code=400, detail="この科目コードは既に登録されています。")
|
||
except StringDataRightTruncation:
|
||
raise HTTPException(status_code=400, detail="入力文字数が制限を超えています。")
|
||
except CheckViolation:
|
||
raise HTTPException(status_code=400, detail="入力値が不正です。")
|