Files
CKB/app/Exports/ProductStockDealers.php

202 lines
6.4 KiB
PHP

<?php
namespace App\Exports;
use App\Models\Dealer;
use App\Models\Product;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithMultipleSheets;
use Maatwebsite\Excel\Concerns\WithTitle;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithStyles;
use Maatwebsite\Excel\Concerns\WithColumnWidths;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Style\Border;
use PhpOffice\PhpSpreadsheet\Style\Fill;
class ProductStockDealers implements WithMultipleSheets
{
public function sheets(): array
{
$sheets = [];
$usedNames = [];
// Get all dealers with their stock data
$dealers = Dealer::with(['stocks.product.category'])->get();
/** @var Dealer $dealer */
foreach ($dealers as $dealer) {
$dealerSheet = new DealerStockSheet($dealer);
$sheetTitle = $dealerSheet->title();
// Handle duplicate sheet names
$originalTitle = $sheetTitle;
$counter = 1;
while (in_array($sheetTitle, $usedNames)) {
$sheetTitle = substr($originalTitle, 0, 28) . '_' . $counter;
$counter++;
}
$usedNames[] = $sheetTitle;
// Set the unique title
$dealerSheet->setUniqueTitle($sheetTitle);
$sheets[] = $dealerSheet;
}
return $sheets;
}
}
class DealerStockSheet implements FromCollection, WithTitle, WithHeadings, WithStyles, WithColumnWidths
{
protected $dealer;
protected $uniqueTitle;
public function __construct(Dealer $dealer)
{
$this->dealer = $dealer;
}
public function collection()
{
// Get all products with stock for this dealer
$stocks = $this->dealer->stocks()
->with(['product.category'])
->whereHas('product', function($query) {
$query->where('active', true);
})
->get();
$data = collect();
$no = 1;
foreach ($stocks as $stock) {
$product = $stock->product;
$data->push([
'no' => $no++,
'kode_produk' => $product->code,
'nama_produk' => $product->name,
'kategori' => $product->category ? $product->category->name : '-',
'satuan' => $product->unit ?? '-',
'stok' => number_format($stock->quantity, 2)
]);
}
// If no stock, add empty row
if ($data->isEmpty()) {
$data->push([
'no' => '-',
'kode_produk' => '-',
'nama_produk' => 'Tidak ada stok produk',
'kategori' => '-',
'satuan' => '-',
'stok' => '0'
]);
}
return $data;
}
public function setUniqueTitle(string $title): void
{
$this->uniqueTitle = $title;
}
public function title(): string
{
if (isset($this->uniqueTitle)) {
return $this->uniqueTitle;
}
// Clean dealer name for sheet title (remove invalid characters and handle edge cases)
$cleanName = $this->dealer->name;
// Remove parentheses and their contents
$cleanName = preg_replace('/\([^)]*\)/', '', $cleanName);
// Remove dots, commas, and other special characters
$cleanName = preg_replace('/[^A-Za-z0-9\-_ ]/', '', $cleanName);
// Clean up multiple spaces and trim
$cleanName = preg_replace('/\s+/', ' ', trim($cleanName));
// If name is empty after cleaning, use dealer ID
if (empty($cleanName)) {
$cleanName = 'Dealer_' . $this->dealer->id;
}
// Limit to 31 characters and ensure no leading/trailing spaces
$cleanName = trim(substr($cleanName, 0, 31));
// Ensure it doesn't end with a space (which can cause Excel issues)
return rtrim($cleanName);
}
public function headings(): array
{
return [
'No',
'Kode Produk',
'Nama Produk',
'Kategori',
'Satuan',
'Stok'
];
}
public function styles(Worksheet $sheet)
{
// Add dealer info at the top first
$sheet->insertNewRowBefore(1, 2);
$sheet->setCellValue('A1', 'STOK PRODUK DEALER: ' . strtoupper($this->dealer->name));
$sheet->setCellValue('A2', 'Tanggal Export: ' . now()->format('d/m/Y H:i:s'));
// Merge cells for dealer info
$sheet->mergeCells('A1:F1');
$sheet->mergeCells('A2:F2');
$lastRow = $sheet->getHighestRow();
// Style dealer info
$sheet->getStyle('A1:A2')->applyFromArray([
'font' => ['bold' => true, 'size' => 12],
'alignment' => ['horizontal' => Alignment::HORIZONTAL_CENTER]
]);
// Style headers (row 3 after inserting 2 rows)
$sheet->getStyle('A3:F3')->applyFromArray([
'font' => ['bold' => true, 'color' => ['rgb' => 'FFFFFF']],
'fill' => ['fillType' => Fill::FILL_SOLID, 'startColor' => ['rgb' => '4472C4']],
'alignment' => ['horizontal' => Alignment::HORIZONTAL_CENTER],
'borders' => ['allBorders' => ['borderStyle' => Border::BORDER_THIN]]
]);
// Style data rows if they exist
if ($lastRow > 3) {
$sheet->getStyle('A4:F' . $lastRow)->applyFromArray([
'borders' => ['allBorders' => ['borderStyle' => Border::BORDER_THIN, 'color' => ['rgb' => 'CCCCCC']]],
'alignment' => ['vertical' => Alignment::VERTICAL_CENTER]
]);
// Center align specific columns
$sheet->getStyle('A4:A' . $lastRow)->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER);
$sheet->getStyle('E4:F' . $lastRow)->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER);
}
return $sheet;
}
public function columnWidths(): array
{
return [
'A' => 8, // No
'B' => 15, // Kode Produk
'C' => 30, // Nama Produk
'D' => 20, // Kategori
'E' => 12, // Satuan
'F' => 12 // Stok
];
}
}