admin / Apex
publicBid Management and Orchestration Tool with AI Capability
Apex / Synapse-Apexv2 / backend / app / routers / capabilities.py
4111 B · main
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | from fastapi import APIRouter, Depends, Form, HTTPException, UploadFile from sqlalchemy import select from sqlalchemy.orm import Session from app.core.database import get_db from app.core.deps import audit, require_roles from app.models import ( ROLE_ADMIN, ROLE_BID_MANAGER, ROLE_CONTRIBUTOR, Capability, CapabilityResponse, Document, User, ) from app.schemas import CapabilityOut, CapabilityUpdate from app.services import storage from app.workers.tasks import extract_capabilities, regenerate_capability_response router = APIRouter(prefix="/api/capabilities", tags=["capabilities"]) editor = require_roles(ROLE_ADMIN, ROLE_BID_MANAGER, ROLE_CONTRIBUTOR) @router.post("/upload") async def upload_docs( kind: str = Form("service"), framework_ids: str = Form(""), files: list[UploadFile] = None, db: Session = Depends(get_db), actor: User = Depends(editor), ): if not files: raise HTTPException(400, "No files") doc_ids = [] for f in files: data = await f.read() path, sha = storage.save_file(data, f.filename) text = storage.extract_text(data, f.filename, f.content_type or "") doc = Document( kind=kind, filename=f.filename, path=path, mime=f.content_type or "", size=len(data), sha256=sha, text_content=text, uploaded_by=actor.id, ) db.add(doc) db.flush() doc_ids.append(doc.id) db.commit() fw_ids = [int(x) for x in framework_ids.split(",") if x.strip().isdigit()] task = extract_capabilities.delay(doc_ids, fw_ids) audit(db, actor, "capability_extraction_started", "document", None, {"docs": doc_ids}) return {"document_ids": doc_ids, "task_id": task.id} @router.get("", response_model=list[CapabilityOut]) def list_capabilities(status: str | None = None, db: Session = Depends(get_db), _: User = Depends(editor)): q = select(Capability).order_by(Capability.category, Capability.name) if status: q = q.where(Capability.status == status) return db.execute(q).scalars().unique().all() @router.patch("/{cap_id}", response_model=CapabilityOut) def update_capability(cap_id: int, body: CapabilityUpdate, db: Session = Depends(get_db), actor: User = Depends(editor)): cap = db.get(Capability, cap_id) if not cap: raise HTTPException(404, "Not found") for k, v in body.model_dump(exclude_none=True).items(): setattr(cap, k, v) db.commit() db.refresh(cap) audit(db, actor, "capability_updated", "capability", cap.id, {"status": cap.status}) return cap @router.post("/{cap_id}/approve", response_model=CapabilityOut) def approve_capability(cap_id: int, db: Session = Depends(get_db), actor: User = Depends(editor)): cap = db.get(Capability, cap_id) if not cap: raise HTTPException(404, "Not found") cap.status = "approved" for r in cap.responses: r.approved = True db.commit() db.refresh(cap) audit(db, actor, "capability_approved", "capability", cap.id) return cap @router.delete("/{cap_id}") def delete_capability(cap_id: int, db: Session = Depends(get_db), _: User = Depends(editor)): cap = db.get(Capability, cap_id) if cap: db.delete(cap) db.commit() return {"ok": True} @router.post("/responses/{resp_id}/regenerate") def regenerate_response(resp_id: int, db: Session = Depends(get_db), _: User = Depends(editor)): resp = db.get(CapabilityResponse, resp_id) if not resp: raise HTTPException(404, "Not found") task = regenerate_capability_response.delay(resp_id) return {"task_id": task.id} @router.patch("/responses/{resp_id}") def edit_response(resp_id: int, payload: dict, db: Session = Depends(get_db), _: User = Depends(editor)): resp = db.get(CapabilityResponse, resp_id) if not resp: raise HTTPException(404, "Not found") if "response_text" in payload: resp.response_text = payload["response_text"] if "approved" in payload: resp.approved = bool(payload["approved"]) db.commit() return {"ok": True} |