給与管理システム新規作成
This commit is contained in:
139
backend/app/payroll/bonus/router.py
Normal file
139
backend/app/payroll/bonus/router.py
Normal file
@@ -0,0 +1,139 @@
|
||||
"""
|
||||
賞与計算API (Bonus Calculation API)
|
||||
"""
|
||||
from fastapi import APIRouter, HTTPException, status
|
||||
from typing import List
|
||||
from datetime import datetime
|
||||
from . import schemas
|
||||
from .service import BonusCalculationService
|
||||
from ...core.database import get_connection
|
||||
|
||||
|
||||
router = APIRouter(prefix="/payroll/bonus", tags=["Payroll - Bonus"])
|
||||
|
||||
|
||||
@router.post("/calculate", response_model=schemas.BonusPayment, status_code=status.HTTP_201_CREATED)
|
||||
def calculate_bonus(request: schemas.BonusCalculationRequest):
|
||||
"""賞与を計算"""
|
||||
# 賞与を計算
|
||||
calc_result = BonusCalculationService.calculate_bonus(
|
||||
employee_id=request.employee_id,
|
||||
bonus_year=request.bonus_year,
|
||||
bonus_month=request.bonus_month,
|
||||
bonus_type=request.bonus_type,
|
||||
payment_date=request.payment_date,
|
||||
base_bonus=request.base_bonus,
|
||||
performance_bonus=request.performance_bonus,
|
||||
other_bonus=request.other_bonus,
|
||||
other_deduction=request.other_deduction,
|
||||
calculated_by=request.calculated_by
|
||||
)
|
||||
|
||||
# データベースに保存
|
||||
with get_connection() as conn:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(
|
||||
"""
|
||||
INSERT INTO bonus_payments (
|
||||
employee_id, bonus_year, bonus_month, bonus_type, payment_date, status,
|
||||
base_bonus, performance_bonus, other_bonus, total_bonus,
|
||||
health_insurance, care_insurance, pension_insurance, employment_insurance,
|
||||
income_tax, other_deduction, total_deduction,
|
||||
net_bonus, calculated_at, calculated_by
|
||||
) VALUES (
|
||||
%s, %s, %s, %s, %s, %s,
|
||||
%s, %s, %s, %s,
|
||||
%s, %s, %s, %s,
|
||||
%s, %s, %s,
|
||||
%s, %s, %s
|
||||
)
|
||||
RETURNING *
|
||||
""",
|
||||
(
|
||||
calc_result["employee_id"], calc_result["bonus_year"], calc_result["bonus_month"],
|
||||
calc_result["bonus_type"], calc_result["payment_date"], calc_result["status"],
|
||||
calc_result["base_bonus"], calc_result["performance_bonus"],
|
||||
calc_result["other_bonus"], calc_result["total_bonus"],
|
||||
calc_result["health_insurance"], calc_result["care_insurance"],
|
||||
calc_result["pension_insurance"], calc_result["employment_insurance"],
|
||||
calc_result["income_tax"], calc_result["other_deduction"],
|
||||
calc_result["total_deduction"],
|
||||
calc_result["net_bonus"], datetime.now(), calc_result["calculated_by"]
|
||||
)
|
||||
)
|
||||
result = cur.fetchone()
|
||||
conn.commit()
|
||||
return result
|
||||
|
||||
|
||||
@router.get("/", response_model=List[schemas.BonusPayment])
|
||||
def get_bonuses(bonus_year: int = None, employee_id: int = None):
|
||||
"""賞与一覧を取得"""
|
||||
conditions = []
|
||||
params = []
|
||||
|
||||
if bonus_year:
|
||||
conditions.append("bonus_year = %s")
|
||||
params.append(bonus_year)
|
||||
|
||||
if employee_id:
|
||||
conditions.append("employee_id = %s")
|
||||
params.append(employee_id)
|
||||
|
||||
where_clause = " AND ".join(conditions) if conditions else "1=1"
|
||||
|
||||
with get_connection() as conn:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(
|
||||
f"""
|
||||
SELECT * FROM bonus_payments
|
||||
WHERE {where_clause}
|
||||
ORDER BY bonus_year DESC, bonus_month DESC
|
||||
""",
|
||||
params
|
||||
)
|
||||
return cur.fetchall()
|
||||
|
||||
|
||||
@router.get("/{bonus_id}", response_model=schemas.BonusPayment)
|
||||
def get_bonus(bonus_id: int):
|
||||
"""賞与詳細を取得"""
|
||||
with get_connection() as conn:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute("SELECT * FROM bonus_payments WHERE bonus_id = %s", (bonus_id,))
|
||||
result = cur.fetchone()
|
||||
if not result:
|
||||
raise HTTPException(status_code=404, detail="賞与が見つかりません")
|
||||
return result
|
||||
|
||||
|
||||
@router.post("/{bonus_id}/approve", response_model=schemas.BonusPayment)
|
||||
def approve_bonus(bonus_id: int, approved_by: str):
|
||||
"""賞与を承認"""
|
||||
with get_connection() as conn:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(
|
||||
"""
|
||||
UPDATE bonus_payments
|
||||
SET status = 'approved', approved_at = %s, approved_by = %s
|
||||
WHERE bonus_id = %s AND status = 'calculated'
|
||||
RETURNING *
|
||||
""",
|
||||
(datetime.now(), approved_by, bonus_id)
|
||||
)
|
||||
result = cur.fetchone()
|
||||
if not result:
|
||||
raise HTTPException(status_code=404, detail="賞与が見つかりません、または既に承認済みです")
|
||||
conn.commit()
|
||||
return result
|
||||
|
||||
|
||||
@router.delete("/{bonus_id}", status_code=status.HTTP_204_NO_CONTENT)
|
||||
def delete_bonus(bonus_id: int):
|
||||
"""賞与を削除"""
|
||||
with get_connection() as conn:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute("DELETE FROM bonus_payments WHERE bonus_id = %s AND status = 'draft'", (bonus_id,))
|
||||
if cur.rowcount == 0:
|
||||
raise HTTPException(status_code=404, detail="賞与が見つかりません、または削除できません")
|
||||
conn.commit()
|
||||
Reference in New Issue
Block a user