Files
admin 63ac6bc99a 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: ルーター登録
2026-05-20 17:10:08 +09:00

72 lines
2.7 KiB
Python

"""
給与所得の源泉徴収票 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))