fix(finance): aceita anotacao nula e usa valor liquido na fatura

This commit is contained in:
Felipe Coutinho
2026-03-12 19:23:13 +00:00
parent b0fbb1062a
commit 20c14aa96f
3 changed files with 15 additions and 9 deletions

View File

@@ -7,6 +7,15 @@ e este projeto adere ao [Versionamento Semântico](https://semver.org/lang/pt-BR
## [Unreleased] ## [Unreleased]
### Corrigido
- Lançamentos: o schema compartilhado de observação voltou a aceitar `null`, corrigindo o erro `Invalid input: expected string, received null` ao salvar novos lançamentos sem anotação.
- Cartões/Faturas: o pagamento da fatura passou a usar o valor líquido do período no cartão, evitando que o extrato da conta registre o total bruto das despesas quando houver receitas como estornos ou créditos na mesma fatura.
### Alterado
- Queries e organização de domínios: o dashboard passou a nomear queries de leitura com sufixo `-queries.ts` e `preferences-queries.ts`, relatórios adotaram nomes explícitos como `cards-report-queries.ts`, `category-report-queries.ts`, `category-chart-queries.ts` e `establishments/queries.ts`, `insights/queries.ts` foi renomeado para `constants.ts` e as leituras reutilizáveis de lançamentos foram concentradas em `transactions/queries.ts`, deixando `page-helpers.ts` focado em parsing, filtros e transformação.
## [2.0.0] - 2026-03-09 ## [2.0.0] - 2026-03-09
### Alterado ### Alterado

View File

@@ -124,12 +124,7 @@ export async function updateInvoicePaymentStatusAction(
.select({ .select({
total: sql<number>` total: sql<number>`
coalesce( coalesce(
sum( sum(${lancamentos.amount}),
case
when ${lancamentos.transactionType} = 'Despesa' then ${lancamentos.amount}
else 0
end
),
0 0
) )
`, `,
@@ -145,9 +140,10 @@ export async function updateInvoicePaymentStatusAction(
), ),
); );
const adminShare = Math.abs(Number(adminShareRow?.total ?? 0)); const adminShare = Number(adminShareRow?.total ?? 0);
const adminPayableAmount = Math.abs(Math.min(adminShare, 0));
if (adminShare > 0 && card.contaId) { if (adminPayableAmount > 0 && card.contaId) {
const adminPagador = await tx.query.pagadores.findFirst({ const adminPagador = await tx.query.pagadores.findFirst({
columns: { id: true }, columns: { id: true },
where: and( where: and(
@@ -170,7 +166,7 @@ export async function updateInvoicePaymentStatusAction(
? parseLocalDateString(data.paymentDate) ? parseLocalDateString(data.paymentDate)
: getBusinessTodayDate(); : getBusinessTodayDate();
const amount = `-${formatDecimal(adminShare)}`; const amount = `-${formatDecimal(adminPayableAmount)}`;
const payload = { const payload = {
condition: "À vista", condition: "À vista",
name: `Pagamento fatura - ${card.name}`, name: `Pagamento fatura - ${card.name}`,

View File

@@ -55,5 +55,6 @@ export const noteSchema = z
.string() .string()
.trim() .trim()
.max(500, "A anotação deve ter no máximo 500 caracteres.") .max(500, "A anotação deve ter no máximo 500 caracteres.")
.nullable()
.optional() .optional()
.transform((value) => (value && value.length > 0 ? value : null)); .transform((value) => (value && value.length > 0 ? value : null));