This commit is contained in:
admin
2026-01-22 01:16:54 +09:00
parent 86020ada5c
commit 3d91356877
16 changed files with 1862 additions and 494 deletions

View File

@@ -128,6 +128,69 @@ def approve_bonus(bonus_id: int, approved_by: str):
return result
@router.post("/{bonus_id}/recalculate", response_model=schemas.BonusPayment)
def recalculate_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,))
existing = cur.fetchone()
if not existing:
raise HTTPException(status_code=404, detail="賞与データが見つかりません")
if existing["status"] == "approved":
raise HTTPException(status_code=400, detail="承認済みの賞与は再計算できません")
# 再計算
try:
calc_result = BonusCalculationService.calculate_bonus(
employee_id=existing["employee_id"],
bonus_year=existing["bonus_year"],
bonus_month=existing["bonus_month"],
bonus_type=existing["bonus_type"],
payment_date=existing["payment_date"],
base_bonus=existing["base_bonus"],
performance_bonus=existing["performance_bonus"],
other_bonus=existing["other_bonus"],
other_deduction=existing["other_deduction"],
calculated_by="recalculated"
)
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
# 更新
cur.execute(
"""
UPDATE bonus_payments SET
base_bonus = %s, performance_bonus = %s, other_bonus = %s,
total_bonus = %s,
health_insurance = %s, care_insurance = %s, pension_insurance = %s,
employment_insurance = %s, income_tax = %s, other_deduction = %s,
total_deduction = %s, net_bonus = %s,
calculated_at = %s, calculated_by = %s
WHERE bonus_id = %s
RETURNING *
""",
(
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(), "recalculated",
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):
"""賞与を削除"""

View File

@@ -58,12 +58,15 @@ class BonusCalculationService:
cur.execute(
"""
SELECT AVG(total_payment - commute_allowance) as avg_salary
FROM monthly_payroll
WHERE employee_id = %s
AND payment_date < %s
AND status IN ('approved', 'paid')
ORDER BY payment_date DESC
LIMIT 3
FROM (
SELECT total_payment, commute_allowance
FROM monthly_payroll
WHERE employee_id = %s
AND payment_date < %s
AND status IN ('approved', 'paid')
ORDER BY payment_date DESC
LIMIT 3
) as recent_payroll
""",
(employee_id, payment_date)
)