forked from git.gladyson/openmonetis
feat(v1.5.3): status de pagamento no painel do pagador + SEO landing + WebP
- Card de Status de Pagamento com totais pagos/pendentes e lista de boletos individuais - Validação obrigatória de categoria/conta/cartão no dialog de lançamento (client + server) - SEO completo na landing: Open Graph, Twitter Card, JSON-LD, sitemap.xml, robots.txt - Imagens convertidas de PNG para WebP (performance) - HTML lang corrigido para pt-BR; template de título dinâmico Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
and,
|
||||
asc,
|
||||
eq,
|
||||
gte,
|
||||
ilike,
|
||||
@@ -47,6 +48,29 @@ export type PagadorBoletoStats = {
|
||||
pendingCount: number;
|
||||
};
|
||||
|
||||
export type PagadorBoletoItem = {
|
||||
id: string;
|
||||
name: string;
|
||||
amount: number;
|
||||
dueDate: string | null;
|
||||
boletoPaymentDate: string | null;
|
||||
isSettled: boolean;
|
||||
};
|
||||
|
||||
export type PagadorPaymentStatusData = {
|
||||
paidAmount: number;
|
||||
paidCount: number;
|
||||
pendingAmount: number;
|
||||
pendingCount: number;
|
||||
totalAmount: number;
|
||||
};
|
||||
|
||||
const toISODate = (value: Date | string | null | undefined): string | null => {
|
||||
if (!value) return null;
|
||||
if (value instanceof Date) return value.toISOString().slice(0, 10);
|
||||
return typeof value === "string" ? value : null;
|
||||
};
|
||||
|
||||
const toNumber = (value: string | number | bigint | null) => {
|
||||
if (typeof value === "number") {
|
||||
return value;
|
||||
@@ -323,3 +347,87 @@ export async function fetchPagadorBoletoStats({
|
||||
pendingCount,
|
||||
};
|
||||
}
|
||||
|
||||
export async function fetchPagadorBoletoItems({
|
||||
userId,
|
||||
pagadorId,
|
||||
period,
|
||||
}: BaseFilters): Promise<PagadorBoletoItem[]> {
|
||||
const rows = await db
|
||||
.select({
|
||||
id: lancamentos.id,
|
||||
name: lancamentos.name,
|
||||
amount: lancamentos.amount,
|
||||
dueDate: lancamentos.dueDate,
|
||||
boletoPaymentDate: lancamentos.boletoPaymentDate,
|
||||
isSettled: lancamentos.isSettled,
|
||||
})
|
||||
.from(lancamentos)
|
||||
.where(
|
||||
and(
|
||||
eq(lancamentos.userId, userId),
|
||||
eq(lancamentos.pagadorId, pagadorId),
|
||||
eq(lancamentos.period, period),
|
||||
eq(lancamentos.paymentMethod, PAYMENT_METHOD_BOLETO),
|
||||
excludeAutoInvoiceEntries(),
|
||||
),
|
||||
)
|
||||
.orderBy(asc(lancamentos.dueDate));
|
||||
|
||||
return rows.map((row) => ({
|
||||
id: row.id,
|
||||
name: row.name,
|
||||
amount: Math.abs(toNumber(row.amount)),
|
||||
dueDate: toISODate(row.dueDate),
|
||||
boletoPaymentDate: toISODate(row.boletoPaymentDate),
|
||||
isSettled: Boolean(row.isSettled),
|
||||
}));
|
||||
}
|
||||
|
||||
export async function fetchPagadorPaymentStatus({
|
||||
userId,
|
||||
pagadorId,
|
||||
period,
|
||||
}: BaseFilters): Promise<PagadorPaymentStatusData> {
|
||||
const rows = await db
|
||||
.select({
|
||||
paidAmount: sql<string>`coalesce(sum(case when ${lancamentos.isSettled} = true then abs(${lancamentos.amount}) else 0 end), 0)`,
|
||||
paidCount: sql<number>`sum(case when ${lancamentos.isSettled} = true then 1 else 0 end)`,
|
||||
pendingAmount: sql<string>`coalesce(sum(case when (${lancamentos.isSettled} = false or ${lancamentos.isSettled} is null) then abs(${lancamentos.amount}) else 0 end), 0)`,
|
||||
pendingCount: sql<number>`sum(case when (${lancamentos.isSettled} = false or ${lancamentos.isSettled} is null) then 1 else 0 end)`,
|
||||
})
|
||||
.from(lancamentos)
|
||||
.where(
|
||||
and(
|
||||
eq(lancamentos.userId, userId),
|
||||
eq(lancamentos.pagadorId, pagadorId),
|
||||
eq(lancamentos.period, period),
|
||||
eq(lancamentos.transactionType, DESPESA),
|
||||
excludeAutoInvoiceEntries(),
|
||||
),
|
||||
);
|
||||
|
||||
const row = rows[0];
|
||||
if (!row) {
|
||||
return {
|
||||
paidAmount: 0,
|
||||
paidCount: 0,
|
||||
pendingAmount: 0,
|
||||
pendingCount: 0,
|
||||
totalAmount: 0,
|
||||
};
|
||||
}
|
||||
|
||||
const paidAmount = toNumber(row.paidAmount);
|
||||
const paidCount = toNumber(row.paidCount);
|
||||
const pendingAmount = toNumber(row.pendingAmount);
|
||||
const pendingCount = toNumber(row.pendingCount);
|
||||
|
||||
return {
|
||||
paidAmount,
|
||||
paidCount,
|
||||
pendingAmount,
|
||||
pendingCount,
|
||||
totalAmount: paidAmount + pendingAmount,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user