ultimatepos/Modules/SupplyChain/Http/Controllers/RfqController.php

207 lines
7.0 KiB
PHP

<?php
namespace Modules\SupplyChain\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Modules\SupplyChain\Http\Controllers\Concerns\AuthorizesSupplyChain;
use Modules\SupplyChain\Models\RfqRequest;
use Modules\SupplyChain\Services\RfqService;
use Modules\SupplyChain\Services\SupplyChainIntegrationService;
use Modules\SupplyChain\Utils\SupplyChainUtil;
use Yajra\DataTables\Facades\DataTables;
class RfqController extends Controller
{
use AuthorizesSupplyChain;
public function __construct(
protected SupplyChainUtil $supplyChainUtil,
protected RfqService $rfqService,
protected SupplyChainIntegrationService $integrationService
) {
}
public function index(Request $request)
{
$this->authorizeSupplyChain('supplychain.rfq.view');
$businessId = $this->supplyChainUtil->getBusinessId();
if ($request->ajax()) {
$rfqs = RfqRequest::forBusiness($businessId)
->withCount(['lines', 'responses'])
->orderByDesc('id');
return DataTables::of($rfqs)
->editColumn('due_date', fn ($row) => $row->due_date?->format('Y-m-d') ?? '—')
->addColumn('status_badge', function ($row) {
$class = $this->supplyChainUtil->rfqStatusBadgeClass($row->status);
return '<span class="label '.$class.'">'.__('supplychain::lang.rfq_status_'.$row->status).'</span>';
})
->addColumn('action', function ($row) {
return '<a class="btn btn-xs btn-info" href="'.action([self::class, 'show'], $row->id).'"><i class="fa fa-eye"></i></a>';
})
->rawColumns(['status_badge', 'action'])
->make(true);
}
return view('supplychain::rfq.index');
}
public function create()
{
$this->authorizeSupplyChain('supplychain.rfq.create');
return view('supplychain::rfq.create', [
'suppliers' => $this->supplyChainUtil->getSuppliersDropdown(),
'products' => $this->supplyChainUtil->getProductsDropdown(),
]);
}
public function store(Request $request)
{
$this->authorizeSupplyChain('supplychain.rfq.create');
$businessId = $this->supplyChainUtil->getBusinessId();
$data = $request->validate([
'title' => 'required|string|max:255',
'due_date' => 'nullable|date',
'holding_entity_id' => 'nullable|integer',
'notes' => 'nullable|string',
'status' => 'nullable|in:draft,open',
'supplier_ids' => 'nullable|array',
'supplier_ids.*' => 'integer',
'lines' => 'required|array|min:1',
'lines.*.product_id' => 'required|integer',
'lines.*.variation_id' => 'nullable|integer',
'lines.*.qty' => 'required|numeric|min:0.0001',
'lines.*.specs' => 'nullable|string',
]);
$rfq = $this->rfqService->create(
$businessId,
$data,
$data['lines'],
$data['supplier_ids'] ?? null,
auth()->id()
);
if (($data['status'] ?? 'draft') === 'open') {
$this->rfqService->open($rfq);
}
return $this->supplyChainUtil->jsonOrRedirect(
$request,
true,
__('supplychain::lang.rfq_created'),
action([self::class, 'show'], $rfq->id)
);
}
public function show($id)
{
$this->authorizeSupplyChain('supplychain.rfq.view');
$businessId = $this->supplyChainUtil->getBusinessId();
$rfq = RfqRequest::forBusiness($businessId)
->with(['lines.product', 'lines.variation', 'responses.contact'])
->findOrFail($id);
return view('supplychain::rfq.show', [
'rfq' => $rfq,
'suppliers' => $this->supplyChainUtil->getSuppliersDropdown(),
]);
}
public function open(Request $request, $id)
{
$this->authorizeSupplyChain('supplychain.rfq.update');
$businessId = $this->supplyChainUtil->getBusinessId();
$rfq = RfqRequest::forBusiness($businessId)->findOrFail($id);
$this->rfqService->open($rfq);
return $this->supplyChainUtil->jsonOrRedirect($request, true, __('supplychain::lang.rfq_opened'));
}
public function close(Request $request, $id)
{
$this->authorizeSupplyChain('supplychain.rfq.update');
$businessId = $this->supplyChainUtil->getBusinessId();
$rfq = RfqRequest::forBusiness($businessId)->findOrFail($id);
$this->rfqService->close($rfq);
return $this->supplyChainUtil->jsonOrRedirect($request, true, __('supplychain::lang.rfq_closed'));
}
public function submitResponse(Request $request, $id)
{
$this->authorizeSupplyChain('supplychain.rfq.update');
$businessId = $this->supplyChainUtil->getBusinessId();
$rfq = RfqRequest::forBusiness($businessId)->findOrFail($id);
$data = $request->validate([
'contact_id' => 'required|integer',
'quoted_price' => 'required|numeric|min:0',
'lead_days' => 'required|integer|min:0',
'notes' => 'nullable|string',
]);
$this->rfqService->submitResponse(
$rfq,
(int) $data['contact_id'],
(float) $data['quoted_price'],
(int) $data['lead_days'],
$data['notes'] ?? null
);
return $this->supplyChainUtil->jsonOrRedirect($request, true, __('supplychain::lang.response_submitted'));
}
public function award(Request $request, $id)
{
$this->authorizeSupplyChain('supplychain.rfq.update');
$businessId = $this->supplyChainUtil->getBusinessId();
$rfq = RfqRequest::forBusiness($businessId)->findOrFail($id);
$data = $request->validate(['contact_id' => 'required|integer']);
$this->rfqService->award($rfq, (int) $data['contact_id']);
return $this->supplyChainUtil->jsonOrRedirect($request, true, __('supplychain::lang.rfq_awarded'));
}
public function createFromMrp(Request $request)
{
$this->authorizeSupplyChain('supplychain.rfq.create');
$businessId = $this->supplyChainUtil->getBusinessId();
$data = $request->validate([
'mrp_run_id' => 'required|integer',
'supplier_ids' => 'nullable|array',
'supplier_ids.*' => 'integer',
]);
$rfqId = $this->integrationService->createRfqFromMrpRun(
$businessId,
(int) $data['mrp_run_id'],
$data['supplier_ids'] ?? null
);
if (! $rfqId) {
return $this->supplyChainUtil->jsonOrRedirect($request, false, __('supplychain::lang.mrp_rfq_failed'));
}
return $this->supplyChainUtil->jsonOrRedirect(
$request,
true,
__('supplychain::lang.rfq_created'),
action([self::class, 'show'], $rfqId)
);
}
}