refactor: alinha features financeiras ao novo naming

This commit is contained in:
Felipe Coutinho
2026-03-14 12:50:55 +00:00
parent ef918a3667
commit 67ad4b9d02
51 changed files with 876 additions and 898 deletions

View File

@@ -1,22 +1,22 @@
import { and, eq, ilike, isNull, ne, not, or, sql } from "drizzle-orm";
import { cartoes, contas, lancamentos } from "@/db/schema";
import { cards, financialAccounts, transactions } from "@/db/schema";
import { db } from "@/shared/lib/db";
import { loadLogoOptions } from "@/shared/lib/logo/options";
export type CardData = {
id: string;
name: string;
brand: string | null;
status: string | null;
closingDay: number;
dueDay: number;
brand: string;
status: string;
closingDay: string;
dueDay: string;
note: string | null;
logo: string | null;
limit: number | null;
limitInUse: number;
limitAvailable: number | null;
contaId: string;
contaName: string;
accountId: string;
accountName: string;
};
export type AccountSimple = {
@@ -28,20 +28,14 @@ export type AccountSimple = {
export async function fetchCardsForUser(userId: string): Promise<{
cards: CardData[];
accounts: AccountSimple[];
logoOptions: LogoOption[];
logoOptions: string[];
}> {
const [cardRows, accountRows, logoOptions, usageRows] = await Promise.all([
db.query.cartoes.findMany({
orderBy: (
card: typeof cartoes.$inferSelect,
{ desc }: { desc: (field: unknown) => unknown },
) => [desc(card.name)],
where: and(
eq(cartoes.userId, userId),
not(ilike(cartoes.status, "inativo")),
),
db.query.cards.findMany({
orderBy: (table, { desc }) => [desc(table.name)],
where: and(eq(cards.userId, userId), not(ilike(cards.status, "inativo"))),
with: {
conta: {
financialAccount: {
columns: {
id: true,
name: true,
@@ -49,12 +43,9 @@ export async function fetchCardsForUser(userId: string): Promise<{
},
},
}),
db.query.contas.findMany({
orderBy: (
account: typeof contas.$inferSelect,
{ desc }: { desc: (field: unknown) => unknown },
) => [desc(account.name)],
where: eq(contas.userId, userId),
db.query.financialAccounts.findMany({
orderBy: (table, { desc }) => [desc(table.name)],
where: eq(financialAccounts.userId, userId),
columns: {
id: true,
name: true,
@@ -64,37 +55,35 @@ export async function fetchCardsForUser(userId: string): Promise<{
loadLogoOptions(),
db
.select({
cartaoId: lancamentos.cartaoId,
total: sql<number>`coalesce(sum(${lancamentos.amount}), 0)`,
cardId: transactions.cardId,
total: sql<number>`coalesce(sum(${transactions.amount}), 0)`,
})
.from(lancamentos)
.from(transactions)
.where(
and(
eq(lancamentos.userId, userId),
or(isNull(lancamentos.isSettled), eq(lancamentos.isSettled, false)),
eq(transactions.userId, userId),
or(isNull(transactions.isSettled), eq(transactions.isSettled, false)),
// Recorrente no cartão: só consome limite quando a data da ocorrência já passou
or(
ne(lancamentos.condition, "Recorrente"),
sql`${lancamentos.purchaseDate} <= current_date`,
ne(transactions.condition, "Recorrente"),
sql`${transactions.purchaseDate} <= current_date`,
),
),
)
.groupBy(lancamentos.cartaoId),
.groupBy(transactions.cardId),
]);
const usageMap = new Map<string, number>();
usageRows.forEach(
(row: { cartaoId: string | null; total: number | null }) => {
if (!row.cartaoId) return;
usageMap.set(row.cartaoId, Number(row.total ?? 0));
},
);
usageRows.forEach((row: { cardId: string | null; total: number | null }) => {
if (!row.cardId) return;
usageMap.set(row.cardId, Number(row.total ?? 0));
});
const cards = cardRows.map((card) => ({
const cardList = cardRows.map((card) => ({
id: card.id,
name: card.name,
brand: card.brand,
status: card.status,
brand: card.brand ?? "",
status: card.status ?? "",
closingDay: card.closingDay,
dueDay: card.dueDay,
note: card.note,
@@ -112,8 +101,10 @@ export async function fetchCardsForUser(userId: string): Promise<{
const inUse = total < 0 ? Math.abs(total) : 0;
return Math.max(Number(card.limit) - inUse, 0);
})(),
contaId: card.contaId,
contaName: card.conta?.name ?? "Conta não encontrada",
accountId: card.accountId,
accountName:
(card.financialAccount as { name?: string } | null)?.name ??
"Conta não encontrada",
}));
const accounts = accountRows.map((account) => ({
@@ -122,23 +113,20 @@ export async function fetchCardsForUser(userId: string): Promise<{
logo: account.logo,
}));
return { cards, accounts, logoOptions };
return { cards: cardList, accounts, logoOptions };
}
export async function fetchInativosForUser(userId: string): Promise<{
export async function fetchInactiveForUser(userId: string): Promise<{
cards: CardData[];
accounts: AccountSimple[];
logoOptions: LogoOption[];
logoOptions: string[];
}> {
const [cardRows, accountRows, logoOptions, usageRows] = await Promise.all([
db.query.cartoes.findMany({
orderBy: (
card: typeof cartoes.$inferSelect,
{ desc }: { desc: (field: unknown) => unknown },
) => [desc(card.name)],
where: and(eq(cartoes.userId, userId), ilike(cartoes.status, "inativo")),
db.query.cards.findMany({
orderBy: (table, { desc }) => [desc(table.name)],
where: and(eq(cards.userId, userId), ilike(cards.status, "inativo")),
with: {
conta: {
financialAccount: {
columns: {
id: true,
name: true,
@@ -146,12 +134,9 @@ export async function fetchInativosForUser(userId: string): Promise<{
},
},
}),
db.query.contas.findMany({
orderBy: (
account: typeof contas.$inferSelect,
{ desc }: { desc: (field: unknown) => unknown },
) => [desc(account.name)],
where: eq(contas.userId, userId),
db.query.financialAccounts.findMany({
orderBy: (table, { desc }) => [desc(table.name)],
where: eq(financialAccounts.userId, userId),
columns: {
id: true,
name: true,
@@ -161,37 +146,35 @@ export async function fetchInativosForUser(userId: string): Promise<{
loadLogoOptions(),
db
.select({
cartaoId: lancamentos.cartaoId,
total: sql<number>`coalesce(sum(${lancamentos.amount}), 0)`,
cardId: transactions.cardId,
total: sql<number>`coalesce(sum(${transactions.amount}), 0)`,
})
.from(lancamentos)
.from(transactions)
.where(
and(
eq(lancamentos.userId, userId),
or(isNull(lancamentos.isSettled), eq(lancamentos.isSettled, false)),
eq(transactions.userId, userId),
or(isNull(transactions.isSettled), eq(transactions.isSettled, false)),
// Recorrente no cartão: só consome limite quando a data da ocorrência já passou
or(
ne(lancamentos.condition, "Recorrente"),
sql`${lancamentos.purchaseDate} <= current_date`,
ne(transactions.condition, "Recorrente"),
sql`${transactions.purchaseDate} <= current_date`,
),
),
)
.groupBy(lancamentos.cartaoId),
.groupBy(transactions.cardId),
]);
const usageMap = new Map<string, number>();
usageRows.forEach(
(row: { cartaoId: string | null; total: number | null }) => {
if (!row.cartaoId) return;
usageMap.set(row.cartaoId, Number(row.total ?? 0));
},
);
usageRows.forEach((row: { cardId: string | null; total: number | null }) => {
if (!row.cardId) return;
usageMap.set(row.cardId, Number(row.total ?? 0));
});
const cards = cardRows.map((card) => ({
const cardList = cardRows.map((card) => ({
id: card.id,
name: card.name,
brand: card.brand,
status: card.status,
brand: card.brand ?? "",
status: card.status ?? "",
closingDay: card.closingDay,
dueDay: card.dueDay,
note: card.note,
@@ -209,8 +192,10 @@ export async function fetchInativosForUser(userId: string): Promise<{
const inUse = total < 0 ? Math.abs(total) : 0;
return Math.max(Number(card.limit) - inUse, 0);
})(),
contaId: card.contaId,
contaName: card.conta?.name ?? "Conta não encontrada",
accountId: card.accountId,
accountName:
(card.financialAccount as { name?: string } | null)?.name ??
"Conta não encontrada",
}));
const accounts = accountRows.map((account) => ({
@@ -219,18 +204,18 @@ export async function fetchInativosForUser(userId: string): Promise<{
logo: account.logo,
}));
return { cards, accounts, logoOptions };
return { cards: cardList, accounts, logoOptions };
}
export async function fetchAllCardsForUser(userId: string): Promise<{
activeCards: CardData[];
archivedCards: CardData[];
accounts: AccountSimple[];
logoOptions: LogoOption[];
logoOptions: string[];
}> {
const [activeData, archivedData] = await Promise.all([
fetchCardsForUser(userId),
fetchInativosForUser(userId),
fetchInactiveForUser(userId),
]);
return {