feat: 子ども・子育て支援金を給与・賞与計算に追加(令和8年4月以降)

This commit is contained in:
admin
2026-04-27 01:04:54 +09:00
parent 31a64d5b59
commit a646a81719
9 changed files with 3988 additions and 426 deletions

View File

@@ -38,12 +38,14 @@ def calculate_bonus(request: schemas.BonusCalculationRequest):
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,
child_support,
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, %s
)
@@ -56,6 +58,7 @@ def calculate_bonus(request: schemas.BonusCalculationRequest):
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["child_support"],
calc_result["income_tax"], calc_result["other_deduction"],
calc_result["total_deduction"],
calc_result["net_bonus"], datetime.now(), calc_result["calculated_by"]
@@ -196,7 +199,12 @@ 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:
# 承認済みは削除不可
cur.execute("SELECT status FROM bonus_payments WHERE bonus_id = %s", (bonus_id,))
row = cur.fetchone()
if not row:
raise HTTPException(status_code=404, detail="賞与が見つかりません、または削除できません")
if row["status"] == "approved":
raise HTTPException(status_code=400, detail="承認済みの賞与は削除できません")
cur.execute("DELETE FROM bonus_payments WHERE bonus_id = %s", (bonus_id,))
conn.commit()

View File

@@ -139,12 +139,12 @@ class BonusCalculationService:
# 総支給額
total_bonus = base_bonus + performance_bonus + other_bonus
# 社会保険料上限を取得
# 社会保険料上限を取得(賞与専用の標準賞与額上限を使用)
health_insurance_limit = BonusCalculationService.get_insurance_limit(
"健康保険標準報酬月額上限", payment_date
"健康保険標準賞与額上限", payment_date
)
pension_insurance_limit = BonusCalculationService.get_insurance_limit(
"厚生年金標準報酬月額上限", payment_date
"厚生年金標準賞与額上限", payment_date
)
# 賞与の標準賞与額(上限適用)
@@ -203,6 +203,34 @@ class BonusCalculationService:
total_bonus * Decimal(str(employment_insurance_rate["employee_rate"]))
).quantize(Decimal("1"))
# 子ども・子育て支援金令和8年4月分以降のみ適用
# 賞与の場合: 標準報酬月額表の淨化率を使い、total_bonus × 子育て率 / 2
child_support = Decimal("0")
is_child_support_applicable = (
(bonus_year == 2026 and bonus_month >= 4) or bonus_year >= 2027
)
if is_child_support_applicable:
with get_connection() as conn:
with conn.cursor() as cur:
# 標準報酬月額表から子育て率を取得最上位等級rowの child_support/monthly_amountで率を計算
cur.execute(
"""
SELECT child_support, monthly_amount
FROM standard_remuneration
WHERE rate_year = %s
AND monthly_amount > 0 AND child_support > 0
ORDER BY monthly_amount DESC
LIMIT 1
""",
(payment_date.year,)
)
sr = cur.fetchone()
if sr and sr["monthly_amount"] and sr["monthly_amount"] > 0:
cs_rate = Decimal(str(sr["child_support"])) / Decimal(str(sr["monthly_amount"]))
# 標準賞与額に封上限なし(法定上賞与には標準賞与額上限なし)
child_support = (total_bonus * cs_rate / Decimal("2")).quantize(Decimal("1"))
print(f"[DEBUG] 賞与子育て支援金: 率={cs_rate}, 賞与総額={total_bonus} → 従業員負担={child_support}")
# 所得税の計算(賞与特有の計算)
from ..calculation.service import PayrollCalculationService
dependents_count = PayrollCalculationService.get_active_dependents_count(employee_id, payment_date)
@@ -214,7 +242,8 @@ class BonusCalculationService:
health_insurance -
care_insurance -
pension_insurance -
employment_insurance
employment_insurance -
child_support
)
income_tax = BonusCalculationService.calculate_bonus_income_tax(
@@ -229,6 +258,7 @@ class BonusCalculationService:
care_insurance +
pension_insurance +
employment_insurance +
child_support +
income_tax +
other_deduction
)
@@ -255,6 +285,7 @@ class BonusCalculationService:
"care_insurance": care_insurance,
"pension_insurance": pension_insurance,
"employment_insurance": employment_insurance,
"child_support": child_support,
"income_tax": income_tax,
"other_deduction": other_deduction,
"total_deduction": total_deduction,