diff --git a/src/lib/analytics-queries.ts b/src/lib/analytics-queries.ts new file mode 100644 index 0000000..d9381b8 --- /dev/null +++ b/src/lib/analytics-queries.ts @@ -0,0 +1,71 @@ +import { db } from "@/db"; +import { clients, payments } from "@/db/schema"; +import { sql, and, eq } from "drizzle-orm"; + +export async function getAnalyticsByYear(year: number) { + const [contracted] = await db + .select({ total: sql`coalesce(sum(${clients.accepted_total}::numeric), 0)` }) + .from(clients) + .where(sql`extract(year from ${clients.created_at}) = ${year}`); + + const [clientsRow] = await db + .select({ count: sql`count(*)` }) + .from(clients) + .where(sql`extract(year from ${clients.created_at}) = ${year}`); + + const [collected] = await db + .select({ total: sql`coalesce(sum(${payments.amount}::numeric), 0)` }) + .from(payments) + .where( + and( + eq(payments.status, "saldato"), + sql`${payments.paid_at} is not null and extract(year from ${payments.paid_at}) = ${year}` + ) + ); + + const [pending] = await db + .select({ total: sql`coalesce(sum(${payments.amount}::numeric), 0)` }) + .from(payments) + .where(sql`${payments.status} in ('da_saldare', 'inviata')`); + + return { + contracted: parseFloat(contracted?.total ?? "0"), + collected: parseFloat(collected?.total ?? "0"), + clientsAcquired: parseInt(clientsRow?.count ?? "0"), + pending: parseFloat(pending?.total ?? "0"), + }; +} + +export async function getMonthlyCollected(year: number): Promise { + const rows = await db + .select({ + month: sql`extract(month from ${payments.paid_at})::int`, + total: sql`coalesce(sum(${payments.amount}::numeric), 0)`, + }) + .from(payments) + .where( + and( + eq(payments.status, "saldato"), + sql`${payments.paid_at} is not null and extract(year from ${payments.paid_at}) = ${year}` + ) + ) + .groupBy(sql`extract(month from ${payments.paid_at})`); + + const byMonth: number[] = Array(12).fill(0); + for (const row of rows) { + byMonth[(row.month as number) - 1] = parseFloat(row.total); + } + return byMonth; +} + +export async function getAvailableYears(): Promise { + const rows = await db + .select({ year: sql`extract(year from ${clients.created_at})::int` }) + .from(clients) + .groupBy(sql`extract(year from ${clients.created_at})`); + + const years = rows.map((r) => r.year as number); + const currentYear = new Date().getFullYear(); + if (!years.includes(currentYear)) years.push(currentYear); + return years.sort((a, b) => b - a); +} \ No newline at end of file