Files
JiuContinent bf309ecdf7 ```
refactor(core,ai): 调整模块导入路径并移除废弃文件

- 修复 scheduler.py 中的导入路径错误,将 reports.service
  改为 reports.services
- 移除废弃的 app/core/background/task_queue.py 文件
- 移除废弃的 app/modules/ai_agent/adapters.py 文件
- 修复 ai_memory/service.py 中的导入路径错误,将
  events.service 改为 events.services
```
2026-07-09 18:50:52 +08:00

96 lines
3.0 KiB
Python

from datetime import date, datetime
from decimal import Decimal
from typing import Any
from sqlalchemy import func, select
from app.core.http.pagination import bounded_limit
from app.core.utils.time import utc_now
from app.modules.reports.constants import ReportStatus
def _money(value: Decimal | int | float | None) -> str:
"""Format a numeric value as a two-decimal money string."""
amount = Decimal(value or 0)
return f"{amount:,.2f}"
def _json_safe(value: Any) -> Any:
"""Convert nested report payloads into JSON-storable values."""
if isinstance(value, Decimal):
return float(value)
if isinstance(value, (datetime, date)):
return value.isoformat()
if isinstance(value, list):
return [_json_safe(item) for item in value]
if isinstance(value, dict):
return {key: _json_safe(item) for key, item in value.items()}
return value
def _next_code(prefix: str) -> str:
"""Build a compact unique code for generated report records."""
return f"{prefix}-{utc_now():%Y%m%d%H%M%S%f}"
def _rate(numerator: int | Decimal, denominator: int | Decimal) -> float:
"""Return a rounded percentage rate, using zero when the denominator is empty."""
if not denominator:
return 0.0
return round(float(numerator) / float(denominator) * 100, 2)
def _as_decimal(value: Decimal | int | float | None) -> Decimal:
return Decimal(str(value or 0))
class ReportQueryMixin:
def _count(self, model: type, *conditions: Any) -> int:
stmt = select(func.count()).select_from(model)
for condition in conditions:
stmt = stmt.where(condition)
return int(self.db.execute(stmt).scalar() or 0)
def _sum(self, column: Any, *conditions: Any) -> Decimal:
stmt = select(func.sum(column))
for condition in conditions:
stmt = stmt.where(condition)
return _as_decimal(self.db.execute(stmt).scalar())
def _avg(self, column: Any, *conditions: Any) -> float:
stmt = select(func.avg(column))
for condition in conditions:
stmt = stmt.where(condition)
value = self.db.execute(stmt).scalar()
return round(float(value or 0), 2)
def _group_counts(self, model: type, column: Any, *conditions: Any) -> dict[str, int]:
stmt = select(column, func.count()).select_from(model)
for condition in conditions:
stmt = stmt.where(condition)
stmt = stmt.group_by(column)
return {
str(key or ReportStatus.UNKNOWN): int(count)
for key, count in self.db.execute(stmt).all()
}
def _records(
self,
model: type,
*conditions: Any,
limit: int = 10,
order_by: Any | None = None,
) -> list[Any]:
stmt = select(model)
for condition in conditions:
stmt = stmt.where(condition)
if order_by is not None:
stmt = stmt.order_by(order_by)
else:
stmt = stmt.order_by(model.id.desc())
return list(self.db.execute(stmt.limit(bounded_limit(limit))).scalars())