73 lines
2.5 KiB
PHP
73 lines
2.5 KiB
PHP
<?php
|
|
|
|
namespace Modules\IndustrialEngineering\Services;
|
|
|
|
use Modules\IndustrialEngineering\Models\Bom;
|
|
use Modules\IndustrialEngineering\Models\ItemMaster;
|
|
|
|
/**
|
|
* Validates integration health; blocks critical ops until required links exist.
|
|
*/
|
|
class ConnectionGateService
|
|
{
|
|
public function __construct(
|
|
protected BomService $bomService,
|
|
protected LiveBomCostingService $liveCosting
|
|
) {
|
|
}
|
|
|
|
public function assessBom(Bom $bom, float $plannedQty = 1): array
|
|
{
|
|
$analysis = $this->liveCosting->analyze($bom, $plannedQty);
|
|
$leafParts = collect($analysis['leaf_lines']);
|
|
$unlinked = $leafParts->filter(fn ($l) => empty($l['variation_id']));
|
|
$linked = $leafParts->filter(fn ($l) => ! empty($l['variation_id']));
|
|
$assemblies = $leafParts->filter(fn ($l) => in_array($l['item_type'], ['assembly', 'subassembly', 'device'], true));
|
|
|
|
$blockers = [];
|
|
if ($leafParts->isEmpty()) {
|
|
$blockers[] = __('industrialengineering::lang.gate_no_bom_leaves');
|
|
}
|
|
|
|
$warnings = [];
|
|
foreach ($unlinked as $row) {
|
|
$warnings[] = __('industrialengineering::lang.gate_unlinked_item', [
|
|
'code' => $row['item_code'],
|
|
'name' => $row['item_name'],
|
|
]);
|
|
}
|
|
|
|
return [
|
|
'can_run_mrp' => empty($blockers) && $unlinked->isEmpty(),
|
|
'can_run_mrp_with_warnings' => empty($blockers) && $unlinked->isNotEmpty(),
|
|
'blockers' => $blockers,
|
|
'warnings' => $warnings,
|
|
'stats' => [
|
|
'total_leaves' => $leafParts->count(),
|
|
'erp_linked' => $linked->count(),
|
|
'unlinked' => $unlinked->count(),
|
|
'assemblies' => $assemblies->count(),
|
|
'shortage_count' => count($analysis['shortages']),
|
|
],
|
|
'analysis' => $analysis,
|
|
];
|
|
}
|
|
|
|
public function assertMrpAllowed(Bom $bom, float $plannedQty = 1, bool $force = false): void
|
|
{
|
|
$gate = $this->assessBom($bom, $plannedQty);
|
|
|
|
if (! empty($gate['blockers'])) {
|
|
throw new \RuntimeException(implode("\n", $gate['blockers']));
|
|
}
|
|
|
|
if (! empty($gate['warnings']) && ! $force) {
|
|
throw new \RuntimeException(
|
|
__('industrialengineering::lang.gate_mrp_blocked_unlinked')."\n".
|
|
implode("\n", array_slice($gate['warnings'], 0, 5)).
|
|
(count($gate['warnings']) > 5 ? "\n..." : '')
|
|
);
|
|
}
|
|
}
|
|
}
|