From f4a33b88bc8074b3b62808f22695dd611a2854bc Mon Sep 17 00:00:00 2001 From: marcoitaloesp-ai Date: Mon, 15 Dec 2025 16:57:26 +0000 Subject: [PATCH] =?UTF-8?q?v1.38.0=20-=20Proje=C3=A7=C3=A3o=20de=20Saldo?= =?UTF-8?q?=20considera=20transa=C3=A7=C3=B5es=20em=20atraso=20+=20alerta?= =?UTF-8?q?=20visual?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 12 +++++++ VERSION | 2 +- .../Http/Controllers/Api/ReportController.php | 35 +++++++++++++++---- .../dashboard/BalanceProjectionChart.jsx | 20 ++++++++++- frontend/src/i18n/locales/en.json | 5 ++- frontend/src/i18n/locales/es.json | 5 ++- frontend/src/i18n/locales/pt-BR.json | 5 ++- 7 files changed, 72 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d7023fc..e0c14ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,18 @@ O formato segue [Keep a Changelog](https://keepachangelog.com/pt-BR/). Este projeto adota [Versionamento Semântico](https://semver.org/pt-BR/). +## [1.38.0] - 2025-12-15 + +### Added +- **Projeção de Saldo** - Agora considera transações em atraso + - Backend busca todas as transações pendentes (incluindo atrasadas) + - Processa transações atrasadas ANTES do ponto inicial da projeção + - Adiciona informações de transações em atraso no summary da API + - Frontend exibe alerta amarelo quando há transações em atraso incluídas + - Alerta mostra quantidade de transações e impacto no saldo + - Traduções completas: overdueIncluded, overdueTransactions, includedInProjection (pt-BR, en, es) + - Melhora precisão da projeção ao incluir todas as pendências + ## [1.37.0] - 2025-12-15 ### Added diff --git a/VERSION b/VERSION index bf50e91..ebeef2f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.37.0 +1.38.0 diff --git a/backend/app/Http/Controllers/Api/ReportController.php b/backend/app/Http/Controllers/Api/ReportController.php index e69946c..a6ace8a 100644 --- a/backend/app/Http/Controllers/Api/ReportController.php +++ b/backend/app/Http/Controllers/Api/ReportController.php @@ -942,29 +942,45 @@ public function projectionChart(Request $request) ORDER BY li.due_date ", [$this->userId, $today->toDateString(), $endDate->toDateString()]); - // Buscar transações agendadas/pendentes + // Buscar transações agendadas/pendentes (incluindo atrasadas) $scheduledTransactions = DB::select(" SELECT t.effective_date as date, t.amount, t.type, - COALESCE(a.currency, 'EUR') as currency + COALESCE(a.currency, 'EUR') as currency, + CASE WHEN t.effective_date < ? THEN 1 ELSE 0 END as is_overdue FROM transactions t LEFT JOIN accounts a ON t.account_id = a.id WHERE t.user_id = ? AND t.status IN ('pending', 'scheduled') - AND t.effective_date >= ? AND t.effective_date <= ? AND t.deleted_at IS NULL ORDER BY t.effective_date - ", [$this->userId, $today->toDateString(), $endDate->toDateString()]); + ", [$today->toDateString(), $this->userId, $endDate->toDateString()]); - // Ponto inicial + // Separar transações atrasadas para processar primeiro + $overdueTransactions = array_filter($scheduledTransactions, fn($tx) => $tx->is_overdue); + $futureTransactions = array_filter($scheduledTransactions, fn($tx) => !$tx->is_overdue); + + // Processar transações atrasadas ANTES do ponto inicial + foreach ($overdueTransactions as $tx) { + $amount = $this->convertToPrimaryCurrency(abs($tx->amount), $tx->currency); + if ($tx->type === 'credit') { + $currentBalance += $amount; + } else { + $currentBalance -= $amount; + } + $runningBalance = $currentBalance; + } + + // Ponto inicial (já inclui o impacto das transações atrasadas) $dataPoints[] = [ 'date' => $today->toDateString(), 'balance' => round($runningBalance, 2), 'label' => $today->format('d/m'), 'isToday' => true, + 'has_overdue' => count($overdueTransactions) > 0, ]; // Gerar pontos até a data final @@ -1001,8 +1017,8 @@ public function projectionChart(Request $request) } } - // Somar transações agendadas neste período - foreach ($scheduledTransactions as $tx) { + // Somar transações agendadas neste período (apenas futuras) + foreach ($futureTransactions as $tx) { if ($tx->date > $periodStart && $tx->date <= $periodEnd) { $amount = $this->convertToPrimaryCurrency(abs($tx->amount), $tx->currency); if ($tx->type === 'credit') { @@ -1048,6 +1064,11 @@ public function projectionChart(Request $request) 'change' => round($finalBalance - $currentBalance, 2), 'change_percent' => $currentBalance != 0 ? round((($finalBalance - $currentBalance) / abs($currentBalance)) * 100, 1) : 0, 'negative_month' => $negativeMonth, + 'overdue_count' => count($overdueTransactions), + 'overdue_impact' => round(array_reduce($overdueTransactions, function($carry, $tx) { + $amount = $this->convertToPrimaryCurrency(abs($tx->amount), $tx->currency); + return $carry + ($tx->type === 'credit' ? $amount : -$amount); + }, 0), 2), ], 'period' => [ 'start' => $today->toDateString(), diff --git a/frontend/src/components/dashboard/BalanceProjectionChart.jsx b/frontend/src/components/dashboard/BalanceProjectionChart.jsx index 0de2e00..44be99c 100644 --- a/frontend/src/components/dashboard/BalanceProjectionChart.jsx +++ b/frontend/src/components/dashboard/BalanceProjectionChart.jsx @@ -228,7 +228,24 @@ const BalanceProjectionChart = () => {
{/* Summary Stats */} {summary && ( -
+ <> + {/* Alert if overdue transactions included */} + {summary.overdue_count > 0 && ( +
+ +
+ {t('reports.projectionChart.overdueIncluded') || 'Atenção'}:{' '} + {summary.overdue_count} {t('reports.projectionChart.overdueTransactions') || 'transação(ões) em atraso'}{' '} + {t('reports.projectionChart.includedInProjection') || 'já incluída(s) no saldo atual'}. + {' '} + + ({summary.overdue_impact >= 0 ? '+' : ''}{currency(summary.overdue_impact, data?.currency)}) + +
+
+ )} + +
{t('reports.projectionChart.currentBalance') || 'Saldo Atual'} @@ -262,6 +279,7 @@ const BalanceProjectionChart = () => {
+ )} {/* Alert if negative balance predicted */} diff --git a/frontend/src/i18n/locales/en.json b/frontend/src/i18n/locales/en.json index 3cf2b64..95c5f58 100644 --- a/frontend/src/i18n/locales/en.json +++ b/frontend/src/i18n/locales/en.json @@ -1922,7 +1922,10 @@ "2months": "2 months", "3months": "3 months", "6months": "6 months", - "12months": "12 months" + "12months": "12 months", + "overdueIncluded": "Overdue Transactions Included", + "overdueTransactions": "overdue transaction(s)", + "includedInProjection": "already included in balance projection" } }, "months": { diff --git a/frontend/src/i18n/locales/es.json b/frontend/src/i18n/locales/es.json index 1d5d6d5..579fd75 100644 --- a/frontend/src/i18n/locales/es.json +++ b/frontend/src/i18n/locales/es.json @@ -1905,7 +1905,10 @@ "2months": "2 meses", "3months": "3 meses", "6months": "6 meses", - "12months": "12 meses" + "12months": "12 meses", + "overdueIncluded": "Transacciones Vencidas Incluidas", + "overdueTransactions": "transacción(es) vencida(s)", + "includedInProjection": "ya incluida(s) en la proyección del saldo" } }, "months": { diff --git a/frontend/src/i18n/locales/pt-BR.json b/frontend/src/i18n/locales/pt-BR.json index 7508c41..4879480 100644 --- a/frontend/src/i18n/locales/pt-BR.json +++ b/frontend/src/i18n/locales/pt-BR.json @@ -1924,7 +1924,10 @@ "2months": "2 meses", "3months": "3 meses", "6months": "6 meses", - "12months": "12 meses" + "12months": "12 meses", + "overdueIncluded": "Transações em Atraso Incluídas", + "overdueTransactions": "transação(ões) em atraso", + "includedInProjection": "já incluída(s) na projeção do saldo" } }, "months": {