| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653 |
- from datetime import UTC, date, datetime
- from fastapi.testclient import TestClient
- from zbt.commands.seed import build_seed_manifest
- from zbt.core.config import Settings
- from zbt.core.passwords import PasswordService
- from zbt.domains.catalog.repository import InMemoryCatalogRepository
- from zbt.domains.enrollment.models import Policy
- from zbt.domains.enrollment.repository import InMemoryEnrollmentRepository
- from zbt.domains.identity.repository import InMemoryIdentityRepository
- from zbt.main import create_app
- NOW = datetime(2026, 7, 26, 10, 0, tzinfo=UTC)
- def test_active_policy_owner_can_preview_deterministic_surrender_refund() -> None:
- identities = InMemoryIdentityRepository()
- enrollments = InMemoryEnrollmentRepository()
- app = create_app(
- settings=Settings(
- app_env="test",
- jwt_access_secret="a" * 32,
- jwt_refresh_secret="b" * 32,
- field_encryption_key="c" * 32,
- ),
- identity_repository=identities,
- catalog_repository=InMemoryCatalogRepository(),
- enrollment_repository=enrollments,
- clock=lambda: NOW,
- )
- with TestClient(app) as client:
- token = client.post(
- "/api/v1/h5/auth/login",
- json={"mobile": "18800000001", "code": "147258"},
- ).json()["data"]["tokens"]["access_token"]
- user = identities.get_h5_user_by_mobile("18800000001")
- assert user is not None
- enrollments.save_policy(
- Policy(
- id="01KZ0000000000000000000001",
- policy_no="ZBT-P-20260701-0001",
- order_id="01KZ0000000000000000000002",
- user_id=user.id,
- product_id="01KZ0000000000000000000003",
- product_version_id="01KZ0000000000000000000004",
- plan_id="01KZ0000000000000000000005",
- premium_cents=36_500,
- currency="CNY",
- coverage_start=date(2026, 7, 1),
- coverage_end=date(2027, 6, 30),
- status="ACTIVE",
- issued_at=datetime(2026, 7, 1, 8, 0, tzinfo=UTC),
- )
- )
- response = client.get(
- "/api/v1/h5/policies/01KZ0000000000000000000001/surrender-preview",
- headers={"Authorization": f"Bearer {token}"},
- )
- assert response.status_code == 200
- assert response.json()["data"] == {
- "policy_id": "01KZ0000000000000000000001",
- "policy_no": "ZBT-P-20260701-0001",
- "eligible": True,
- "reason_code": "ELIGIBLE",
- "reason": "保单符合退保申请条件",
- "refund_amount_cents": 30_600,
- "refund_basis": "UNEARNED_PREMIUM_WITH_DEDUCTION",
- "refund_explanation": (
- "已超过10天犹豫期,按剩余保障天数折算未满期保费,并扣减10%。"
- ),
- "currency": "CNY",
- "rule_version": "surrender-v1",
- "calculation": {
- "premium_cents": 36_500,
- "total_days": 365,
- "elapsed_days": 25,
- "remaining_days": 340,
- "gross_unearned_cents": 34_000,
- "deduction_cents": 3_400,
- "cooling_off": False,
- "pre_effective": False,
- },
- }
- def test_newly_issued_policy_can_be_cancelled_before_coverage_starts() -> None:
- identities = InMemoryIdentityRepository()
- enrollments = InMemoryEnrollmentRepository()
- app = create_app(
- settings=Settings(
- app_env="test",
- jwt_access_secret="a" * 32,
- jwt_refresh_secret="b" * 32,
- field_encryption_key="c" * 32,
- ),
- identity_repository=identities,
- catalog_repository=InMemoryCatalogRepository(),
- enrollment_repository=enrollments,
- clock=lambda: NOW,
- )
- with TestClient(app) as client:
- token = client.post(
- "/api/v1/h5/auth/login",
- json={"mobile": "18800000001", "code": "147258"},
- ).json()["data"]["tokens"]["access_token"]
- user = identities.get_h5_user_by_mobile("18800000001")
- assert user is not None
- enrollments.save_policy(
- Policy(
- id="01KZ0000000000000000000006",
- policy_no="POL-20260726-NEW001",
- order_id="01KZ0000000000000000000007",
- user_id=user.id,
- product_id="01KZ0000000000000000000008",
- product_version_id="01KZ0000000000000000000009",
- plan_id="01KZ0000000000000000000010",
- premium_cents=15_900,
- currency="CNY",
- coverage_start=date(2026, 7, 27),
- coverage_end=date(2027, 7, 26),
- status="ACTIVE",
- issued_at=NOW,
- )
- )
- response = client.get(
- "/api/v1/h5/policies/01KZ0000000000000000000006/surrender-preview",
- headers={"Authorization": f"Bearer {token}"},
- )
- created = client.post(
- "/api/v1/h5/surrenders",
- headers={
- "Authorization": f"Bearer {token}",
- "Idempotency-Key": "pre-effective-surrender-001",
- },
- json={
- "policy_id": "01KZ0000000000000000000006",
- "reason": "保障计划调整",
- },
- )
- request_id = created.json()["data"]["request_id"]
- confirmed = client.post(
- f"/api/v1/h5/surrenders/{request_id}/confirm",
- headers={"Authorization": f"Bearer {token}"},
- )
- assert response.status_code == 200
- assert response.json()["data"] == {
- "policy_id": "01KZ0000000000000000000006",
- "policy_no": "POL-20260726-NEW001",
- "eligible": True,
- "reason_code": "ELIGIBLE",
- "reason": "保单符合退保申请条件",
- "refund_amount_cents": 15_900,
- "refund_basis": "PRE_EFFECTIVE_FULL_REFUND",
- "refund_explanation": "保单保障尚未开始,按已交保费全额退还。",
- "currency": "CNY",
- "rule_version": "surrender-v1",
- "calculation": {
- "premium_cents": 15_900,
- "total_days": 365,
- "elapsed_days": 0,
- "remaining_days": 365,
- "gross_unearned_cents": 15_900,
- "deduction_cents": 0,
- "cooling_off": False,
- "pre_effective": True,
- },
- }
- assert created.status_code == 201
- assert created.json()["data"]["status"] == "PENDING_CONFIRMATION"
- assert created.json()["data"]["calculation"]["pre_effective"] is True
- assert confirmed.status_code == 200
- assert confirmed.json()["data"]["status"] == "REFUND_PENDING"
- assert confirmed.json()["data"]["risk_level"] == "LOW"
- policy = enrollments.get_policy("01KZ0000000000000000000006")
- assert policy is not None
- assert policy.status == "SURRENDERING"
- def test_surrender_submission_is_idempotent_and_waits_for_customer_confirmation() -> None:
- identities = InMemoryIdentityRepository()
- enrollments = InMemoryEnrollmentRepository()
- app = create_app(
- settings=Settings(
- app_env="test",
- jwt_access_secret="a" * 32,
- jwt_refresh_secret="b" * 32,
- field_encryption_key="c" * 32,
- ),
- identity_repository=identities,
- catalog_repository=InMemoryCatalogRepository(),
- enrollment_repository=enrollments,
- clock=lambda: NOW,
- )
- with TestClient(app) as client:
- token = client.post(
- "/api/v1/h5/auth/login",
- json={"mobile": "18800000001", "code": "147258"},
- ).json()["data"]["tokens"]["access_token"]
- user = identities.get_h5_user_by_mobile("18800000001")
- assert user is not None
- enrollments.save_policy(
- Policy(
- id="01KZ0000000000000000000011",
- policy_no="ZBT-P-20260701-0011",
- order_id="01KZ0000000000000000000012",
- user_id=user.id,
- product_id="01KZ0000000000000000000013",
- product_version_id="01KZ0000000000000000000014",
- plan_id="01KZ0000000000000000000015",
- premium_cents=36_500,
- currency="CNY",
- coverage_start=date(2026, 7, 1),
- coverage_end=date(2027, 6, 30),
- status="ACTIVE",
- issued_at=datetime(2026, 7, 1, 8, 0, tzinfo=UTC),
- )
- )
- headers = {
- "Authorization": f"Bearer {token}",
- "Idempotency-Key": "surrender-client-001",
- }
- payload = {
- "policy_id": "01KZ0000000000000000000011",
- "reason": "保障计划调整",
- }
- first = client.post("/api/v1/h5/surrenders", headers=headers, json=payload)
- repeated = client.post("/api/v1/h5/surrenders", headers=headers, json=payload)
- assert first.status_code == 201
- assert first.json()["data"]["status"] == "PENDING_CONFIRMATION"
- assert first.json()["data"]["refund_amount_cents"] == 30_600
- assert first.json()["data"]["request_no"].startswith("ZBT-TB-20260726-")
- assert repeated.status_code == 200
- assert repeated.json()["data"]["request_id"] == first.json()["data"]["request_id"]
- def test_customer_confirmation_pauses_workflow_for_operations_approval() -> None:
- identities = InMemoryIdentityRepository()
- enrollments = InMemoryEnrollmentRepository()
- app = create_app(
- settings=Settings(
- app_env="test",
- jwt_access_secret="a" * 32,
- jwt_refresh_secret="b" * 32,
- field_encryption_key="c" * 32,
- ),
- identity_repository=identities,
- catalog_repository=InMemoryCatalogRepository(),
- enrollment_repository=enrollments,
- clock=lambda: NOW,
- )
- with TestClient(app) as client:
- token = client.post(
- "/api/v1/h5/auth/login",
- json={"mobile": "18800000001", "code": "147258"},
- ).json()["data"]["tokens"]["access_token"]
- user = identities.get_h5_user_by_mobile("18800000001")
- assert user is not None
- enrollments.save_policy(
- Policy(
- id="01KZ0000000000000000000021",
- policy_no="ZBT-P-20260701-0021",
- order_id="01KZ0000000000000000000022",
- user_id=user.id,
- product_id="01KZ0000000000000000000023",
- product_version_id="01KZ0000000000000000000024",
- plan_id="01KZ0000000000000000000025",
- premium_cents=36_500,
- currency="CNY",
- coverage_start=date(2026, 7, 1),
- coverage_end=date(2027, 6, 30),
- status="ACTIVE",
- issued_at=datetime(2026, 7, 1, 8, 0, tzinfo=UTC),
- )
- )
- headers = {
- "Authorization": f"Bearer {token}",
- "Idempotency-Key": "surrender-client-002",
- }
- created = client.post(
- "/api/v1/h5/surrenders",
- headers=headers,
- json={
- "policy_id": "01KZ0000000000000000000021",
- "reason": "保障计划调整",
- },
- ).json()["data"]
- confirmed = client.post(
- f"/api/v1/h5/surrenders/{created['request_id']}/confirm",
- headers={"Authorization": f"Bearer {token}"},
- )
- detail = client.get(
- f"/api/v1/h5/surrenders/{created['request_id']}",
- headers={"Authorization": f"Bearer {token}"},
- )
- assert confirmed.status_code == 200
- assert confirmed.json()["data"]["status"] == "WAITING_APPROVAL"
- assert confirmed.json()["data"]["workflow"]["paused"] is True
- assert confirmed.json()["data"]["workflow"]["step"] == "OPERATIONS_APPROVAL"
- assert detail.status_code == 200
- assert [item["event_type"] for item in detail.json()["data"]["timeline"]] == [
- "REQUEST_CREATED",
- "CUSTOMER_CONFIRMED",
- "RISK_ASSESSED",
- "WAITING_APPROVAL",
- ]
- def test_low_risk_surrender_is_auto_approved_and_enters_refund_queue() -> None:
- identities = InMemoryIdentityRepository()
- enrollments = InMemoryEnrollmentRepository()
- app = create_app(
- settings=Settings(
- app_env="test",
- jwt_access_secret="a" * 32,
- jwt_refresh_secret="b" * 32,
- field_encryption_key="c" * 32,
- ),
- identity_repository=identities,
- catalog_repository=InMemoryCatalogRepository(),
- enrollment_repository=enrollments,
- clock=lambda: NOW,
- )
- with TestClient(app) as client:
- token = client.post(
- "/api/v1/h5/auth/login",
- json={"mobile": "18800000001", "code": "147258"},
- ).json()["data"]["tokens"]["access_token"]
- user = identities.get_h5_user_by_mobile("18800000001")
- assert user is not None
- policy_id = "01KZ0000000000000000000061"
- enrollments.save_policy(
- Policy(
- id=policy_id,
- policy_no="ZBT-P-20260701-0061",
- order_id="01KZ0000000000000000000062",
- user_id=user.id,
- product_id="01KZ0000000000000000000063",
- product_version_id="01KZ0000000000000000000064",
- plan_id="01KZ0000000000000000000065",
- premium_cents=19_900,
- currency="CNY",
- coverage_start=date(2026, 7, 1),
- coverage_end=date(2027, 6, 30),
- status="ACTIVE",
- issued_at=datetime(2026, 7, 1, 8, 0, tzinfo=UTC),
- )
- )
- created = client.post(
- "/api/v1/h5/surrenders",
- headers={
- "Authorization": f"Bearer {token}",
- "Idempotency-Key": "surrender-low-risk-001",
- },
- json={"policy_id": policy_id, "reason": "保障计划调整"},
- ).json()["data"]
- confirmed = client.post(
- f"/api/v1/h5/surrenders/{created['request_id']}/confirm",
- headers={"Authorization": f"Bearer {token}"},
- )
- detail = client.get(
- f"/api/v1/h5/surrenders/{created['request_id']}",
- headers={"Authorization": f"Bearer {token}"},
- ).json()["data"]
- assert confirmed.status_code == 200
- assert confirmed.json()["data"]["status"] == "REFUND_PENDING"
- assert confirmed.json()["data"]["risk_level"] == "LOW"
- assert confirmed.json()["data"]["workflow"]["paused"] is False
- assert confirmed.json()["data"]["workflow"]["step"] == "AUTO_APPROVED"
- assert {
- event["node"]
- for event in confirmed.json()["data"]["workflow"]["node_events"]
- } >= {
- "planner",
- "check_amount",
- "check_reason",
- "check_cooling_off",
- "aggregate_risk",
- "auto_approved",
- }
- assert [item["event_type"] for item in detail["timeline"]] == [
- "REQUEST_CREATED",
- "CUSTOMER_CONFIRMED",
- "RISK_ASSESSED",
- "AUTO_APPROVED",
- "REFUND_PROCESSING",
- ]
- policy = enrollments.get_policy(policy_id)
- assert policy is not None
- assert policy.status == "SURRENDERING"
- def test_surrender_reason_detail_can_trigger_sensitive_reason_review() -> None:
- identities = InMemoryIdentityRepository()
- enrollments = InMemoryEnrollmentRepository()
- app = create_app(
- settings=Settings(
- app_env="test",
- jwt_access_secret="a" * 32,
- jwt_refresh_secret="b" * 32,
- field_encryption_key="c" * 32,
- ),
- identity_repository=identities,
- catalog_repository=InMemoryCatalogRepository(),
- enrollment_repository=enrollments,
- clock=lambda: NOW,
- )
- with TestClient(app) as client:
- token = client.post(
- "/api/v1/h5/auth/login",
- json={"mobile": "18800000001", "code": "147258"},
- ).json()["data"]["tokens"]["access_token"]
- user = identities.get_h5_user_by_mobile("18800000001")
- assert user is not None
- policy_id = "01KZ0000000000000000000071"
- enrollments.save_policy(
- Policy(
- id=policy_id,
- policy_no="ZBT-P-20260701-0071",
- order_id="01KZ0000000000000000000072",
- user_id=user.id,
- product_id="01KZ0000000000000000000073",
- product_version_id="01KZ0000000000000000000074",
- plan_id="01KZ0000000000000000000075",
- premium_cents=19_900,
- currency="CNY",
- coverage_start=date(2026, 7, 1),
- coverage_end=date(2027, 6, 30),
- status="ACTIVE",
- issued_at=datetime(2026, 7, 1, 8, 0, tzinfo=UTC),
- )
- )
- created_response = client.post(
- "/api/v1/h5/surrenders",
- headers={
- "Authorization": f"Bearer {token}",
- "Idempotency-Key": "surrender-sensitive-reason-001",
- },
- json={
- "policy_id": policy_id,
- "reason_category": "其他原因",
- "reason_detail": "发现存在重复扣费,希望人工协助核实。",
- },
- )
- created = created_response.json()["data"]
- confirmed = client.post(
- f"/api/v1/h5/surrenders/{created['request_id']}/confirm",
- headers={"Authorization": f"Bearer {token}"},
- )
- assert created_response.status_code == 201
- assert created["reason"] == "其他原因:发现存在重复扣费,希望人工协助核实。"
- assert confirmed.status_code == 200
- assert confirmed.json()["data"]["status"] == "WAITING_APPROVAL"
- assert confirmed.json()["data"]["risk_level"] == "HIGH"
- assert any(
- "重复扣费" in reason
- for reason in confirmed.json()["data"]["risk_reasons"]
- )
- def test_operations_approval_resumes_workflow_and_marks_policy_surrendering() -> None:
- identities = InMemoryIdentityRepository()
- enrollments = InMemoryEnrollmentRepository()
- manifest = build_seed_manifest(PasswordService().hash("zaq1XSW@"))
- for admin in manifest.admin_users:
- identities.save_admin_user(admin)
- app = create_app(
- settings=Settings(
- app_env="test",
- jwt_access_secret="a" * 32,
- jwt_refresh_secret="b" * 32,
- field_encryption_key="c" * 32,
- ),
- identity_repository=identities,
- catalog_repository=InMemoryCatalogRepository(),
- enrollment_repository=enrollments,
- clock=lambda: NOW,
- )
- with TestClient(app) as client:
- h5_token = client.post(
- "/api/v1/h5/auth/login",
- json={"mobile": "18800000001", "code": "147258"},
- ).json()["data"]["tokens"]["access_token"]
- user = identities.get_h5_user_by_mobile("18800000001")
- assert user is not None
- policy_id = "01KZ0000000000000000000031"
- enrollments.save_policy(
- Policy(
- id=policy_id,
- policy_no="ZBT-P-20260701-0031",
- order_id="01KZ0000000000000000000032",
- user_id=user.id,
- product_id="01KZ0000000000000000000033",
- product_version_id="01KZ0000000000000000000034",
- plan_id="01KZ0000000000000000000035",
- premium_cents=36_500,
- currency="CNY",
- coverage_start=date(2026, 7, 1),
- coverage_end=date(2027, 6, 30),
- status="ACTIVE",
- issued_at=datetime(2026, 7, 1, 8, 0, tzinfo=UTC),
- )
- )
- h5_headers = {
- "Authorization": f"Bearer {h5_token}",
- "Idempotency-Key": "surrender-client-003",
- }
- created = client.post(
- "/api/v1/h5/surrenders",
- headers=h5_headers,
- json={"policy_id": policy_id, "reason": "保障计划调整"},
- ).json()["data"]
- client.post(
- f"/api/v1/h5/surrenders/{created['request_id']}/confirm",
- headers={"Authorization": f"Bearer {h5_token}"},
- )
- admin_token = client.post(
- "/api/v1/admin/auth/login",
- json={"username": "admin", "password": "zaq1XSW@"},
- ).json()["data"]["tokens"]["access_token"]
- admin_headers = {"Authorization": f"Bearer {admin_token}"}
- rejected_without_note = client.post(
- f"/api/v1/admin/surrenders/{created['request_id']}/review",
- headers=admin_headers,
- json={"decision": "REJECT", "note": " "},
- )
- approved = client.post(
- f"/api/v1/admin/surrenders/{created['request_id']}/review",
- headers=admin_headers,
- json={"decision": "APPROVE", "note": "资料与退款试算无误"},
- )
- repeated = client.post(
- f"/api/v1/admin/surrenders/{created['request_id']}/review",
- headers=admin_headers,
- json={"decision": "APPROVE", "note": "重复审批"},
- )
- assert rejected_without_note.status_code == 400
- assert rejected_without_note.json()["error"]["code"] == (
- "SURRENDER_REJECTION_NOTE_REQUIRED"
- )
- assert approved.status_code == 200
- assert approved.json()["data"]["status"] == "REFUND_PENDING"
- assert repeated.status_code == 200
- assert repeated.json()["data"]["status"] == "REFUND_PENDING"
- policy = enrollments.get_policy(policy_id)
- assert policy is not None
- assert policy.status == "SURRENDERING"
- def test_outbox_worker_completes_approved_refund_idempotently() -> None:
- identities = InMemoryIdentityRepository()
- enrollments = InMemoryEnrollmentRepository()
- manifest = build_seed_manifest(PasswordService().hash("zaq1XSW@"))
- for admin in manifest.admin_users:
- identities.save_admin_user(admin)
- app = create_app(
- settings=Settings(
- app_env="test",
- jwt_access_secret="a" * 32,
- jwt_refresh_secret="b" * 32,
- field_encryption_key="c" * 32,
- ),
- identity_repository=identities,
- catalog_repository=InMemoryCatalogRepository(),
- enrollment_repository=enrollments,
- clock=lambda: NOW,
- )
- with TestClient(app) as client:
- h5_token = client.post(
- "/api/v1/h5/auth/login",
- json={"mobile": "18800000001", "code": "147258"},
- ).json()["data"]["tokens"]["access_token"]
- user = identities.get_h5_user_by_mobile("18800000001")
- assert user is not None
- policy_id = "01KZ0000000000000000000041"
- enrollments.save_policy(
- Policy(
- id=policy_id,
- policy_no="ZBT-P-20260701-0041",
- order_id="01KZ0000000000000000000042",
- user_id=user.id,
- product_id="01KZ0000000000000000000043",
- product_version_id="01KZ0000000000000000000044",
- plan_id="01KZ0000000000000000000045",
- premium_cents=36_500,
- currency="CNY",
- coverage_start=date(2026, 7, 1),
- coverage_end=date(2027, 6, 30),
- status="ACTIVE",
- issued_at=datetime(2026, 7, 1, 8, 0, tzinfo=UTC),
- )
- )
- created = client.post(
- "/api/v1/h5/surrenders",
- headers={
- "Authorization": f"Bearer {h5_token}",
- "Idempotency-Key": "surrender-client-004",
- },
- json={"policy_id": policy_id, "reason": "保障计划调整"},
- ).json()["data"]
- client.post(
- f"/api/v1/h5/surrenders/{created['request_id']}/confirm",
- headers={"Authorization": f"Bearer {h5_token}"},
- )
- admin_token = client.post(
- "/api/v1/admin/auth/login",
- json={"username": "admin", "password": "zaq1XSW@"},
- ).json()["data"]["tokens"]["access_token"]
- admin_headers = {"Authorization": f"Bearer {admin_token}"}
- client.post(
- f"/api/v1/admin/surrenders/{created['request_id']}/review",
- headers=admin_headers,
- json={"decision": "APPROVE", "note": "审批通过"},
- )
- dispatched = app.state.refund_worker.run_once()
- repeated = app.state.refund_worker.run_once()
- completed = client.get(
- f"/api/v1/h5/surrenders/{created['request_id']}",
- headers={"Authorization": f"Bearer {h5_token}"},
- )
- assert dispatched["processed"] == 1
- assert dispatched["items"][0]["status"] == "SUCCEEDED"
- assert repeated["processed"] == 0
- assert completed.status_code == 200
- assert completed.json()["data"]["status"] == "REFUNDED"
- assert completed.json()["data"]["refund_attempts"][-1]["status"] == "SUCCEEDED"
- assert completed.json()["data"]["timeline"][-1]["event_type"] == "REFUND_SUCCEEDED"
- policy = enrollments.get_policy(policy_id)
- assert policy is not None
- assert policy.status == "SURRENDERED"
|