mirror of
https://github.com/escalante29/WealthySmart.git
synced 2026-05-19 10:28:48 +02:00
Add DEPOSITO transaction type and Salarios page
All checks were successful
Deploy to VPS / deploy (push) Successful in 21s
All checks were successful
Deploy to VPS / deploy (push) Successful in 21s
New TransactionType.DEPOSITO for salary deposits from n8n/Gmail flow. New /salarios endpoint with summary. New top-level Salarios page with DataTable and summary cards. Push notifications link to /salarios for deposits. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
54
backend/app/api/v1/endpoints/salarios.py
Normal file
54
backend/app/api/v1/endpoints/salarios.py
Normal file
@@ -0,0 +1,54 @@
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import APIRouter, Depends, Query
|
||||
from pydantic import BaseModel
|
||||
from sqlmodel import Session, col, func, select
|
||||
|
||||
from app.auth import get_current_user
|
||||
from app.db import get_session
|
||||
from app.models.models import Transaction, TransactionRead, TransactionType
|
||||
|
||||
router = APIRouter(prefix="/salarios", tags=["salarios"])
|
||||
|
||||
|
||||
class SalariosSummary(BaseModel):
|
||||
count: int
|
||||
total_amount: float
|
||||
latest_date: Optional[datetime] = None
|
||||
|
||||
|
||||
@router.get("/", response_model=list[TransactionRead])
|
||||
def list_salarios(
|
||||
limit: int = Query(default=50, le=500),
|
||||
offset: int = 0,
|
||||
session: Session = Depends(get_session),
|
||||
_user: str = Depends(get_current_user),
|
||||
):
|
||||
query = (
|
||||
select(Transaction)
|
||||
.where(Transaction.transaction_type == TransactionType.DEPOSITO)
|
||||
.order_by(col(Transaction.date).desc())
|
||||
.offset(offset)
|
||||
.limit(limit)
|
||||
)
|
||||
return session.exec(query).all()
|
||||
|
||||
|
||||
@router.get("/summary", response_model=SalariosSummary)
|
||||
def salarios_summary(
|
||||
session: Session = Depends(get_session),
|
||||
_user: str = Depends(get_current_user),
|
||||
):
|
||||
result = session.exec(
|
||||
select(
|
||||
func.count(),
|
||||
func.coalesce(func.sum(Transaction.amount), 0),
|
||||
func.max(Transaction.date),
|
||||
).where(Transaction.transaction_type == TransactionType.DEPOSITO)
|
||||
).first()
|
||||
return SalariosSummary(
|
||||
count=result[0] if result else 0,
|
||||
total_amount=float(result[1]) if result else 0.0,
|
||||
latest_date=result[2] if result else None,
|
||||
)
|
||||
@@ -15,6 +15,7 @@ from app.models.models import (
|
||||
TransactionCreate,
|
||||
TransactionRead,
|
||||
TransactionSource,
|
||||
TransactionType,
|
||||
TransactionUpdate,
|
||||
)
|
||||
|
||||
@@ -183,11 +184,12 @@ def create_transaction(
|
||||
# Send push notification
|
||||
symbol = "₡" if tx.currency == Currency.CRC else tx.currency.value
|
||||
amount_str = f"{symbol}{tx.amount:,.0f}" if tx.currency == Currency.CRC else f"{symbol}{tx.amount:,.2f}"
|
||||
is_deposit = tx.transaction_type == TransactionType.DEPOSITO
|
||||
send_push_to_all(
|
||||
session,
|
||||
title=f"💳 {tx.merchant}",
|
||||
body=f"{amount_str} — {tx.bank.value} {tx.transaction_type.value.lower()}",
|
||||
url=f"/budget",
|
||||
title=f"{'🏦' if is_deposit else '💳'} {tx.merchant}",
|
||||
body=f"{amount_str} — {tx.bank.value} {'depósito' if is_deposit else tx.transaction_type.value.lower()}",
|
||||
url="/salarios" if is_deposit else "/budget",
|
||||
)
|
||||
|
||||
return tx
|
||||
|
||||
@@ -9,6 +9,7 @@ from app.api.v1.endpoints import (
|
||||
exchange_rate,
|
||||
import_transactions,
|
||||
notifications,
|
||||
salarios,
|
||||
settings,
|
||||
tokens,
|
||||
transactions,
|
||||
@@ -26,3 +27,4 @@ api_router.include_router(analytics.router)
|
||||
api_router.include_router(settings.router)
|
||||
api_router.include_router(budget.router)
|
||||
api_router.include_router(notifications.router)
|
||||
api_router.include_router(salarios.router)
|
||||
|
||||
Reference in New Issue
Block a user