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

135 lines
3.8 KiB
Python

"""Analysis service for legal research."""
from typing import List, Optional
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from app.models.analysis import LegalAnalysis, Case, AnalysisStatus
class AnalysisService:
"""Service for legal analysis operations."""
def __init__(self, db: AsyncSession):
self.db = db
async def create_analysis(
self,
user_id: int,
title: str,
case_description: str,
legal_basis: Optional[dict] = None,
) -> LegalAnalysis:
"""Create a new legal analysis."""
analysis = LegalAnalysis(
user_id=user_id,
title=title,
case_description=case_description,
legal_basis=legal_basis,
)
self.db.add(analysis)
await self.db.flush()
await self.db.refresh(analysis)
return analysis
async def get_analysis_by_id(self, analysis_id: int) -> Optional[LegalAnalysis]:
"""Get an analysis by ID."""
result = await self.db.execute(
select(LegalAnalysis).where(LegalAnalysis.id == analysis_id)
)
return result.scalar_one_or_none()
async def get_analyses_by_user(
self,
user_id: int,
skip: int = 0,
limit: int = 20,
) -> List[LegalAnalysis]:
"""Get analyses by user ID."""
result = await self.db.execute(
select(LegalAnalysis)
.where(LegalAnalysis.user_id == user_id)
.offset(skip)
.limit(limit)
.order_by(LegalAnalysis.created_at.desc())
)
return list(result.scalars().all())
async def update_analysis(
self,
analysis_id: int,
**kwargs
) -> Optional[LegalAnalysis]:
"""Update an analysis."""
analysis = await self.get_analysis_by_id(analysis_id)
if not analysis:
return None
for key, value in kwargs.items():
if hasattr(analysis, key) and value is not None:
setattr(analysis, key, value)
await self.db.flush()
await self.db.refresh(analysis)
return analysis
async def delete_analysis(self, analysis_id: int) -> bool:
"""Delete an analysis."""
analysis = await self.get_analysis_by_id(analysis_id)
if not analysis:
return False
await self.db.delete(analysis)
await self.db.flush()
return True
class CaseService:
"""Service for case operations."""
def __init__(self, db: AsyncSession):
self.db = db
async def create_case(
self,
title: str,
case_number: Optional[str] = None,
court: Optional[str] = None,
case_type: Optional[str] = None,
**kwargs
) -> Case:
"""Create a new case."""
case = Case(
title=title,
case_number=case_number,
court=court,
case_type=case_type,
**kwargs
)
self.db.add(case)
await self.db.flush()
await self.db.refresh(case)
return case
async def get_case_by_id(self, case_id: int) -> Optional[Case]:
"""Get a case by ID."""
result = await self.db.execute(
select(Case).where(Case.id == case_id)
)
return result.scalar_one_or_none()
async def get_cases_list(
self,
skip: int = 0,
limit: int = 20,
case_type: Optional[str] = None,
) -> List[Case]:
"""Get list of cases."""
query = select(Case)
if case_type:
query = query.where(Case.case_type == case_type)
query = query.offset(skip).limit(limit).order_by(Case.created_at.desc())
result = await self.db.execute(query)
return list(result.scalars().all())