user_id !== $user->id) { throw new \InvalidArgumentException('El mes no pertenece al usuario'); } // Total de ventas del usuario $totalUserSales = $month->dailySales()->sum('user_sales'); // Total de ventas del sistema $totalSystemSales = $month->dailySales()->sum('system_sales'); // Total de gastos $totalExpenses = $month->expenses()->sum('amount'); // Salario base $monthlySalary = $user->monthly_salary; // Porcentaje de comisión $commissionPercentage = $user->commission_percentage; // Calcular comisión basada en ventas del sistema (ventas consolidadas) $commission = ($totalSystemSales * $commissionPercentage) / 100; // Calcular ISR sobre (salario + comisión) // Los gastos personales NO son deducibles del ISR $incomeForIsr = $monthlySalary + $commission; $isrTable = $month->isrTable; $isrResult = IsrCalculator::calculateMonthly($incomeForIsr, $isrTable); $isrAmount = $isrResult['isr']; // Calcular percepción total con ISR (salario + comisión - gastos - ISR) $totalEarning = $monthlySalary + $commission - $totalExpenses - $isrAmount; return [ 'user_id' => $user->id, 'month_id' => $month->id, 'month_name' => $month->name . ' ' . $month->year, 'total_user_sales' => round($totalUserSales, 2), 'total_system_sales' => round($totalSystemSales, 2), 'total_expenses' => round($totalExpenses, 2), 'monthly_salary' => round($monthlySalary, 2), 'commission_percentage' => round($commissionPercentage, 2), 'commission_amount' => round($commission, 2), 'isr_amount' => round($isrAmount, 2), 'isr_details' => $isrResult, 'total_earning' => round($totalEarning, 2), 'has_difference' => ($totalUserSales !== $totalSystemSales), 'sales_difference' => round($totalUserSales - $totalSystemSales, 2), ]; } /** * Calcular quincena (primera o segunda) * * QUINCENA 1 (ANTICIPO): mitad salary + comisiones del MES completo - ISR quincenal * QUINCENA 2 (LIQUIDACIÓN): mitad salary - gastos de la segunda quincena - ISR quincenal */ public static function calculateBiweekly(User $user, Month $month, int $biweekly): array { if ($month->user_id !== $user->id) { throw new \InvalidArgumentException('El mes no pertenece al usuario'); } $monthlySalary = $user->monthly_salary; $biweeklySalary = $monthlySalary / 2; // Mitad del sueldo $commissionPercentage = $user->commission_percentage; // Get month number $monthNumber = self::getMonthNumber($month->name); $year = $month->year; $lastDay = self::getLastDayOfMonth($month->name, $year); // Calcular ISR mensual completo (salario + comisión) $totalSystemSales = $month->dailySales()->sum('system_sales'); $commission = ($totalSystemSales * $commissionPercentage) / 100; $incomeForIsr = $monthlySalary + $commission; $isrTable = $month->isrTable; $isrResult = IsrCalculator::calculateMonthly($incomeForIsr, $isrTable); $isrMonthlyAmount = $isrResult['isr']; $isrBiweekly = IsrCalculator::calculateBiweekly($isrMonthlyAmount); if ($biweekly === 1) { // ===================== // QUINCENA 1 - ANTICIPO // ===================== // Anticipo = mitad del sueldo + comisiones del MES completo - ISR quincenal // Gastos: q1 completo + mensual/2 $expensesQ1Amount = $month->expenses() ->where(function($q) { $q->where('expense_type', 'q1') ->orWhere('expense_type', 'mensual'); }) ->get() ->sum(function($e) { return $e->expense_type === 'mensual' ? $e->amount / 2 : $e->amount; }); $totalEarning = $biweeklySalary + $commission - $expensesQ1Amount - $isrBiweekly; return [ 'user_id' => $user->id, 'month_id' => $month->id, 'month_name' => $month->name . ' ' . $year, 'biweekly' => $biweekly, 'period' => '1ra Quincena (1-15) - ANTICIPO', 'description' => 'Mitad del sueldo + comisiones del mes completo - ISR', 'biweekly_salary' => round($biweeklySalary, 2), 'total_system_sales' => round($totalSystemSales, 2), 'commission_percentage' => round($commissionPercentage, 2), 'commission_amount' => round($commission, 2), 'isr_amount' => round($isrBiweekly, 2), 'total_expenses_month' => 0, 'expenses_q1' => round($expensesQ1Amount, 2), 'expenses_q2' => 0, 'total_earning' => round($totalEarning, 2), 'type' => 'anticipo', ]; } else { // ===================== // QUINCENA 2 - LIQUIDACIÓN // ===================== // Liquidación = mitad del sueldo - gastos de Q2 - ISR quincenal // Gastos: q2 completo + mensual/2 $expensesQ2Amount = $month->expenses() ->where(function($q) { $q->where('expense_type', 'q2') ->orWhere('expense_type', 'mensual'); }) ->get() ->sum(function($e) { return $e->expense_type === 'mensual' ? $e->amount / 2 : $e->amount; }); // Total a pagar en liquidacion $totalEarning = $biweeklySalary - $expensesQ2Amount - $isrBiweekly; return [ 'user_id' => $user->id, 'month_id' => $month->id, 'month_name' => $month->name . ' ' . $year, 'biweekly' => $biweekly, 'period' => "2da Quincena (16-$lastDay) - LIQUIDACIÓN", 'description' => 'Mitad del sueldo - mitad de gastos del mes - ISR', 'biweekly_salary' => round($biweeklySalary, 2), 'total_system_sales' => 0, 'isr_amount' => round($isrBiweekly, 2), 'expenses_q2' => round($expensesQ2Amount, 2), 'total_earning' => round($totalEarning, 2), 'type' => 'liquidacion', ]; } } /** * Resumen anual del usuario */ public static function calculateYearly(User $user, int $year): array { $months = $user->months()->where('year', $year)->get(); $totalUserSales = 0; $totalSystemSales = 0; $totalExpenses = 0; $totalSalary = 0; $totalCommission = 0; foreach ($months as $month) { $totalUserSales += $month->dailySales()->sum('user_sales'); $totalSystemSales += $month->dailySales()->sum('system_sales'); $totalExpenses += $month->expenses()->sum('amount'); $totalSalary += $user->monthly_salary; $totalCommission += ($month->dailySales()->sum('system_sales') * $user->commission_percentage) / 100; } return [ 'user_id' => $user->id, 'year' => $year, 'months_count' => $months->count(), 'total_user_sales' => round($totalUserSales, 2), 'total_system_sales' => round($totalSystemSales, 2), 'total_expenses' => round($totalExpenses, 2), 'total_salary' => round($totalSalary, 2), 'total_commission' => round($totalCommission, 2), 'total_earning' => round($totalSalary + $totalCommission - $totalExpenses, 2), ]; } /** * Obtener número del mes por nombre */ private static function getMonthNumber(string $monthName): int { $months = [ 'Enero' => 1, 'Febrero' => 2, 'Marzo' => 3, 'Abril' => 4, 'Mayo' => 5, 'Junio' => 6, 'Julio' => 7, 'Agosto' => 8, 'Septiembre' => 9, 'Octubre' => 10, 'Noviembre' => 11, 'Diciembre' => 12 ]; return $months[$monthName] ?? 1; } /** * Obtener último día del mes */ private static function getLastDayOfMonth(string $monthName, int $year): int { $monthNumber = self::getMonthNumber($monthName); return (int) date('t', mktime(0, 0, 0, $monthNumber, 1, $year)); } }