Aller au contenu principal

Server Actions — Budget

Source : src/app/actions/budget.ts


getBudget()

Retourne le plan budget de l'utilisateur. Le crée automatiquement s'il n'existe pas encore.

export async function getBudget(): Promise<BudgetPlanWithRelations>

Comportement : cherche un BudgetPlan { userId, month: "reference" }. Si inexistant, le crée avec totalIncomeExpected = 0. Il y a donc toujours exactement un plan par utilisateur après ce premier appel.

Retour : plan avec incomeSources[] et allocations[] triés par order asc, puis id asc.


upsertIncomeSource(data)

Crée ou met à jour une source de revenus dans le plan.

export async function upsertIncomeSource(data: {
id?: string; // si fourni → update, sinon → create
budgetPlanId: string;
label: string;
type: IncomeType; // SALARY | FREELANCE | REIMBURSEMENT | INVESTMENT | OTHER
expectedMonthly: number;
color?: string; // défaut: "#10b981"
order?: number; // défaut: 0
}): Promise<UpsertResult>

Pré-conditions : budgetPlanId appartient à l'utilisateur courant.

Effets :

  • Crée ou met à jour la source.
  • Appelle syncTotalIncome() → recalcule BudgetPlan.totalIncomeExpected = Σ expectedMonthly.
  • revalidatePath("/budget").

deleteIncomeSource(id)

Supprime une source de revenus et resynchronise le total.

export async function deleteIncomeSource(id: string): Promise<ActionResult>

Effets : suppression + syncTotalIncome() + revalidatePath("/budget").


upsertAllocation(data)

Crée ou met à jour une allocation budgétaire.

export async function upsertAllocation(data: {
id?: string;
budgetPlanId: string;
label: string;
type: AllocationType; // FIXED_EXPENSE | VARIABLE_EXPENSE | SAVINGS | INVESTMENT
targetAmount: number;
color?: string; // défaut: "#6366f1"
order?: number; // défaut: 0
}): Promise<UpsertResult>

Pré-conditions : budgetPlanId appartient à l'utilisateur courant.

Calcul automatique : targetPercent = (targetAmount / totalIncomeExpected) × 100. Si totalIncomeExpected = 0, targetPercent = 0.

Effets : revalidatePath("/budget").


deleteAllocation(id)

Supprime une allocation budgétaire.

export async function deleteAllocation(id: string): Promise<ActionResult>

Effets : revalidatePath("/budget").


Synchronisation totalIncomeExpected

La fonction interne syncTotalIncome(budgetPlanId) est appelée après chaque mutation de BudgetIncomeSource. Elle recalcule le total depuis la DB :

totalIncomeExpected = Σ incomeSources.expectedMonthly

Ce champ est donc toujours cohérent — il n'est jamais saisi directement.


Voir aussi