# -*- coding: utf-8 -*- """业务层 · 补贴服务(政务三级审批状态机)。""" from __future__ import annotations from fastapi import HTTPException from ..infrastructure.repositories import Database # 各政务级别可推进的状态映射(领域规则) SUBSIDY_NEXT: dict[str, dict[str, str]] = { "gov_district": {"applying": "district_review"}, "gov_city": {"district_review": "city_review"}, "gov_province": {"city_review": "province_review", "province_review": "approved"}, } class SubsidyService: """补贴申报审批(区县→市→省→发放)。""" def __init__(self, db: Database): self.db = db async def approve(self, aid: str, user: dict) -> dict: """按级别推进补贴审批;越级/越权 403/400。""" sub = await self.db.subsidies.get(aid) if sub is None: raise HTTPException(status_code=404, detail="Subsidy not found") if sub.get("region_id") and sub["region_id"] not in user.get("scope_region_ids", []): raise HTTPException(status_code=403, detail="Forbidden: out of data scope") nxt = (SUBSIDY_NEXT.get(user.get("sub_role") or "") or {}).get(sub["status"]) if not nxt: raise HTTPException(status_code=400, detail="当前级别不能审批该状态") return await self.db.subsidies.set_status(aid, nxt) async def pay(self, aid: str) -> dict: """发放补贴:仅已终审(approved)可发放。""" sub = await self.db.subsidies.get(aid) if sub is None: raise HTTPException(status_code=404, detail="Subsidy not found") if sub["status"] != "approved": raise HTTPException(status_code=400, detail="仅已终审的补贴可发放") return await self.db.subsidies.set_status(aid, "paid")