mirror of
https://github.com/felipegcoutinho/openmonetis.git
synced 2026-05-09 19:01:47 +00:00
fix(financeiro): alinhar saldo, métricas e relatórios
This commit is contained in:
@@ -17,12 +17,18 @@ import type { PaymentMethodsData } from "@/features/dashboard/payments/payment-m
|
||||
import type { PaymentStatusData } from "@/features/dashboard/payments/payment-status-queries";
|
||||
import type { PurchasesByCategoryData } from "@/features/dashboard/purchases-by-category-queries";
|
||||
import type { TopEstablishmentsData } from "@/features/dashboard/top-establishments-queries";
|
||||
import { excludeTransactionsFromExcludedAccounts } from "@/features/dashboard/transaction-filters";
|
||||
import {
|
||||
ACCOUNT_AUTO_INVOICE_NOTE_PREFIX,
|
||||
INITIAL_BALANCE_NOTE,
|
||||
} from "@/shared/lib/accounts/constants";
|
||||
import { db } from "@/shared/lib/db";
|
||||
import { getAdminPayerId } from "@/shared/lib/payers/get-admin-id";
|
||||
import {
|
||||
compareDateOnly,
|
||||
getBusinessDateString,
|
||||
isDateOnlyPast,
|
||||
} from "@/shared/utils/date";
|
||||
import { safeToNumber as toNumber } from "@/shared/utils/number";
|
||||
|
||||
const PAYMENT_METHOD_BOLETO = "Boleto";
|
||||
@@ -54,6 +60,7 @@ type CurrentPeriodTransactionRow = {
|
||||
categoryType: string | null;
|
||||
cardLogo: string | null;
|
||||
accountLogo: string | null;
|
||||
accountExcludeInitialBalanceFromIncome: boolean | null;
|
||||
};
|
||||
|
||||
type CategoryOption = PurchasesByCategoryData["categories"][number];
|
||||
@@ -112,6 +119,21 @@ const shouldIncludeWithoutAutoInvoice = (note: string | null | undefined) =>
|
||||
const shouldIncludeWithoutAutoGenerated = (note: string | null | undefined) =>
|
||||
!isInitialBalanceNote(note) && !isAutoInvoiceNote(note);
|
||||
|
||||
const shouldIncludeInPaymentStatus = (row: CurrentPeriodTransactionRow) => {
|
||||
if (!shouldIncludeWithoutAutoInvoice(row.note)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
isInitialBalanceNote(row.note) &&
|
||||
row.accountExcludeInitialBalanceFromIncome === true
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
const shouldIncludeNamedItem = (name: string) => {
|
||||
const normalized = name.trim().toLowerCase();
|
||||
|
||||
@@ -126,9 +148,30 @@ const shouldIncludeNamedItem = (name: string) => {
|
||||
return true;
|
||||
};
|
||||
|
||||
const compareDateOnlyAscWithNullsLast = (
|
||||
left: string | null,
|
||||
right: string | null,
|
||||
) => {
|
||||
if (!left && !right) return 0;
|
||||
if (!left) return 1;
|
||||
if (!right) return -1;
|
||||
return compareDateOnly(left, right);
|
||||
};
|
||||
|
||||
const compareDateOnlyDescWithNullsLast = (
|
||||
left: string | null,
|
||||
right: string | null,
|
||||
) => {
|
||||
if (!left && !right) return 0;
|
||||
if (!left) return 1;
|
||||
if (!right) return -1;
|
||||
return compareDateOnly(right, left);
|
||||
};
|
||||
|
||||
const buildBillsSnapshot = (
|
||||
rows: CurrentPeriodTransactionRow[],
|
||||
): DashboardBillsSnapshot => {
|
||||
const today = getBusinessDateString();
|
||||
const bills = rows
|
||||
.filter((row) => row.paymentMethod === PAYMENT_METHOD_BOLETO)
|
||||
.map((row) => ({
|
||||
@@ -143,17 +186,44 @@ const buildBillsSnapshot = (
|
||||
}))
|
||||
.sort((a, b) => {
|
||||
if (a.isSettled !== b.isSettled) {
|
||||
return Number(a.isSettled) - Number(b.isSettled);
|
||||
return a.isSettled ? 1 : -1;
|
||||
}
|
||||
|
||||
const dueA = a.dueDate
|
||||
? new Date(a.dueDate).getTime()
|
||||
: Number.POSITIVE_INFINITY;
|
||||
const dueB = b.dueDate
|
||||
? new Date(b.dueDate).getTime()
|
||||
: Number.POSITIVE_INFINITY;
|
||||
if (dueA !== dueB) {
|
||||
return dueA - dueB;
|
||||
if (!a.isSettled && !b.isSettled) {
|
||||
const aIsOverdue = a.dueDate ? isDateOnlyPast(a.dueDate, today) : false;
|
||||
const bIsOverdue = b.dueDate ? isDateOnlyPast(b.dueDate, today) : false;
|
||||
|
||||
if (aIsOverdue !== bIsOverdue) {
|
||||
return aIsOverdue ? -1 : 1;
|
||||
}
|
||||
|
||||
const dueDateDiff = compareDateOnlyAscWithNullsLast(
|
||||
a.dueDate,
|
||||
b.dueDate,
|
||||
);
|
||||
if (dueDateDiff !== 0) {
|
||||
return dueDateDiff;
|
||||
}
|
||||
|
||||
const amountDiff = b.amount - a.amount;
|
||||
if (amountDiff !== 0) {
|
||||
return amountDiff;
|
||||
}
|
||||
}
|
||||
|
||||
if (a.isSettled && b.isSettled) {
|
||||
const paidAtDiff = compareDateOnlyDescWithNullsLast(
|
||||
a.boletoPaymentDate,
|
||||
b.boletoPaymentDate,
|
||||
);
|
||||
if (paidAtDiff !== 0) {
|
||||
return paidAtDiff;
|
||||
}
|
||||
|
||||
const amountDiff = b.amount - a.amount;
|
||||
if (amountDiff !== 0) {
|
||||
return amountDiff;
|
||||
}
|
||||
}
|
||||
|
||||
return a.name.localeCompare(b.name, "pt-BR");
|
||||
@@ -181,7 +251,7 @@ const buildPaymentStatusData = (
|
||||
|
||||
for (const row of rows) {
|
||||
if (
|
||||
!shouldIncludeWithoutAutoInvoice(row.note) ||
|
||||
!shouldIncludeInPaymentStatus(row) ||
|
||||
(row.transactionType !== TRANSACTION_TYPE_INCOME &&
|
||||
row.transactionType !== TRANSACTION_TYPE_EXPENSE)
|
||||
) {
|
||||
@@ -496,6 +566,8 @@ export async function fetchDashboardCurrentPeriodOverview(
|
||||
categoryType: categories.type,
|
||||
cardLogo: cards.logo,
|
||||
accountLogo: financialAccounts.logo,
|
||||
accountExcludeInitialBalanceFromIncome:
|
||||
financialAccounts.excludeInitialBalanceFromIncome,
|
||||
})
|
||||
.from(transactions)
|
||||
.leftJoin(cards, eq(transactions.cardId, cards.id))
|
||||
@@ -509,6 +581,7 @@ export async function fetchDashboardCurrentPeriodOverview(
|
||||
eq(transactions.userId, userId),
|
||||
eq(transactions.period, period),
|
||||
eq(transactions.payerId, adminPayerId),
|
||||
excludeTransactionsFromExcludedAccounts(),
|
||||
),
|
||||
)
|
||||
.orderBy(
|
||||
|
||||
Reference in New Issue
Block a user