ultimatepos/Modules/Maintenance/Services/MaterialPurchaseSuggestionService.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)
: '—';
}
}