root 656f596d7e feat: implement AI legal assistant system MVP
Core modules:
- Laws: CRUD, search, AI-powered QA
- Analysis: legal research and case management
- Contracts: lifecycle management with templates
- Signatures: electronic signature workflow

Infrastructure:
- FastAPI + SQLite + async SQLAlchemy
- Docker deployment support
- 54 unit tests passing

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 03:34:44 +08:00

141 lines
3.9 KiB
Python

"""Analysis API endpoints."""
from typing import Optional
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.database import get_db
from app.schemas.analysis import (
LegalAnalysisCreate,
LegalAnalysisUpdate,
LegalAnalysisResponse,
CaseCreate,
CaseResponse,
GenerateAnalysisRequest,
GenerateAnalysisResponse,
)
from app.services.analysis_service import AnalysisService, CaseService
from app.services.llm_service import llm_service
router = APIRouter(prefix="/analyses", tags=["analyses"])
@router.post("", response_model=LegalAnalysisResponse)
async def create_analysis(
analysis_data: LegalAnalysisCreate,
user_id: int = 1, # TODO: Get from auth
db: AsyncSession = Depends(get_db),
):
"""Create a new legal analysis."""
service = AnalysisService(db)
analysis = await service.create_analysis(
user_id=user_id,
title=analysis_data.title,
case_description=analysis_data.case_description,
legal_basis=analysis_data.legal_basis,
)
return analysis
@router.get("", response_model=list[LegalAnalysisResponse])
async def list_analyses(
skip: int = Query(0, ge=0),
limit: int = Query(20, ge=1, le=100),
user_id: int = 1, # TODO: Get from auth
db: AsyncSession = Depends(get_db),
):
"""List analyses for current user."""
service = AnalysisService(db)
analyses = await service.get_analyses_by_user(user_id, skip, limit)
return analyses
@router.get("/{analysis_id}", response_model=LegalAnalysisResponse)
async def get_analysis(
analysis_id: int,
db: AsyncSession = Depends(get_db),
):
"""Get an analysis by ID."""
service = AnalysisService(db)
analysis = await service.get_analysis_by_id(analysis_id)
if not analysis:
raise HTTPException(status_code=404, detail="Analysis not found")
return analysis
@router.put("/{analysis_id}", response_model=LegalAnalysisResponse)
async def update_analysis(
analysis_id: int,
analysis_data: LegalAnalysisUpdate,
db: AsyncSession = Depends(get_db),
):
"""Update an analysis."""
service = AnalysisService(db)
analysis = await service.update_analysis(
analysis_id,
**analysis_data.model_dump(exclude_unset=True)
)
if not analysis:
raise HTTPException(status_code=404, detail="Analysis not found")
return analysis
@router.delete("/{analysis_id}")
async def delete_analysis(
analysis_id: int,
db: AsyncSession = Depends(get_db),
):
"""Delete an analysis."""
service = AnalysisService(db)
success = await service.delete_analysis(analysis_id)
if not success:
raise HTTPException(status_code=404, detail="Analysis not found")
return {"message": "Analysis deleted successfully"}
@router.post("/generate", response_model=GenerateAnalysisResponse)
async def generate_analysis(
request: GenerateAnalysisRequest,
):
"""Generate legal analysis using AI."""
result = await llm_service.analyze_legal_issue(
issue_description=request.case_description,
relevant_laws=request.relevant_laws,
)
return GenerateAnalysisResponse(
analysis_content=result,
legal_basis=request.relevant_laws or [],
conclusion=result,
)
# Case endpoints
@router.post("/cases", response_model=CaseResponse)
async def create_case(
case_data: CaseCreate,
db: AsyncSession = Depends(get_db),
):
"""Create a new case."""
service = CaseService(db)
case = await service.create_case(**case_data.model_dump())
return case
@router.get("/cases", response_model=list[CaseResponse])
async def list_cases(
skip: int = Query(0, ge=0),
limit: int = Query(20, ge=1, le=100),
case_type: Optional[str] = Query(None),
db: AsyncSession = Depends(get_db),
):
"""List cases."""
service = CaseService(db)
cases = await service.get_cases_list(skip, limit, case_type)
return cases