413bd29390
- FinanceService:opc_add_finance 直写 ORM 改为走 Repository.create(修复四层依赖违规) - SettlementService:结算佣金(5%)/电子合同幂等/争议联动/投资撮合评分 - SubsidyService:政务三级审批状态机(区县→市→省→发放) - rbac_ecosystem/rbac_government/rbac_opc 接线,路由瘦身
277 lines
9.1 KiB
Python
277 lines
9.1 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""OPC 超级个体端端点(工作台聚合数据)。
|
|
|
|
所有数据均由服务端(SQLite 演示库)提供,前端不落地任何演示数据。
|
|
当前角色要求 opc_member;后续各页面端点在此扩展。
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, Request
|
|
from pydantic import BaseModel
|
|
|
|
from ..dependencies import get_db
|
|
from ...rbac import require_roles, write_audit
|
|
from ...infrastructure.repositories import Database, new_id, utcnow_iso
|
|
from ...infrastructure.models import FinanceRecord
|
|
|
|
router = APIRouter(prefix="/opc", tags=["opc"])
|
|
|
|
|
|
@router.get("/dashboard", summary="OPC 工作台总览")
|
|
async def opc_dashboard(
|
|
db: Database = Depends(get_db),
|
|
user: dict = Depends(require_roles("opc_member")),
|
|
):
|
|
"""返回当前 OPC 用户的工作台聚合数据(统计/进行中任务/智能体建议/月度收入/最新消息)。"""
|
|
uid = user["id"]
|
|
|
|
profile = await db.opc_profiles.get(uid)
|
|
task_counts = await db.opc_tasks.counts(uid)
|
|
opc_tasks = await db.opc_tasks.list_by_user(uid)
|
|
|
|
# 进行中任务:进行中/紧急优先,取前 3 条
|
|
active_tasks = [
|
|
t for t in opc_tasks if t["status"] in ("in_progress", "urgent")
|
|
][:3]
|
|
|
|
# 智能体建议(由服务端依据真实数据生成)
|
|
policy_count = len(
|
|
[c for c in await db.content.list(ctype="policy", status="published")]
|
|
)
|
|
agent_tips = [
|
|
{
|
|
"title": "政策匹配提醒",
|
|
"desc": f"{policy_count} 项新政策与您高度匹配",
|
|
"type": "policy",
|
|
},
|
|
{
|
|
"title": "报税截止提醒",
|
|
"desc": "本月报税截止 7月31日",
|
|
"type": "tax",
|
|
},
|
|
{
|
|
"title": "技能提升推荐",
|
|
"desc": "推荐参加 UI 设计研修班",
|
|
"type": "skill",
|
|
},
|
|
]
|
|
|
|
return {
|
|
"stats": {
|
|
"inProgressTasks": task_counts["in_progress"],
|
|
"completedTasks": task_counts["completed"],
|
|
"totalEarnings": await db.finance.total_income(uid),
|
|
"creditScore": (profile or {}).get("credit_score", 80),
|
|
},
|
|
"activeTasks": active_tasks,
|
|
"agentTips": agent_tips,
|
|
"monthlyIncome": await db.finance.monthly_income(uid),
|
|
"recentMessages": await db.messages.recent(uid, limit=4),
|
|
}
|
|
|
|
|
|
# ── OPC 子页面(全部由服务端提供标准数据)─────────────────────────────────
|
|
|
|
@router.get("/agent", summary="OPC 智能体助手")
|
|
async def opc_agent(
|
|
db: Database = Depends(get_db),
|
|
user: dict = Depends(require_roles("opc_member")),
|
|
):
|
|
agents = await db.agents.get_by_user(user["id"], port=user.get("port") or "opc")
|
|
default = next((a for a in agents if a.get("id", "").startswith("pine_agents_official_001")), None)
|
|
return {
|
|
"agent": {
|
|
"name": (default or {}).get("name", "小云"),
|
|
"desc": (default or {}).get("description", "您的智能体助手,可处理创业、政策、财税等事务"),
|
|
"port": user.get("port") or "opc",
|
|
},
|
|
"quick_actions": [
|
|
{"title": "查询政策", "desc": "为您匹配最新创业政策"},
|
|
{"title": "发布能力", "desc": "快速发布您的服务能力"},
|
|
{"title": "财务助手", "desc": "查看收入与支出"},
|
|
],
|
|
"chat_path": "/chat",
|
|
}
|
|
|
|
|
|
@router.get("/tasks", summary="任务广场(已发布平台任务)")
|
|
async def opc_task_square(
|
|
db: Database = Depends(get_db),
|
|
_u: dict = Depends(require_roles("opc_member")),
|
|
):
|
|
return {"items": await db.tasks.list(status="published")}
|
|
|
|
|
|
@router.get("/my-tasks", summary="我的任务看板")
|
|
async def opc_my_tasks(
|
|
db: Database = Depends(get_db),
|
|
user: dict = Depends(require_roles("opc_member")),
|
|
):
|
|
return {"items": await db.opc_tasks.list_by_user(user["id"])}
|
|
|
|
|
|
@router.get("/services", summary="服务市场(在营服务商)")
|
|
async def opc_services(
|
|
db: Database = Depends(get_db),
|
|
_u: dict = Depends(require_roles("opc_member")),
|
|
):
|
|
return {"items": await db.providers.list(status="active")}
|
|
|
|
|
|
@router.get("/policy", summary="政策列表(已发布政策)")
|
|
async def opc_policy(
|
|
db: Database = Depends(get_db),
|
|
_u: dict = Depends(require_roles("opc_member")),
|
|
):
|
|
return {"items": await db.content.list(ctype="policy", status="published")}
|
|
|
|
|
|
@router.get("/finance", summary="财务流水")
|
|
async def opc_finance(
|
|
db: Database = Depends(get_db),
|
|
user: dict = Depends(require_roles("opc_member")),
|
|
):
|
|
uid = user["id"]
|
|
return {
|
|
"records": await db.finance.list_by_user(uid),
|
|
"total_income": await db.finance.total_income(uid),
|
|
}
|
|
|
|
|
|
@router.get("/messages", summary="站内消息")
|
|
async def opc_messages(
|
|
db: Database = Depends(get_db),
|
|
user: dict = Depends(require_roles("opc_member")),
|
|
):
|
|
return {"items": await db.messages.list_by_user(user["id"])}
|
|
|
|
|
|
@router.get("/profile", summary="个人资料")
|
|
async def opc_profile(
|
|
db: Database = Depends(get_db),
|
|
user: dict = Depends(require_roles("opc_member")),
|
|
):
|
|
profile = await db.users.to_profile(user)
|
|
profile["opc_profile"] = await db.opc_profiles.get(user["id"])
|
|
return profile
|
|
|
|
|
|
class BidRequest(BaseModel):
|
|
quote: int = 0
|
|
plan: str = ""
|
|
|
|
|
|
@router.post("/tasks/{task_id}/grab", summary="OPC 抢单")
|
|
async def opc_grab(
|
|
task_id: str,
|
|
request: Request,
|
|
db: Database = Depends(get_db),
|
|
actor: dict = Depends(require_roles("opc_member")),
|
|
):
|
|
from ...services.task_service import TaskService
|
|
|
|
updated = await TaskService(db).grab(task_id, actor)
|
|
await write_audit(db, action="task.grab", resource="task", resource_id=task_id,
|
|
detail=actor.get("username"), user=actor, request=request)
|
|
return updated
|
|
|
|
|
|
@router.post("/tasks/{task_id}/bid", summary="OPC 投标")
|
|
async def opc_bid(
|
|
task_id: str,
|
|
req: BidRequest,
|
|
request: Request,
|
|
db: Database = Depends(get_db),
|
|
actor: dict = Depends(require_roles("opc_member")),
|
|
):
|
|
from ...services.task_service import TaskService
|
|
|
|
bid = await TaskService(db).bid(task_id, actor, req.quote, req.plan)
|
|
await write_audit(db, action="task.bid", resource="bid", resource_id=bid["id"],
|
|
user=actor, request=request)
|
|
return bid
|
|
|
|
|
|
@router.post("/tasks/{task_id}/deliver", summary="OPC 交付")
|
|
async def opc_deliver(
|
|
task_id: str,
|
|
request: Request,
|
|
db: Database = Depends(get_db),
|
|
actor: dict = Depends(require_roles("opc_member")),
|
|
):
|
|
from ...services.task_service import TaskService
|
|
|
|
updated = await TaskService(db).deliver(task_id, actor)
|
|
await write_audit(db, action="task.deliver", resource="task", resource_id=task_id,
|
|
user=actor, request=request)
|
|
return updated
|
|
|
|
|
|
class ProfileUpdate(BaseModel):
|
|
nickname: str | None = None
|
|
account: str | None = None
|
|
company: str | None = None
|
|
room: str | None = None
|
|
skills: list[str] = []
|
|
credit_score: int | None = None
|
|
|
|
|
|
@router.put("/profile", summary="OPC 基础资料编辑")
|
|
async def opc_update_profile(
|
|
req: ProfileUpdate,
|
|
request: Request,
|
|
db: Database = Depends(get_db),
|
|
actor: dict = Depends(require_roles("opc_member")),
|
|
):
|
|
profile_updates = {k: v for k, v in req.model_dump(exclude_none=True).items()
|
|
if k in ("nickname", "account", "company", "room")}
|
|
if profile_updates:
|
|
await db.users.update_profile(actor["id"], profile_updates)
|
|
if req.credit_score is not None:
|
|
await db.opc_profiles.upsert(actor["id"], req.credit_score)
|
|
await write_audit(db, action="profile.update", resource="user", resource_id=actor["id"],
|
|
user=actor, request=request)
|
|
fresh_user = await db.users.get_by_id(actor["id"])
|
|
return await opc_profile(db, fresh_user)
|
|
|
|
|
|
class FinanceRecordCreate(BaseModel):
|
|
category: str = "income" # income | expense
|
|
amount: int
|
|
date: str = ""
|
|
note: str = ""
|
|
|
|
|
|
@router.post("/finance/record", summary="OPC 记一笔收支")
|
|
async def opc_add_finance(
|
|
req: FinanceRecordCreate,
|
|
request: Request,
|
|
db: Database = Depends(get_db),
|
|
actor: dict = Depends(require_roles("opc_member")),
|
|
):
|
|
from ...services.finance_service import FinanceService
|
|
|
|
record = await FinanceService(db).add_record(
|
|
user_id=actor["id"], category=req.category, amount=req.amount,
|
|
date=req.date or utcnow_iso()[:10], note=req.note,
|
|
)
|
|
await write_audit(db, action="finance.add", resource="finance", resource_id=record["id"],
|
|
user=actor, request=request)
|
|
return record
|
|
|
|
|
|
@router.get("/tax", summary="OPC 税务申报")
|
|
async def opc_tax(
|
|
db: Database = Depends(get_db),
|
|
_u: dict = Depends(require_roles("opc_member")),
|
|
):
|
|
return await db.portal_pages.get("opc", "tax") or {"items": []}
|
|
|
|
|
|
@router.get("/affairs", summary="OPC 工商/政务办事")
|
|
async def opc_affairs(
|
|
db: Database = Depends(get_db),
|
|
_u: dict = Depends(require_roles("opc_member")),
|
|
):
|
|
return await db.portal_pages.get("opc", "affairs") or {"items": []}
|