mitlist/be/app/crud/audit.py
Mohamad 29e42b8d80 feat: Enhance cost management features with new endpoints and services
This commit introduces significant updates to the cost management functionality, including:

- New endpoints for retrieving cost summaries and generating expenses from lists, improving user interaction with financial data.
- Implementation of a service layer for cost-related logic, encapsulating the core business rules for calculating cost summaries and managing expenses.
- Introduction of a financial activity endpoint to consolidate user expenses and settlements, enhancing the user experience by providing a comprehensive view of financial activities.
- Refactoring of existing code to improve maintainability and clarity, including the addition of new exception handling for financial conflicts.

These changes aim to streamline cost management processes and enhance the overall functionality of the application.
2025-06-21 00:53:03 +02:00

76 lines
2.8 KiB
Python

from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.future import select
from sqlalchemy import union_all, or_
from typing import List, Optional
from app.models import FinancialAuditLog, Base, User, Group, Expense, Settlement
from app.schemas.audit import FinancialAuditLogCreate
async def create_financial_audit_log(
db: AsyncSession,
*,
user_id: int | None,
action_type: str,
entity: Base,
details: dict | None = None
) -> FinancialAuditLog:
log_entry_data = FinancialAuditLogCreate(
user_id=user_id,
action_type=action_type,
entity_type=entity.__class__.__name__,
entity_id=entity.id,
details=details
)
log_entry = FinancialAuditLog(**log_entry_data.dict())
db.add(log_entry)
await db.flush()
return log_entry
async def get_financial_audit_logs_for_group(db: AsyncSession, *, group_id: int, skip: int = 0, limit: int = 100) -> List[FinancialAuditLog]:
"""
Get financial audit logs for all entities that belong to a specific group.
This includes Expenses and Settlements that are linked to the group.
"""
# Get all expense IDs for this group
expense_ids_query = select(Expense.id).where(Expense.group_id == group_id)
expense_result = await db.execute(expense_ids_query)
expense_ids = [row[0] for row in expense_result.fetchall()]
# Get all settlement IDs for this group
settlement_ids_query = select(Settlement.id).where(Settlement.group_id == group_id)
settlement_result = await db.execute(settlement_ids_query)
settlement_ids = [row[0] for row in settlement_result.fetchall()]
# Build conditions for the audit log query
conditions = []
if expense_ids:
conditions.append(
(FinancialAuditLog.entity_type == 'Expense') &
(FinancialAuditLog.entity_id.in_(expense_ids))
)
if settlement_ids:
conditions.append(
(FinancialAuditLog.entity_type == 'Settlement') &
(FinancialAuditLog.entity_id.in_(settlement_ids))
)
# If no entities exist for this group, return empty list
if not conditions:
return []
# Query audit logs for all relevant entities
query = select(FinancialAuditLog).where(
or_(*conditions)
).order_by(FinancialAuditLog.timestamp.desc()).offset(skip).limit(limit)
result = await db.execute(query)
return result.scalars().all()
async def get_financial_audit_logs_for_user(db: AsyncSession, *, user_id: int, skip: int = 0, limit: int = 100) -> List[FinancialAuditLog]:
result = await db.execute(
select(FinancialAuditLog)
.where(FinancialAuditLog.user_id == user_id)
.order_by(FinancialAuditLog.timestamp.desc())
.offset(skip).limit(limit)
)
return result.scalars().all()