202 lines
6.4 KiB
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
|
|
];
|
|
}
|
|
}
|