This commit is contained in:
admin
2026-01-21 10:58:19 +09:00
parent 8a00de8f03
commit 86020ada5c
36 changed files with 3417 additions and 363 deletions

View File

@@ -81,6 +81,7 @@ class MonthlyPayroll(MonthlyPayrollBase):
# 控除項目
health_insurance: Decimal
care_insurance: Decimal
pension_insurance: Decimal
employment_insurance: Decimal
income_tax: Decimal

View File

@@ -12,17 +12,21 @@ class PayrollCalculationService:
@staticmethod
def get_active_dependents_count(employee_id: int, target_date: date) -> int:
"""有効な扶養家族数を取得"""
"""有効な扶養家族数を取得源泉税控除対象のみ19歳以上"""
with get_connection() as conn:
with conn.cursor() as cur:
# その年の12月31日時点で19歳以上の扶養家族のみをカウント
# 16-18歳は住民税のみ対象なので源泉税控除対象外
cur.execute(
"""
SELECT COUNT(*) as count FROM dependents
WHERE employee_id = %s
AND valid_from <= %s
AND (valid_to IS NULL OR valid_to >= %s)
AND birth_date IS NOT NULL
AND EXTRACT(YEAR FROM AGE(DATE(EXTRACT(YEAR FROM %s) || '-12-31'), birth_date)) >= 19
""",
(employee_id, target_date, target_date)
(employee_id, target_date, target_date, target_date)
)
result = cur.fetchone()
return result["count"] if result else 0
@@ -46,20 +50,22 @@ class PayrollCalculationService:
return cur.fetchone()
@staticmethod
def get_insurance_rate(rate_type: str, target_date: date) -> Dict[str, Any]:
def get_insurance_rate(rate_type: str, target_date: date, calculation_target: str = '給与') -> Dict[str, Any]:
"""保険料率を取得"""
with get_connection() as conn:
with conn.cursor() as cur:
# rate_yearで年度を判定
target_year = target_date.year
cur.execute(
"""
SELECT * FROM insurance_rates
WHERE rate_type = %s
AND valid_from <= %s
AND (valid_to IS NULL OR valid_to >= %s)
ORDER BY valid_from DESC
AND rate_year = %s
AND calculation_target = %s
ORDER BY rate_id DESC
LIMIT 1
""",
(rate_type, target_date, target_date)
(rate_type, target_year, calculation_target)
)
return cur.fetchone()
@@ -202,10 +208,15 @@ class PayrollCalculationService:
)
employee_info = cur.fetchone()
# 年齢を計算介護保険は40歳以上が対象
# 年齢を計算介護保険は40歳以上65歳未満が対象)
age = 0
if employee_info and employee_info["birth_date"]:
age = (payment_date - employee_info["birth_date"]).days // 365
birth_date = employee_info["birth_date"]
# より正確な年齢計算
age = payment_date.year - birth_date.year
# 誕生日がまだ来ていない場合は-1
if (payment_date.month, payment_date.day) < (birth_date.month, birth_date.day):
age -= 1
# 健康保険(上限適用後の標準報酬月額で計算)
health_insurance_rate = PayrollCalculationService.get_insurance_rate("健康保険", payment_date)