@@ -1,7 +1,7 @@
|
||||
"""
|
||||
給与計算サービス (Payroll Calculation Service)
|
||||
"""
|
||||
from decimal import Decimal
|
||||
from decimal import Decimal, ROUND_HALF_UP
|
||||
from datetime import date
|
||||
from typing import Dict, Any
|
||||
from ...core.database import get_connection
|
||||
@@ -58,8 +58,10 @@ class PayrollCalculationService:
|
||||
"""保険料率を取得(年度がない場合は前年度を参照)"""
|
||||
with get_connection() as conn:
|
||||
with conn.cursor() as cur:
|
||||
# rate_yearで年度を判定
|
||||
target_year = target_date.year
|
||||
# 翌月払いのため、新年度料率は5月支払分(4月分)から適用
|
||||
# rate_year=XXXX は XXXX年5月支払〜(XXXX+1)年4月支払に適用
|
||||
# 1〜4月支払は前年度(year-1)の料率を使用
|
||||
target_year = target_date.year if target_date.month >= 5 else target_date.year - 1
|
||||
cur.execute(
|
||||
"""
|
||||
SELECT * FROM insurance_rates
|
||||
@@ -300,7 +302,7 @@ class PayrollCalculationService:
|
||||
# まず指定年度の標準報酬月額表を検索
|
||||
cur.execute(
|
||||
"""
|
||||
SELECT monthly_amount, child_support
|
||||
SELECT monthly_amount
|
||||
FROM standard_remuneration
|
||||
WHERE rate_year = %s
|
||||
AND salary_from <= %s
|
||||
@@ -318,7 +320,7 @@ class PayrollCalculationService:
|
||||
previous_year = target_year - year_offset
|
||||
cur.execute(
|
||||
"""
|
||||
SELECT monthly_amount, child_support
|
||||
SELECT monthly_amount
|
||||
FROM standard_remuneration
|
||||
WHERE rate_year = %s
|
||||
AND salary_from <= %s
|
||||
@@ -334,11 +336,9 @@ class PayrollCalculationService:
|
||||
|
||||
if result:
|
||||
standard_monthly_salary = Decimal(str(result["monthly_amount"]))
|
||||
child_support_full = Decimal(str(result["child_support"])) if result["child_support"] is not None else Decimal("0")
|
||||
print(f"[DEBUG] 標準報酬月額表検索: 総支給額={total_payment} → 標準報酬月額={standard_monthly_salary}, 子育て支援金全額={child_support_full}")
|
||||
print(f"[DEBUG] 標準報酬月額表検索: 総支給額={total_payment} → 標準報酬月額={standard_monthly_salary}")
|
||||
else:
|
||||
print(f"[DEBUG] 標準報酬月額表検索: 該当等級なし(総支給額={total_payment})")
|
||||
child_support_full = Decimal("0")
|
||||
|
||||
|
||||
# 社会保険料上限を取得
|
||||
@@ -381,7 +381,7 @@ class PayrollCalculationService:
|
||||
if health_insurance_rate:
|
||||
health_insurance = (
|
||||
health_standard_salary * Decimal(str(health_insurance_rate["employee_rate"]))
|
||||
).quantize(Decimal("0.01"))
|
||||
).quantize(Decimal("1"), rounding=ROUND_HALF_UP)
|
||||
elif calc_social_insurance:
|
||||
errors.append(f"健康保険料率が見つかりません(年度: {payment_date.year})")
|
||||
|
||||
@@ -392,7 +392,7 @@ class PayrollCalculationService:
|
||||
if care_insurance_rate:
|
||||
care_insurance = (
|
||||
health_standard_salary * Decimal(str(care_insurance_rate["employee_rate"]))
|
||||
).quantize(Decimal("0.01"))
|
||||
).quantize(Decimal("1"), rounding=ROUND_HALF_UP)
|
||||
print(f"[DEBUG] 介護保険計算: {health_standard_salary} × {care_insurance_rate['employee_rate']}% = {care_insurance}")
|
||||
else:
|
||||
errors.append(f"介護保険料率が見つかりません(年度: {payment_date.year})") if calc_social_insurance else None
|
||||
@@ -403,7 +403,7 @@ class PayrollCalculationService:
|
||||
if pension_insurance_rate:
|
||||
pension_insurance = (
|
||||
pension_standard_salary * Decimal(str(pension_insurance_rate["employee_rate"]))
|
||||
).quantize(Decimal("0.01"))
|
||||
).quantize(Decimal("1"), rounding=ROUND_HALF_UP)
|
||||
print(f"[DEBUG] 厚生年金計算: {pension_standard_salary} × {pension_insurance_rate['employee_rate']}% = {pension_insurance}")
|
||||
elif calc_social_insurance:
|
||||
errors.append(f"厚生年金保険料率が見つかりません(年度: {payment_date.year})")
|
||||
@@ -412,14 +412,19 @@ class PayrollCalculationService:
|
||||
employment_insurance_rate = PayrollCalculationService.get_insurance_rate("雇用保険", payment_date)
|
||||
employment_insurance = Decimal("0")
|
||||
|
||||
# 子ども・子育て支援金(令和8年4月分以降のみ適用)
|
||||
# 子ども・子育て支援金(令和8年4月分=5月納付分以降のみ適用)
|
||||
# 翌月払いのため、payroll_month=5(5月支払)が4月分保険料の初回控除月
|
||||
child_support = Decimal("0")
|
||||
is_child_support_applicable = (
|
||||
(payroll_year == 2026 and payroll_month >= 4) or payroll_year >= 2027
|
||||
(payroll_year == 2026 and payroll_month >= 5) or payroll_year >= 2027
|
||||
)
|
||||
if is_child_support_applicable and calc_social_insurance:
|
||||
child_support = (child_support_full / Decimal("2")).quantize(Decimal("0.01"))
|
||||
print(f"[DEBUG] 子育て支援金: 全額={child_support_full} → 折半額(従業員負担)={child_support}")
|
||||
child_support_rate = PayrollCalculationService.get_insurance_rate("子ども・子育て支援金", payment_date)
|
||||
if child_support_rate:
|
||||
child_support = (
|
||||
standard_monthly_salary * Decimal(str(child_support_rate["employee_rate"]))
|
||||
).quantize(Decimal("1"), rounding=ROUND_HALF_UP)
|
||||
print(f"[DEBUG] 子育て支援金: 標準報酬月額={standard_monthly_salary} × 料率={child_support_rate['employee_rate']} = {child_support}")
|
||||
|
||||
# 雇用保険加入対象かどうか確認
|
||||
is_employment_insurance_eligible = salary_setting.get("employment_insurance_eligible", True) if salary_setting else True
|
||||
@@ -427,7 +432,7 @@ class PayrollCalculationService:
|
||||
if is_employment_insurance_eligible and employment_insurance_rate:
|
||||
employment_insurance = (
|
||||
total_payment * Decimal(str(employment_insurance_rate["employee_rate"]))
|
||||
).quantize(Decimal("0.01"))
|
||||
).quantize(Decimal("1"), rounding=ROUND_HALF_UP)
|
||||
elif not is_employment_insurance_eligible:
|
||||
print(f"[DEBUG] この従業員は雇用保険非対象です")
|
||||
elif not employment_insurance_rate and calc_social_insurance:
|
||||
|
||||
Reference in New Issue
Block a user