aboutsummaryrefslogtreecommitdiff
path: root/api/src/modules/recurring-expenses/recurring-expenses.service.ts
blob: 2bb972080b42203ab7bdb858dd6405813f97b42b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import { and, eq } from 'drizzle-orm';
import { db } from '@/db/client';
import { recurringExpenses } from '@/db/schema';
import type {
  CreateRecurringExpenseInput,
  UpdateRecurringExpenseInput,
} from './recurring-expenses.schema';

export async function findRecurringExpensesByUser(userId: number) {
  return db
    .select()
    .from(recurringExpenses)
    .where(eq(recurringExpenses.user_id, userId))
    .orderBy(recurringExpenses.name);
}

export async function findRecurringExpenseById(userId: number, id: number) {
  const result = await db
    .select()
    .from(recurringExpenses)
    .where(
      and(
        eq(recurringExpenses.user_id, userId),
        eq(recurringExpenses.id, id),
      ),
    )
    .limit(1);
  return result[0] ?? null;
}

export async function createRecurringExpense(
  userId: number,
  data: CreateRecurringExpenseInput,
) {
  const [created] = await db
    .insert(recurringExpenses)
    .values({
      user_id: userId,
      name: data.name,
      amount: data.amount,
      category: data.category,
      type: data.type,
      due_day: data.due_day ?? null,
      is_active: data.is_active,
      starts_at: data.starts_at,
      ends_at: data.ends_at ?? null,
    })
    .returning();
  return created;
}

export async function updateRecurringExpense(
  userId: number,
  id: number,
  data: UpdateRecurringExpenseInput,
) {
  const now = new Date().toISOString();

  const [updated] = await db
    .update(recurringExpenses)
    .set({
      ...(data.name !== undefined && { name: data.name }),
      ...(data.amount !== undefined && { amount: data.amount }),
      ...(data.category !== undefined && { category: data.category }),
      ...(data.type !== undefined && { type: data.type }),
      ...(data.due_day !== undefined && { due_day: data.due_day }),
      ...(data.is_active !== undefined && { is_active: data.is_active }),
      ...(data.starts_at !== undefined && { starts_at: data.starts_at }),
      ...(data.ends_at !== undefined && { ends_at: data.ends_at }),
      updated_at: now,
    })
    .where(
      and(
        eq(recurringExpenses.user_id, userId),
        eq(recurringExpenses.id, id),
      ),
    )
    .returning();

  return updated ?? null;
}

export async function toggleRecurringExpense(userId: number, id: number) {
  const expense = await findRecurringExpenseById(userId, id);
  if (!expense) return null;

  const [updated] = await db
    .update(recurringExpenses)
    .set({
      is_active: !expense.is_active,
      updated_at: new Date().toISOString(),
    })
    .where(
      and(
        eq(recurringExpenses.user_id, userId),
        eq(recurringExpenses.id, id),
      ),
    )
    .returning();

  return updated ?? null;
}

export async function deleteRecurringExpense(userId: number, id: number) {
  const [deleted] = await db
    .delete(recurringExpenses)
    .where(
      and(
        eq(recurringExpenses.user_id, userId),
        eq(recurringExpenses.id, id),
      ),
    )
    .returning();
  return deleted ?? null;
}