Skip to main content

Overview

Budgets in BudgetView help you control spending by setting monthly limits for each expense category. The system automatically tracks your spending and alerts you when approaching or exceeding limits.
Budgets are category-specific and monthly. Each category can have one budget per month.

Creating a Budget

1

Navigate to Presupuestos

Go to the Presupuestos page from your dashboard sidebar.
2

Click New Budget

Click Nuevo Presupuesto in the top-right corner.
3

Select Category

Choose an expense category (gasto) from the dropdown.
Only expense categories appear. Income categories cannot have budgets.
const gastoCategories = React.useMemo(
  () => categories.filter((cat) => cat.tipo === "gasto"),
  [categories]
)
4

Enter Budget Limit

Type the maximum amount you want to spend in USD.Requirements:
  • Must be greater than 0
  • Accepts decimal values (e.g., 500.50)
  • Stored in USD
if (Number.isNaN(amountValue) || amountValue <= 0) {
  setFormError("Ingresa un monto válido mayor a 0.")
  return
}
5

Choose Period

Select the month using the month/year picker.Important rules:
  • Can only create budgets for current or future months
  • Cannot create budgets for past months
  • One budget per category per month
if (isPastMonthValue(formPeriod) && (!editingBudget || formPeriod !== originalPeriod)) {
  setFormError(
    editingBudget
      ? "Solo puedes mover el presupuesto a meses actuales o futuros."
      : "Solo puedes crear presupuestos desde el mes actual en adelante."
  )
  return
}
6

Save Budget

Click Crear presupuesto.The system validates that you don’t already have a budget for this category in this month:
const duplicateQuery = supabase
  .from("presupuestos")
  .select("id")
  .eq("categoria_id", formCategoryId)
  .eq("periodo", normalizedPeriod)
  .limit(1)

if (duplicateRows && duplicateRows.length > 0) {
  setFormError("Ya tienes un presupuesto para esa categoría en el periodo seleccionado.")
  return
}

Understanding Budget Metrics

Each budget card displays comprehensive tracking information:

Limit

Maximum amount you set for this category.Displayed in USD and VES (BCV rate)

Spent

Total of all expense transactions in this category for the month.Auto-calculated from transactions

Available

Remaining budget: Limit - SpentCan be negative if exceeded

Budget Status Indicators

Green indicator - Under 90% of budget used.
const nearLimit = !exceeded && percentage >= 90
const statusLabel = budget.exceeded
  ? "Excedido"
  : budget.nearLimit
  ? "90% del límite"
  : "Disponible"
Safe spending level. Keep it up!

How Budget Tracking Works

Real-Time Calculation

Budgets track spending automatically by querying transactions:
const { data: expensesData, error: expensesError } = await supabase
  .from("transacciones")
  .select("categoria_id,monto,tipo,fecha_transaccion")
  .in("categoria_id", categoryIds)
  .eq("tipo", "gasto")  // Only expenses count
  .gte("fecha_transaccion", start.toISOString())  // Month start
  .lt("fecha_transaccion", end.toISOString())     // Month end

(expensesData ?? []).forEach((row) => {
  const dataRow = row as TransactionRow
  if (!dataRow.categoria_id) return
  const amount = Number(dataRow.monto ?? 0)
  if (Number.isNaN(amount)) return
  spendMap.set(
    dataRow.categoria_id,
    (spendMap.get(dataRow.categoria_id) ?? 0) + amount
  )
})

Progress Bar Visualization

The colored progress bar shows percentage used:
const percentage = limit === 0 ? 0 : Math.min(100, (spent / limit) * 100)

<div className="h-3 rounded-full bg-muted/60">
  <div
    className={cn(
      "h-full rounded-full",
      budget.exceeded
        ? "bg-red-500"
        : budget.nearLimit
        ? "bg-amber-500"
        : "bg-emerald-500"
    )}
    style={{ width: `${Math.min(100, budget.percentage)}%` }}
  />
</div>
The bar caps at 100% width even if you overspend. The “Available” amount shows the negative value.

Summary Dashboard

The top of the page shows aggregated budget metrics:

Presupuesto Total

Sum of all budget limits for the selected month.Color: Blue

Gastado

Total spent across all budgeted categories.Color: Red

Disponible

Remaining budget: Total Budget - Total Spent
  • Green if positive
  • Red if negative (overspent overall)

Estado

Budget health summary:{controlCount} en control · {exceededCount} excedidos
  • Purple if any budgets exceeded
  • Green if all budgets healthy

Calculation Logic

const summary = React.useMemo(() => {
  const totalBudget = budgets.reduce((acc, budget) => acc + budget.limit, 0)
  const totalSpent = budgets.reduce((acc, budget) => acc + budget.spent, 0)
  const available = totalBudget - totalSpent
  const controlCount = budgets.filter((budget) => !budget.exceeded).length
  const exceededCount = budgets.length - controlCount
  return {
    totalBudget,
    totalSpent,
    available,
    controlCount,
    exceededCount,
  }
}, [budgets])

Filtering by Month

Month/Year Picker

Use the period selector to view budgets for different months:
1

Click Period Button

Click the period button showing the current month (e.g., “enero 2024”).
2

Select Year

Choose a year from the dropdown (range: 2018-2035).
3

Select Month

Click a month button (Jan, Feb, Mar, etc.).The view updates to show budgets for that month.

Custom Month Picker Component

