Files
ai-contract-platform/backend/app/api/legal_document_drafts.py
T
yuqei 3df85fdb04 feat: land phase15 legal docs and commercial ops
Includes legal document generation workflows, prompt governance runtime wiring, legal change impact scans, operation KPI dashboards, invoice files, sales follow-up events, mobile review polish, deployment automation, and updated project docs.
2026-05-21 14:42:44 +08:00

210 lines
7.8 KiB
Python

from typing import Any, Optional
from fastapi import APIRouter, Depends, Header, HTTPException, Request
from pydantic import BaseModel, Field
from sqlalchemy.orm import Session
from app.core.response import success_response
from app.db import get_db_session
from app.services.audit_log_service import AuditLogService
from app.services.auth_service import AuthService
from app.services.contract_generation_service import ExportFormat
from app.services.legal_document_draft_service import LegalDocumentDraftService
router = APIRouter(prefix="/legal-document-drafts", tags=["legal-document-drafts"])
ROUTE_PERMISSION_SCOPE = "legal_document_drafts"
ROUTE_PERMISSION_ACTIONS = {
"list": "legal_document_drafts:list",
"create": "legal_document_drafts:create",
"detail": "legal_document_drafts:detail",
"update": "legal_document_drafts:update",
"delete": "legal_document_drafts:delete",
"generate": "legal_document_drafts:generate",
}
class LegalDocumentDraftCreateRequest(BaseModel):
document_type_code: str
element_values: dict[str, Any] = Field(default_factory=dict)
title: Optional[str] = None
template_id: Optional[str] = None
class LegalDocumentDraftUpdateRequest(BaseModel):
element_values: Optional[dict[str, Any]] = None
title: Optional[str] = None
template_id: Optional[str] = None
class LegalDocumentDraftGenerateRequest(BaseModel):
export_format: str = "docx"
template_id: Optional[str] = None
options: dict[str, Any] = Field(default_factory=dict)
def get_legal_document_draft_service(db: Session = Depends(get_db_session)) -> LegalDocumentDraftService:
return LegalDocumentDraftService(db)
def get_audit_log_service(db: Session = Depends(get_db_session)) -> AuditLogService:
return AuditLogService(db)
def require_current_user(
authorization: Optional[str] = Header(default=None),
db: Session = Depends(get_db_session),
):
return AuthService(db).require_current_user(authorization)
@router.get("")
def list_legal_document_drafts(
document_type_code: Optional[str] = None,
status: Optional[str] = "draft",
limit: int = 20,
legal_document_draft_service: LegalDocumentDraftService = Depends(get_legal_document_draft_service),
current_user: dict = Depends(require_current_user),
):
result = legal_document_draft_service.list_drafts(
current_user,
document_type_code=document_type_code,
status_value=status,
limit=limit,
)
return success_response(result)
@router.post("")
def create_legal_document_draft(
payload: LegalDocumentDraftCreateRequest,
request: Request,
legal_document_draft_service: LegalDocumentDraftService = Depends(get_legal_document_draft_service),
audit_log_service: AuditLogService = Depends(get_audit_log_service),
current_user: dict = Depends(require_current_user),
):
result = legal_document_draft_service.create_draft(
current_user,
document_type_code=payload.document_type_code,
element_values=payload.element_values,
title=payload.title,
template_id=payload.template_id,
)
audit_log_service.record_event(
tenant_id=current_user.get("tenant_id"),
user_id=current_user.get("id"),
action="save_legal_document_draft",
resource_type="legal_document_draft",
resource_id=result["id"],
detail_json={
"document_type_code": result["document_type_code"],
"template_id": result.get("template_id"),
"valid": (result.get("validation_result") or {}).get("valid"),
},
ip_address=request.client.host if request.client else None,
user_agent=request.headers.get("user-agent"),
)
return success_response(result)
@router.get("/{draft_id}")
def get_legal_document_draft(
draft_id: str,
legal_document_draft_service: LegalDocumentDraftService = Depends(get_legal_document_draft_service),
current_user: dict = Depends(require_current_user),
):
return success_response(legal_document_draft_service.get_draft(current_user, draft_id))
@router.put("/{draft_id}")
def update_legal_document_draft(
draft_id: str,
payload: LegalDocumentDraftUpdateRequest,
request: Request,
legal_document_draft_service: LegalDocumentDraftService = Depends(get_legal_document_draft_service),
audit_log_service: AuditLogService = Depends(get_audit_log_service),
current_user: dict = Depends(require_current_user),
):
result = legal_document_draft_service.update_draft(
current_user,
draft_id,
element_values=payload.element_values,
title=payload.title,
template_id=payload.template_id,
)
audit_log_service.record_event(
tenant_id=current_user.get("tenant_id"),
user_id=current_user.get("id"),
action="update_legal_document_draft",
resource_type="legal_document_draft",
resource_id=result["id"],
detail_json={
"document_type_code": result["document_type_code"],
"template_id": result.get("template_id"),
"valid": (result.get("validation_result") or {}).get("valid"),
},
ip_address=request.client.host if request.client else None,
user_agent=request.headers.get("user-agent"),
)
return success_response(result)
@router.delete("/{draft_id}")
def delete_legal_document_draft(
draft_id: str,
request: Request,
legal_document_draft_service: LegalDocumentDraftService = Depends(get_legal_document_draft_service),
audit_log_service: AuditLogService = Depends(get_audit_log_service),
current_user: dict = Depends(require_current_user),
):
result = legal_document_draft_service.delete_draft(current_user, draft_id)
audit_log_service.record_event(
tenant_id=current_user.get("tenant_id"),
user_id=current_user.get("id"),
action="delete_legal_document_draft",
resource_type="legal_document_draft",
resource_id=result["id"],
detail_json={"document_type_code": result["document_type_code"]},
ip_address=request.client.host if request.client else None,
user_agent=request.headers.get("user-agent"),
)
return success_response(result)
@router.post("/{draft_id}/generate")
def generate_contract_from_legal_document_draft(
draft_id: str,
payload: LegalDocumentDraftGenerateRequest,
request: Request,
legal_document_draft_service: LegalDocumentDraftService = Depends(get_legal_document_draft_service),
audit_log_service: AuditLogService = Depends(get_audit_log_service),
current_user: dict = Depends(require_current_user),
):
try:
export_format = ExportFormat(payload.export_format.lower())
except ValueError:
raise HTTPException(status_code=400, detail=f"unsupported export format: {payload.export_format}")
result = legal_document_draft_service.generate_from_draft(
current_user,
draft_id,
export_format=export_format,
template_id=payload.template_id,
options=payload.options,
)
audit_log_service.record_event(
tenant_id=current_user.get("tenant_id"),
user_id=current_user.get("id"),
action="generate_contract_from_legal_document_draft",
resource_type="legal_document_draft",
resource_id=result["draft"]["id"],
detail_json={
"document_type_code": result["draft"]["document_type_code"],
"template_id": result["draft"].get("template_id"),
"generated_contract_id": result["draft"].get("generated_contract_id"),
"element_schema_id": result["draft"].get("element_schema_id"),
"element_schema_version_label": result["draft"].get("element_schema_version_label"),
},
ip_address=request.client.host if request.client else None,
user_agent=request.headers.get("user-agent"),
)
return success_response(result)