"""审计台账(PRD §4.6):本人操作记录筛选 + CSV 导出。""" from __future__ import annotations import csv import io from datetime import datetime from sqlalchemy.ext.asyncio import AsyncSession from model.sys_user import SysUser from repositories.audit_log import AuditLogRepo def _audit_item(a) -> dict: return { "id": a.id, "module": a.module, "action": a.action, "target": a.target, "detail": a.detail, "trace_id": a.trace_id, "status": a.status, "create_time": a.create_time.isoformat() if a.create_time else None, } async def list_ledger( db: AsyncSession, user: SysUser, *, action: str | None = None, customer_id: int | None = None, keyword: str | None = None, start: datetime | None = None, end: datetime | None = None, page: int = 1, page_size: int = 20, ) -> dict: repo = AuditLogRepo(db) items = await repo.list_by_advisor( user_id=user.id, action=action, customer_id=customer_id, keyword=keyword, start=start, end=end, limit=page_size, offset=(page - 1) * page_size, ) total = await repo.count_by_advisor( user_id=user.id, action=action, keyword=keyword, start=start, end=end ) return {"total": total, "page": page, "page_size": page_size, "items": [_audit_item(a) for a in items]} def _to_csv(rows: list[dict]) -> str: """行列表 → CSV 文本(空列表返回空串)。""" if not rows: return "" buf = io.StringIO() writer = csv.DictWriter(buf, fieldnames=list(rows[0].keys())) writer.writeheader() writer.writerows(rows) return buf.getvalue() async def export_ledger( db: AsyncSession, user: SysUser, *, action: str | None = None, customer_id: int | None = None, keyword: str | None = None, start: datetime | None = None, end: datetime | None = None, ) -> str: """导出本人审计台账为 CSV 文本(全量,不限分页大小,上限 10000 条)。""" repo = AuditLogRepo(db) items = await repo.list_by_advisor( user_id=user.id, action=action, customer_id=customer_id, keyword=keyword, start=start, end=end, limit=10000, offset=0, ) return _to_csv([_audit_item(a) for a in items])