ultimatepos/Modules/IndustrialEngineering/Http/Controllers/MrpController.php

144 lines
4.7 KiB
PHP

<?php
namespace Modules\IndustrialEngineering\Http\Controllers;
use App\BusinessLocation;
use App\Contact;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Modules\IndustrialEngineering\Http\Controllers\Concerns\AuthorizesIndustrialEngineering;
use Modules\IndustrialEngineering\Models\Bom;
use Modules\IndustrialEngineering\Models\LineRevision;
use Modules\IndustrialEngineering\Models\LineTemplate;
use Modules\IndustrialEngineering\Models\MrpRun;
use Modules\IndustrialEngineering\Services\AutoIntegrationService;
use Modules\IndustrialEngineering\Services\MrpService;
use Modules\IndustrialEngineering\Support\OperationErrorMessages;
class MrpController extends Controller
{
use AuthorizesIndustrialEngineering;
public function __construct(
protected MrpService $mrpService,
protected AutoIntegrationService $autoIntegration
) {
}
public function index()
{
$this->authorizeIe('ie.costing.view');
$boms = Bom::forBusiness($this->businessId())
->where('bom_type', 'mbom')
->with('lineRevision')
->orderByDesc('id')
->get();
$locations = BusinessLocation::forDropdown($this->businessId(), false, true);
$suppliers = Contact::suppliersDropdown($this->businessId(), false);
return view('industrialengineering::mrp.index', compact('boms', 'locations', 'suppliers'));
}
public function run(Request $request)
{
$this->authorizeIe('ie.costing.create');
if ($request->filled('line_id')) {
return $this->runForLine($request, (int) $request->input('line_id'));
}
if ($request->filled('bom_id')) {
return $this->runForBom($request, (int) $request->input('bom_id'));
}
$msg = __('industrialengineering::lang.mrp_missing_context');
return back()->with('status', ['success' => false, 'msg' => $msg]);
}
protected function runForLine(Request $request, int $lineId)
{
$line = LineTemplate::forBusiness($this->businessId())
->productionLines()
->with(['revisions.boms', 'bom'])
->findOrFail($lineId);
$ensured = $this->autoIntegration->ensureLineMbom($line);
$revision = $ensured['revision'];
$mbom = $ensured['mbom'];
if (! $mbom) {
return back()->with('status', [
'success' => false,
'msg' => __('industrialengineering::lang.no_mbom_for_line', ['line' => $line->name]),
]);
}
return $this->executeRun($request, $mbom, $revision);
}
protected function runForBom(Request $request, int $bomId)
{
$bom = Bom::forBusiness($this->businessId())
->with('lineRevision')
->findOrFail($bomId);
$revision = $bom->lineRevision;
if (! $revision) {
return back()->with('status', [
'success' => false,
'msg' => __('industrialengineering::lang.no_line_revision_for_bom'),
]);
}
return $this->executeRun($request, $bom, $revision);
}
protected function executeRun(Request $request, Bom $bom, LineRevision $revision)
{
$data = $request->validate([
'planned_quantity' => 'nullable|numeric|min:0.0001',
'location_id' => 'nullable|integer',
'supplier_contact_id' => 'nullable|integer',
'create_purchase_orders' => 'nullable|boolean',
'create_work_order' => 'nullable|boolean',
]);
try {
$run = $this->mrpService->run(
$this->businessId(),
$bom,
$revision,
(float) ($data['planned_quantity'] ?? 1),
isset($data['location_id']) ? (int) $data['location_id'] : null,
$request->boolean('create_purchase_orders', true),
$request->boolean('create_work_order', true),
isset($data['supplier_contact_id']) ? (int) $data['supplier_contact_id'] : null,
$request->boolean('force_mrp', false)
);
} catch (\Throwable $e) {
report($e);
return back()->with('status', [
'success' => false,
'msg' => OperationErrorMessages::for($e),
]);
}
return back()->with('status', [
'success' => true,
'msg' => $this->completionMessage($run),
]);
}
protected function completionMessage(MrpRun $run): string
{
return __('industrialengineering::lang.mrp_completed', [
'po' => count($run->purchase_order_ids ?? []),
'wo' => $run->work_order_id ? $run->workOrder?->work_order_number : '—',
]);
}
}