const MonthYearPicker: React.FC<MonthYearPickerProps> = ({
  selected,
  onSelect,
  fromYear = 2018,
  toYear = 2035,
  minMonth,
}) => {
  const [year, setYear] = React.useState(initialYear)

  return (
    <div className="w-72 space-y-4 p-4">
      <Select value={String(year)} onValueChange={handleYearChange}>
        {/* Year selector */}
      </Select>
      <div className="grid grid-cols-3 gap-2">
        {MONTH_LABELS.map((monthName, index) => {
          const isActive = selectedMonthIndex === index && selectedYear === year
          const candidateDate = new Date(year, index, 1)
          const candidateValue = format(candidateDate, "yyyy-MM")
          const disabled = Boolean(minMonth && candidateValue < minMonth && !isActive)
          return (
            <Button
              key={monthName}
              variant={isActive ? "default" : "outline"}
              onClick={() => handleMonthSelect(index)}
              disabled={disabled}
            >
              {monthName.slice(0, 3)}
            </Button>
          )
        })}
      </div>
    </div>
  )
}

Editing a Budget

1

Click Edit

Click Editar on the budget card you want to modify.
2

Update Fields

You can change:
  • Category: Switch to a different expense category
  • Amount: Adjust the budget limit
  • Period: Move to a different month (current or future only)
If you change the category or period, the system checks for existing budgets to prevent duplicates.
3

Save Changes

Click Guardar cambios.
const { error: updateError } = await supabase
  .from("presupuestos")
  .update(payload)
  .eq("id", editingBudget.id)
Spending amounts recalculate automatically if you changed the period.

Deleting a Budget

1

Click Delete

Click Eliminar on the budget card.
2

Confirm Deletion

A browser confirmation dialog appears:“¿Eliminar este presupuesto? Esta acción no se puede deshacer.”
3

Complete Deletion

Click OK to permanently delete the budget.
const { error: deleteError } = await supabase
  .from("presupuestos")
  .delete()
  .eq("id", budgetId)
Deleting a budget does NOT delete your transactions. It only removes the spending limit.

Budget Best Practices

Create budgets for your biggest spending categories first:
  • Food/Groceries
  • Housing/Rent
  • Transportation
  • Utilities
Add more categories as you get comfortable.
Don’t set budgets too low. Review your last 3 months of spending to find realistic limits:
  1. Export transactions for the category
  2. Calculate average monthly spending
  3. Add 10-15% buffer for flexibility
  4. Set that as your budget limit
Check budget progress weekly, especially for categories where you frequently spend:
  • Are you on track?
  • Do you need to slow down spending?
  • Is the limit too restrictive?
Some categories vary by season:
  • Higher utility budgets in summer/winter
  • Increased travel budgets during holidays
  • Back-to-school spending in fall
Edit budgets each month to reflect seasonal changes.
When a budget reaches 90%, you get an amber warning. This is your signal to:
  1. Stop spending in that category if possible
  2. Review transactions for errors or unnecessary purchases
  3. Consider if you need to adjust the budget limit
Even if you overspend, keep the budget. It provides valuable data:
  • Historical spending patterns
  • What limits work vs. don’t work
  • Trends over time
Instead of deleting, adjust the limit for next month.

Multi-Wallet Budget Tracking

Important: Budgets track spending across ALL your wallets, not per wallet.
Example:
  • Budget: $500 for “Groceries” in March
  • Transactions:
    • $200 from “Checking” wallet
    • $150 from “Credit Card” wallet
    • $100 from “Cash” wallet
  • Total spent: 450(countstowardthesingle450 (counts toward the single 500 budget)
This design reflects real-world budgeting: you care about total category spending, not which account paid.

Auto-Update on Transaction Changes

Budgets refresh automatically when you:
  • Create a new transaction
  • Edit an existing transaction
  • Delete a transaction
React.useEffect(() => {
  const handleTransactionsChange = () => {
    loadBudgets()
  }
  window.addEventListener("transactions:updated", handleTransactionsChange as EventListener)
  return () => {
    window.removeEventListener("transactions:updated", handleTransactionsChange as EventListener)
  }
}, [loadBudgets])
No manual refresh needed. Spending amounts update in real-time.

Troubleshooting

Possible causes:
  1. No expense categories: Create at least one “gasto” category first
  2. Duplicate budget: You already have a budget for this category in this month
  3. Past month selected: Choose current or future month
  4. Invalid amount: Enter a number greater than 0
Error messages:
  • “No tienes categorías de gasto disponibles”
  • “Ya tienes un presupuesto para esa categoría en el periodo seleccionado”
  • “Solo puedes crear presupuestos desde el mes actual en adelante”
Check these:
  1. Period filter: Are you viewing the correct month?
  2. Transaction dates: Ensure transactions fall within the budget month
  3. Category assignments: Verify transactions are assigned to the right category
  4. Transaction type: Only “gasto” (expenses) count toward budgets
Debugging:
  • Go to Transacciones
  • Filter by the budget’s month
  • Manually count category expenses
  • Compare with budget “Spent” amount
This is intentional. You cannot move a budget to a past month because:
  1. Historical budgets should remain fixed for accurate records
  2. Past months may already have a budget for that category
  3. Prevents accidental data inconsistencies
Solution: Create a new budget for the current/future month instead.
Possible causes:
  1. Duplicate transactions: Check for accidentally recorded transactions twice
  2. Wrong category: Transactions assigned to this category by mistake
  3. Budget limit too low: Adjust the limit if it’s unrealistic
Solution:
  • Review all transactions in this category for the month
  • Delete or recategorize duplicates/errors
  • Increase budget limit if appropriate
Cause: The BCV API is temporarily unavailable.Impact: Budget cards only show USD amounts until the rate loads.Solution: The system retries automatically. VES equivalents appear once the API responds.

Tracking Transactions

Learn how to record expenses that count toward budgets

Creating Wallets

Understand how budgets track across all wallets

Currency Conversion

See how VES equivalents are calculated for budgets

Exporting Data

Export budget data for external analysis

Build docs developers (and LLMs) love