calculationEngine = $calculationEngine; } /** * 견적 파라미터 조회 * * @param int $modelId 모델 ID * @param string|null $companyName 업체명 */ public function getEstimateParameters(int $modelId, ?string $companyName = null): array { try { // 모델의 기본 BOM 템플릿 조회 $bomTemplate = BomTemplate::with(['modelVersion.model']) ->where('tenant_id', $this->tenantId()) ->whereHas('modelVersion', function ($query) use ($modelId) { $query->whereHas('model', function ($q) use ($modelId) { $q->where('id', $modelId); }); }) ->where('is_primary', true) ->first(); if (! $bomTemplate) { throw new \Exception("모델 ID {$modelId}에 대한 BOM 템플릿을 찾을 수 없습니다."); } // 파라미터 스키마 추출 $parameters = $this->calculationEngine->getRequiredParameters($bomTemplate->id); // 업체별 추가 파라미터가 있는지 확인 if ($companyName) { $companyParameters = $this->getCompanySpecificParameters($companyName); if ($companyParameters) { $parameters = array_merge_recursive($parameters, $companyParameters); } } return [ 'model_info' => [ 'id' => $bomTemplate->modelVersion->model->id, 'name' => $bomTemplate->modelVersion->model->name ?? '모델명 없음', 'version' => $bomTemplate->modelVersion->version_no ?? 'v1.0', 'bom_template_id' => $bomTemplate->id, ], 'company_info' => [ 'company_type' => $bomTemplate->company_type, 'formula_version' => $bomTemplate->formula_version, 'requested_company' => $companyName, ], 'parameters' => $parameters, 'calculation_preview' => true, ]; } catch (\Exception $e) { Log::error('견적 파라미터 조회 실패', [ 'model_id' => $modelId, 'company_name' => $companyName, 'error' => $e->getMessage(), ]); throw $e; } } /** * BOM 계산 실행 * * @param int $bomTemplateId BOM 템플릿 ID * @param array $parameters 입력 파라미터 * @param string|null $companyName 업체명 */ public function calculateBomEstimate(int $bomTemplateId, array $parameters, ?string $companyName = null): array { try { DB::beginTransaction(); // BOM 템플릿 조회 및 권한 확인 $bomTemplate = BomTemplate::where('tenant_id', $this->tenantId()) ->findOrFail($bomTemplateId); // 업체명이 지정된 경우 BOM 템플릿 업데이트 if ($companyName && $bomTemplate->company_type !== $companyName) { $bomTemplate->update(['company_type' => $companyName]); } // 계산 엔진 실행 $result = $this->calculationEngine->calculateBOM($bomTemplateId, $parameters, $companyName); // 계산 이력 로그 저장 (선택사항) $this->logCalculationHistory($bomTemplateId, $parameters, $result, $companyName); DB::commit(); return [ 'success' => $result['success'], 'data' => $result['success'] ? $result : null, 'error' => $result['success'] ? null : $result['error'], ]; } catch (\Exception $e) { DB::rollBack(); Log::error('BOM 계산 실행 실패', [ 'bom_template_id' => $bomTemplateId, 'parameters' => $parameters, 'company_name' => $companyName, 'error' => $e->getMessage(), ]); return [ 'success' => false, 'data' => null, 'error' => $e->getMessage(), ]; } } /** * 업체별 산출식 목록 조회 * * @param string $companyName 업체명 */ public function getCompanyFormulas(string $companyName): array { $formulas = CalculationConfig::getActiveFormulasForCompany($this->tenantId(), $companyName); return [ 'company_name' => $companyName, 'total_formulas' => count($formulas), 'formulas' => array_map(function ($formula) { return [ 'type' => $formula['formula_type'], 'version' => $formula['version'], 'description' => $formula['description'], 'parameters' => $formula['parameters'], 'updated_at' => $formula['updated_at'], ]; }, $formulas), ]; } /** * 업체별 산출식 등록/수정 * * @param string $companyName 업체명 * @param string $formulaType 산출식 타입 * @param array $formulaData 산출식 데이터 */ public function saveCompanyFormula(string $companyName, string $formulaType, array $formulaData): array { try { DB::beginTransaction(); // 기존 산출식이 있는지 확인 $existingFormula = CalculationConfig::getLatestFormula($this->tenantId(), $companyName, $formulaType); if ($existingFormula) { // 버전 업그레이드 $newVersion = $this->incrementVersion($existingFormula->version); $existingFormula->update(['is_active' => false]); // 기존 비활성화 } else { $newVersion = 'v1.0'; } // 새 산출식 생성 $formula = CalculationConfig::create([ 'tenant_id' => $this->tenantId(), 'company_name' => $companyName, 'formula_type' => $formulaType, 'version' => $newVersion, 'formula_expression' => $formulaData['formula_expression'], 'parameters' => $formulaData['parameters'], 'conditions' => $formulaData['conditions'] ?? null, 'validation_rules' => $formulaData['validation_rules'] ?? null, 'description' => $formulaData['description'] ?? null, 'is_active' => true, 'created_by' => $this->apiUserId(), ]); DB::commit(); return [ 'id' => $formula->id, 'company_name' => $formula->company_name, 'formula_type' => $formula->formula_type, 'version' => $formula->version, 'is_active' => $formula->is_active, 'created_at' => $formula->created_at, ]; } catch (\Exception $e) { DB::rollBack(); Log::error('업체별 산출식 저장 실패', [ 'company_name' => $companyName, 'formula_type' => $formulaType, 'error' => $e->getMessage(), ]); throw $e; } } /** * 업체별 추가 파라미터 조회 */ protected function getCompanySpecificParameters(string $companyName): ?array { // 업체별 특수 파라미터가 있는지 확인 $companyConfig = CalculationConfig::forTenant($this->tenantId()) ->forCompany($companyName) ->forType('additional_parameters') ->active() ->latest() ->first(); return $companyConfig ? $companyConfig->parameters : null; } /** * 계산 이력 로그 저장 */ protected function logCalculationHistory(int $bomTemplateId, array $parameters, array $result, ?string $companyName): void { // 필요에 따라 계산 이력을 별도 테이블에 저장 Log::info('BOM 계산 완료', [ 'bom_template_id' => $bomTemplateId, 'company_name' => $companyName, 'parameters' => $parameters, 'success' => $result['success'], 'calculated_items_count' => $result['success'] ? count($result['bom_items']) : 0, 'calculated_by' => $this->apiUserId(), ]); } /** * 버전 번호 증가 */ protected function incrementVersion(string $currentVersion): string { if (preg_match('/^v(\d+)\.(\d+)$/', $currentVersion, $matches)) { $major = (int) $matches[1]; $minor = (int) $matches[2]; return "v{$major}.".($minor + 1); } return 'v1.0'; } }