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; } }