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