207 lines
7.0 KiB
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)
|
|
);
|
|
}
|
|
}
|