"""PlanData Snapshot 鉴权 API。""" from flask import Blueprint, jsonify, request from insurance.middleware.auth_middleware import jwt_required plan_snapshot_bp = Blueprint("insurance_plan_snapshots", __name__) def _response(data=None, message="success", code=0, status=200): return jsonify({"code": code, "message": message, "data": data}), status def _run(action): from insurance.plan_data.service import SnapshotError try: return action() except SnapshotError as exc: return _response( {"errorCode": exc.code, **exc.data}, exc.message, 4201 if exc.status < 500 else 5001, exc.status, ) @plan_snapshot_bp.route("", methods=["POST"]) @jwt_required def create_plan_snapshot(): from insurance.plan_data.service import create_draft_from_legacy, create_snapshot user_id = str(getattr(request, "user_id", "guest")) payload = request.get_json(silent=True) or {} def action(): document_id = int(payload.get("documentId") or 0) if isinstance(payload.get("planData"), dict): snapshot = create_snapshot(document_id, user_id, payload["planData"], status="draft") else: snapshot = create_draft_from_legacy( document_id, user_id, payload.get("extraction") or {}, evidence_entries=payload.get("evidence") or [], ) return _response(snapshot.to_public_dict(), status=201) return _run(action) @plan_snapshot_bp.route("/", methods=["GET"]) @jwt_required def get_plan_snapshot(snapshot_id: int): from insurance.plan_data.service import SnapshotError, get_owned_snapshot user_id = str(getattr(request, "user_id", "guest")) def action(): snapshot = get_owned_snapshot(snapshot_id, user_id) if not snapshot: raise SnapshotError("SNAPSHOT_NOT_FOUND", "快照不存在", status=404) return _response(snapshot.to_public_dict()) return _run(action) @plan_snapshot_bp.route("//evidence", methods=["GET"]) @jwt_required def get_snapshot_evidence(snapshot_id: int): from insurance.plan_data.service import list_evidence user_id = str(getattr(request, "user_id", "guest")) field_path = str(request.args.get("fieldPath") or "").strip() page = max(1, request.args.get("page", 1, type=int)) page_size = min(100, max(1, request.args.get("pageSize", 50, type=int))) return _run(lambda: _response(list_evidence(snapshot_id, user_id, field_path, page, page_size))) @plan_snapshot_bp.route("//draft", methods=["PATCH"]) @jwt_required def update_snapshot_draft(snapshot_id: int): from insurance.plan_data.service import patch_draft user_id = str(getattr(request, "user_id", "guest")) payload = request.get_json(silent=True) or {} return _run(lambda: _response(patch_draft( snapshot_id, user_id, expected_hash=str(payload.get("expectedHash") or ""), changes=payload.get("changes") or [], ).to_public_dict())) @plan_snapshot_bp.route("//validate", methods=["POST"]) @jwt_required def validate_plan_snapshot(snapshot_id: int): from insurance.plan_data.service import validate_snapshot user_id = str(getattr(request, "user_id", "guest")) return _run(lambda: _response(validate_snapshot(snapshot_id, user_id))) @plan_snapshot_bp.route("//confirm", methods=["POST"]) @jwt_required def confirm_plan_snapshot(snapshot_id: int): from insurance.plan_data.service import confirm_snapshot user_id = str(getattr(request, "user_id", "guest")) return _run(lambda: _response(confirm_snapshot(snapshot_id, user_id).to_public_dict(), status=201)) @plan_snapshot_bp.route("//poster-projection", methods=["GET"]) @jwt_required def poster_projection(snapshot_id: int): from insurance.plan_data.projections import to_poster_projection from insurance.plan_data.service import SnapshotError, get_owned_snapshot user_id = str(getattr(request, "user_id", "guest")) def action(): snapshot = get_owned_snapshot(snapshot_id, user_id) if not snapshot: raise SnapshotError("SNAPSHOT_NOT_FOUND", "快照不存在", status=404) if snapshot.status != "confirmed": raise SnapshotError("SNAPSHOT_NOT_CONFIRMED", "只有 confirmed 快照可以投影", status=422) return _response({ "snapshotId": snapshot.id, "snapshotHash": snapshot.snapshot_hash, "projection": to_poster_projection(snapshot.plan_data()), }) return _run(action) @plan_snapshot_bp.route("//deck-contract", methods=["GET"]) @jwt_required def deck_contract(snapshot_id: int): from insurance.plan_data.projections import to_deck_contract from insurance.plan_data.service import SnapshotError, get_owned_snapshot user_id = str(getattr(request, "user_id", "guest")) def action(): snapshot = get_owned_snapshot(snapshot_id, user_id) if not snapshot: raise SnapshotError("SNAPSHOT_NOT_FOUND", "快照不存在", status=404) if snapshot.status != "confirmed": raise SnapshotError("SNAPSHOT_NOT_CONFIRMED", "只有 confirmed 快照可以投影", status=422) return _response({ "snapshotId": snapshot.id, "snapshotHash": snapshot.snapshot_hash, "deckContract": to_deck_contract(snapshot.plan_data(), document_sha256=snapshot.document_sha256), }) return _run(action)