109 lines
4.0 KiB
PHP
109 lines
4.0 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Master;
|
|
|
|
use App\Enums\RawMaterialUnit;
|
|
use App\Models\Product;
|
|
use App\Models\ProductVariant;
|
|
use App\Models\RawMaterial;
|
|
use App\Models\RawMaterialPrice;
|
|
use App\Support\Media\MediaPresenter;
|
|
use Illuminate\Database\Eloquent\Builder;
|
|
|
|
class MasterInventoryService
|
|
{
|
|
public function outOfStockProductGroups(int $limit = 50): array
|
|
{
|
|
return Product::query()
|
|
->where('is_active', true)
|
|
->whereHas('variants', fn (Builder $query) => $query->where('stock', '<=', 0))
|
|
->with([
|
|
'variants' => fn ($query) => $query
|
|
->where('stock', '<=', 0)
|
|
->with('media')
|
|
->orderBy('name'),
|
|
])
|
|
->orderBy('name')
|
|
->limit($limit)
|
|
->get()
|
|
->map(fn (Product $product) => [
|
|
'id' => $product->id,
|
|
'name' => $product->name,
|
|
'edit_url' => route('admin.master.products.edit', $product),
|
|
'variants' => $product->variants->map(fn (ProductVariant $variant) => [
|
|
'id' => $variant->id,
|
|
'name' => $variant->name,
|
|
'stock_formatted' => $variant->stock_formatted,
|
|
'images' => MediaPresenter::collection($variant, 'images'),
|
|
])->values()->all(),
|
|
])
|
|
->filter(fn (array $group) => $group['variants'] !== [])
|
|
->values()
|
|
->all();
|
|
}
|
|
|
|
public function outOfStockRawMaterialGroups(int $limit = 50): array
|
|
{
|
|
return $this->rawMaterialGroupsWithStockFilter(
|
|
fn (Builder $query) => $query->where('stock', '<=', 0),
|
|
$limit,
|
|
);
|
|
}
|
|
|
|
public function lowStockRawMaterialGroups(int $limit = 50): array
|
|
{
|
|
$minStock = [
|
|
RawMaterialUnit::YARD->value => 20,
|
|
RawMaterialUnit::METER->value => 10,
|
|
RawMaterialUnit::KILOGRAM->value => 5,
|
|
];
|
|
|
|
return $this->rawMaterialGroupsWithStockFilter(
|
|
function (Builder $query) use ($minStock): void {
|
|
$query->where('stock', '>', 0)->where(function (Builder $query) use ($minStock): void {
|
|
foreach (RawMaterialUnit::cases() as $unit) {
|
|
$query->orWhere(function (Builder $query) use ($unit, $minStock): void {
|
|
$query->whereHas(
|
|
'rawMaterial',
|
|
fn (Builder $rawMaterialQuery) => $rawMaterialQuery->where('unit', $unit),
|
|
)->where('stock', '<', $minStock[$unit->value]);
|
|
});
|
|
}
|
|
});
|
|
},
|
|
$limit,
|
|
);
|
|
}
|
|
|
|
private function rawMaterialGroupsWithStockFilter(callable $priceConstraint, int $limit): array
|
|
{
|
|
return RawMaterial::query()
|
|
->where('is_active', true)
|
|
->whereHas('prices', $priceConstraint)
|
|
->with([
|
|
'prices' => function ($query) use ($priceConstraint): void {
|
|
$priceConstraint($query);
|
|
$query->with('media')->orderBy('variant');
|
|
},
|
|
])
|
|
->orderBy('name')
|
|
->limit($limit)
|
|
->get()
|
|
->map(fn (RawMaterial $rawMaterial) => [
|
|
'id' => $rawMaterial->id,
|
|
'name' => $rawMaterial->name,
|
|
'edit_url' => route('admin.master.raw_materials.edit', $rawMaterial),
|
|
'unit_label' => $rawMaterial->unit_label,
|
|
'variants' => $rawMaterial->prices->map(fn (RawMaterialPrice $price) => [
|
|
'id' => $price->id,
|
|
'name' => $price->variant,
|
|
'stock_formatted' => $price->stock_formatted,
|
|
'images' => MediaPresenter::collection($price, 'images'),
|
|
])->values()->all(),
|
|
])
|
|
->filter(fn (array $group) => $group['variants'] !== [])
|
|
->values()
|
|
->all();
|
|
}
|
|
}
|