ultimatepos/Modules/IndustrialEngineering/Services/ProductDefinitionService.php

194 lines
7.0 KiB
PHP

<?php
namespace Modules\IndustrialEngineering\Services;
use Illuminate\Support\Facades\DB;
use Modules\IndustrialEngineering\Models\Bom;
use Modules\IndustrialEngineering\Models\BomLine;
use Modules\IndustrialEngineering\Models\ItemMaster;
use Modules\IndustrialEngineering\Models\LineRevision;
use Modules\IndustrialEngineering\Models\LineTemplate;
use Modules\IndustrialEngineering\Models\ProductPlatform;
class ProductDefinitionService
{
public function __construct(
protected CodeGeneratorService $codeGenerator,
protected BomService $bomService,
protected AutoIntegrationService $autoIntegration
) {
}
public function createProduct(int $businessId, array $data): ProductPlatform
{
return DB::transaction(function () use ($businessId, $data) {
$codes = $this->codeGenerator->resolveCode(
'product',
$businessId,
$data['platform_code'] ?? null,
new ProductPlatform(),
'platform_code'
);
return ProductPlatform::create(array_merge($data, $codes, [
'business_id' => $businessId,
]));
});
}
public function addProductionLine(ProductPlatform $platform, array $data): array
{
return DB::transaction(function () use ($platform, $data) {
$codes = $this->codeGenerator->resolveCode(
'line',
$platform->business_id,
$data['template_code'] ?? null,
new LineTemplate(),
'template_code'
);
$line = LineTemplate::create(array_merge($data, $codes, [
'business_id' => $platform->business_id,
'product_platform_id' => $platform->id,
'line_type' => 'production_line',
'parent_template_id' => null,
'sort_order' => (int) LineTemplate::where('product_platform_id', $platform->id)
->whereNull('parent_template_id')->max('sort_order') + 10,
]));
$revAuto = $this->codeGenerator->suggest('revision', $platform->business_id);
$revisionCode = trim((string) ($data['revision_code'] ?? '')) ?: 'A';
$revision = LineRevision::create([
'business_id' => $platform->business_id,
'line_template_id' => $line->id,
'revision_code' => $revisionCode,
'auto_code' => $revAuto,
'name' => $line->name,
'status' => 'draft',
]);
$bomCodes = $this->codeGenerator->resolveCode(
'bom',
$platform->business_id,
$data['bom_code'] ?? null,
new Bom(),
'bom_code'
);
Bom::create(array_merge($bomCodes, [
'business_id' => $platform->business_id,
'line_revision_id' => $revision->id,
'bom_type' => 'mbom',
'name' => $line->name.' — MBOM',
'revision_code' => $revision->revision_code,
'status' => 'draft',
]));
$mbom = $revision->boms()->where('bom_type', 'mbom')->first();
$messages = $this->autoIntegration->afterLineCreated($line, $revision, $mbom);
return [
'line' => $line->load(['revisions.boms']),
'integration_messages' => $messages,
];
});
}
public function addMachine(LineRevision $revision, array $itemData, ?string $manualCode = null): BomLine
{
return DB::transaction(function () use ($revision, $itemData, $manualCode) {
$positionCode = $itemData['position_code'] ?? null;
unset($itemData['position_code']);
$itemCodes = $this->codeGenerator->resolveCode(
'item',
$revision->business_id,
$manualCode ?? ($itemData['item_code'] ?? null),
new ItemMaster(),
'item_code'
);
$item = ItemMaster::create(array_merge($itemData, $itemCodes, [
'business_id' => $revision->business_id,
'item_type' => $itemData['item_type'] ?? 'device',
]));
$this->autoIntegration->afterItemCreated($item, $itemData);
$mbom = $revision->boms()->where('bom_type', 'mbom')->firstOrFail();
return BomLine::create([
'business_id' => $revision->business_id,
'bom_id' => $mbom->id,
'item_master_id' => $item->id,
'parent_line_id' => null,
'quantity' => 1,
'position_code' => $positionCode,
'is_serviceable' => true,
'sort_order' => (int) $mbom->lines()->whereNull('parent_line_id')->max('sort_order') + 10,
]);
});
}
public function addPart(BomLine $parentLine, array $itemData, float $qty = 1, ?string $manualCode = null): BomLine
{
return DB::transaction(function () use ($parentLine, $itemData, $qty, $manualCode) {
$bom = $parentLine->bom;
$positionCode = $itemData['position_code'] ?? null;
unset($itemData['position_code'], $itemData['quantity']);
$itemCodes = $this->codeGenerator->resolveCode(
'item',
$bom->business_id,
$manualCode ?? ($itemData['item_code'] ?? null),
new ItemMaster(),
'item_code'
);
$item = ItemMaster::create(array_merge($itemData, $itemCodes, [
'business_id' => $bom->business_id,
'item_type' => $itemData['item_type'] ?? 'part',
]));
$this->autoIntegration->afterItemCreated($item, $itemData);
return BomLine::create([
'business_id' => $bom->business_id,
'bom_id' => $bom->id,
'item_master_id' => $item->id,
'parent_line_id' => $parentLine->id,
'quantity' => $qty,
'position_code' => $positionCode,
'is_serviceable' => $itemData['is_serviceable'] ?? true,
'sort_order' => (int) $parentLine->children()->max('sort_order') + 10,
]);
});
}
public function loadProductStructure(ProductPlatform $platform): array
{
$platform->load([
'lineTemplates' => fn ($q) => $q->whereNull('parent_template_id')->orderBy('sort_order'),
'lineTemplates.revisions.boms',
]);
$lines = [];
foreach ($platform->lineTemplates as $line) {
$revision = $line->revisions->sortByDesc('id')->first();
$mbom = $revision?->boms->where('bom_type', 'mbom')->first();
$tree = $mbom ? $this->bomService->buildTree($mbom) : [];
$lines[] = [
'line' => $line,
'revision' => $revision,
'mbom' => $mbom,
'tree' => $tree,
];
}
return $lines;
}
}