138 lines
4.9 KiB
PHP
138 lines
4.9 KiB
PHP
<?php
|
|
|
|
namespace Modules\IndustrialEngineering\Services;
|
|
|
|
use Illuminate\Support\Facades\DB;
|
|
use Modules\IndustrialEngineering\Models\Bom;
|
|
use Modules\IndustrialEngineering\Models\CostScenario;
|
|
use Modules\IndustrialEngineering\Models\LineRevision;
|
|
use Modules\IndustrialEngineering\Models\ManufacturingWorkOrder;
|
|
use Modules\IndustrialEngineering\Models\ReleasePackage;
|
|
use Modules\IndustrialEngineering\Models\ReleaseSignoff;
|
|
|
|
class ReleaseService
|
|
{
|
|
public function __construct(
|
|
protected BomService $bomService
|
|
) {
|
|
}
|
|
|
|
public function createReleasePackage(
|
|
int $businessId,
|
|
LineRevision $revision,
|
|
Bom $mbom,
|
|
?CostScenario $costScenario,
|
|
string $packageCode,
|
|
string $name
|
|
): ReleasePackage {
|
|
$routing = $revision->routingOperations()->with('workCenter')->get()->map(fn ($op) => [
|
|
'operation_code' => $op->operation_code,
|
|
'name' => $op->name,
|
|
'sequence' => $op->sequence,
|
|
'work_center' => $op->workCenter?->name,
|
|
'setup_hours' => (float) $op->setup_time_hours,
|
|
'run_hours' => (float) $op->run_time_hours,
|
|
])->values()->all();
|
|
|
|
return ReleasePackage::create([
|
|
'business_id' => $businessId,
|
|
'line_revision_id' => $revision->id,
|
|
'mbom_id' => $mbom->id,
|
|
'cost_scenario_id' => $costScenario?->id,
|
|
'package_code' => $packageCode,
|
|
'name' => $name,
|
|
'status' => 'draft',
|
|
'mbom_snapshot' => $this->bomService->snapshot($mbom),
|
|
'routing_snapshot' => $routing,
|
|
'cost_snapshot' => $costScenario ? [
|
|
'scenario_id' => $costScenario->id,
|
|
'total_cost' => (float) $costScenario->total_cost,
|
|
'material' => (float) $costScenario->total_material_cost,
|
|
'labor' => (float) $costScenario->total_labor_cost,
|
|
'machine' => (float) $costScenario->total_machine_cost,
|
|
] : null,
|
|
]);
|
|
}
|
|
|
|
public function requestSignoffs(ReleasePackage $package, array $roles = ['engineering', 'manufacturing', 'quality']): void
|
|
{
|
|
foreach ($roles as $role) {
|
|
ReleaseSignoff::firstOrCreate(
|
|
['release_package_id' => $package->id, 'signoff_role' => $role],
|
|
['business_id' => $package->business_id, 'status' => 'pending']
|
|
);
|
|
}
|
|
$package->update(['status' => 'pending_approval']);
|
|
}
|
|
|
|
public function signoff(ReleasePackage $package, string $role, int $userId, string $status = 'approved', ?string $notes = null): void
|
|
{
|
|
ReleaseSignoff::where('release_package_id', $package->id)
|
|
->where('signoff_role', $role)
|
|
->update([
|
|
'signer_id' => $userId,
|
|
'signer_name' => auth()->user()?->user_full_name ?? auth()->user()?->username,
|
|
'status' => $status,
|
|
'signed_at' => now(),
|
|
'notes' => $notes,
|
|
]);
|
|
}
|
|
|
|
public function release(ReleasePackage $package, int $userId): ReleasePackage
|
|
{
|
|
$pending = ReleaseSignoff::where('release_package_id', $package->id)
|
|
->where('status', '!=', 'approved')
|
|
->exists();
|
|
|
|
if ($pending) {
|
|
throw new \RuntimeException('All signoffs must be approved before release.');
|
|
}
|
|
|
|
return DB::transaction(function () use ($package, $userId) {
|
|
$package->update([
|
|
'status' => 'released',
|
|
'released_by' => $userId,
|
|
'released_at' => now(),
|
|
]);
|
|
|
|
$package->lineRevision->update([
|
|
'status' => 'released',
|
|
'released_by' => $userId,
|
|
'released_at' => now(),
|
|
]);
|
|
|
|
if ($package->mbom) {
|
|
$package->mbom->update([
|
|
'status' => 'released',
|
|
'released_by' => $userId,
|
|
'released_at' => now(),
|
|
]);
|
|
}
|
|
|
|
return $package->fresh();
|
|
});
|
|
}
|
|
|
|
public function createWorkOrder(
|
|
ReleasePackage $package,
|
|
string $workOrderNumber,
|
|
float $plannedQty = 1,
|
|
?int $locationId = null
|
|
): ManufacturingWorkOrder {
|
|
if ($package->status !== 'released') {
|
|
throw new \RuntimeException('Release package must be released before creating work orders.');
|
|
}
|
|
|
|
return ManufacturingWorkOrder::create([
|
|
'business_id' => $package->business_id,
|
|
'release_package_id' => $package->id,
|
|
'location_id' => $locationId,
|
|
'work_order_number' => $workOrderNumber,
|
|
'planned_quantity' => $plannedQty,
|
|
'status' => 'planned',
|
|
'bom_snapshot' => $package->mbom_snapshot,
|
|
'routing_snapshot' => $package->routing_snapshot,
|
|
]);
|
|
}
|
|
}
|