Kasir/app/Http/Controllers/LaporanController.php
2025-09-03 13:53:06 +07:00

176 lines
6.8 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\Transaksi;
use Carbon\Carbon;
use Carbon\CarbonPeriod;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
class LaporanController extends Controller
{
public function ringkasan(Request $request)
{
$filter = $request->query('filter', 'bulan');
$page = $request->query('page', 1);
$allSalesNames = Transaksi::select('nama_sales')->distinct()->pluck('nama_sales');
if ($filter === 'hari') {
return $this->laporanHarian($page, $allSalesNames);
}
return $this->laporanBulanan($page, $allSalesNames);
}
private function laporanHarian(int $page, Collection $allSalesNames)
{
$perPage = 7;
$endDate = Carbon::today()->subDays(($page - 1) * $perPage);
$startDate = $endDate->copy()->subDays($perPage - 1);
$transaksis = Transaksi::with('itemTransaksi.item.produk')
->whereBetween('created_at', [$startDate->startOfDay(), $endDate->endOfDay()])
->orderBy('created_at', 'desc')
->get();
$transaksisByDay = $transaksis->groupBy(function ($transaksi) {
return Carbon::parse($transaksi->created_at)->format('Y-m-d');
});
$period = CarbonPeriod::create($startDate, $endDate);
$laporan = [];
foreach ($period as $date) {
$dateString = $date->format('Y-m-d');
$tanggalFormatted = $date->isoFormat('dddd, D MMMM Y');
if (isset($transaksisByDay[$dateString])) {
$transaksisPerTanggal = $transaksisByDay[$dateString];
$salesDataTransaksi = $transaksisPerTanggal->groupBy('nama_sales')
->map(fn ($transaksisPerSales) => $this->hitungDataSales($transaksisPerSales));
$fullSalesData = $allSalesNames->map(function ($namaSales) use ($salesDataTransaksi) {
return $salesDataTransaksi->get($namaSales) ?? $this->defaultSalesData($namaSales);
});
$totalItem = $fullSalesData->sum('item_terjual');
$totalBerat = $fullSalesData->sum('berat_terjual_raw');
$totalPendapatan = $fullSalesData->sum('pendapatan_raw');
$laporan[$dateString] = [
'tanggal' => $tanggalFormatted,
'total_item_terjual' => $totalItem > 0 ? $totalItem : '-',
'total_berat' => $totalBerat > 0 ? number_format($totalBerat, 2, ',', '.') . 'g' : '-',
'total_pendapatan' => $totalPendapatan > 0 ? 'Rp' . number_format($totalPendapatan, 2, ',', '.') : '-',
'sales' => $this->formatSalesDataValues($fullSalesData)->values(),
];
} else {
$laporan[$dateString] = [
'tanggal' => $tanggalFormatted,
'total_item_terjual' => '-',
'total_berat' => '-',
'total_pendapatan' => '-',
'sales' => [],
];
}
}
$totalHariUntukPaginasi = 365;
$paginatedData = new LengthAwarePaginator(
array_reverse(array_values($laporan)),
$totalHariUntukPaginasi,
$perPage,
$page,
['path' => request()->url(), 'query' => request()->query()]
);
return response()->json($paginatedData);
}
private function laporanBulanan(int $page, Collection $allSalesNames)
{
$perPage = 12;
$transaksis = Transaksi::with('itemTransaksi.item.produk')
->orderBy('created_at', 'desc')
->get();
$laporan = $transaksis->groupBy(function ($transaksi) {
return Carbon::parse($transaksi->created_at)->format('F Y');
})
->map(function ($transaksisPerTanggal, $tanggal) use ($allSalesNames) {
$salesDataTransaksi = $transaksisPerTanggal
->groupBy('nama_sales')
->map(fn ($transaksisPerSales) => $this->hitungDataSales($transaksisPerSales));
$fullSalesData = $allSalesNames->map(function ($namaSales) use ($salesDataTransaksi) {
return $salesDataTransaksi->get($namaSales) ?? $this->defaultSalesData($namaSales);
});
$totalItem = $fullSalesData->sum('item_terjual');
$totalBerat = $fullSalesData->sum('berat_terjual_raw');
$totalPendapatan = $fullSalesData->sum('pendapatan_raw');
return [
'tanggal' => $tanggal,
'total_item_terjual' => $totalItem > 0 ? $totalItem : '-',
'total_berat' => $totalBerat > 0 ? number_format($totalBerat, 2, ',', '.') . 'g' : '-',
'total_pendapatan' => $totalPendapatan > 0 ? 'Rp' . number_format($totalPendapatan, 2, ',', '.') : '-',
'sales' => $this->formatSalesDataValues($fullSalesData)->values(),
];
});
$paginatedData = new LengthAwarePaginator(
$laporan->forPage($page, $perPage)->values(),
$laporan->count(),
$perPage,
$page,
['path' => request()->url(), 'query' => request()->query()]
);
return response()->json($paginatedData);
}
private function hitungDataSales(Collection $transaksisPerSales): array
{
$itemTerjual = $transaksisPerSales->sum(fn ($t) => $t->itemTransaksi->count());
$beratTerjual = $transaksisPerSales->sum(fn ($t) =>
$t->itemTransaksi->sum(fn ($it) => $it->item->produk->berat ?? 0)
);
$pendapatan = $transaksisPerSales->sum('total_harga');
return [
'nama' => $transaksisPerSales->first()->nama_sales,
'item_terjual' => $itemTerjual,
'berat_terjual_raw' => $beratTerjual,
'pendapatan_raw' => $pendapatan,
];
}
private function defaultSalesData(string $namaSales): array
{
return [
'nama' => $namaSales,
'item_terjual' => 0,
'berat_terjual_raw' => 0,
'pendapatan_raw' => 0,
];
}
private function formatSalesDataValues(Collection $salesData): Collection
{
return $salesData->map(function ($sale) {
$sale['item_terjual'] = $sale['item_terjual'] > 0 ? $sale['item_terjual'] : '-';
$sale['berat_terjual'] = $sale['berat_terjual_raw'] > 0 ? number_format($sale['berat_terjual_raw'], 2, ',', '.') . 'g' : '-';
$sale['pendapatan'] = $sale['pendapatan_raw'] > 0 ? 'Rp' . number_format($sale['pendapatan_raw'], 2, ',', '.') : '-';
unset($sale['berat_terjual_raw'], $sale['pendapatan_raw']);
return $sale;
});
}
}