Files
openmonetis/src/features/invoices/queries.ts
2026-03-14 12:50:55 +00:00

118 lines
2.9 KiB
TypeScript

import { and, desc, eq, type SQL, sum } from "drizzle-orm";
import { cards, invoices, transactions } from "@/db/schema";
import { buildInvoicePaymentNote } from "@/shared/lib/accounts/constants";
import { db } from "@/shared/lib/db";
import {
INVOICE_PAYMENT_STATUS,
type InvoicePaymentStatus,
} from "@/shared/lib/invoices";
const toNumber = (value: string | number | null | undefined) => {
if (typeof value === "number") {
return value;
}
if (value === null || value === undefined) {
return 0;
}
const parsed = Number(value);
return Number.isNaN(parsed) ? 0 : parsed;
};
export async function fetchCardData(userId: string, cardId: string) {
const card = await db.query.cards.findFirst({
columns: {
id: true,
name: true,
brand: true,
closingDay: true,
dueDay: true,
logo: true,
limit: true,
status: true,
note: true,
accountId: true,
},
where: and(eq(cards.id, cardId), eq(cards.userId, userId)),
});
return card;
}
export async function fetchInvoiceData(
userId: string,
cardId: string,
selectedPeriod: string,
): Promise<{
totalAmount: number;
invoiceStatus: InvoicePaymentStatus;
paymentDate: Date | null;
}> {
const [invoiceRow, totalRow] = await Promise.all([
db.query.invoices.findFirst({
columns: {
id: true,
period: true,
paymentStatus: true,
},
where: and(
eq(invoices.cardId, cardId),
eq(invoices.userId, userId),
eq(invoices.period, selectedPeriod),
),
}),
db
.select({ totalAmount: sum(transactions.amount) })
.from(transactions)
.where(
and(
eq(transactions.userId, userId),
eq(transactions.cardId, cardId),
eq(transactions.period, selectedPeriod),
),
),
]);
const totalAmount = toNumber(totalRow[0]?.totalAmount);
const isInvoiceStatus = (
value: string | null | undefined,
): value is InvoicePaymentStatus =>
!!value && ["pendente", "pago"].includes(value);
const invoiceStatus = isInvoiceStatus(invoiceRow?.paymentStatus)
? invoiceRow?.paymentStatus
: INVOICE_PAYMENT_STATUS.PENDING;
// Buscar data do pagamento se a fatura estiver paga
let paymentDate: Date | null = null;
if (invoiceStatus === INVOICE_PAYMENT_STATUS.PAID) {
const invoiceNote = buildInvoicePaymentNote(cardId, selectedPeriod);
const paymentLancamento = await db.query.transactions.findFirst({
columns: {
purchaseDate: true,
},
where: and(
eq(transactions.userId, userId),
eq(transactions.note, invoiceNote),
),
});
paymentDate = paymentLancamento?.purchaseDate
? new Date(paymentLancamento.purchaseDate)
: null;
}
return { totalAmount, invoiceStatus, paymentDate };
}
export async function fetchCardTransactions(filters: SQL[]) {
return db.query.transactions.findMany({
where: and(...filters),
with: {
payer: true,
financialAccount: true,
card: true,
category: true,
},
orderBy: desc(transactions.purchaseDate),
});
}