init commit
This commit is contained in:
94
app/services/finance/transaction_service.py
Normal file
94
app/services/finance/transaction_service.py
Normal file
@@ -0,0 +1,94 @@
|
||||
"""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
|
||||
Reference in New Issue
Block a user