Files
finance_bot/app/services/finance/transaction_service.py
2025-12-10 22:09:31 +09:00

95 lines
3.5 KiB
Python

"""Transaction service"""
from typing import Optional, List
from datetime import datetime, timedelta
from sqlalchemy.orm import Session
from app.db.repositories import TransactionRepository, AccountRepository, BudgetRepository
from app.db.models import Transaction, TransactionType
from app.schemas import TransactionCreateSchema
class TransactionService:
"""Service for transaction operations"""
def __init__(self, session: Session):
self.session = session
self.transaction_repo = TransactionRepository(session)
self.account_repo = AccountRepository(session)
self.budget_repo = BudgetRepository(session)
def create_transaction(
self,
family_id: int,
user_id: int,
account_id: int,
data: TransactionCreateSchema,
) -> Transaction:
"""Create new transaction and update account balance"""
# Create transaction
transaction = self.transaction_repo.create(
family_id=family_id,
user_id=user_id,
account_id=account_id,
amount=data.amount,
transaction_type=data.transaction_type,
description=data.description,
notes=data.notes,
tags=data.tags,
category_id=data.category_id,
receipt_photo_url=data.receipt_photo_url,
transaction_date=data.transaction_date,
)
# Update account balance
if data.transaction_type == TransactionType.EXPENSE:
self.account_repo.update_balance(account_id, -data.amount)
elif data.transaction_type == TransactionType.INCOME:
self.account_repo.update_balance(account_id, data.amount)
# Update budget if expense
if (
data.transaction_type == TransactionType.EXPENSE
and data.category_id
):
budget = self.budget_repo.get_category_budget(family_id, data.category_id)
if budget:
self.budget_repo.update_spent_amount(budget.id, data.amount)
return transaction
def get_family_summary(self, family_id: int, days: int = 30) -> dict:
"""Get financial summary for family"""
end_date = datetime.utcnow()
start_date = end_date - timedelta(days=days)
transactions = self.transaction_repo.get_transactions_by_period(
family_id, start_date, end_date
)
income = sum(t.amount for t in transactions if t.transaction_type == TransactionType.INCOME)
expenses = sum(t.amount for t in transactions if t.transaction_type == TransactionType.EXPENSE)
net = income - expenses
return {
"period_days": days,
"income": income,
"expenses": expenses,
"net": net,
"average_daily_expense": expenses / days if days > 0 else 0,
"transaction_count": len(transactions),
}
def delete_transaction(self, transaction_id: int) -> bool:
"""Delete transaction and rollback balance"""
transaction = self.transaction_repo.get_by_id(transaction_id)
if transaction:
# Rollback balance
if transaction.transaction_type == TransactionType.EXPENSE:
self.account_repo.update_balance(transaction.account_id, transaction.amount)
elif transaction.transaction_type == TransactionType.INCOME:
self.account_repo.update_balance(transaction.account_id, -transaction.amount)
# Delete transaction
return self.transaction_repo.delete(transaction_id)
return False