Files
openmonetis/lib/dashboard/top-establishments.ts

92 lines
2.2 KiB
TypeScript

import { and, eq, sql } from "drizzle-orm";
import { cartoes, contas, lancamentos } from "@/db/schema";
import {
buildDashboardAdminPeriodFilters,
excludeAutoGeneratedEntryNotes,
} from "@/lib/dashboard/lancamento-filters";
import { db } from "@/lib/db";
import { getAdminPagadorId } from "@/lib/pagadores/get-admin-id";
import { safeToNumber as toNumber } from "@/lib/utils/number";
export type TopEstablishment = {
id: string;
name: string;
amount: number;
occurrences: number;
logo: string | null;
};
export type TopEstablishmentsData = {
establishments: TopEstablishment[];
};
const shouldIncludeEstablishment = (name: string) => {
const normalized = name.trim().toLowerCase();
if (normalized === "saldo inicial") {
return false;
}
if (normalized.includes("fatura")) {
return false;
}
return true;
};
export async function fetchTopEstablishments(
userId: string,
period: string,
): Promise<TopEstablishmentsData> {
const adminPagadorId = await getAdminPagadorId(userId);
if (!adminPagadorId) {
return { establishments: [] };
}
const rows = await db
.select({
name: lancamentos.name,
totalAmount: sql<number>`coalesce(sum(${lancamentos.amount}), 0)`,
occurrences: sql<number>`count(${lancamentos.id})`,
logo: sql<string | null>`max(coalesce(${cartoes.logo}, ${contas.logo}))`,
})
.from(lancamentos)
.leftJoin(cartoes, eq(lancamentos.cartaoId, cartoes.id))
.leftJoin(contas, eq(lancamentos.contaId, contas.id))
.where(
and(
...buildDashboardAdminPeriodFilters({
userId,
period,
adminPagadorId,
}),
eq(lancamentos.transactionType, "Despesa"),
excludeAutoGeneratedEntryNotes(),
),
)
.groupBy(lancamentos.name)
.orderBy(
sql`count(${lancamentos.id}) DESC`,
sql`ABS(sum(${lancamentos.amount})) DESC`,
)
.limit(10);
const establishments = rows
.filter((row: (typeof rows)[number]) =>
shouldIncludeEstablishment(row.name),
)
.map(
(row: (typeof rows)[number]): TopEstablishment => ({
id: row.name,
name: row.name,
amount: Math.abs(toNumber(row.totalAmount)),
occurrences: Number(row.occurrences ?? 0),
logo: row.logo ?? null,
}),
);
return {
establishments,
};
}