NEW:
- Agregado grafico de torta de "Ingresos por categoria" para mayor utiidad de los reportes.
This commit is contained in:
@@ -23,6 +23,31 @@ class ReportController extends Controller
|
||||
->groupBy('expense_category')
|
||||
->get();
|
||||
|
||||
// 2.5 Ingresos por Categoría (Para Pie Chart)
|
||||
$rawEarningsByCategory = \App\Models\SaleDetail::join('products', 'sale_details.product_id', '=', 'products.id')
|
||||
->select('products.type', DB::raw('SUM(sale_details.quantity * sale_details.price) as total_earnings'))
|
||||
->groupBy('products.type')
|
||||
->get();
|
||||
|
||||
$categoryTranslations = [
|
||||
'bike' => 'Bicicletas',
|
||||
'clothing' => 'Indumentaria',
|
||||
'accessory' => 'Accesorios',
|
||||
'spare' => 'Repuestos',
|
||||
'children' => 'Niños',
|
||||
'rollers' => 'Rollers',
|
||||
'skate' => 'Skates',
|
||||
'other' => 'Otros'
|
||||
];
|
||||
|
||||
$earningsByCategory = $rawEarningsByCategory->map(function($item) use ($categoryTranslations) {
|
||||
$type = $item->type;
|
||||
return [
|
||||
'category' => $categoryTranslations[$type] ?? ucfirst($type),
|
||||
'total' => $item->total_earnings
|
||||
];
|
||||
});
|
||||
|
||||
// 3. Ingresos y Egresos por Mes (Últimos 6 meses)
|
||||
$months = [];
|
||||
$monthlyIncomeData = [];
|
||||
@@ -81,6 +106,7 @@ class ReportController extends Controller
|
||||
'totalOutcome',
|
||||
'balance',
|
||||
'expensesByCategory',
|
||||
'earningsByCategory',
|
||||
'months',
|
||||
'monthlyIncomeData',
|
||||
'monthlyOutcomeData',
|
||||
|
||||
@@ -50,19 +50,27 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Gráficos -->
|
||||
<!-- Gráfico de Evolución -->
|
||||
<div class="mb-6 bg-gray-200 dark:bg-panel-bg border border-neutral-400 dark:border-neutral-800 rounded-xl p-6 shadow-lg">
|
||||
<h3 class="text-lg font-bold text-neutral-900 dark:text-white mb-4">Evolución de Ingresos y Egresos (Últimos 6 meses)</h3>
|
||||
<div class="relative h-72 w-full">
|
||||
<canvas id="balanceChart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Gráficos de Torta (Distribución) -->
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||
<!-- Gráfico de Líneas/Barras -->
|
||||
<!-- Gráfico de Torta Ingresos -->
|
||||
<div class="bg-gray-200 dark:bg-panel-bg border border-neutral-400 dark:border-neutral-800 rounded-xl p-6 shadow-lg">
|
||||
<h3 class="text-lg font-bold text-neutral-900 dark:text-white mb-4">Evolución de Ingresos y Egresos (Últimos 6 meses)</h3>
|
||||
<div class="relative h-72 w-full">
|
||||
<canvas id="balanceChart"></canvas>
|
||||
<h3 class="text-lg font-bold text-neutral-900 dark:text-white mb-4">Ingresos por Categoría</h3>
|
||||
<div class="relative h-72 w-full flex justify-center">
|
||||
<canvas id="earningsChart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Gráfico de Torta -->
|
||||
<!-- Gráfico de Torta Gastos -->
|
||||
<div class="bg-gray-200 dark:bg-panel-bg border border-neutral-400 dark:border-neutral-800 rounded-xl p-6 shadow-lg">
|
||||
<h3 class="text-lg font-bold text-neutral-900 dark:text-white mb-4">Distribución de Gastos por Categoría</h3>
|
||||
<h3 class="text-lg font-bold text-neutral-900 dark:text-white mb-4">Gastos por Categoría</h3>
|
||||
<div class="relative h-72 w-full flex justify-center">
|
||||
<canvas id="expensesChart"></canvas>
|
||||
</div>
|
||||
@@ -211,6 +219,49 @@
|
||||
}
|
||||
});
|
||||
|
||||
// --- GRÁFICO DE INGRESOS POR CATEGORÍA (Torta) ---
|
||||
const ctxEarnings = document.getElementById('earningsChart').getContext('2d');
|
||||
|
||||
const rawEarnings = @json($earningsByCategory);
|
||||
const earnLabels = rawEarnings.map(item => item.category);
|
||||
const earnData = rawEarnings.map(item => item.total);
|
||||
|
||||
// Paleta de colores distintiva (verdes/limas/turquesas)
|
||||
const earnColors = [
|
||||
'#84cc16', // neon-lime / lime-500
|
||||
'#14b8a6', // teal-500
|
||||
'#06b6d4', // cyan-500
|
||||
'#6366f1', // indigo-500
|
||||
'#10b981', // emerald-500
|
||||
'#eab308', // yellow-500
|
||||
'#f97316', // orange-500
|
||||
'#8b5cf6' // violet-500
|
||||
];
|
||||
|
||||
new Chart(ctxEarnings, {
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
labels: earnLabels,
|
||||
datasets: [{
|
||||
data: earnData,
|
||||
backgroundColor: earnColors,
|
||||
borderWidth: 2,
|
||||
borderColor: isDark ? '#1f2937' : '#ffffff'
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
legend: {
|
||||
position: 'right',
|
||||
labels: { color: textColor, padding: 20 }
|
||||
}
|
||||
},
|
||||
cutout: '60%'
|
||||
}
|
||||
});
|
||||
|
||||
// --- GRÁFICO DE TOP PRODUCTOS ---
|
||||
const ctxTopProducts = document.getElementById('topProductsChart').getContext('2d');
|
||||
const rawTopProducts = @json($topProducts);
|
||||
|
||||
Reference in New Issue
Block a user