82 lines
2.8 KiB
PHP
82 lines
2.8 KiB
PHP
<?php
|
|
|
|
namespace Modules\Maintenance\Services;
|
|
|
|
use App\Contact;
|
|
use App\PurchaseLine;
|
|
use Illuminate\Support\Collection;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Modules\Maintenance\Models\SparePart;
|
|
|
|
class MaterialPurchaseSuggestionService
|
|
{
|
|
/**
|
|
* Suggest suppliers for a variation based on purchase history.
|
|
*
|
|
* @return Collection<int, array{supplier_id: int, supplier_name: string, last_price: float, last_date: ?string, purchase_count: int}>
|
|
*/
|
|
public function suggestSuppliers(int $businessId, int $variationId, int $limit = 5): Collection
|
|
{
|
|
$lines = PurchaseLine::query()
|
|
->join('transactions as t', 'purchase_lines.transaction_id', '=', 't.id')
|
|
->join('contacts as c', 't.contact_id', '=', 'c.id')
|
|
->where('t.business_id', $businessId)
|
|
->where('t.type', 'purchase')
|
|
->where('t.status', 'received')
|
|
->where('purchase_lines.variation_id', $variationId)
|
|
->whereNotNull('t.contact_id')
|
|
->select(
|
|
't.contact_id as supplier_id',
|
|
DB::raw("TRIM(CONCAT(COALESCE(c.supplier_business_name, ''), ' ', COALESCE(c.name, ''))) as supplier_name"),
|
|
't.transaction_date',
|
|
'purchase_lines.purchase_price'
|
|
)
|
|
->orderByDesc('t.transaction_date')
|
|
->get();
|
|
|
|
return $lines->groupBy('supplier_id')->map(function ($group, $supplierId) {
|
|
$latest = $group->first();
|
|
|
|
return [
|
|
'supplier_id' => (int) $supplierId,
|
|
'supplier_name' => trim($latest->supplier_name) ?: __('maintenance::lang.unknown_supplier'),
|
|
'last_price' => (float) $latest->purchase_price,
|
|
'last_date' => $latest->transaction_date,
|
|
'purchase_count' => $group->count(),
|
|
];
|
|
})->sortByDesc('purchase_count')->take($limit)->values();
|
|
}
|
|
|
|
public function resolveDefaultSupplierId(int $businessId, ?int $variationId, ?int $sparePartId = null): ?int
|
|
{
|
|
if ($sparePartId) {
|
|
$part = SparePart::where('business_id', $businessId)->find($sparePartId);
|
|
if ($part?->supplier_id) {
|
|
return (int) $part->supplier_id;
|
|
}
|
|
}
|
|
|
|
if ($variationId) {
|
|
$suggestions = $this->suggestSuppliers($businessId, $variationId, 1);
|
|
if ($suggestions->isNotEmpty()) {
|
|
return $suggestions->first()['supplier_id'];
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public function supplierName(?int $supplierId): string
|
|
{
|
|
if (! $supplierId) {
|
|
return '—';
|
|
}
|
|
|
|
$contact = Contact::find($supplierId);
|
|
|
|
return $contact
|
|
? trim($contact->supplier_business_name.' '.$contact->name)
|
|
: '—';
|
|
}
|
|
}
|