Files
star-erp/app/Modules/Inventory/Exports/StockQueryExport.php

168 lines
6.0 KiB
PHP

<?php
namespace App\Modules\Inventory\Exports;
use App\Modules\Inventory\Models\Inventory;
use Illuminate\Support\Facades\DB;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
use Maatwebsite\Excel\Concerns\WithStyles;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
class StockQueryExport implements FromCollection, WithHeadings, WithMapping, ShouldAutoSize, WithStyles
{
protected array $filters;
public function __construct(array $filters = [])
{
$this->filters = $filters;
}
public function collection()
{
$today = now()->toDateString();
$expiryThreshold = now()->addDays(30)->toDateString();
$query = Inventory::query()
->join('products', 'inventories.product_id', '=', 'products.id')
->join('warehouses', 'inventories.warehouse_id', '=', 'warehouses.id')
->leftJoin('categories', 'products.category_id', '=', 'categories.id')
->leftJoin('warehouse_product_safety_stocks as ss', function ($join) {
$join->on('inventories.warehouse_id', '=', 'ss.warehouse_id')
->on('inventories.product_id', '=', 'ss.product_id');
})
->whereNull('inventories.deleted_at')
->select([
'inventories.id',
'inventories.quantity',
'inventories.batch_number',
'inventories.expiry_date',
'inventories.quality_status',
'products.code as product_code',
'products.name as product_name',
'categories.name as category_name',
'warehouses.name as warehouse_name',
'ss.safety_stock',
]);
// 篩選
if (!empty($this->filters['warehouse_id'])) {
$query->where('inventories.warehouse_id', $this->filters['warehouse_id']);
}
if (!empty($this->filters['category_id'])) {
$query->where('products.category_id', $this->filters['category_id']);
}
if (!empty($this->filters['search'])) {
$search = $this->filters['search'];
$query->where(function ($q) use ($search) {
$q->where('products.code', 'like', "%{$search}%")
->orWhere('products.name', 'like', "%{$search}%");
});
}
if (!empty($this->filters['status'])) {
switch ($this->filters['status']) {
case 'low_stock':
$query->whereNotNull('ss.safety_stock')
->whereRaw('inventories.quantity <= ss.safety_stock')
->where('inventories.quantity', '>=', 0);
break;
case 'negative':
$query->where('inventories.quantity', '<', 0);
break;
case 'expiring':
$query->whereNotNull('inventories.expiry_date')
->where('inventories.expiry_date', '>', $today)
->where('inventories.expiry_date', '<=', $expiryThreshold);
break;
case 'expired':
$query->whereNotNull('inventories.expiry_date')
->where('inventories.expiry_date', '<=', $today);
break;
case 'abnormal':
$query->where(function ($q) use ($today, $expiryThreshold) {
$q->where('inventories.quantity', '<', 0)
->orWhere(function ($q2) {
$q2->whereNotNull('ss.safety_stock')
->whereRaw('inventories.quantity <= ss.safety_stock');
})
->orWhere(function ($q2) use ($expiryThreshold) {
$q2->whereNotNull('inventories.expiry_date')
->where('inventories.expiry_date', '<=', $expiryThreshold);
});
});
break;
}
}
return $query->orderBy('products.code', 'asc')->get();
}
public function headings(): array
{
return [
'商品代碼',
'商品名稱',
'分類',
'倉庫',
'批號',
'數量',
'安全庫存',
'到期日',
'品質狀態',
'狀態',
];
}
public function map($row): array
{
$today = now()->toDateString();
$expiryThreshold = now()->addDays(30)->toDateString();
$statuses = [];
if ($row->quantity < 0) {
$statuses[] = '負庫存';
}
if ($row->safety_stock !== null && $row->quantity <= $row->safety_stock && $row->quantity >= 0) {
$statuses[] = '低庫存';
}
if ($row->expiry_date) {
if ($row->expiry_date <= $today) {
$statuses[] = '已過期';
} elseif ($row->expiry_date <= $expiryThreshold) {
$statuses[] = '即將過期';
}
}
if (empty($statuses)) {
$statuses[] = '正常';
}
$qualityLabels = [
'normal' => '正常',
'inspecting' => '檢驗中',
'rejected' => '不合格',
];
return [
$row->product_code,
$row->product_name,
$row->category_name ?? '-',
$row->warehouse_name,
$row->batch_number ?? '-',
$row->quantity,
$row->safety_stock ?? '-',
$row->expiry_date ?? '-',
$qualityLabels[$row->quality_status] ?? $row->quality_status ?? '-',
implode('、', $statuses),
];
}
public function styles(Worksheet $sheet): array
{
return [
1 => ['font' => ['bold' => true]],
];
}
}