更新UI相关部分

This commit is contained in:
焦龙言
2026-06-23 09:13:13 +08:00
parent faa09101a1
commit f213848719
29 changed files with 1990 additions and 397 deletions
+55
View File
@@ -0,0 +1,55 @@
from __future__ import annotations
from pathlib import Path
import sys
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from financial_system.domain.models import EmployeeAttendance, PayrollResult
from financial_system.domain.payroll_exceptions import detect_payroll_exceptions
def test_detect_payroll_exceptions_flags_core_payroll_risks() -> None:
result = PayrollResult(
employee=EmployeeAttendance(name="张三", employee_no="ZA0001", department="生产中心"),
salary_month="2026-06",
salary_mode="monthly",
attendance_days=0,
absence_days=22,
actual_work_hours=0,
punch_overtime_hours=1,
leave_hours=3,
remaining_overtime_hours=-2,
workday_overtime_hours=0,
weekend_overtime_hours=0,
holiday_overtime_hours=0,
minor_late_count=4,
major_late_count=1,
penalized_late_count=2,
late_deduction=60,
missing_card_count=1,
missing_card_deduction=20,
total_deduction=80,
base_salary=None,
base_pay=None,
commission_amount=0,
overtime_rate=0,
weekend_overtime_rate=0,
holiday_overtime_rate=0,
overtime_pay=0,
gross_salary=None,
net_salary=None,
note="未配置薪资档案",
)
exception_types = {item.exception_type for item in detect_payroll_exceptions([result])}
assert "missing_salary_profile" in exception_types
assert "missing_card" in exception_types
assert "late_penalty" in exception_types
assert "negative_remaining_overtime" in exception_types
assert "empty_attendance" in exception_types
if __name__ == "__main__":
test_detect_payroll_exceptions_flags_core_payroll_risks()
+80
View File
@@ -0,0 +1,80 @@
from __future__ import annotations
from datetime import date
from pathlib import Path
import sys
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from financial_system.services.realtime_attendance_service import TodayAttendanceItemData, build_realtime_summary
def test_build_realtime_summary_counts_today_status() -> None:
items = [
TodayAttendanceItemData(
employee_id=1,
employee_no="ZA0001",
employee_name="张三",
department="生产中心",
position="技工",
first_punch="08:58",
last_punch="18:30",
attendance_status="present",
late_minutes=0,
missing_card_count=0,
leave_hours=0,
today_overtime_hours=1,
month_remaining_overtime_hours=4,
estimated_net_salary=6800,
note="",
),
TodayAttendanceItemData(
employee_id=2,
employee_no="ZA0002",
employee_name="李四",
department="行政人事部",
position="人事专员",
first_punch="09:08",
last_punch="",
attendance_status="missing",
late_minutes=8,
missing_card_count=1,
leave_hours=2,
today_overtime_hours=0,
month_remaining_overtime_hours=-2,
estimated_net_salary=None,
note="缺少下班卡",
),
TodayAttendanceItemData(
employee_id=3,
employee_no="ZA0003",
employee_name="王五",
department="财务部",
position="财务",
first_punch="",
last_punch="",
attendance_status="unchecked",
late_minutes=0,
missing_card_count=0,
leave_hours=0,
today_overtime_hours=0,
month_remaining_overtime_hours=0,
estimated_net_salary=5000,
note="",
),
]
summary = build_realtime_summary(date(2026, 6, 22), items)
assert summary.employee_total == 3
assert summary.checked_in_count == 2
assert summary.unchecked_count == 1
assert summary.late_count == 1
assert summary.leave_count == 1
assert summary.missing_card_count == 1
assert summary.estimated_overtime_count == 1
assert summary.estimated_net_total == 11800
if __name__ == "__main__":
test_build_realtime_summary_counts_today_status()
+47
View File
@@ -0,0 +1,47 @@
from __future__ import annotations
import json
import os
from pathlib import Path
import sys
from tempfile import TemporaryDirectory
from unittest.mock import patch
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from financial_system.core.settings import get_settings
def test_database_url_environment_variable_overrides_config_file() -> None:
with TemporaryDirectory() as temp_dir:
config_path = Path(temp_dir) / "app_settings.json"
config_path.write_text(
json.dumps(
{
"database": {
"url": "mysql+pymysql://json-user:json-pass@json-host:3306/financial_system?charset=utf8mb4"
}
}
),
encoding="utf-8",
)
docker_database_url = (
"mysql+pymysql://docker-user:docker-pass@mysql.example.com:3306/"
"financial_system?charset=utf8mb4"
)
with patch.dict(
os.environ,
{
"APP_CONFIG_FILE": str(config_path),
"DATABASE_URL": docker_database_url,
},
clear=False,
):
settings = get_settings()
assert settings.database_url == docker_database_url
if __name__ == "__main__":
test_database_url_environment_variable_overrides_config_file()