Kasir/app/Helpers/LaporanHelper.php
2025-09-19 13:26:53 +07:00

213 lines
7.4 KiB
PHP

<?php
namespace App\Helpers;
use App\Models\Nampan;
use App\Models\Sales;
use App\Models\Produk;
use Carbon\Carbon;
use Illuminate\Support\Collection;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\DB;
class LaporanHelper
{
public const CURRENCY_SYMBOL = 'Rp ';
public const WEIGHT_UNIT = ' g';
public const DEFAULT_DISPLAY = '-';
public function calculateTotals(Collection $data): array
{
// Asumsi $data punya raw numeric (int/float)
$totalPendapatan = $data->sum('pendapatan'); // Raw float
$totalItemTerjual = $data->sum('jumlah_item_terjual'); // Int
$totalBeratTerjual = $data->sum('berat_terjual'); // Float
return [
'total_item_terjual' => $totalItemTerjual,
'total_berat_terjual' => $this->formatWeight($totalBeratTerjual),
'total_pendapatan' => $this->formatCurrency($totalPendapatan),
];
}
public function getAllNampanWithPagination(int $page, int $perPage): LengthAwarePaginator
{
$semuaPosisi = DB::table('item_transaksis')
->select('posisi_asal')
->distinct()
->pluck('posisi_asal')
->sort()
->values();
$offset = ($page - 1) * $perPage;
$itemsForCurrentPage = $semuaPosisi->slice($offset, $perPage);
return new LengthAwarePaginator(
$itemsForCurrentPage,
$semuaPosisi->count(),
$perPage,
$page,
['path' => request()->url(), 'query' => request()->query()]
);
}
public function mapProductsWithSalesData($paginatedData, Collection $salesData): Collection
{
return $paginatedData->getCollection()->map(function ($item) use ($salesData) {
if ($salesData->has($item->id)) {
$dataTerjual = $salesData->get($item->id);
return [
'nama_produk' => $item->nama,
'jumlah_item_terjual' => (int) $dataTerjual->jumlah_item_terjual, // Selalu int
'berat_terjual' => $this->formatWeight($dataTerjual->berat_terjual),
'pendapatan' => $this->formatCurrency($dataTerjual->pendapatan),
];
}
return [ // Untuk kosong, return dengan 0 (akan difilter nanti)
'nama_produk' => $item->nama,
'jumlah_item_terjual' => 0,
'berat_terjual' => self::DEFAULT_DISPLAY,
'pendapatan' => self::DEFAULT_DISPLAY,
];
});
}
public function mapNampanWithSalesData($paginatedData, Collection $salesData): Collection
{
return $paginatedData->getCollection()->map(function ($item) use ($salesData) {
if ($salesData->has($item)) {
$dataTerjual = $salesData->get($item);
return [
'nama_nampan' => $item, // sekarang langsung string posisi
'jumlah_item_terjual' => (int) $dataTerjual->jumlah_item_terjual,
'berat_terjual' => $this->formatWeight($dataTerjual->berat_terjual),
'pendapatan' => $this->formatCurrency($dataTerjual->pendapatan),
];
}
return [
'nama_nampan' => $item,
'jumlah_item_terjual' => self::DEFAULT_DISPLAY,
'berat_terjual' => self::DEFAULT_DISPLAY,
'pendapatan' => self::DEFAULT_DISPLAY,
];
});
}
public function buildProdukFilterInfo(Carbon $startDate, Carbon $endDate, array $params): array
{
$filterInfo = [
'periode' => "{$startDate->isoFormat('D MMMM Y')} - {$endDate->isoFormat('D MMMM Y')}",
'nama_sales' => null,
'nampan' => null, // Default null
'nama_pembeli' => $params['nama_pembeli'] ?? null,
];
if (!empty($params['sales_id'])) {
$sales = Sales::find($params['sales_id']);
$filterInfo['nama_sales'] = $sales?->nama;
}
if (isset($params['nampan_id'])) {
if ($params['nampan_id'] === -1) {
$filterInfo['nampan'] = 'Brankas';
} elseif ($params['nampan_id'] > 0) {
$nampan = Nampan::find($params['nampan_id']);
$filterInfo['nampan'] = $nampan?->nama;
} else { // 0: Semua
$filterInfo['nampan'] = 'Semua Nampan';
}
}
return $filterInfo;
}
public function buildNampanFilterInfo(Carbon $startDate, Carbon $endDate, array $params): array
{
$filterInfo = [
'periode' => "{$startDate->isoFormat('D MMMM Y')} - {$endDate->isoFormat('D MMMM Y')}", // FIXED: Range
'nama_sales' => null,
'produk' => null,
'nama_pembeli' => $params['nama_pembeli'] ?? null,
];
if (!empty($params['sales_id'])) {
$sales = Sales::find($params['sales_id']);
$filterInfo['nama_sales'] = $sales?->nama;
}
if (!empty($params['produk_id'])) {
$produk = Produk::find($params['produk_id']);
$filterInfo['produk'] = $produk?->nama;
}
return $filterInfo;
}
public function buildPaginationInfo($paginatedData): array
{
return [
'current_page' => $paginatedData->currentPage(),
'last_page' => $paginatedData->lastPage(),
'per_page' => $paginatedData->perPage(),
'total' => $paginatedData->total(),
'from' => $paginatedData->firstItem(),
'to' => $paginatedData->lastItem(),
];
}
public function hitungDataSales(Collection $transaksisPerSales): array
{
$itemTerjual = $transaksisPerSales->sum(fn($t) => $t->itemTransaksi->count());
// UBAH BAGIAN INI: Hapus ->item dari path relasi
$beratTerjual = $transaksisPerSales->sum(
fn($t) => $t->itemTransaksi->sum(fn($it) => $it->produk?->berat ?? 0)
);
$pendapatan = $transaksisPerSales->sum('total_harga');
return [
'nama' => $transaksisPerSales->first()->nama_sales,
'item_terjual' => $itemTerjual,
'berat_terjual_raw' => $beratTerjual,
'pendapatan_raw' => $pendapatan,
];
}
public function defaultSalesData(string $namaSales): array
{
return [
'nama' => $namaSales,
'item_terjual' => 0,
'berat_terjual_raw' => 0,
'pendapatan_raw' => 0,
];
}
public function formatSalesDataValues(Collection $salesData): Collection
{
return $salesData->map(function ($sale) {
$sale['item_terjual'] = $sale['item_terjual'] > 0 ? $sale['item_terjual'] : self::DEFAULT_DISPLAY;
$sale['berat_terjual'] = $sale['berat_terjual_raw'] > 0 ?
$this->formatWeight($sale['berat_terjual_raw']) : self::DEFAULT_DISPLAY;
$sale['pendapatan'] = $sale['pendapatan_raw'] > 0 ?
$this->formatCurrency($sale['pendapatan_raw']) : self::DEFAULT_DISPLAY;
unset($sale['berat_terjual_raw'], $sale['pendapatan_raw']);
return $sale;
});
}
public function formatCurrency(float $amount): string
{
return self::CURRENCY_SYMBOL . number_format($amount, 2, ',', '.');
}
public function formatWeight(float $weight): string
{
return number_format($weight, 2, ',', '.') . self::WEIGHT_UNIT;
}
}