- Removido README.md padrão do Laravel (backend) - Removidos scripts de deploy (não mais necessários) - Atualizado copilot-instructions.md para novo fluxo - Adicionada documentação de auditoria do servidor - Sincronizado código de produção com repositório Novo workflow: - Trabalhamos diretamente em /root/webmoney (symlink para /var/www/webmoney) - Mudanças PHP são instantâneas - Mudanças React requerem 'npm run build' - Commit após validação funcional
662 lines
26 KiB
PHP
Executable File
662 lines
26 KiB
PHP
Executable File
<?php
|
|
|
|
namespace App\Console\Commands;
|
|
|
|
use App\Models\Account;
|
|
use App\Models\Category;
|
|
use App\Models\Transaction;
|
|
use App\Models\User;
|
|
use Carbon\Carbon;
|
|
use Illuminate\Console\Command;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class PopulateDemoData extends Command
|
|
{
|
|
protected $signature = 'demo:populate {--fresh : Limpar dados existentes antes de popular}';
|
|
protected $description = 'Popular dados de demonstração (contas, categorias, transações) para o usuário DEMO';
|
|
|
|
private User $user;
|
|
private array $accounts = [];
|
|
private array $categories = [];
|
|
private array $subcategories = [];
|
|
|
|
public function handle(): int
|
|
{
|
|
$this->user = User::where('email', 'demo@webmoney.com')->first();
|
|
|
|
if (!$this->user) {
|
|
$this->error('Usuário demo@webmoney.com não encontrado!');
|
|
return Command::FAILURE;
|
|
}
|
|
|
|
$this->info("Populando dados para usuário DEMO (ID: {$this->user->id})...");
|
|
|
|
if ($this->option('fresh')) {
|
|
$this->clearExistingData();
|
|
}
|
|
|
|
DB::beginTransaction();
|
|
try {
|
|
$this->createAccounts();
|
|
$this->createCategories();
|
|
$this->createTransactions();
|
|
|
|
// Recalcular saldos das contas
|
|
$this->recalculateBalances();
|
|
|
|
DB::commit();
|
|
$this->newLine();
|
|
$this->info('✓ Dados DEMO populados com sucesso!');
|
|
$this->showSummary();
|
|
return Command::SUCCESS;
|
|
} catch (\Exception $e) {
|
|
DB::rollBack();
|
|
$this->error('Erro: ' . $e->getMessage());
|
|
$this->error($e->getTraceAsString());
|
|
return Command::FAILURE;
|
|
}
|
|
}
|
|
|
|
private function clearExistingData(): void
|
|
{
|
|
$this->info('Limpando dados existentes...');
|
|
Transaction::where('user_id', $this->user->id)->delete();
|
|
// Subcategorias são Category com parent_id
|
|
Category::where('user_id', $this->user->id)->whereNotNull('parent_id')->delete();
|
|
Category::where('user_id', $this->user->id)->whereNull('parent_id')->delete();
|
|
Account::where('user_id', $this->user->id)->delete();
|
|
}
|
|
|
|
private function createAccounts(): void
|
|
{
|
|
$this->info('Criando contas...');
|
|
|
|
$accountsData = [
|
|
[
|
|
'name' => 'Cuenta Corriente Principal',
|
|
'type' => 'checking',
|
|
'bank_name' => 'Santander',
|
|
'account_number' => 'ES12 3456 7890 1234',
|
|
'initial_balance' => 5000.00,
|
|
'currency' => 'EUR',
|
|
'color' => '#3B82F6',
|
|
'icon' => 'bi-bank',
|
|
'is_active' => true,
|
|
'include_in_total' => true,
|
|
],
|
|
[
|
|
'name' => 'Cuenta de Ahorro',
|
|
'type' => 'savings',
|
|
'bank_name' => 'BBVA',
|
|
'account_number' => 'ES98 7654 3210 9876',
|
|
'initial_balance' => 15000.00,
|
|
'currency' => 'EUR',
|
|
'color' => '#10B981',
|
|
'icon' => 'bi-piggy-bank',
|
|
'is_active' => true,
|
|
'include_in_total' => true,
|
|
],
|
|
[
|
|
'name' => 'Efectivo',
|
|
'type' => 'cash',
|
|
'bank_name' => null,
|
|
'account_number' => null,
|
|
'initial_balance' => 500.00,
|
|
'currency' => 'EUR',
|
|
'color' => '#F59E0B',
|
|
'icon' => 'bi-cash-stack',
|
|
'is_active' => true,
|
|
'include_in_total' => true,
|
|
],
|
|
];
|
|
|
|
foreach ($accountsData as $data) {
|
|
$account = Account::create([
|
|
'user_id' => $this->user->id,
|
|
'name' => $data['name'],
|
|
'type' => $data['type'],
|
|
'bank_name' => $data['bank_name'],
|
|
'account_number' => $data['account_number'],
|
|
'initial_balance' => $data['initial_balance'],
|
|
'current_balance' => $data['initial_balance'],
|
|
'currency' => $data['currency'],
|
|
'color' => $data['color'],
|
|
'icon' => $data['icon'],
|
|
'is_active' => $data['is_active'],
|
|
'include_in_total' => $data['include_in_total'],
|
|
]);
|
|
$this->accounts[$data['type']] = $account;
|
|
$this->info(" ✓ {$data['name']}");
|
|
}
|
|
}
|
|
|
|
private function createCategories(): void
|
|
{
|
|
$this->info('Criando categorias e subcategorias...');
|
|
|
|
$categoriesData = [
|
|
// DESPESAS (expense)
|
|
[
|
|
'name' => 'Vivienda',
|
|
'type' => 'debit',
|
|
'icon' => 'bi-house',
|
|
'color' => '#EF4444',
|
|
'subcategories' => ['Alquiler', 'Hipoteca', 'Comunidad', 'Seguro Hogar', 'Reparaciones', 'Muebles'],
|
|
],
|
|
[
|
|
'name' => 'Alimentación',
|
|
'type' => 'debit',
|
|
'icon' => 'bi-cart',
|
|
'color' => '#F97316',
|
|
'subcategories' => ['Supermercado', 'Restaurantes', 'Cafeterías', 'Delivery', 'Panadería'],
|
|
],
|
|
[
|
|
'name' => 'Transporte',
|
|
'type' => 'debit',
|
|
'icon' => 'bi-car-front',
|
|
'color' => '#8B5CF6',
|
|
'subcategories' => ['Combustible', 'Transporte Público', 'Taxi/Uber', 'Mantenimiento Coche', 'Parking', 'Seguro Coche'],
|
|
],
|
|
[
|
|
'name' => 'Servicios',
|
|
'type' => 'debit',
|
|
'icon' => 'bi-lightning',
|
|
'color' => '#EC4899',
|
|
'subcategories' => ['Electricidad', 'Gas', 'Agua', 'Internet', 'Teléfono', 'Streaming'],
|
|
],
|
|
[
|
|
'name' => 'Salud',
|
|
'type' => 'debit',
|
|
'icon' => 'bi-heart-pulse',
|
|
'color' => '#14B8A6',
|
|
'subcategories' => ['Médico', 'Farmacia', 'Dentista', 'Óptica', 'Gimnasio', 'Seguro Médico'],
|
|
],
|
|
[
|
|
'name' => 'Ocio',
|
|
'type' => 'debit',
|
|
'icon' => 'bi-controller',
|
|
'color' => '#6366F1',
|
|
'subcategories' => ['Cine', 'Conciertos', 'Viajes', 'Hobbies', 'Libros', 'Videojuegos'],
|
|
],
|
|
[
|
|
'name' => 'Ropa',
|
|
'type' => 'debit',
|
|
'icon' => 'bi-bag',
|
|
'color' => '#A855F7',
|
|
'subcategories' => ['Ropa', 'Calzado', 'Accesorios', 'Ropa Deportiva'],
|
|
],
|
|
[
|
|
'name' => 'Educación',
|
|
'type' => 'debit',
|
|
'icon' => 'bi-book',
|
|
'color' => '#0EA5E9',
|
|
'subcategories' => ['Cursos', 'Material Escolar', 'Idiomas', 'Certificaciones'],
|
|
],
|
|
[
|
|
'name' => 'Mascotas',
|
|
'type' => 'debit',
|
|
'icon' => 'bi-piggy-bank',
|
|
'color' => '#84CC16',
|
|
'subcategories' => ['Comida Mascota', 'Veterinario', 'Accesorios Mascota'],
|
|
],
|
|
[
|
|
'name' => 'Otros Gastos',
|
|
'type' => 'debit',
|
|
'icon' => 'bi-three-dots',
|
|
'color' => '#64748B',
|
|
'subcategories' => ['Regalos', 'Donaciones', 'Imprevistos', 'Varios'],
|
|
],
|
|
// INGRESOS (income)
|
|
[
|
|
'name' => 'Salario',
|
|
'type' => 'credit',
|
|
'icon' => 'bi-briefcase',
|
|
'color' => '#22C55E',
|
|
'subcategories' => ['Nómina', 'Horas Extra', 'Bonus', 'Comisiones'],
|
|
],
|
|
[
|
|
'name' => 'Inversiones',
|
|
'type' => 'credit',
|
|
'icon' => 'bi-graph-up-arrow',
|
|
'color' => '#10B981',
|
|
'subcategories' => ['Dividendos', 'Intereses', 'Plusvalías', 'Alquileres'],
|
|
],
|
|
[
|
|
'name' => 'Freelance',
|
|
'type' => 'credit',
|
|
'icon' => 'bi-laptop',
|
|
'color' => '#06B6D4',
|
|
'subcategories' => ['Proyectos', 'Consultoría', 'Clases Particulares'],
|
|
],
|
|
[
|
|
'name' => 'Otros Ingresos',
|
|
'type' => 'credit',
|
|
'icon' => 'bi-plus-circle',
|
|
'color' => '#84CC16',
|
|
'subcategories' => ['Reembolsos', 'Ventas', 'Premios', 'Herencias'],
|
|
],
|
|
];
|
|
|
|
foreach ($categoriesData as $catData) {
|
|
$category = Category::create([
|
|
'user_id' => $this->user->id,
|
|
'name' => $catData['name'],
|
|
'type' => $catData['type'],
|
|
'icon' => $catData['icon'],
|
|
'color' => $catData['color'],
|
|
'is_active' => true,
|
|
'parent_id' => null,
|
|
]);
|
|
|
|
$this->categories[$catData['name']] = $category;
|
|
|
|
// Subcategorias são Category com parent_id
|
|
foreach ($catData['subcategories'] as $subName) {
|
|
$sub = Category::create([
|
|
'user_id' => $this->user->id,
|
|
'parent_id' => $category->id,
|
|
'name' => $subName,
|
|
'type' => $catData['type'],
|
|
'icon' => $catData['icon'],
|
|
'color' => $catData['color'],
|
|
'is_active' => true,
|
|
]);
|
|
$this->subcategories[$subName] = $sub;
|
|
}
|
|
|
|
$this->info(" ✓ {$catData['name']} ({$catData['type']}) - " . count($catData['subcategories']) . " subcategorias");
|
|
}
|
|
}
|
|
|
|
private function createTransactions(): void
|
|
{
|
|
$this->info('Criando transações de 2025-2026...');
|
|
|
|
$checkingAccount = $this->accounts['checking'];
|
|
$savingsAccount = $this->accounts['savings'];
|
|
$cashAccount = $this->accounts['cash'];
|
|
|
|
$transactionCount = 0;
|
|
$today = Carbon::today();
|
|
|
|
// Helper para determinar status baseado na data
|
|
$getStatus = function(Carbon $date) use ($today) {
|
|
return $date->isAfter($today) ? 'pending' : 'effective';
|
|
};
|
|
|
|
// Gerar transações de Janeiro 2025 a Março 2026
|
|
for ($i = 1; $i <= 15; $i++) { // 12 meses de 2025 + 3 de 2026
|
|
$year = $i <= 12 ? 2025 : 2026;
|
|
$month = $i <= 12 ? $i : $i - 12;
|
|
|
|
$daysInMonth = Carbon::create($year, $month)->daysInMonth;
|
|
|
|
// RECEITAS FIXAS (mensais)
|
|
// Salário - dia 28 ou último dia útil
|
|
$salaryDay = min(28, $daysInMonth);
|
|
$salaryDate = Carbon::create($year, $month, $salaryDay);
|
|
$this->createTransaction([
|
|
'account_id' => $checkingAccount->id,
|
|
'category' => 'Salario',
|
|
'subcategory' => 'Nómina',
|
|
'type' => 'credit',
|
|
'amount' => 3200.00,
|
|
'date' => $salaryDate,
|
|
'status' => $getStatus($salaryDate),
|
|
'description' => 'Salario mensual',
|
|
]);
|
|
$transactionCount++;
|
|
|
|
// DESPESAS FIXAS (mensais)
|
|
// Aluguel - dia 1
|
|
$rentDate = Carbon::create($year, $month, 1);
|
|
$this->createTransaction([
|
|
'account_id' => $checkingAccount->id,
|
|
'category' => 'Vivienda',
|
|
'subcategory' => 'Alquiler',
|
|
'type' => 'debit',
|
|
'amount' => 850.00,
|
|
'date' => $rentDate,
|
|
'status' => $getStatus($rentDate),
|
|
'description' => 'Alquiler apartamento',
|
|
]);
|
|
$transactionCount++;
|
|
|
|
// Serviços - vários dias do mês
|
|
$services = [
|
|
['subcategory' => 'Electricidad', 'amount' => rand(45, 85), 'day' => 5],
|
|
['subcategory' => 'Gas', 'amount' => rand(25, 55), 'day' => 8],
|
|
['subcategory' => 'Agua', 'amount' => rand(20, 35), 'day' => 10],
|
|
['subcategory' => 'Internet', 'amount' => 49.99, 'day' => 15],
|
|
['subcategory' => 'Teléfono', 'amount' => 25.00, 'day' => 15],
|
|
['subcategory' => 'Streaming', 'amount' => 17.99, 'day' => 20],
|
|
];
|
|
|
|
foreach ($services as $service) {
|
|
if ($service['day'] <= $daysInMonth) {
|
|
$serviceDate = Carbon::create($year, $month, $service['day']);
|
|
$this->createTransaction([
|
|
'account_id' => $checkingAccount->id,
|
|
'category' => 'Servicios',
|
|
'subcategory' => $service['subcategory'],
|
|
'type' => 'debit',
|
|
'amount' => $service['amount'],
|
|
'date' => $serviceDate,
|
|
'status' => $getStatus($serviceDate),
|
|
'description' => $service['subcategory'],
|
|
]);
|
|
$transactionCount++;
|
|
}
|
|
}
|
|
|
|
// Supermercado - várias vezes por mês
|
|
$supermarketDays = [3, 10, 17, 24];
|
|
foreach ($supermarketDays as $day) {
|
|
if ($day <= $daysInMonth) {
|
|
$marketDate = Carbon::create($year, $month, $day);
|
|
$this->createTransaction([
|
|
'account_id' => $checkingAccount->id,
|
|
'category' => 'Alimentación',
|
|
'subcategory' => 'Supermercado',
|
|
'type' => 'debit',
|
|
'amount' => rand(60, 120),
|
|
'date' => $marketDate,
|
|
'status' => $getStatus($marketDate),
|
|
'description' => 'Compra supermercado',
|
|
]);
|
|
$transactionCount++;
|
|
}
|
|
}
|
|
|
|
// Transporte - combustível e outros
|
|
$fuelDate = Carbon::create($year, $month, rand(1, min(15, $daysInMonth)));
|
|
$this->createTransaction([
|
|
'account_id' => $checkingAccount->id,
|
|
'category' => 'Transporte',
|
|
'subcategory' => 'Combustible',
|
|
'type' => 'debit',
|
|
'amount' => rand(50, 80),
|
|
'date' => $fuelDate,
|
|
'status' => $getStatus($fuelDate),
|
|
'description' => 'Gasolina',
|
|
]);
|
|
$transactionCount++;
|
|
|
|
// Restaurantes - algumas vezes por mês
|
|
$restaurantCount = rand(2, 4);
|
|
for ($j = 0; $j < $restaurantCount; $j++) {
|
|
$restaurantDate = Carbon::create($year, $month, rand(1, $daysInMonth));
|
|
$this->createTransaction([
|
|
'account_id' => $cashAccount->id,
|
|
'category' => 'Alimentación',
|
|
'subcategory' => 'Restaurantes',
|
|
'type' => 'debit',
|
|
'amount' => rand(25, 60),
|
|
'date' => $restaurantDate,
|
|
'status' => $getStatus($restaurantDate),
|
|
'description' => 'Cena/Almuerzo fuera',
|
|
]);
|
|
$transactionCount++;
|
|
}
|
|
|
|
// Café - várias vezes
|
|
$coffeeCount = rand(5, 10);
|
|
for ($j = 0; $j < $coffeeCount; $j++) {
|
|
$coffeeDate = Carbon::create($year, $month, rand(1, $daysInMonth));
|
|
$this->createTransaction([
|
|
'account_id' => $cashAccount->id,
|
|
'category' => 'Alimentación',
|
|
'subcategory' => 'Cafeterías',
|
|
'type' => 'debit',
|
|
'amount' => rand(3, 8),
|
|
'date' => $coffeeDate,
|
|
'status' => $getStatus($coffeeDate),
|
|
'description' => 'Café',
|
|
]);
|
|
$transactionCount++;
|
|
}
|
|
|
|
// Retirada de cajero para efectivo (do banco para cash)
|
|
$atmDate = Carbon::create($year, $month, rand(1, min(5, $daysInMonth)));
|
|
$this->createTransaction([
|
|
'account_id' => $checkingAccount->id,
|
|
'category' => 'Otros Gastos',
|
|
'subcategory' => 'Varios',
|
|
'type' => 'debit',
|
|
'amount' => 200.00,
|
|
'date' => $atmDate,
|
|
'status' => $getStatus($atmDate),
|
|
'description' => 'Retiro cajero automático',
|
|
]);
|
|
$transactionCount++;
|
|
|
|
$this->createTransaction([
|
|
'account_id' => $cashAccount->id,
|
|
'category' => 'Otros Ingresos',
|
|
'subcategory' => 'Reembolsos',
|
|
'type' => 'credit',
|
|
'amount' => 200.00,
|
|
'date' => $atmDate,
|
|
'status' => $getStatus($atmDate),
|
|
'description' => 'Retiro cajero automático',
|
|
]);
|
|
$transactionCount++;
|
|
|
|
// Saúde - eventual
|
|
if (rand(1, 3) == 1) {
|
|
$healthDate = Carbon::create($year, $month, rand(1, $daysInMonth));
|
|
$healthSubs = ['Farmacia', 'Médico', 'Gimnasio'];
|
|
$this->createTransaction([
|
|
'account_id' => $checkingAccount->id,
|
|
'category' => 'Salud',
|
|
'subcategory' => $healthSubs[array_rand($healthSubs)],
|
|
'type' => 'debit',
|
|
'amount' => rand(15, 80),
|
|
'date' => $healthDate,
|
|
'status' => $getStatus($healthDate),
|
|
'description' => 'Gasto salud',
|
|
]);
|
|
$transactionCount++;
|
|
}
|
|
|
|
// Ginásio - mensal
|
|
$gymDate = Carbon::create($year, $month, 1);
|
|
$this->createTransaction([
|
|
'account_id' => $checkingAccount->id,
|
|
'category' => 'Salud',
|
|
'subcategory' => 'Gimnasio',
|
|
'type' => 'debit',
|
|
'amount' => 35.00,
|
|
'date' => $gymDate,
|
|
'status' => $getStatus($gymDate),
|
|
'description' => 'Cuota gimnasio',
|
|
]);
|
|
$transactionCount++;
|
|
|
|
// Lazer - algumas vezes
|
|
if (rand(1, 2) == 1) {
|
|
$leisureDate = Carbon::create($year, $month, rand(1, $daysInMonth));
|
|
$leisureSubs = ['Cine', 'Conciertos', 'Hobbies', 'Libros', 'Videojuegos'];
|
|
$this->createTransaction([
|
|
'account_id' => $checkingAccount->id,
|
|
'category' => 'Ocio',
|
|
'subcategory' => $leisureSubs[array_rand($leisureSubs)],
|
|
'type' => 'debit',
|
|
'amount' => rand(15, 60),
|
|
'date' => $leisureDate,
|
|
'status' => $getStatus($leisureDate),
|
|
'description' => 'Entretenimiento',
|
|
]);
|
|
$transactionCount++;
|
|
}
|
|
|
|
// Roupa - eventual
|
|
if (rand(1, 4) == 1) {
|
|
$clothesDate = Carbon::create($year, $month, rand(1, $daysInMonth));
|
|
$this->createTransaction([
|
|
'account_id' => $checkingAccount->id,
|
|
'category' => 'Ropa',
|
|
'subcategory' => 'Ropa',
|
|
'type' => 'debit',
|
|
'amount' => rand(30, 120),
|
|
'date' => $clothesDate,
|
|
'status' => $getStatus($clothesDate),
|
|
'description' => 'Compra ropa',
|
|
]);
|
|
$transactionCount++;
|
|
}
|
|
|
|
// Freelance - eventual (2-3 vezes por trimestre)
|
|
if ($month % 3 == 0 || rand(1, 5) == 1) {
|
|
$freelanceDate = Carbon::create($year, $month, rand(10, min(25, $daysInMonth)));
|
|
$this->createTransaction([
|
|
'account_id' => $checkingAccount->id,
|
|
'category' => 'Freelance',
|
|
'subcategory' => 'Proyectos',
|
|
'type' => 'credit',
|
|
'amount' => rand(200, 800),
|
|
'date' => $freelanceDate,
|
|
'status' => $getStatus($freelanceDate),
|
|
'description' => 'Proyecto freelance',
|
|
]);
|
|
$transactionCount++;
|
|
}
|
|
|
|
// Dividendos - trimestral
|
|
if ($month % 3 == 0) {
|
|
$dividendDate = Carbon::create($year, $month, 15);
|
|
$this->createTransaction([
|
|
'account_id' => $savingsAccount->id,
|
|
'category' => 'Inversiones',
|
|
'subcategory' => 'Dividendos',
|
|
'type' => 'credit',
|
|
'amount' => rand(50, 150),
|
|
'date' => $dividendDate,
|
|
'status' => $getStatus($dividendDate),
|
|
'description' => 'Dividendos trimestre',
|
|
]);
|
|
$transactionCount++;
|
|
}
|
|
|
|
// Juros poupança - mensal
|
|
$interestDate = Carbon::create($year, $month, $daysInMonth);
|
|
$this->createTransaction([
|
|
'account_id' => $savingsAccount->id,
|
|
'category' => 'Inversiones',
|
|
'subcategory' => 'Intereses',
|
|
'type' => 'credit',
|
|
'amount' => round(rand(15, 35) + (rand(0, 99) / 100), 2),
|
|
'date' => $interestDate,
|
|
'status' => $getStatus($interestDate),
|
|
'description' => 'Intereses cuenta ahorro',
|
|
]);
|
|
$transactionCount++;
|
|
|
|
// Transferência para poupança - mensal
|
|
if (rand(1, 2) == 1) {
|
|
$transferDate = Carbon::create($year, $month, rand(25, min(28, $daysInMonth)));
|
|
$transferAmount = rand(200, 500);
|
|
$this->createTransaction([
|
|
'account_id' => $checkingAccount->id,
|
|
'category' => 'Otros Gastos',
|
|
'subcategory' => 'Varios',
|
|
'type' => 'debit',
|
|
'amount' => $transferAmount,
|
|
'date' => $transferDate,
|
|
'status' => $getStatus($transferDate),
|
|
'description' => 'Transferencia a cuenta ahorro',
|
|
]);
|
|
$transactionCount++;
|
|
|
|
$this->createTransaction([
|
|
'account_id' => $savingsAccount->id,
|
|
'category' => 'Otros Ingresos',
|
|
'subcategory' => 'Reembolsos',
|
|
'type' => 'credit',
|
|
'amount' => $transferAmount,
|
|
'date' => $transferDate,
|
|
'status' => $getStatus($transferDate),
|
|
'description' => 'Transferencia desde cuenta corriente',
|
|
]);
|
|
$transactionCount++;
|
|
}
|
|
|
|
$this->info(" ✓ Mes $month/$year procesado");
|
|
}
|
|
|
|
$this->info(" Total: $transactionCount transacciones creadas");
|
|
}
|
|
|
|
private function createTransaction(array $data): Transaction
|
|
{
|
|
$category = $this->categories[$data['category']] ?? null;
|
|
// Subcategoria é usada diretamente como category_id (pois são Categories com parent_id)
|
|
$subcategory = $this->subcategories[$data['subcategory']] ?? null;
|
|
|
|
// Se tiver subcategoria, usa ela; senão usa a categoria pai
|
|
$categoryId = $subcategory?->id ?? $category?->id;
|
|
|
|
// Status vem do data ou default 'effective'
|
|
$status = $data['status'] ?? 'effective';
|
|
|
|
// Para transações pendentes, não definir effective_date
|
|
$effectiveDate = $status === 'pending' ? null : $data['date'];
|
|
|
|
return Transaction::create([
|
|
'user_id' => $this->user->id,
|
|
'account_id' => $data['account_id'],
|
|
'category_id' => $categoryId,
|
|
'type' => $data['type'],
|
|
'amount' => $status === 'pending' ? null : $data['amount'],
|
|
'planned_amount' => $data['amount'],
|
|
'planned_date' => $data['date'],
|
|
'effective_date' => $effectiveDate,
|
|
'description' => $data['description'],
|
|
'notes' => null,
|
|
'is_recurring' => false,
|
|
'status' => $status,
|
|
]);
|
|
}
|
|
|
|
private function recalculateBalances(): void
|
|
{
|
|
$this->info('Recalculando saldos das contas...');
|
|
|
|
foreach ($this->accounts as $account) {
|
|
// Apenas transações efetivas afetam o saldo atual
|
|
$income = Transaction::where('account_id', $account->id)
|
|
->where('type', 'credit')
|
|
->where('status', 'effective')
|
|
->sum('amount');
|
|
|
|
$expense = Transaction::where('account_id', $account->id)
|
|
->where('type', 'debit')
|
|
->where('status', 'effective')
|
|
->sum('amount');
|
|
|
|
$newBalance = $account->initial_balance + $income - $expense;
|
|
|
|
$account->update(['current_balance' => $newBalance]);
|
|
|
|
$this->info(" ✓ {$account->name}: €" . number_format($newBalance, 2));
|
|
}
|
|
}
|
|
|
|
private function showSummary(): void
|
|
{
|
|
$this->newLine();
|
|
$this->info('=== RESUMO ===');
|
|
$this->info('Contas: ' . count($this->accounts));
|
|
$this->info('Categorias: ' . count($this->categories));
|
|
$this->info('Subcategorias: ' . count($this->subcategories));
|
|
$this->info('Transações: ' . Transaction::where('user_id', $this->user->id)->count());
|
|
|
|
$this->newLine();
|
|
$this->info('Saldos finais:');
|
|
foreach ($this->accounts as $account) {
|
|
$account->refresh();
|
|
$this->info(" {$account->name}: €" . number_format($account->current_balance, 2));
|
|
}
|
|
}
|
|
}
|