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')
|
->groupBy('expense_category')
|
||||||
->get();
|
->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)
|
// 3. Ingresos y Egresos por Mes (Últimos 6 meses)
|
||||||
$months = [];
|
$months = [];
|
||||||
$monthlyIncomeData = [];
|
$monthlyIncomeData = [];
|
||||||
@@ -81,6 +106,7 @@ class ReportController extends Controller
|
|||||||
'totalOutcome',
|
'totalOutcome',
|
||||||
'balance',
|
'balance',
|
||||||
'expensesByCategory',
|
'expensesByCategory',
|
||||||
|
'earningsByCategory',
|
||||||
'months',
|
'months',
|
||||||
'monthlyIncomeData',
|
'monthlyIncomeData',
|
||||||
'monthlyOutcomeData',
|
'monthlyOutcomeData',
|
||||||
|
|||||||
@@ -50,19 +50,27 @@
|
|||||||
</div>
|
</div>
|
||||||
</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">
|
<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">
|
<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>
|
<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">
|
<div class="relative h-72 w-full flex justify-center">
|
||||||
<canvas id="balanceChart"></canvas>
|
<canvas id="earningsChart"></canvas>
|
||||||
</div>
|
</div>
|
||||||
</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">
|
<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">
|
<div class="relative h-72 w-full flex justify-center">
|
||||||
<canvas id="expensesChart"></canvas>
|
<canvas id="expensesChart"></canvas>
|
||||||
</div>
|
</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 ---
|
// --- GRÁFICO DE TOP PRODUCTOS ---
|
||||||
const ctxTopProducts = document.getElementById('topProductsChart').getContext('2d');
|
const ctxTopProducts = document.getElementById('topProductsChart').getContext('2d');
|
||||||
const rawTopProducts = @json($topProducts);
|
const rawTopProducts = @json($topProducts);
|
||||||
|
|||||||
Reference in New Issue
Block a user