78 lines
2.2 KiB
Python
78 lines
2.2 KiB
Python
"""审计台账(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])
|