mirror of
https://github.com/escalante29/WealthySmart.git
synced 2026-07-17 11:08:47 +02:00
Agent: fix date handling — Costa Rica timezone and future cuotas
Two bugs from prod (server clock is UTC, user is UTC-6): - get_recent_transactions returned future-dated Tasa Cero cuotas; it now excludes anything dated after the user's today, same rule as /transactions/recent. - "¿Cuánto he gastado hoy?" answered for the wrong day: the prompt baked date.today() in at boot — frozen from startup AND in server-UTC (8 pm in Costa Rica is already tomorrow in UTC). The prompt no longer carries a date; a new get_current_date tool returns today in CR time plus the active billing cycle, and the prompt directs the model to call it for any relative date reference. today_cr() lives in timeutil (CR has no DST, fixed UTC-6). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -13,7 +13,7 @@ write tool requires an explicit user-confirmation step in the UI.
|
||||
from __future__ import annotations
|
||||
|
||||
import contextvars
|
||||
from datetime import datetime
|
||||
from datetime import datetime, time, timedelta
|
||||
from typing import Annotated, Optional
|
||||
|
||||
from pydantic import Field
|
||||
@@ -40,6 +40,7 @@ from app.services.budget_projection import (
|
||||
get_cycle_range,
|
||||
)
|
||||
from app.services import exchange_rate as fx
|
||||
from app.timeutil import today_cr
|
||||
from app.services.exchange_rate import (
|
||||
get_converted_amount_expr,
|
||||
get_current_rate,
|
||||
@@ -140,7 +141,11 @@ def get_recent_transactions(
|
||||
q = select(Transaction).where(
|
||||
col(Transaction.transaction_type).notin_(
|
||||
[TransactionType.SALARY, TransactionType.DEPOSITO]
|
||||
)
|
||||
),
|
||||
# Tasa Cero generates future-dated cuotas; "recent" means already
|
||||
# billed (same rule as /transactions/recent). Bound is end of the
|
||||
# user's today, Costa Rica time.
|
||||
Transaction.date < datetime.combine(today_cr() + timedelta(days=1), time.min),
|
||||
)
|
||||
if source:
|
||||
q = q.where(Transaction.source == TransactionSource(source))
|
||||
@@ -491,7 +496,33 @@ def list_categories() -> list[dict]:
|
||||
|
||||
|
||||
# Registered with the agent in agent.py
|
||||
def get_current_date() -> dict:
|
||||
"""Today's date in the user's timezone (Costa Rica, UTC-6) and the
|
||||
active credit-card billing cycle. ALWAYS call this before resolving any
|
||||
relative date reference — 'hoy', 'ayer', 'este mes', 'este ciclo',
|
||||
'el ciclo pasado' — the server clock and your own assumptions about
|
||||
today are unreliable."""
|
||||
today = today_cr()
|
||||
# get_cycle_range(y, m) is the cycle STARTING on the 18th of m; before
|
||||
# the 18th we are still in the cycle that started last month.
|
||||
if today.day >= 18:
|
||||
cycle_year, cycle_month = today.year, today.month
|
||||
elif today.month == 1:
|
||||
cycle_year, cycle_month = today.year - 1, 12
|
||||
else:
|
||||
cycle_year, cycle_month = today.year, today.month - 1
|
||||
start, end = get_cycle_range(cycle_year, cycle_month)
|
||||
return {
|
||||
"date": today.isoformat(),
|
||||
"weekday": today.strftime("%A"),
|
||||
"cycle_year": cycle_year,
|
||||
"cycle_month": cycle_month,
|
||||
"cycle_range": [start.date().isoformat(), end.date().isoformat()],
|
||||
}
|
||||
|
||||
|
||||
TOOLS = [
|
||||
get_current_date,
|
||||
get_accounts,
|
||||
get_net_worth,
|
||||
get_recent_transactions,
|
||||
|
||||
Reference in New Issue
Block a user