| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- from datetime import UTC, date, datetime
- import pytest
- from zbt.core.errors import AppError
- from zbt.domains.enrollment.models import Policy
- from zbt.domains.enrollment.repository import InMemoryEnrollmentRepository
- from zbt.domains.identity.models import H5User
- from zbt.domains.service_request.models import ServiceRequest
- from zbt.domains.service_request.repository import InMemoryServiceRequestRepository
- from zbt.domains.service_request.service import ServiceRequestService
- from zbt.domains.service_request.vision import MaterialExtraction
- class FakeVisionGateway:
- def recognize(
- self,
- *,
- content: bytes,
- media_type: str,
- material_type: str,
- ) -> MaterialExtraction:
- assert content == b"invoice-image"
- assert media_type == "image/jpeg"
- assert material_type == "MEDICAL_INVOICE"
- return MaterialExtraction(
- fields={
- "invoice_no": "INV-20260727-001",
- "hospital_name": "成都市第一人民医院",
- "visit_date": "2026-07-20",
- "amount_yuan": "1280.50",
- },
- confidence=0.94,
- warnings=("请人工核对票据号码",),
- )
- def test_user_recognizes_confirms_and_submits_service_request() -> None:
- enrollments = InMemoryEnrollmentRepository()
- enrollments.save_policy(_policy())
- repository = InMemoryServiceRequestRepository()
- service = ServiceRequestService(
- repository,
- enrollments,
- FakeVisionGateway(),
- lambda: datetime(2026, 7, 27, 6, 0, tzinfo=UTC),
- )
- user = H5User(
- id="01USER00000000000000000001",
- mobile="13800138000",
- mobile_masked="138****8000",
- display_name="张先生",
- status="ACTIVE",
- created_at=datetime(2026, 7, 1, tzinfo=UTC),
- )
- recognition = service.recognize_material(
- user,
- policy_id="01POLICY00000000000000001",
- material_type="MEDICAL_INVOICE",
- source_name="医疗发票.jpg",
- media_type="image/jpeg",
- content=b"invoice-image",
- )
- request = service.submit_request(
- user,
- policy_id="01POLICY00000000000000001",
- request_type="MEDICAL_REIMBURSEMENT_ASSISTANCE",
- recognition_id=recognition["recognition_id"],
- confirmed_fields={
- **recognition["fields"],
- "contact_mobile": "13800138000",
- },
- )
- assert recognition["status"] == "PENDING_CONFIRMATION"
- assert "confidence" not in recognition
- assert request["request_no"].startswith("ZBT-SVC-20260727-")
- assert request["status"] == "SUBMITTED"
- assert service.list_user_requests(user)["total"] == 1
- assert "recognition" not in service.list_user_requests(user)["items"][0]
- admin_request = service.list_all_requests()["items"][0]
- assert admin_request["recognition"]["confidence"] == 0.94
- assert admin_request["recognition"]["material_available"] is True
- material, media_type, source_name = service.get_request_material(
- request["request_id"]
- )
- assert material.content == b"invoice-image"
- assert media_type == "image/jpeg"
- assert source_name == "医疗发票.jpg"
- reviewed = service.review_request(
- request["request_id"],
- decision="ACCEPTED",
- reviewer_id="01ADMIN000000000000000001",
- )
- assert reviewed["status"] == "ACCEPTED"
- assert reviewed["reviewed_by"] == "01ADMIN000000000000000001"
- assert reviewed["review_note"] is None
- assert service.list_user_requests(user)["items"][0]["status"] == "ACCEPTED"
- def test_user_cannot_recognize_material_for_another_users_policy() -> None:
- enrollments = InMemoryEnrollmentRepository()
- enrollments.save_policy(_policy())
- service = ServiceRequestService(
- InMemoryServiceRequestRepository(),
- enrollments,
- FakeVisionGateway(),
- lambda: datetime(2026, 7, 27, 6, 0, tzinfo=UTC),
- )
- another_user = H5User(
- id="01OTHER0000000000000000001",
- mobile="13900139000",
- mobile_masked="139****9000",
- display_name="李女士",
- status="ACTIVE",
- created_at=datetime(2026, 7, 1, tzinfo=UTC),
- )
- with pytest.raises(AppError) as caught:
- service.recognize_material(
- another_user,
- policy_id="01POLICY00000000000000001",
- material_type="MEDICAL_INVOICE",
- source_name="医疗发票.jpg",
- media_type="image/jpeg",
- content=b"invoice-image",
- )
- assert caught.value.code == "POLICY_NOT_FOUND"
- def test_rejected_request_uses_standard_reason() -> None:
- repository = InMemoryServiceRequestRepository()
- submitted_at = datetime(2026, 7, 27, 6, 0, tzinfo=UTC)
- repository.save_request(
- ServiceRequest(
- id="01SERVICE00000000000000001",
- request_no="ZBT-SVC-20260727-0001",
- user_id="01USER00000000000000000001",
- policy_id="01POLICY00000000000000001",
- request_type="MEDICAL_REIMBURSEMENT_ASSISTANCE",
- recognition_id="01RECOGNITION000000000001",
- confirmed_fields={},
- status="SUBMITTED",
- submitted_at=submitted_at,
- )
- )
- service = ServiceRequestService(
- repository,
- InMemoryEnrollmentRepository(),
- FakeVisionGateway(),
- lambda: submitted_at,
- )
- reviewed = service.review_request(
- "01SERVICE00000000000000001",
- decision="REJECTED",
- reviewer_id="01ADMIN000000000000000001",
- )
- assert reviewed["status"] == "REJECTED"
- assert reviewed["review_note"] == "不满足赔付条件"
- def _policy() -> Policy:
- return Policy(
- id="01POLICY00000000000000001",
- policy_no="POL-20260727-0001",
- order_id="01ORDER000000000000000001",
- user_id="01USER00000000000000000001",
- product_id="01PRODUCT0000000000000001",
- product_version_id="01VERSION0000000000000001",
- plan_id="01PLAN0000000000000000001",
- premium_cents=29900,
- currency="CNY",
- coverage_start=date(2026, 7, 28),
- coverage_end=date(2027, 7, 27),
- status="ACTIVE",
- issued_at=datetime(2026, 7, 27, 5, 0, tzinfo=UTC),
- )
|