3df85fdb04
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.
164 lines
6.2 KiB
Python
164 lines
6.2 KiB
Python
import unittest
|
|
|
|
from fastapi.testclient import TestClient
|
|
|
|
from app.api.legal_document_drafts import (
|
|
get_audit_log_service,
|
|
get_legal_document_draft_service,
|
|
require_current_user,
|
|
)
|
|
from app.main import app
|
|
|
|
|
|
class StubAuditLogService:
|
|
def __init__(self):
|
|
self.events = []
|
|
|
|
def record_event(self, **kwargs):
|
|
self.events.append(kwargs)
|
|
return kwargs
|
|
|
|
|
|
class StubLegalDocumentDraftService:
|
|
def __init__(self):
|
|
self.draft = {
|
|
"id": "ldd-001",
|
|
"tenant_id": "tenant-demo-001",
|
|
"user_id": "user-member",
|
|
"document_type_code": "procurement_goods",
|
|
"title": "采购合同草稿",
|
|
"status": "draft",
|
|
"element_values": {"party_a": {"name": "甲方公司"}},
|
|
"validation_result": {"valid": False, "errors": [{"field_key": "party_b.name", "message": "required"}]},
|
|
"element_schema_id": "ldes-procurement-v1",
|
|
"element_schema_version_label": "v1.0",
|
|
"template_id": "tpl-procurement",
|
|
"generated_contract_id": None,
|
|
"submitted_at": None,
|
|
"deleted_at": None,
|
|
"created_at": "2026-05-20T00:00:00+00:00",
|
|
"updated_at": "2026-05-20T00:00:00+00:00",
|
|
}
|
|
|
|
def list_drafts(self, current_user, document_type_code=None, status_value="draft", limit=20):
|
|
return {"items": [self.draft], "total": 1}
|
|
|
|
def create_draft(self, current_user, **kwargs):
|
|
created = dict(self.draft)
|
|
created.update(
|
|
{
|
|
"document_type_code": kwargs["document_type_code"],
|
|
"element_values": kwargs["element_values"],
|
|
"title": kwargs.get("title"),
|
|
"template_id": kwargs.get("template_id"),
|
|
}
|
|
)
|
|
return created
|
|
|
|
def get_draft(self, current_user, draft_id):
|
|
return dict(self.draft, id=draft_id)
|
|
|
|
def update_draft(self, current_user, draft_id, **kwargs):
|
|
updated = dict(self.draft, id=draft_id)
|
|
updated.update({key: value for key, value in kwargs.items() if value is not None})
|
|
return updated
|
|
|
|
def delete_draft(self, current_user, draft_id):
|
|
return dict(self.draft, id=draft_id, status="deleted", deleted_at="2026-05-20T00:01:00+00:00")
|
|
|
|
def generate_from_draft(self, current_user, draft_id, **kwargs):
|
|
generated_draft = dict(self.draft, id=draft_id, status="generated", generated_contract_id="contract-001")
|
|
return {
|
|
"draft": generated_draft,
|
|
"generated_contract": {
|
|
"id": "contract-001",
|
|
"document_type_code": "procurement_goods",
|
|
"elements_snapshot": self.draft["element_values"],
|
|
"metadata": {
|
|
"element_schema_id": "ldes-procurement-v1",
|
|
"element_schema_version_label": "v1.0",
|
|
},
|
|
},
|
|
}
|
|
|
|
|
|
class LegalDocumentDraftsApiTestCase(unittest.TestCase):
|
|
def setUp(self):
|
|
self.audit_log_service = StubAuditLogService()
|
|
self.draft_service = StubLegalDocumentDraftService()
|
|
app.dependency_overrides[get_legal_document_draft_service] = lambda: self.draft_service
|
|
app.dependency_overrides[get_audit_log_service] = lambda: self.audit_log_service
|
|
app.dependency_overrides[require_current_user] = lambda: {
|
|
"id": "user-member",
|
|
"tenant_id": "tenant-demo-001",
|
|
"role": "member",
|
|
}
|
|
self.client = TestClient(app)
|
|
|
|
def tearDown(self):
|
|
app.dependency_overrides.clear()
|
|
|
|
def test_user_can_list_recent_drafts(self):
|
|
response = self.client.get("/api/v1/legal-document-drafts")
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
body = response.json()
|
|
self.assertEqual(body["data"]["total"], 1)
|
|
self.assertEqual(body["data"]["items"][0]["id"], "ldd-001")
|
|
|
|
def test_user_can_save_draft_and_write_audit_log(self):
|
|
response = self.client.post(
|
|
"/api/v1/legal-document-drafts",
|
|
json={
|
|
"document_type_code": "procurement_goods",
|
|
"title": "采购合同草稿",
|
|
"template_id": "tpl-procurement",
|
|
"element_values": {"party_a": {"name": "甲方公司"}},
|
|
},
|
|
)
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
body = response.json()
|
|
self.assertEqual(body["data"]["document_type_code"], "procurement_goods")
|
|
self.assertEqual(body["data"]["element_values"]["party_a"]["name"], "甲方公司")
|
|
self.assertEqual(self.audit_log_service.events[0]["action"], "save_legal_document_draft")
|
|
|
|
def test_user_can_restore_update_delete_and_generate_from_draft(self):
|
|
detail = self.client.get("/api/v1/legal-document-drafts/ldd-001")
|
|
self.assertEqual(detail.status_code, 200)
|
|
self.assertEqual(detail.json()["data"]["id"], "ldd-001")
|
|
|
|
updated = self.client.put(
|
|
"/api/v1/legal-document-drafts/ldd-001",
|
|
json={"title": "已恢复草稿", "element_values": {"party_a": {"name": "甲方公司"}}},
|
|
)
|
|
self.assertEqual(updated.status_code, 200)
|
|
self.assertEqual(updated.json()["data"]["title"], "已恢复草稿")
|
|
|
|
generated = self.client.post(
|
|
"/api/v1/legal-document-drafts/ldd-001/generate",
|
|
json={"export_format": "pdf", "options": {"watermark": True}},
|
|
)
|
|
self.assertEqual(generated.status_code, 200)
|
|
self.assertEqual(generated.json()["data"]["draft"]["generated_contract_id"], "contract-001")
|
|
self.assertEqual(
|
|
generated.json()["data"]["generated_contract"]["elements_snapshot"]["party_a"]["name"],
|
|
"甲方公司",
|
|
)
|
|
|
|
deleted = self.client.delete("/api/v1/legal-document-drafts/ldd-001")
|
|
self.assertEqual(deleted.status_code, 200)
|
|
self.assertEqual(deleted.json()["data"]["status"], "deleted")
|
|
self.assertEqual(
|
|
[event["action"] for event in self.audit_log_service.events],
|
|
[
|
|
"update_legal_document_draft",
|
|
"generate_contract_from_legal_document_draft",
|
|
"delete_legal_document_draft",
|
|
],
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|