feat(faturas/extrato): ajuste de fatura, reembolso e ajuste de saldo da conta

- botão "Ajustar fatura" na página da fatura abre dialog com input do valor real
  e preview da diferença; action faz upsert/delete idempotente do lançamento de ajuste
- opção "Reembolso" no dropdown de ações de despesas à vista cria receita espelhada
  no extrato ou fatura correta, vinculada ao lançamento original
- botão "Ajustar saldo" no extrato da conta compara saldo real informado e gera
  lançamento de ajuste por (accountId, period) via upsert/delete idempotente
- constantes INVOICE_ADJUSTMENT_NAME, ACCOUNT_BALANCE_ADJUSTMENT_NAME,
  REFUND_NOTE_PREFIX e buildRefundNote() centralizadas em shared/lib/accounts/constants.ts
- extrato agora contabiliza transferências internas em Entradas e Saídas corretamente

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Felipe Coutinho
2026-05-02 22:08:07 +00:00
parent 8389752172
commit 4bea6330bf
9 changed files with 638 additions and 47 deletions

View File

@@ -4,7 +4,10 @@ import {
fetchTransactionsPageWithRelations,
fetchTransactionsWithRelations,
} from "@/features/transactions/queries";
import { INITIAL_BALANCE_NOTE } from "@/shared/lib/accounts/constants";
import {
INITIAL_BALANCE_NOTE,
REFUND_NOTE_PREFIX,
} from "@/shared/lib/accounts/constants";
import { db } from "@/shared/lib/db";
import { getAdminPayerId } from "@/shared/lib/payers/get-admin-id";
@@ -74,7 +77,9 @@ export async function fetchAccountSummary(
sum(
case
when ${transactions.note} = ${INITIAL_BALANCE_NOTE} then 0
when ${transactions.note} ilike ${`${REFUND_NOTE_PREFIX}%`} then 0
when ${transactions.transactionType} = 'Receita' then ${transactions.amount}
when ${transactions.transactionType} = 'Transferência' and ${transactions.amount} > 0 then ${transactions.amount}
else 0
end
),
@@ -86,7 +91,9 @@ export async function fetchAccountSummary(
sum(
case
when ${transactions.note} = ${INITIAL_BALANCE_NOTE} then 0
when ${transactions.note} ilike ${`${REFUND_NOTE_PREFIX}%`} then abs(${transactions.amount})
when ${transactions.transactionType} = 'Despesa' then ${transactions.amount}
when ${transactions.transactionType} = 'Transferência' and ${transactions.amount} < 0 then ${transactions.amount}
else 0
end
),
@@ -135,7 +142,8 @@ export async function fetchAccountSummary(
const openingBalance = initialBalance + previousMovements;
const netAmount = Number(periodSummary?.netAmount ?? 0);
const totalIncomes = Number(periodSummary?.incomes ?? 0);
const totalExpenses = Math.abs(Number(periodSummary?.expenses ?? 0));
const expenseNet = Number(periodSummary?.expenses ?? 0);
const totalExpenses = Math.max(0, -expenseNet);
const currentBalance = openingBalance + netAmount;
return {