From f9571656d54fcdda1bf68d71abfbddc300b0bac6 Mon Sep 17 00:00:00 2001 From: marcoitaloesp-ai Date: Sun, 14 Dec 2025 22:11:41 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20Corre=C3=A7=C3=A3o=20relat=C3=B3rios=20d?= =?UTF-8?q?e=20Passivos=20e=20Transa=C3=A7=C3=B5es=20Futuras=20(v1.34.0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Relatório Passivos: total_amount → total_contract_value - Transações Futuras: total_items → total_transactions - Atualizado VERSION e CHANGELOG --- CHANGELOG.md | 11 + VERSION | 2 +- .../Http/Controllers/Api/ReportController.php | 19 +- backend/database/seeders/CategoriesSeeder.php | 373 ++++++++++++++++++ 4 files changed, 397 insertions(+), 8 deletions(-) create mode 100644 backend/database/seeders/CategoriesSeeder.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 9760731..fd7710e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,17 @@ O formato segue [Keep a Changelog](https://keepachangelog.com/pt-BR/). Este projeto adota [Versionamento Semântico](https://semver.org/pt-BR/). +## [1.34.0] - 2025-12-14 + +### Fixed +- **Relatório de Passivos** - Correção de campo para valor total da dívida + - Alterado `total_amount` para `total_contract_value` (campo correto do modelo) + - Dívida Total agora exibe o valor correto das contas de passivo + +- **Relatório de Transações Futuras** - Padronização de nomenclatura + - Alterado `total_items` para `total_transactions` no resumo + - Melhora consistência com outros endpoints da API + ## [1.33.0] - 2025-12-14 ### Added diff --git a/VERSION b/VERSION index 7aa332e..2b17ffd 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.33.0 +1.34.0 diff --git a/backend/app/Http/Controllers/Api/ReportController.php b/backend/app/Http/Controllers/Api/ReportController.php index 42a260d..e69946c 100644 --- a/backend/app/Http/Controllers/Api/ReportController.php +++ b/backend/app/Http/Controllers/Api/ReportController.php @@ -856,6 +856,10 @@ public function projection(Request $request) 'total' => round($overdueExpense, 2), ], 'projection' => [ + // Valores principais (usa projeção inteligente) + 'income' => round($smartProjectedIncome, 2), + 'expense' => round($smartProjectedExpense, 2), + 'balance' => round($smartProjectedIncome - $smartProjectedExpense, 2), // Projeção simples (extrapolação linear) 'simple' => [ 'income' => round($simpleProjectedIncome, 2), @@ -1161,9 +1165,10 @@ public function liabilities(Request $request) $result = $liabilities->map(function($l) use (&$totalDebtConverted, &$totalPaidConverted, &$totalPendingConverted) { $currency = $l->currency ?? 'EUR'; - $totalAmount = $l->total_amount ?? 0; - $paidAmount = $l->installments->where('status', 'paid')->sum('amount'); - $pendingAmount = $l->installments->where('status', '!=', 'paid')->sum('amount'); + $totalAmount = $l->total_contract_value ?? 0; + // Usar installment_amount en lugar de amount + $paidAmount = $l->installments->where('status', 'paid')->sum('installment_amount'); + $pendingAmount = $l->installments->where('status', '!=', 'paid')->sum('installment_amount'); $totalDebtConverted += $this->convertToPrimaryCurrency($totalAmount, $currency); $totalPaidConverted += $this->convertToPrimaryCurrency($paidAmount, $currency); @@ -1191,7 +1196,7 @@ public function liabilities(Request $request) 'paid_installments' => $l->installments->where('status', 'paid')->count(), 'overdue_installments' => $overdueInstallments, 'next_installment' => $nextInstallment ? [ - 'amount' => round($nextInstallment->amount, 2), + 'amount' => round($nextInstallment->installment_amount, 2), 'due_date' => $nextInstallment->due_date, 'is_overdue' => $nextInstallment->due_date < now()->format('Y-m-d'), ] : null, @@ -1395,7 +1400,7 @@ public function futureTransactions(Request $request) 'data' => $result, 'currency' => $this->primaryCurrency, 'summary' => [ - 'total_items' => count($result), + 'total_transactions' => count($result), 'total_income' => round($totalIncomeConverted, 2), 'total_expense' => round($totalExpenseConverted, 2), 'net_impact' => round($totalIncomeConverted - $totalExpenseConverted, 2), @@ -1660,8 +1665,8 @@ private function getNextRecurrenceDates($recurrence, $startDate, $endDate) // Calcular la primera fecha dentro del período $current = $recStart->copy(); - // Avanzar hasta estar dentro del período - while ($current->lt($start)) { + // Avanzar hasta estar dentro del período (EXCLUYE startDate para evitar duplicados) + while ($current->lte($start)) { $current = $this->advanceToNextOccurrence($current, $recurrence); if ($current->gt($end)) { return $dates; diff --git a/backend/database/seeders/CategoriesSeeder.php b/backend/database/seeders/CategoriesSeeder.php new file mode 100644 index 0000000..39c1dc5 --- /dev/null +++ b/backend/database/seeders/CategoriesSeeder.php @@ -0,0 +1,373 @@ +command->error('Nenhum usuário encontrado! Crie um usuário primeiro.'); + return; + } + + $this->command->info('Populando categorias para o usuário: ' . $user->email); + + // Define as categorias e subcategorias + $categories = [ + // DESPESAS + [ + 'name' => 'Alimentação', + 'type' => 'expense', + 'color' => '#EF4444', + 'icon' => 'bi-egg-fried', + 'children' => [ + ['name' => 'Supermercado', 'color' => '#DC2626', 'icon' => 'bi-cart4'], + ['name' => 'Restaurantes', 'color' => '#B91C1C', 'icon' => 'bi-cup-hot'], + ['name' => 'Fast Food', 'color' => '#991B1B', 'icon' => 'bi-basket'], + ['name' => 'Padaria', 'color' => '#7F1D1D', 'icon' => 'bi-shop'], + ['name' => 'Café', 'color' => '#450A0A', 'icon' => 'bi-cup-straw'], + ['name' => 'Delivery', 'color' => '#FCA5A5', 'icon' => 'bi-box-seam'], + ] + ], + [ + 'name' => 'Transporte', + 'type' => 'expense', + 'color' => '#3B82F6', + 'icon' => 'bi-car-front', + 'children' => [ + ['name' => 'Combustível', 'color' => '#2563EB', 'icon' => 'bi-fuel-pump'], + ['name' => 'Estacionamento', 'color' => '#1D4ED8', 'icon' => 'bi-p-square'], + ['name' => 'Táxi/Uber', 'color' => '#1E40AF', 'icon' => 'bi-taxi-front'], + ['name' => 'Transporte Público', 'color' => '#1E3A8A', 'icon' => 'bi-bus-front'], + ['name' => 'Manutenção Veículo', 'color' => '#172554', 'icon' => 'bi-tools'], + ['name' => 'Pedágio', 'color' => '#93C5FD', 'icon' => 'bi-coin'], + ['name' => 'Seguro Veículo', 'color' => '#60A5FA', 'icon' => 'bi-shield-check'], + ] + ], + [ + 'name' => 'Moradia', + 'type' => 'expense', + 'color' => '#8B5CF6', + 'icon' => 'bi-house-door', + 'children' => [ + ['name' => 'Aluguel', 'color' => '#7C3AED', 'icon' => 'bi-key'], + ['name' => 'Condomínio', 'color' => '#6D28D9', 'icon' => 'bi-building'], + ['name' => 'Luz', 'color' => '#5B21B6', 'icon' => 'bi-lightbulb'], + ['name' => 'Água', 'color' => '#4C1D95', 'icon' => 'bi-droplet'], + ['name' => 'Gás', 'color' => '#2E1065', 'icon' => 'bi-fire'], + ['name' => 'Internet', 'color' => '#C4B5FD', 'icon' => 'bi-wifi'], + ['name' => 'Telefone', 'color' => '#A78BFA', 'icon' => 'bi-telephone'], + ['name' => 'Reparos', 'color' => '#8B5CF6', 'icon' => 'bi-hammer'], + ] + ], + [ + 'name' => 'Saúde', + 'type' => 'expense', + 'color' => '#10B981', + 'icon' => 'bi-heart-pulse', + 'children' => [ + ['name' => 'Farmácia', 'color' => '#059669', 'icon' => 'bi-capsule'], + ['name' => 'Médico', 'color' => '#047857', 'icon' => 'bi-hospital'], + ['name' => 'Dentista', 'color' => '#065F46', 'icon' => 'bi-activity'], + ['name' => 'Exames', 'color' => '#064E3B', 'icon' => 'bi-clipboard2-pulse'], + ['name' => 'Plano de Saúde', 'color' => '#6EE7B7', 'icon' => 'bi-bandaid'], + ['name' => 'Academia', 'color' => '#34D399', 'icon' => 'bi-bicycle'], + ] + ], + [ + 'name' => 'Educação', + 'type' => 'expense', + 'color' => '#F59E0B', + 'icon' => 'bi-mortarboard', + 'children' => [ + ['name' => 'Mensalidade', 'color' => '#D97706', 'icon' => 'bi-bank'], + ['name' => 'Livros', 'color' => '#B45309', 'icon' => 'bi-book'], + ['name' => 'Material Escolar', 'color' => '#92400E', 'icon' => 'bi-pencil'], + ['name' => 'Cursos Online', 'color' => '#78350F', 'icon' => 'bi-laptop'], + ['name' => 'Idiomas', 'color' => '#FCD34D', 'icon' => 'bi-translate'], + ] + ], + [ + 'name' => 'Lazer', + 'type' => 'expense', + 'color' => '#EC4899', + 'icon' => 'bi-controller', + 'children' => [ + ['name' => 'Cinema', 'color' => '#DB2777', 'icon' => 'bi-film'], + ['name' => 'Teatro', 'color' => '#BE185D', 'icon' => 'bi-music-note-beamed'], + ['name' => 'Streaming', 'color' => '#9F1239', 'icon' => 'bi-play-btn'], + ['name' => 'Viagens', 'color' => '#881337', 'icon' => 'bi-airplane'], + ['name' => 'Hobbies', 'color' => '#F9A8D4', 'icon' => 'bi-palette'], + ['name' => 'Eventos', 'color' => '#F472B6', 'icon' => 'bi-calendar-event'], + ] + ], + [ + 'name' => 'Vestuário', + 'type' => 'expense', + 'color' => '#06B6D4', + 'icon' => 'bi-bag', + 'children' => [ + ['name' => 'Roupas', 'color' => '#0891B2', 'icon' => 'bi-person'], + ['name' => 'Calçados', 'color' => '#0E7490', 'icon' => 'bi-foot'], + ['name' => 'Acessórios', 'color' => '#155E75', 'icon' => 'bi-watch'], + ['name' => 'Óculos', 'color' => '#164E63', 'icon' => 'bi-sunglasses'], + ] + ], + [ + 'name' => 'Beleza & Cuidados', + 'type' => 'expense', + 'color' => '#A855F7', + 'icon' => 'bi-scissors', + 'children' => [ + ['name' => 'Cabeleireiro', 'color' => '#9333EA', 'icon' => 'bi-brush'], + ['name' => 'Barbeiro', 'color' => '#7E22CE', 'icon' => 'bi-scissors'], + ['name' => 'Manicure', 'color' => '#6B21A8', 'icon' => 'bi-hand-index'], + ['name' => 'Estética', 'color' => '#581C87', 'icon' => 'bi-stars'], + ['name' => 'Cosméticos', 'color' => '#E9D5FF', 'icon' => 'bi-basket'], + ] + ], + [ + 'name' => 'Tecnologia', + 'type' => 'expense', + 'color' => '#6366F1', + 'icon' => 'bi-cpu', + 'children' => [ + ['name' => 'Eletrônicos', 'color' => '#4F46E5', 'icon' => 'bi-laptop'], + ['name' => 'Software', 'color' => '#4338CA', 'icon' => 'bi-code-slash'], + ['name' => 'Smartphone', 'color' => '#3730A3', 'icon' => 'bi-phone'], + ['name' => 'Manutenção TI', 'color' => '#312E81', 'icon' => 'bi-tools'], + ['name' => 'Cloud/SaaS', 'color' => '#C7D2FE', 'icon' => 'bi-cloud'], + ] + ], + [ + 'name' => 'Pets', + 'type' => 'expense', + 'color' => '#14B8A6', + 'icon' => 'bi-paw', + 'children' => [ + ['name' => 'Ração', 'color' => '#0D9488', 'icon' => 'bi-basket'], + ['name' => 'Veterinário', 'color' => '#0F766E', 'icon' => 'bi-hospital'], + ['name' => 'Pet Shop', 'color' => '#115E59', 'icon' => 'bi-shop'], + ['name' => 'Medicamentos', 'color' => '#134E4A', 'icon' => 'bi-capsule'], + ] + ], + [ + 'name' => 'Vending', + 'type' => 'expense', + 'color' => '#FB923C', + 'icon' => 'bi-grid-3x3', + 'children' => [ + ['name' => 'Máquinas de Café', 'color' => '#F97316', 'icon' => 'bi-cup-hot'], + ['name' => 'Máquinas de Snacks', 'color' => '#EA580C', 'icon' => 'bi-basket3'], + ['name' => 'Máquinas de Bebidas', 'color' => '#C2410C', 'icon' => 'bi-cup-straw'], + ['name' => 'Manutenção Máquinas', 'color' => '#9A3412', 'icon' => 'bi-gear'], + ['name' => 'Reposição Produtos', 'color' => '#7C2D12', 'icon' => 'bi-box-seam'], + ['name' => 'Aluguel Máquinas', 'color' => '#FDBA74', 'icon' => 'bi-receipt'], + ['name' => 'Logística Vending', 'color' => '#FB923C', 'icon' => 'bi-truck'], + ] + ], + [ + 'name' => 'Vaper/Tabaco', + 'type' => 'expense', + 'color' => '#64748B', + 'icon' => 'bi-cloud-fog2', + 'children' => [ + ['name' => 'Vapes/Pods', 'color' => '#475569', 'icon' => 'bi-cloud-fog'], + ['name' => 'E-líquidos', 'color' => '#334155', 'icon' => 'bi-droplet'], + ['name' => 'Cigarros', 'color' => '#1E293B', 'icon' => 'bi-fire'], + ['name' => 'Acessórios Vaping', 'color' => '#0F172A', 'icon' => 'bi-gear'], + ['name' => 'Resistências/Coils', 'color' => '#94A3B8', 'icon' => 'bi-cpu'], + ['name' => 'Carregadores', 'color' => '#CBD5E1', 'icon' => 'bi-battery-charging'], + ] + ], + [ + 'name' => 'Investimentos', + 'type' => 'expense', + 'color' => '#22C55E', + 'icon' => 'bi-graph-up-arrow', + 'children' => [ + ['name' => 'Ações', 'color' => '#16A34A', 'icon' => 'bi-bar-chart'], + ['name' => 'Fundos', 'color' => '#15803D', 'icon' => 'bi-piggy-bank'], + ['name' => 'Cripto', 'color' => '#166534', 'icon' => 'bi-currency-bitcoin'], + ['name' => 'Previdência', 'color' => '#14532D', 'icon' => 'bi-shield'], + ] + ], + [ + 'name' => 'Impostos & Taxas', + 'type' => 'expense', + 'color' => '#DC2626', + 'icon' => 'bi-file-earmark-text', + 'children' => [ + ['name' => 'IPTU', 'color' => '#B91C1C', 'icon' => 'bi-house'], + ['name' => 'IPVA', 'color' => '#991B1B', 'icon' => 'bi-car-front'], + ['name' => 'Imposto de Renda', 'color' => '#7F1D1D', 'icon' => 'bi-file-ruled'], + ['name' => 'Taxas Bancárias', 'color' => '#450A0A', 'icon' => 'bi-bank'], + ] + ], + [ + 'name' => 'Seguros', + 'type' => 'expense', + 'color' => '#0EA5E9', + 'icon' => 'bi-shield-check', + 'children' => [ + ['name' => 'Seguro de Vida', 'color' => '#0284C7', 'icon' => 'bi-heart'], + ['name' => 'Seguro Residencial', 'color' => '#0369A1', 'icon' => 'bi-house-door'], + ['name' => 'Seguro Auto', 'color' => '#075985', 'icon' => 'bi-car-front'], + ] + ], + [ + 'name' => 'Presentes & Doações', + 'type' => 'expense', + 'color' => '#F43F5E', + 'icon' => 'bi-gift', + 'children' => [ + ['name' => 'Presentes', 'color' => '#E11D48', 'icon' => 'bi-box2-heart'], + ['name' => 'Doações', 'color' => '#BE123C', 'icon' => 'bi-heart-fill'], + ['name' => 'Caridade', 'color' => '#9F1239', 'icon' => 'bi-people'], + ] + ], + [ + 'name' => 'Empréstimos', + 'type' => 'expense', + 'color' => '#84CC16', + 'icon' => 'bi-cash-coin', + 'children' => [ + ['name' => 'Financiamento Imóvel', 'color' => '#65A30D', 'icon' => 'bi-house'], + ['name' => 'Financiamento Veículo', 'color' => '#4D7C0F', 'icon' => 'bi-car-front'], + ['name' => 'Empréstimo Pessoal', 'color' => '#3F6212', 'icon' => 'bi-person'], + ['name' => 'Cartão de Crédito', 'color' => '#365314', 'icon' => 'bi-credit-card'], + ] + ], + + // RECEITAS + [ + 'name' => 'Salário', + 'type' => 'income', + 'color' => '#22C55E', + 'icon' => 'bi-wallet2', + 'children' => [ + ['name' => 'Salário Fixo', 'color' => '#16A34A', 'icon' => 'bi-cash-stack'], + ['name' => 'Horas Extra', 'color' => '#15803D', 'icon' => 'bi-clock'], + ['name' => 'Bonificação', 'color' => '#166534', 'icon' => 'bi-star'], + ['name' => 'Comissões', 'color' => '#14532D', 'icon' => 'bi-percent'], + ] + ], + [ + 'name' => 'Negócios', + 'type' => 'income', + 'color' => '#3B82F6', + 'icon' => 'bi-briefcase', + 'children' => [ + ['name' => 'Vendas', 'color' => '#2563EB', 'icon' => 'bi-cart-check'], + ['name' => 'Serviços', 'color' => '#1D4ED8', 'icon' => 'bi-tools'], + ['name' => 'Consultoria', 'color' => '#1E40AF', 'icon' => 'bi-person-badge'], + ['name' => 'Freelance', 'color' => '#1E3A8A', 'icon' => 'bi-laptop'], + ] + ], + [ + 'name' => 'Investimentos', + 'type' => 'income', + 'color' => '#10B981', + 'icon' => 'bi-graph-up', + 'children' => [ + ['name' => 'Dividendos', 'color' => '#059669', 'icon' => 'bi-currency-dollar'], + ['name' => 'Juros', 'color' => '#047857', 'icon' => 'bi-percent'], + ['name' => 'Lucro Cripto', 'color' => '#065F46', 'icon' => 'bi-currency-bitcoin'], + ['name' => 'Aluguel de Imóveis', 'color' => '#064E3B', 'icon' => 'bi-house'], + ] + ], + [ + 'name' => 'Receitas Vending', + 'type' => 'income', + 'color' => '#F59E0B', + 'icon' => 'bi-grid-3x3-gap', + 'children' => [ + ['name' => 'Vendas Café', 'color' => '#D97706', 'icon' => 'bi-cup-hot'], + ['name' => 'Vendas Snacks', 'color' => '#B45309', 'icon' => 'bi-basket'], + ['name' => 'Vendas Bebidas', 'color' => '#92400E', 'icon' => 'bi-cup-straw'], + ['name' => 'Vendas Produtos', 'color' => '#78350F', 'icon' => 'bi-box'], + ] + ], + [ + 'name' => 'Receitas Vaper/Tabaco', + 'type' => 'income', + 'color' => '#475569', + 'icon' => 'bi-cloud-fog2-fill', + 'children' => [ + ['name' => 'Vendas Vapes', 'color' => '#334155', 'icon' => 'bi-cloud'], + ['name' => 'Vendas E-líquidos', 'color' => '#1E293B', 'icon' => 'bi-droplet-fill'], + ['name' => 'Vendas Cigarros', 'color' => '#0F172A', 'icon' => 'bi-fire'], + ['name' => 'Vendas Acessórios', 'color' => '#64748B', 'icon' => 'bi-gear-fill'], + ] + ], + [ + 'name' => 'Outras Receitas', + 'type' => 'income', + 'color' => '#8B5CF6', + 'icon' => 'bi-cash', + 'children' => [ + ['name' => 'Reembolsos', 'color' => '#7C3AED', 'icon' => 'bi-arrow-return-left'], + ['name' => 'Presentes Recebidos', 'color' => '#6D28D9', 'icon' => 'bi-gift'], + ['name' => 'Prêmios', 'color' => '#5B21B6', 'icon' => 'bi-trophy'], + ['name' => 'Pensão', 'color' => '#4C1D95', 'icon' => 'bi-people'], + ] + ], + ]; + + $order = 0; + foreach ($categories as $categoryData) { + $children = $categoryData['children'] ?? []; + unset($categoryData['children']); + + // Cria a categoria pai + $category = Category::create([ + 'user_id' => $user->id, + 'name' => $categoryData['name'], + 'type' => $categoryData['type'], + 'color' => $categoryData['color'], + 'icon' => $categoryData['icon'], + 'order' => $order++, + 'is_active' => true, + 'is_system' => false, + ]); + + $this->command->info("✓ Criada: {$category->name}"); + + // Cria as subcategorias + $childOrder = 0; + foreach ($children as $childData) { + $child = Category::create([ + 'user_id' => $user->id, + 'parent_id' => $category->id, + 'name' => $childData['name'], + 'type' => $category->type, + 'color' => $childData['color'], + 'icon' => $childData['icon'], + 'order' => $childOrder++, + 'is_active' => true, + 'is_system' => false, + ]); + + $this->command->info(" └─ {$child->name}"); + } + } + + $totalCategories = Category::where('user_id', $user->id)->whereNull('parent_id')->count(); + $totalSubcategories = Category::where('user_id', $user->id)->whereNotNull('parent_id')->count(); + + $this->command->info("\n✅ Concluído!"); + $this->command->info("Total de categorias: {$totalCategories}"); + $this->command->info("Total de subcategorias: {$totalSubcategories}"); + } +}