413bd29390
- FinanceService:opc_add_finance 直写 ORM 改为走 Repository.create(修复四层依赖违规) - SettlementService:结算佣金(5%)/电子合同幂等/争议联动/投资撮合评分 - SubsidyService:政务三级审批状态机(区县→市→省→发放) - rbac_ecosystem/rbac_government/rbac_opc 接线,路由瘦身
150 lines
5.5 KiB
Python
150 lines
5.5 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""政务端端点(证明数据范围层级:上级可看下级,下级不可看上级)。"""
|
|
from __future__ import annotations
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, Request
|
|
|
|
from ..dependencies import get_db
|
|
from ...rbac import require_permission, require_scope, write_audit
|
|
from ...infrastructure.repositories import Database
|
|
|
|
router = APIRouter(prefix="/government", tags=["government"])
|
|
|
|
|
|
@router.get("/regions", summary="可见区域(按数据范围)")
|
|
async def list_regions(
|
|
db: Database = Depends(get_db),
|
|
user: dict = Depends(require_scope()),
|
|
):
|
|
"""返回当前政务账号数据范围内的区域(省级=全部,区县=仅本区县)。"""
|
|
all_regions = await db.regions.all()
|
|
visible = {rid for rid in user.get("scope_region_ids", [])}
|
|
return [r for r in all_regions if r["id"] in visible]
|
|
|
|
|
|
@router.get("/enterprises", summary="区域内企业列表")
|
|
async def list_enterprises(
|
|
request: Request,
|
|
db: Database = Depends(get_db),
|
|
user: dict = Depends(require_permission("menu:gov_data")),
|
|
):
|
|
"""返回数据范围内的甲方企业;每次访问写一条 data.view 审计。"""
|
|
orgs = await db.orgs.list_by_region(user.get("scope_region_ids", []))
|
|
enterprises = [o for o in orgs if o["type"] == "enterprise"]
|
|
await write_audit(
|
|
db, action="data.view", resource="enterprise",
|
|
detail=f"scope={user.get('scope_region_ids', [])}",
|
|
user=user, request=request,
|
|
)
|
|
return enterprises
|
|
|
|
|
|
@router.get("/enterprises/{org_id}", summary="企业详情(范围校验)")
|
|
async def get_enterprise(
|
|
org_id: str,
|
|
request: Request,
|
|
db: Database = Depends(get_db),
|
|
user: dict = Depends(require_permission("menu:gov_data")),
|
|
):
|
|
org = await db.orgs.get(org_id)
|
|
if org is None or org["type"] != "enterprise":
|
|
raise HTTPException(status_code=404, detail="Enterprise not found")
|
|
if org["region_id"] not in user.get("scope_region_ids", []):
|
|
raise HTTPException(status_code=403, detail="Forbidden: out of data scope")
|
|
return org
|
|
|
|
|
|
# ── 三级数据范围:范围内 OPC / 载体 / 数据看板 ────────────────────────────
|
|
|
|
def _in_scope(region_id, user) -> bool:
|
|
return region_id in user.get("scope_region_ids", [])
|
|
|
|
|
|
@router.get("/opc", summary="范围内 OPC 列表")
|
|
async def gov_opc(
|
|
db: Database = Depends(get_db),
|
|
user: dict = Depends(require_permission("menu:gov_data")),
|
|
):
|
|
opcs = [u for u in await db.users.list() if u.get("role") == "opc_member"]
|
|
opcs = [u for u in opcs if _in_scope(u.get("region_id"), user)]
|
|
return {"items": [
|
|
{"title": u.get("nickname") or u.get("username"), "meta": f"信用 {u.get('region_id', '')} · OPC",
|
|
"tag": "OPC"}
|
|
for u in opcs
|
|
]}
|
|
|
|
|
|
@router.get("/carriers", summary="范围内载体列表")
|
|
async def gov_carriers(
|
|
db: Database = Depends(get_db),
|
|
user: dict = Depends(require_permission("menu:gov_data")),
|
|
):
|
|
carriers = [o for o in await db.orgs.all() if o["type"] == "carrier"]
|
|
carriers = [o for o in carriers if _in_scope(o.get("region_id"), user)]
|
|
return {"items": [
|
|
{"title": o["name"], "meta": f"{o.get('region_id', '')} · 载体", "tag": "载体"}
|
|
for o in carriers
|
|
]}
|
|
|
|
|
|
@router.get("/data", summary="范围内数据看板")
|
|
async def gov_data(
|
|
db: Database = Depends(get_db),
|
|
user: dict = Depends(require_permission("menu:gov_data")),
|
|
):
|
|
scope = user.get("scope_region_ids", [])
|
|
stats = await db.stats.overview(region_ids=scope)
|
|
return {
|
|
"stats": [
|
|
{"key": "totalOPC", "value": stats["user_count"]},
|
|
{"key": "taskTotal", "value": stats["task_count"]},
|
|
{"key": "carrierTotal", "value": stats["provider_count"]},
|
|
{"key": "policyTotal", "value": stats["content_count"]},
|
|
],
|
|
"chart": [
|
|
{"label": "6月", "value": 3200}, {"label": "7月", "value": 3600},
|
|
{"label": "8月", "value": 4100},
|
|
],
|
|
"scope": scope,
|
|
}
|
|
|
|
|
|
# ── 补贴三级审批(区县→市→省→发放)─────────────────────────────────────────
|
|
|
|
@router.get("/subsidies", summary="范围内补贴申报列表")
|
|
async def gov_subsidies(
|
|
db: Database = Depends(get_db),
|
|
user: dict = Depends(require_permission("menu:gov_data")),
|
|
):
|
|
return {"items": await db.subsidies.list(user.get("scope_region_ids", []))}
|
|
|
|
|
|
@router.post("/subsidies/{aid}/approve", summary="补贴审批(按级别推进)")
|
|
async def gov_approve_subsidy(
|
|
aid: str,
|
|
request: Request,
|
|
db: Database = Depends(get_db),
|
|
user: dict = Depends(require_permission("menu:gov_data")),
|
|
):
|
|
from ...services.subsidy_service import SubsidyService
|
|
|
|
updated = await SubsidyService(db).approve(aid, user)
|
|
await write_audit(db, action="subsidy.approve", resource="subsidy", resource_id=aid,
|
|
detail=updated.get("status"), user=user, request=request)
|
|
return updated
|
|
|
|
|
|
@router.post("/subsidies/{aid}/pay", summary="补贴发放")
|
|
async def gov_pay_subsidy(
|
|
aid: str,
|
|
request: Request,
|
|
db: Database = Depends(get_db),
|
|
user: dict = Depends(require_permission("menu:gov_data")),
|
|
):
|
|
from ...services.subsidy_service import SubsidyService
|
|
|
|
updated = await SubsidyService(db).pay(aid)
|
|
await write_audit(db, action="subsidy.pay", resource="subsidy", resource_id=aid,
|
|
user=user, request=request)
|
|
return updated
|