feat: 同步报销流程与工作台改动
This commit is contained in:
@@ -113,6 +113,135 @@ def seed_claim(db: Session) -> tuple[ExpenseClaim, ExpenseClaimItem]:
|
||||
return claim, item
|
||||
|
||||
|
||||
def test_claim_read_uses_organization_manager_and_dedupes_budget_warnings() -> None:
|
||||
client, session_factory = build_client()
|
||||
with session_factory() as db:
|
||||
department = OrganizationUnit(
|
||||
id="dept-org-manager",
|
||||
unit_code="DEPT-ORG-MANAGER",
|
||||
name="交付部",
|
||||
manager_name="王总",
|
||||
)
|
||||
employee = Employee(
|
||||
id="emp-org-manager",
|
||||
employee_no="E30001",
|
||||
name="赵六",
|
||||
email="zhaoliu@example.com",
|
||||
organization_unit=department,
|
||||
position="实施顾问",
|
||||
grade="P5",
|
||||
finance_owner_name="Wang Finance",
|
||||
)
|
||||
duplicated_warning = {
|
||||
"source": "budget_control",
|
||||
"event_type": "budget_warning",
|
||||
"severity": "medium",
|
||||
"label": "预算接近预警线",
|
||||
"message": "预算 SIM-BUD-2026-R0048 本次占用后使用率预计达到 99.27%,已达到预警线 80.00%。",
|
||||
"budget_no": "SIM-BUD-2026-R0048",
|
||||
"allocation_id": "allocation-0048",
|
||||
"subject_code": "travel",
|
||||
}
|
||||
claim = ExpenseClaim(
|
||||
id="claim-org-manager",
|
||||
claim_no="EXP-202606-ORG-MGR",
|
||||
employee_id=employee.id,
|
||||
employee_name=employee.name,
|
||||
department_id=department.id,
|
||||
department_name=department.name,
|
||||
project_code=None,
|
||||
expense_type="travel",
|
||||
reason="差旅报销",
|
||||
location="上海",
|
||||
amount=Decimal("880.00"),
|
||||
currency="CNY",
|
||||
invoice_count=1,
|
||||
occurred_at=datetime(2026, 6, 3, tzinfo=UTC),
|
||||
submitted_at=datetime(2026, 6, 3, 10, 0, tzinfo=UTC),
|
||||
status="submitted",
|
||||
approval_stage="直属领导审批",
|
||||
risk_flags_json=[
|
||||
{**duplicated_warning, "created_at": "2026-06-03T10:00:00+00:00"},
|
||||
{**duplicated_warning, "created_at": "2026-06-03T10:01:00+00:00"},
|
||||
],
|
||||
)
|
||||
db.add_all([department, employee, claim])
|
||||
db.commit()
|
||||
|
||||
headers = {"x-auth-username": "zhaoliu@example.com"}
|
||||
response = client.get("/api/v1/reimbursements/claims/claim-org-manager", headers=headers)
|
||||
assert response.status_code == 200
|
||||
payload = response.json()
|
||||
assert payload["manager_name"] == "王总"
|
||||
assert payload["finance_owner_name"] == "Wang Finance"
|
||||
budget_warnings = [
|
||||
flag
|
||||
for flag in payload["risk_flags_json"]
|
||||
if flag.get("source") == "budget_control" and flag.get("event_type") == "budget_warning"
|
||||
]
|
||||
assert len(budget_warnings) == 1
|
||||
assert budget_warnings[0]["message"] == duplicated_warning["message"]
|
||||
|
||||
|
||||
def test_claim_read_attaches_finance_approver_name_for_finance_stage() -> None:
|
||||
client, session_factory = build_client()
|
||||
with session_factory() as db:
|
||||
finance_role = Role(
|
||||
id="role-finance-reader",
|
||||
role_code="finance",
|
||||
name="财务",
|
||||
description="可处理财务复核任务",
|
||||
)
|
||||
applicant = Employee(
|
||||
id="emp-finance-stage-applicant",
|
||||
employee_no="E30002",
|
||||
name="钱七",
|
||||
email="qianqi@example.com",
|
||||
position="实施顾问",
|
||||
grade="P5",
|
||||
finance_owner_name="Wang Finance Group",
|
||||
)
|
||||
finance_user = Employee(
|
||||
id="emp-finance-stage-approver",
|
||||
employee_no="F30002",
|
||||
name="Wang Finance",
|
||||
email="wang.finance@example.com",
|
||||
position="财务专员",
|
||||
grade="P6",
|
||||
finance_owner_name="Wang Finance Group",
|
||||
roles=[finance_role],
|
||||
)
|
||||
claim = ExpenseClaim(
|
||||
id="claim-finance-stage-reader",
|
||||
claim_no="EXP-202606-FINANCE-MGR",
|
||||
employee_id=applicant.id,
|
||||
employee_name=applicant.name,
|
||||
department_id=None,
|
||||
department_name="交付部",
|
||||
project_code=None,
|
||||
expense_type="travel",
|
||||
reason="差旅报销",
|
||||
location="上海",
|
||||
amount=Decimal("880.00"),
|
||||
currency="CNY",
|
||||
invoice_count=1,
|
||||
occurred_at=datetime(2026, 6, 3, tzinfo=UTC),
|
||||
submitted_at=datetime(2026, 6, 3, 10, 0, tzinfo=UTC),
|
||||
status="submitted",
|
||||
approval_stage="财务审批",
|
||||
risk_flags_json=[],
|
||||
)
|
||||
db.add_all([finance_role, applicant, finance_user, claim])
|
||||
db.commit()
|
||||
|
||||
headers = {"x-auth-username": "qianqi@example.com"}
|
||||
response = client.get("/api/v1/reimbursements/claims/claim-finance-stage-reader", headers=headers)
|
||||
assert response.status_code == 200
|
||||
payload = response.json()
|
||||
assert payload["finance_owner_name"] == "Wang Finance Group"
|
||||
assert payload["finance_approver_name"] == "Wang Finance"
|
||||
|
||||
|
||||
def test_claim_standard_adjustment_endpoint_recalculates_and_marks_reviewer_notice() -> None:
|
||||
client, session_factory = build_client()
|
||||
with session_factory() as db:
|
||||
|
||||
Reference in New Issue
Block a user