Merge pull request #21 from felipegcoutinho/feat/pr18-partial-bulk-delete-recurring-limit
feat: aproveitamento parcial da PR #18
This commit is contained in:
11
CHANGELOG.md
11
CHANGELOG.md
@@ -5,6 +5,17 @@ Todas as mudanças notáveis deste projeto serão documentadas neste arquivo.
|
||||
O formato é baseado em [Keep a Changelog](https://keepachangelog.com/pt-BR/1.1.0/),
|
||||
e este projeto adere ao [Versionamento Semântico](https://semver.org/lang/pt-BR/).
|
||||
|
||||
## [1.7.4] - 2026-02-28
|
||||
|
||||
### Alterado
|
||||
|
||||
- Card de análise de parcelas (`/dashboard/analise-parcelas`): layout empilhado no mobile — nome/cartão e valores Total/Pendente em linhas separadas ao invés de lado-a-lado, evitando truncamento
|
||||
- Página de top estabelecimentos (`/top-estabelecimentos`): cards "Top Estabelecimentos por Frequência" e "Principais Categorias" empilhados verticalmente no mobile (`grid-cols-1 lg:grid-cols-2`)
|
||||
- Padding da lista de parcelas expandida reduzido no mobile (`px-2 sm:px-8`)
|
||||
- Ajustes gerais de responsividade em navbar, filtros, skeletons, widgets e dialogs (26 componentes)
|
||||
- Remover selecionados: quando todos os itens selecionados pertencem à mesma série (parcelado ou recorrente), abre dialog de escopo com 3 opções ao invés de confirmação simples (parcial da PR #18)
|
||||
- Despesa recorrente no cartão de crédito: só consome o limite do cartão quando a data da ocorrência já passou; mesma regra no relatório de cartões (parcial da PR #18)
|
||||
|
||||
## [1.7.3] - 2026-02-27
|
||||
|
||||
### Adicionado
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { and, eq, ilike, isNull, not, or, sql } from "drizzle-orm";
|
||||
import { and, eq, ilike, isNull, ne, not, or, sql } from "drizzle-orm";
|
||||
import { cartoes, contas, lancamentos } from "@/db/schema";
|
||||
import { db } from "@/lib/db";
|
||||
import { loadLogoOptions } from "@/lib/logo/options";
|
||||
@@ -72,6 +72,11 @@ export async function fetchCardsForUser(userId: string): Promise<{
|
||||
and(
|
||||
eq(lancamentos.userId, userId),
|
||||
or(isNull(lancamentos.isSettled), eq(lancamentos.isSettled, false)),
|
||||
// Recorrente no cartão: só consome limite quando a data da ocorrência já passou
|
||||
or(
|
||||
ne(lancamentos.condition, "Recorrente"),
|
||||
sql`${lancamentos.purchaseDate} <= current_date`,
|
||||
),
|
||||
),
|
||||
)
|
||||
.groupBy(lancamentos.cartaoId),
|
||||
@@ -164,6 +169,11 @@ export async function fetchInativosForUser(userId: string): Promise<{
|
||||
and(
|
||||
eq(lancamentos.userId, userId),
|
||||
or(isNull(lancamentos.isSettled), eq(lancamentos.isSettled, false)),
|
||||
// Recorrente no cartão: só consome limite quando a data da ocorrência já passou
|
||||
or(
|
||||
ne(lancamentos.condition, "Recorrente"),
|
||||
sql`${lancamentos.purchaseDate} <= current_date`,
|
||||
),
|
||||
),
|
||||
)
|
||||
.groupBy(lancamentos.cartaoId),
|
||||
|
||||
@@ -296,6 +296,17 @@ export function LancamentosPage({
|
||||
}, []);
|
||||
|
||||
const handleMultipleBulkDelete = useCallback((items: LancamentoItem[]) => {
|
||||
// Se todos os selecionados são da mesma série (parcelado/recorrente), abrir dialog de escopo
|
||||
const withSeries = items.filter((i) => i.seriesId);
|
||||
const sameSeries =
|
||||
withSeries.length > 0 &&
|
||||
withSeries.length === items.length &&
|
||||
withSeries.every((i) => i.seriesId === withSeries[0]?.seriesId);
|
||||
if (sameSeries && withSeries[0]) {
|
||||
setPendingDeleteData(withSeries[0]);
|
||||
setBulkDeleteOpen(true);
|
||||
return;
|
||||
}
|
||||
setPendingMultipleDeleteData(items);
|
||||
setMultipleBulkDeleteOpen(true);
|
||||
}, []);
|
||||
|
||||
@@ -1,4 +1,16 @@
|
||||
import { and, eq, gte, ilike, inArray, lte, not, sum } from "drizzle-orm";
|
||||
import {
|
||||
and,
|
||||
eq,
|
||||
gte,
|
||||
ilike,
|
||||
inArray,
|
||||
lte,
|
||||
ne,
|
||||
not,
|
||||
or,
|
||||
sql,
|
||||
sum,
|
||||
} from "drizzle-orm";
|
||||
import {
|
||||
cartoes,
|
||||
categorias,
|
||||
@@ -97,7 +109,7 @@ export async function fetchCartoesReportData(
|
||||
|
||||
const cardIds = allCards.map((c) => c.id);
|
||||
|
||||
// Fetch current period usage by card
|
||||
// Fetch current period usage by card (recorrente só conta quando a data da ocorrência já passou)
|
||||
const currentUsageData = await db
|
||||
.select({
|
||||
cartaoId: lancamentos.cartaoId,
|
||||
@@ -112,6 +124,10 @@ export async function fetchCartoesReportData(
|
||||
eq(pagadores.role, PAGADOR_ROLE_ADMIN),
|
||||
eq(lancamentos.transactionType, DESPESA),
|
||||
inArray(lancamentos.cartaoId, cardIds),
|
||||
or(
|
||||
ne(lancamentos.condition, "Recorrente"),
|
||||
sql`${lancamentos.purchaseDate} <= current_date`,
|
||||
),
|
||||
),
|
||||
)
|
||||
.groupBy(lancamentos.cartaoId);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "openmonetis",
|
||||
"version": "1.7.3",
|
||||
"version": "1.7.4",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev --turbopack",
|
||||
|
||||
Reference in New Issue
Block a user