修正
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -1,11 +1,18 @@
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from fastapi import APIRouter
|
||||
from pydantic import BaseModel, field_validator
|
||||
from enum import Enum
|
||||
from psycopg.errors import UniqueViolation, CheckViolation, StringDataRightTruncation
|
||||
from app.core.database import get_connection
|
||||
from app.core.exceptions import BusinessException
|
||||
import psycopg
|
||||
|
||||
|
||||
router = APIRouter(prefix="/accounts", tags=["科目マスタ"])
|
||||
|
||||
|
||||
# ======================================================
|
||||
# Enum:科目種別
|
||||
# ======================================================
|
||||
class AccountType(str, Enum):
|
||||
asset = "asset"
|
||||
liability = "liability"
|
||||
@@ -13,6 +20,10 @@ class AccountType(str, Enum):
|
||||
revenue = "revenue"
|
||||
expense = "expense"
|
||||
|
||||
|
||||
# ======================================================
|
||||
# Model:登録入力用
|
||||
# ======================================================
|
||||
class AccountCreate(BaseModel):
|
||||
account_code: str
|
||||
account_name: str
|
||||
@@ -22,45 +33,86 @@ class AccountCreate(BaseModel):
|
||||
@classmethod
|
||||
def validate_code(cls, v: str):
|
||||
if not v.isdigit():
|
||||
raise ValueError("科目コードは数字のみで入力してください")
|
||||
raise BusinessException(
|
||||
error_code="ACCOUNT_CODE_INVALID",
|
||||
message="科目コードは数字のみで入力してください"
|
||||
)
|
||||
if len(v) > 20:
|
||||
raise ValueError("科目コードが長すぎます(20文字以内)")
|
||||
raise BusinessException(
|
||||
error_code="ACCOUNT_CODE_TOO_LONG",
|
||||
message="科目コードは20文字以内で入力してください"
|
||||
)
|
||||
return v
|
||||
|
||||
@field_validator("account_name")
|
||||
@classmethod
|
||||
def validate_name(cls, v: str):
|
||||
if not v.strip():
|
||||
raise ValueError("科目名を入力してください")
|
||||
raise BusinessException(
|
||||
error_code="ACCOUNT_NAME_EMPTY",
|
||||
message="科目名を入力してください"
|
||||
)
|
||||
if len(v) > 100:
|
||||
raise ValueError("科目名が長すぎます(100文字以内)")
|
||||
raise BusinessException(
|
||||
error_code="ACCOUNT_NAME_TOO_LONG",
|
||||
message="科目名は100文字以内で入力してください"
|
||||
)
|
||||
return v
|
||||
|
||||
|
||||
# ======================================================
|
||||
# GET:科目一覧取得
|
||||
# ======================================================
|
||||
@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
|
||||
FROM accounts
|
||||
ORDER BY account_code
|
||||
""")
|
||||
return cur.fetchall()
|
||||
rows = cur.fetchall()
|
||||
|
||||
if not rows:
|
||||
raise BusinessException(
|
||||
error_code="ACCOUNT_NOT_FOUND",
|
||||
message="科目が登録されていません"
|
||||
)
|
||||
|
||||
return rows
|
||||
|
||||
|
||||
# ======================================================
|
||||
# POST:科目登録
|
||||
# ======================================================
|
||||
@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
|
||||
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="この科目コードは既に登録されています。")
|
||||
raise BusinessException(
|
||||
error_code="ACCOUNT_DUPLICATE",
|
||||
message="この科目コードは既に登録されています"
|
||||
)
|
||||
|
||||
except StringDataRightTruncation:
|
||||
raise HTTPException(status_code=400, detail="入力文字数が制限を超えています。")
|
||||
raise BusinessException(
|
||||
error_code="ACCOUNT_VALUE_TOO_LONG",
|
||||
message="入力文字数が制限を超えています"
|
||||
)
|
||||
|
||||
except CheckViolation:
|
||||
raise HTTPException(status_code=400, detail="入力値が不正です。")
|
||||
raise BusinessException(
|
||||
error_code="ACCOUNT_VALUE_INVALID",
|
||||
message="入力値が不正です"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user