feat: 給与所得の源泉徴収票機能を追加
- 新規モジュール: backend/app/payroll/withholding_slip/ - schemas.py: 源泉徴収票データモデル - service.py: 年間集計・給与所得控除・控除額計算ロジック - router.py: POST /payroll/withholding-slip/generate - frontend/withholding-slip.html: 票面プレビュー・印刷(3部)ページ - frontend/payroll.html: 源泉徴収票メニューカード追加 - backend/app/main.py: ルーター登録
This commit is contained in:
71
backend/app/payroll/withholding_slip/router.py
Normal file
71
backend/app/payroll/withholding_slip/router.py
Normal file
@@ -0,0 +1,71 @@
|
||||
"""
|
||||
給与所得の源泉徴収票 APIルーター
|
||||
"""
|
||||
from fastapi import APIRouter, HTTPException, Query
|
||||
from typing import List, Optional
|
||||
import logging
|
||||
|
||||
from .schemas import WithholdingSlipRequest, WithholdingSlipResponse
|
||||
from .service import get_withholding_slips
|
||||
from app.core.database import get_connection
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
router = APIRouter(prefix="/payroll/withholding-slip", tags=["Payroll - Withholding Slip"])
|
||||
|
||||
|
||||
@router.post("/generate", response_model=WithholdingSlipResponse)
|
||||
def generate_withholding_slips(request: WithholdingSlipRequest):
|
||||
"""
|
||||
指定年度・従業員の給与所得の源泉徴収票データを生成する
|
||||
"""
|
||||
if not request.employee_ids:
|
||||
raise HTTPException(status_code=400, detail="従業員IDを指定してください")
|
||||
if request.tax_year < 2000 or request.tax_year > 2099:
|
||||
raise HTTPException(status_code=400, detail="年度が不正です")
|
||||
|
||||
try:
|
||||
slips = get_withholding_slips(request.tax_year, request.employee_ids)
|
||||
return WithholdingSlipResponse(
|
||||
tax_year=request.tax_year,
|
||||
slips=slips,
|
||||
total_count=len(slips)
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"源泉徴収票生成エラー: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@router.get("/employees")
|
||||
def get_employees_for_slip():
|
||||
"""アクティブな従業員リストを取得(源泉徴収票用)"""
|
||||
try:
|
||||
with get_connection() as conn:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute("""
|
||||
SELECT employee_id, employee_code, name, name_kana
|
||||
FROM employees
|
||||
WHERE is_active = true
|
||||
ORDER BY employee_code
|
||||
""")
|
||||
rows = cur.fetchall()
|
||||
result = []
|
||||
for row in rows:
|
||||
if isinstance(row, dict):
|
||||
result.append({
|
||||
"id": row["employee_id"],
|
||||
"code": row["employee_code"],
|
||||
"name": row["name"],
|
||||
"name_kana": row.get("name_kana", "")
|
||||
})
|
||||
else:
|
||||
result.append({
|
||||
"id": row[0],
|
||||
"code": row[1],
|
||||
"name": row[2],
|
||||
"name_kana": row[3] if len(row) > 3 else ""
|
||||
})
|
||||
return {"employees": result, "total": len(result)}
|
||||
except Exception as e:
|
||||
logger.error(f"従業員リスト取得エラー: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
Reference in New Issue
Block a user