input('table'); $module = request()->input('module'); // Ortak Modül Kontrolleri // joint-release-log özel mantığı aşağıda döngü içerisinde dinamik olarak (weld_logs veya deleted_joints) belirlenecektir. // Tablo geçerlilik kontrolü if (!$tableName || !Schema::hasTable($tableName)) { echo json_encode([ 'storedData' => 0, 'updateOrInsert' => 0, 'insert' => 0, 'update' => 0, 'delete' => 0, 'totalErrors' => 1, 'error' => "Invalid table: " . ($tableName ?: 'empty'), 'errorRows' => [], 'triggerInfo' => 'Table validation failed' ]); exit; } $columns = request()->input('columns'); $numericColumns = []; // Numeric sütunları tespit etme sistemi - sadece Excel'den gelen sütunlar için if($tableName && $columns) { try { // Sadece Excel'den gelen sütunları kontrol et foreach($columns as $column) { $columnType = Schema::getColumnType($tableName, $column); // Numeric tipli sütunları belirle if(in_array(strtolower($columnType), [ 'decimal', 'numeric', 'float', 'double', 'real', 'tinyint', 'smallint', 'mediumint', 'int', 'integer', 'bigint' ])) { $numericColumns[] = $column; } } } catch (\Exception $e) { // Hata durumunda boş array kullan $numericColumns = []; } } if(!function_exists('convertNumericValue')) { // Numeric değer dönüştürme fonksiyonu function convertNumericValue($value, $columnName, $numericColumns) { if(!in_array($columnName, $numericColumns)) { return $value; } if($value === null || $value === '') { return $value; } // String'e çevir ve boşlukları temizle $value = trim((string) $value); // Eğer zaten numeric ise direkt döndür if(is_numeric($value)) { return $value; } // Özel durumları işle $originalValue = $value; // Negatif işareti koru $isNegative = (strpos($value, '-') === 0); if($isNegative) { $value = substr($value, 1); } // Farklı sayı formatlarını normalize et // 1. Türk formatı: 1.234,56 -> 1234.56 if(preg_match('/^(\d{1,3}(?:\.\d{3})*),(\d+)$/', $value, $matches)) { $integerPart = str_replace('.', '', $matches[1]); $decimalPart = $matches[2]; $value = $integerPart . '.' . $decimalPart; } // 2. Basit virgüllü ondalık: 0,375 -> 0.375 elseif(preg_match('/^(\d+),(\d+)$/', $value, $matches)) { $value = $matches[1] . '.' . $matches[2]; } // 3. Binlik ayıracı nokta ile: 1.234 -> 1234 (ondalık kısım yoksa) elseif(preg_match('/^(\d{1,3}(?:\.\d{3})+)$/', $value)) { $value = str_replace('.', '', $value); } // Negatif işareti geri ekle if($isNegative) { $value = '-' . $value; } // Final numeric kontrolü if(is_numeric($value)) { return $value; } // Eğer hala numeric değilse orijinal değeri döndür return $originalValue; } } $u = u(); // Yetki kontrollerini tek seferde tanımla $moduleType = "batch-excel"; $canDelete = isAuth($moduleType, "full_control"); $canModify = isAuth($moduleType, "modify"); $canWrite = isAuth($moduleType, "write"); $canModifyAndWrite = $canModify && $canWrite; $data = j(request()->input('data')); $refactoringData = []; $storedData = 0; $updateOrInsert = 0; $insert = 0; $update = 0; $delete = 0; $error = false; DB::beginTransaction(); $triggerOutput = ""; $commitSize = 1000; // Daha küçük batch boyutu kullanılıyor $say = 0; $totalRow = count($data); // ColumnComment için toplu ekleme işlemini kolaylaştıracak dizi $columnCommentsToAdd = []; $maxColumnCommentsPerBatch = 200; // Daha küçük batch boyutu kullanılıyor if($totalRow<$commitSize) { $commitSize = $totalRow; } $ids = []; $runTrigger = false; // Eklenen, güncellenen, silinen ve işlem yapılmayan satırların Excel'deki satır numaralarını tutacak diziler $insertedRowNumbers = []; $updatedRowNumbers = []; $deletedRowNumbers = []; $skippedRowNumbers = []; // Satır limit değişkeni - maksimum kaç satır detayı döndürüleceğini belirler $rowDetailsLimit = 100; /* if($totalRow<1000) { $runTrigger = true; } */ if(request()->input('run_trigger') == 'true') { $runTrigger = true; } // Hata raporlaması için yeni dizi $errorRows = []; $refactoringRow = []; try { // Veri yükünü küçük parçalara böl ve her bölüm tamamlandığında temizle $batchCounter = 0; foreach($data AS $rowIndex => $d) { try { // Bellek yönetimi - her 500 satırda bir çöp toplama ve bellek temizleme $batchCounter++; if ($batchCounter % 500 == 0) { gc_collect_cycles(); // Çöp toplamayı zorlama // Ara transaction commit - büyük veri setlerinde bellek basıncını azalt if (!empty($columnCommentsToAdd)) { ColumnComment::insert($columnCommentsToAdd); $columnCommentsToAdd = []; // Diziyi temizle } DB::commit(); DB::beginTransaction(); } $row = []; $cursor = 0; $allEmpty = true; // Silme işlemi için özel kontrol if(getisset("delete")) { // Farklı veri yapılarını ele al if(isset($d['id'])) { // Doğrudan id değeri olan bir nesne gönderildi (özel format) if($canDelete) { $deleteResult = db($tableName)->where('id', $d['id'])->delete(); $delete += $deleteResult; // Silinen satır numarasını kaydet if ($deleteResult > 0) { $deletedRowNumbers[] = $rowIndex + 1; // Excel satır numarası (1-based) } } $say++; continue; } else if(is_array($d) && isset($d[0]) && isset($d[0]['value'])) { // Standart Excel veri formatı - id sütunu ilk sütun ise $idValue = $d[0]['value']; if(!empty($idValue) && $canDelete) { $deleteResult = db($tableName)->where('id', $idValue)->delete(); $delete += $deleteResult; // Silinen satır numarasını kaydet if ($deleteResult > 0) { $deletedRowNumbers[] = $rowIndex + 1; // Excel satır numarası (1-based) } $say++; continue; } } else { // Veri yapısını inceleyip hata kaydedelim $errorRows[] = [ 'row' => $rowIndex + 1, 'error' => "Invalid data structure for delete operation: " . json_encode($d), 'data' => $d ]; continue; } } // Excel veri formatı kontrolü if(!is_array($d)) { throw new \Exception("Row data is not an array: " . json_encode($d)); } foreach($columns AS $column) { // Veri yapısı kontrolü - Toleranslı Yaklaşım $cellValue = null; // Eğer indeks varsa ve value anahtarı varsa değeri al if(isset($d[$cursor]) && is_array($d[$cursor]) && array_key_exists('value', $d[$cursor])) { $cellValue = $d[$cursor]['value']; } // Doluluk kontrolü: Null değilse ve trim sonrası boş değilse dolu kabul et if(!is_null($cellValue) && trim((string)$cellValue) !== "") { $allEmpty = false; } if($cellValue == "") $cellValue = null; $row[$column] = $cellValue; $cursor++; } /* if(count($row)<=1000) { $runTrigger = true; } */ if(!$allEmpty) { $updateForIso = false; foreach($row AS $column => $value) { $value = trim($value); if($value != "") { if($value == "NULL*") { $refactoringRow[$column] = null; } else // Adında "date" geçen veya özel tarih sütunları listesinde olan sütunlar if(strpos($column, "date") !== false || in_array($column, $dateColumns)) { try { if (!empty($value)) { // Nokta, slash gibi ayraçları standartlaştır $value = trim(str_replace(['/', '.'], '-', $value)); // Carbon'un tarih çözümlemesini dene $carbonDate = Carbon::parse($value); // Tarihi her durumda ekle, rejected_date kontrolünü kaldır $dateValue = $carbonDate->format('Y-m-d'); if (!rejected_date($dateValue)) { $refactoringRow[$column] = $dateValue; } } } catch (\Exception $e) { // Geçersiz tarih formatında bile en azından orijinal değeri koy $refactoringRow[$column] = $value; } } else { // Numeric sütunlar için özel dönüştürme $convertedValue = convertNumericValue($value, $column, $numericColumns); $refactoringRow[$column] = $convertedValue; } } // Welding_date gibi önemli tarih alanlarını açıkça kontrol et ve yoksa ekle else if($column == "welding_date" && isset($row[$column])) { $refactoringRow[$column] = $row[$column]; } } if(isset($row['no_of_the_joint_as_per_as_built_survey'])) { if(isset($row['iso_number'])) { $updateForIso = true; } } $updateForSpoolNumber = false; if(!$updateForIso) { if(isset($row['spool_number'])) { if(isset($row['iso_number'])) { $updateForSpoolNumber = true; } } } if(getisset("delete")) { if($canDelete) { $deleteResult = db($tableName)->where($refactoringRow)->delete(); $delete += $deleteResult; // Eğer kayıt silindiyse satır numarasını kaydet if ($deleteResult > 0) { $deletedRowNumbers[] = $rowIndex + 1; } } } else { unset($refactoringRow['id']); if ($module === 'joint-release-log') { // Custom logic for joint-release-log: UPDATE joint_releases instead of base table if (!isset($row['iso_number']) || !isset($row['no_of_the_joint_as_per_as_built_survey'])) { $errorRows[] = [ 'row' => $rowIndex + 1, 'error' => "Missing key fields for Joint Release Log update (requires iso_number and joint_no)", 'data' => $refactoringRow ]; $skippedRowNumbers[] = $rowIndex + 1; continue; } $whereData = [ 'no_of_the_joint_as_per_as_built_survey' => $row['no_of_the_joint_as_per_as_built_survey'], 'iso_number' => $row['iso_number'], ]; $existingRecord = db('weld_logs')->where($whereData)->first(); $logTypeKey = 'weld_log_id'; $targetTable = 'weld_logs'; if (!$existingRecord) { $existingRecord = db('deleted_joints')->where($whereData)->first(); $logTypeKey = 'deleted_joint_id'; $targetTable = 'deleted_joints'; } if (!$existingRecord) { $errorRows[] = [ 'row' => $rowIndex + 1, 'error' => "Record not found. Joint Release Log does not allow inserting new joints.", 'data' => $refactoringRow ]; $skippedRowNumbers[] = $rowIndex + 1; continue; } if ($canModify) { $jointReleaseMatch = [$logTypeKey => $existingRecord->id]; // Remove non-release fields from refactoringRow so we don't insert them into joint_releases $allowedReleaseFields = [ 'joint_release_rfi_no', 'joint_release_rfi_date', 'joint_release_document_no', 'joint_release_document_date', 'rt_release_rfi_no', 'rt_release_rfi_date', 'ut_release_rfi_no', 'ut_release_rfi_date', 'pt_release_rfi_no', 'pt_release_rfi_date', 'mt_release_rfi_no', 'mt_release_rfi_date', 'pmi_release_rfi_no', 'pmi_release_rfi_date', 'vt_release_rfi_no', 'vt_release_rfi_date', 'pwht_release_rfi_no', 'pwht_release_rfi_date', 'ht_release_rfi_no', 'ht_release_rfi_date', 'ferrite_release_rfi_no', 'ferrite_release_rfi_date' ]; $releaseDataToUpdate = []; foreach($refactoringRow as $col => $val) { if (in_array($col, $allowedReleaseFields)) { $releaseDataToUpdate[$col] = $val; } } if (!empty($releaseDataToUpdate)) { $existingReleaseRecord = db('joint_releases')->where($jointReleaseMatch)->first(); if ($existingReleaseRecord) { db('joint_releases')->where($jointReleaseMatch)->update($releaseDataToUpdate); } else { $insertData = array_merge($jointReleaseMatch, $releaseDataToUpdate); db('joint_releases')->insert($insertData); } $update++; // Column Comment Logs (using targetTable for transparency in UI) foreach($releaseDataToUpdate as $column => $value) { $oldValue = $existingReleaseRecord ? (isset($existingReleaseRecord->$column) ? $existingReleaseRecord->$column : null) : null; if($oldValue != $value) { $columnCommentsToAdd[] = [ // Make comments appear on the base record view 'table_name' => $targetTable, 'record_id' => $existingRecord->id, 'column_name' => $column, 'comment' => 'Updated via Excel batch (Joint Release Log)', 'column_value' => $value, 'user_id' => u()->id, 'ip_address' => request()->ip(), 'created_at' => Carbon::now(), 'updated_at' => Carbon::now() ]; } } if(count($columnCommentsToAdd) >= $maxColumnCommentsPerBatch) { ColumnComment::insert($columnCommentsToAdd); $columnCommentsToAdd = []; } $updatedRowNumbers[] = $rowIndex + 1; } else { // Data provided contained no release fields $skippedRowNumbers[] = $rowIndex + 1; } } else { $skippedRowNumbers[] = $rowIndex + 1; } continue; } if($updateForIso) { if(in_array($tableName, log_test_types())) { $whereData = [ 'no_of_the_joint_as_per_as_built_survey' => $row['no_of_the_joint_as_per_as_built_survey'], 'iso_number' => $row['iso_number'], ]; // welding_date varsa whereData'ya ekle, yoksa ekli değilse hata oluşmasın if(isset($refactoringRow['welding_date'])) { $whereData['welding_date'] = $refactoringRow['welding_date']; } } elseif($module === 'joint-release-log') { if(!isset($refactoringRow['welding_date']) || $refactoringRow['welding_date'] === null || $refactoringRow['welding_date'] === '') { $errorRows[] = [ 'row' => $rowIndex + 1, 'error' => "Missing required field: welding_date is required for joint-release-log (iso + joint + welding_date)", 'data' => $refactoringRow ]; $skippedRowNumbers[] = $rowIndex + 1; continue; } $whereData = [ 'no_of_the_joint_as_per_as_built_survey' => $row['no_of_the_joint_as_per_as_built_survey'], 'iso_number' => $row['iso_number'], 'welding_date' => $refactoringRow['welding_date'], ]; } else { $whereData = [ 'no_of_the_joint_as_per_as_built_survey' => $row['no_of_the_joint_as_per_as_built_survey'], 'iso_number' => $row['iso_number'], ]; } $existingRecord = db($tableName)->where($whereData)->first(); if($existingRecord) { $ids[] = ['id' => $existingRecord->id]; } if($canModifyAndWrite) { if($existingRecord) { // weld_logs tablosu için update öncesi duplicate kontrol if($tableName == "weld_logs" && isset($refactoringRow['iso_number']) && isset($refactoringRow['no_of_the_joint_as_per_as_built_survey'])) { $duplicateCheck = db($tableName) ->where('iso_number', $refactoringRow['iso_number']) ->where('no_of_the_joint_as_per_as_built_survey', $refactoringRow['no_of_the_joint_as_per_as_built_survey']) ->where('id', '!=', $existingRecord->id) // Kendisi hariç ->exists(); if($duplicateCheck) { // Duplicate bulundu - hata kaydet ve atla $errorRows[] = [ 'row' => $rowIndex + 1, 'error' => "Duplicate weld log entry: ISO '{$refactoringRow['iso_number']}' + Joint '{$refactoringRow['no_of_the_joint_as_per_as_built_survey']}' already exists", 'data' => $refactoringRow ]; $skippedRowNumbers[] = $rowIndex + 1; continue; // Sonraki satıra geç } } // Update işlemi $oldValues = []; foreach($refactoringRow as $column => $value) { // Önceki değerleri kaydet $oldValues[$column] = isset($existingRecord->$column) ? $existingRecord->$column : null; } db($tableName)->where($whereData)->update($refactoringRow); $update++; // weld_logs güncellemesinde release alanları varsa joint_releases tablosuna da sync et if ($tableName === 'weld_logs') { $batchReleaseFields = [ 'joint_release_rfi_no', 'joint_release_rfi_date', 'joint_release_document_no', 'joint_release_document_date', 'rt_release_rfi_no', 'rt_release_rfi_date', 'ut_release_rfi_no', 'ut_release_rfi_date', 'pt_release_rfi_no', 'pt_release_rfi_date', 'mt_release_rfi_no', 'mt_release_rfi_date', 'pmi_release_rfi_no', 'pmi_release_rfi_date', 'vt_release_rfi_no', 'vt_release_rfi_date', 'pwht_release_rfi_no', 'pwht_release_rfi_date', 'ht_release_rfi_no', 'ht_release_rfi_date', 'ferrite_release_rfi_no', 'ferrite_release_rfi_date', ]; $releaseSync = []; foreach ($batchReleaseFields as $rf) { if (array_key_exists($rf, $refactoringRow)) { $releaseSync[$rf] = $refactoringRow[$rf]; } } if (!empty($releaseSync)) { $existingJR = db('joint_releases')->where('weld_log_id', $existingRecord->id)->first(); if ($existingJR) { db('joint_releases')->where('weld_log_id', $existingRecord->id)->update($releaseSync); } else { db('joint_releases')->insert(array_merge(['weld_log_id' => $existingRecord->id], $releaseSync)); } } } // Değişen alanlar için ColumnComment ekle foreach($refactoringRow as $column => $value) { // Sadece değişen kolonlar için ColumnComment oluştur if(isset($oldValues[$column]) && $oldValues[$column] != $value) { $columnCommentsToAdd[] = [ 'table_name' => $tableName, 'record_id' => $existingRecord->id, 'column_name' => $column, 'comment' => 'Updated via Excel batch', 'column_value' => $value, 'user_id' => u()->id, 'ip_address' => request()->ip(), 'created_at' => Carbon::now(), 'updated_at' => Carbon::now() ]; } } // Belirli bir limite ulaşıldığında yorumları toplu şekilde ekle if(count($columnCommentsToAdd) >= $maxColumnCommentsPerBatch) { ColumnComment::insert($columnCommentsToAdd); $columnCommentsToAdd = []; // Diziyi temizle } $updatedRowNumbers[] = $rowIndex + 1; } else { // weld_logs tablosuna insert batch-excel üzerinden yasak if($tableName == "weld_logs") { $errorRows[] = [ 'row' => $rowIndex + 1, 'error' => "Insert into weld_logs is not allowed via batch excel. Use the weld log entry form.", 'data' => $refactoringRow ]; $skippedRowNumbers[] = $rowIndex + 1; continue; } try { // Insert işlemi $rowId = db($tableName)->insertGetId($refactoringRow); $ids[] = ['id' => $rowId]; $insert++; // Yeni eklenen her alan için ColumnComment ekle foreach($refactoringRow as $column => $value) { if($value !== null && $value !== '' && !in_array($column, ['created_at', 'updated_at', 'deleted_at'])) { $columnCommentsToAdd[] = [ 'table_name' => $tableName, 'record_id' => $rowId, 'column_name' => $column, 'comment' => 'Created via Excel batch', 'column_value' => $value, 'user_id' => u()->id, 'ip_address' => request()->ip(), 'created_at' => Carbon::now(), 'updated_at' => Carbon::now() ]; } } // Belirli bir limite ulaşıldığında yorumları toplu şekilde ekle if(count($columnCommentsToAdd) >= $maxColumnCommentsPerBatch) { ColumnComment::insert($columnCommentsToAdd); $columnCommentsToAdd = []; // Diziyi temizle } $insertedRowNumbers[] = $rowIndex + 1; } catch (\Throwable $th) { // Duplicate catch block - try update instead $duplicateUpdateCheck = db($tableName) ->where('iso_number', $refactoringRow['iso_number']) ->where('no_of_the_joint_as_per_as_built_survey', $refactoringRow['no_of_the_joint_as_per_as_built_survey']) ->first(); if($duplicateUpdateCheck) { // Duplicate var, update yap db($tableName)->where('id', $duplicateUpdateCheck->id)->update($refactoringRow); $update++; $updatedRowNumbers[] = $rowIndex + 1; } else { // Başka bir hata, error log'a ekle $errorRows[] = [ 'row' => $rowIndex + 1, 'error' => $th->getMessage(), 'data' => $refactoringRow ]; $skippedRowNumbers[] = $rowIndex + 1; } } } } else { if($canModify && $existingRecord) { db($tableName)->where($whereData)->update($refactoringRow); $update++; // Güncellenen satır numarasını kaydet $updatedRowNumbers[] = $rowIndex + 1; } elseif($canWrite && !$existingRecord) { $rowId = db($tableName)->insertGetId($refactoringRow); $ids[] = ['id' => $rowId]; $insert++; // Insert edilen satırın Excel'deki satır numarasını kaydet $insertedRowNumbers[] = $rowIndex + 1; } else { // Yetki yoksa veya başka bir neden varsa, satır numarasını atlanılan listesine ekle $skippedRowNumbers[] = $rowIndex + 1; } } } elseif($updateForSpoolNumber) { $whereData = [ 'spool_number' => $row['spool_number'], 'iso_number' => $row['iso_number'], ]; $existingRecord = db($tableName)->where($whereData)->first(); if($existingRecord) { $ids[] = ['id' => $existingRecord->id]; // Update işlemi $oldValues = []; foreach($refactoringRow as $column => $value) { // Önceki değerleri kaydet $oldValues[$column] = isset($existingRecord->$column) ? $existingRecord->$column : null; } db($tableName)->where($whereData)->update($refactoringRow); $update++; // Değişen alanlar için ColumnComment ekle foreach($refactoringRow as $column => $value) { // Sadece değişen kolonlar için ColumnComment oluştur if(isset($oldValues[$column]) && $oldValues[$column] != $value) { $columnCommentsToAdd[] = [ 'table_name' => $tableName, 'record_id' => $existingRecord->id, 'column_name' => $column, 'comment' => 'Updated via Excel batch', 'column_value' => $value, 'user_id' => u()->id, 'ip_address' => request()->ip(), 'created_at' => Carbon::now(), 'updated_at' => Carbon::now() ]; } } // Belirli bir limite ulaşıldığında yorumları toplu şekilde ekle if(count($columnCommentsToAdd) >= $maxColumnCommentsPerBatch) { ColumnComment::insert($columnCommentsToAdd); $columnCommentsToAdd = []; // Diziyi temizle } $updatedRowNumbers[] = $rowIndex + 1; } else { // Eşleşen kayıt bulunamadıysa atlanılan olarak işaretle $skippedRowNumbers[] = $rowIndex + 1; } } elseif($tableName == "line_lists") { if(isset($row['id']) && !empty($row['id']) && is_numeric($row['id']) && $row['id'] > 0) { $whereData = ['id' => $row['id']]; // ID varsa sadece güncelleme yap if($canModify) { db($tableName)->where($whereData)->update($refactoringRow); $update++; } } elseif(isset($row['line_no']) && isset($row['fluid_code'])) { $whereData = [ 'line_no' => $row['line_no'], 'fluid_code' => $row['fluid_code'], ]; $existingRecord = db($tableName)->where($whereData)->first(); if($existingRecord) { $ids[] = ['id' => $existingRecord->id]; } if($canModifyAndWrite) { if($existingRecord) { db($tableName)->where($whereData)->update($refactoringRow); // Güncellenen satır numarasını kaydet $updatedRowNumbers[] = $rowIndex + 1; } else { db($tableName)->insert($refactoringRow); // Eklenen satır numarasını kaydet $insertedRowNumbers[] = $rowIndex + 1; } $updateOrInsert++; } else { if($canModify && $existingRecord) { db($tableName)->where($whereData)->update($refactoringRow); $update++; // Güncellenen satır numarasını kaydet $updatedRowNumbers[] = $rowIndex + 1; } else { // Yetki yoksa veya başka bir durum varsa atlanılan olarak işaretle $skippedRowNumbers[] = $rowIndex + 1; } } } else { // Gerekli alanlar yoksa atlanılan olarak işaretle $skippedRowNumbers[] = $rowIndex + 1; } } elseif($tableName == "test_packages") { if(isset($row['id']) && !empty($row['id']) && is_numeric($row['id']) && $row['id'] > 0) { $whereData = ['id' => $row['id']]; // ID varsa sadece güncelleme yap if($canModify) { db($tableName)->where($whereData)->update($refactoringRow); $update++; } } elseif(isset($row['test_package_number'])) { $whereData = [ 'test_package_number' => $row['test_package_number'], ]; if($canModifyAndWrite) { $exists = db($tableName)->where($whereData)->exists(); db($tableName)->updateOrInsert($whereData, $refactoringRow); $updateOrInsert++; // Kayıt varsa güncelleme, yoksa ekleme olarak işaretle if($exists) { $updatedRowNumbers[] = $rowIndex + 1; } else { $insertedRowNumbers[] = $rowIndex + 1; } } else { if($canModify && db($tableName)->where($whereData)->exists()) { db($tableName)->where($whereData)->update($refactoringRow); $update++; // Güncellenen satır numarasını kaydet $updatedRowNumbers[] = $rowIndex + 1; } else { // Yetki yoksa veya başka bir durum varsa atlanılan olarak işaretle $skippedRowNumbers[] = $rowIndex + 1; } } } else { // Gerekli alanlar yoksa atlanılan olarak işaretle $skippedRowNumbers[] = $rowIndex + 1; } } elseif($tableName == "test_pack_base_statuses") { if(isset($row['id']) && !empty($row['id']) && is_numeric($row['id']) && $row['id'] > 0) { $whereData = ['id' => $row['id']]; // ID varsa sadece güncelleme yap if($canModify) { db($tableName)->where($whereData)->update($refactoringRow); $update++; } } elseif(isset($row['test_package_no'])) { $whereData = [ 'test_package_no' => $row['test_package_no'], ]; if($canModifyAndWrite) { db($tableName)->updateOrInsert($whereData, $refactoringRow); $updateOrInsert++; } else { if($canModify && db($tableName)->where($whereData)->exists()) { db($tableName)->where($whereData)->update($refactoringRow); $update++; } } } } elseif($tableName == "paint_matrices") { if(isset($row['id']) && !empty($row['id']) && is_numeric($row['id']) && $row['id'] > 0) { $whereData = ['id' => $row['id']]; // ID varsa sadece güncelleme yap if($canModify) { db($tableName)->where($whereData)->update($refactoringRow); $update++; } } elseif(isset($row['line'])) { if(isset($row['fluid_code'])) { $whereData = [ 'line' => $row['line'], 'fluid_code' => $row['fluid_code'], ]; if($canModifyAndWrite) { db($tableName)->updateOrInsert($whereData, $refactoringRow); $updateOrInsert++; } else { if($canModify && db($tableName)->where($whereData)->exists()) { db($tableName)->where($whereData)->update($refactoringRow); $update++; } } } } } elseif($tableName == "nde_matrices") { if(isset($row['id']) && !empty($row['id']) && is_numeric($row['id']) && $row['id'] > 0) { $whereData = ['id' => $row['id']]; // ID varsa sadece güncelleme yap if($canModify) { db($tableName)->where($whereData)->update($refactoringRow); $update++; } } elseif(isset($row['line'])) { if(isset($row['fluid'])) { if(isset($row['type_of_joint'])) { $whereData = [ 'line' => $row['line'], 'fluid' => $row['fluid'], 'type_of_joint' => $row['type_of_joint'], ]; if($canModifyAndWrite) { db($tableName)->updateOrInsert($whereData, $refactoringRow); $updateOrInsert++; } else { if($canModify && db($tableName)->where($whereData)->exists()) { db($tableName)->where($whereData)->update($refactoringRow); $update++; } } } } } } elseif($tableName == "document_revisions") { // ID sütunu varsa öncelik ID'ye verilmeli if(isset($row['id']) && !empty($row['id']) && is_numeric($row['id']) && $row['id'] > 0) { $whereData = ['id' => $row['id']]; // ID varsa sadece güncelleme yap if($canModify) { db($tableName)->where($whereData)->update($refactoringRow); $update++; } } elseif(isset($row['drawing_no']) && isset($row['zone'])) { $whereData = [ 'drawing_no' => $row['drawing_no'], 'zone' => $row['zone'], ]; if($canModifyAndWrite) { db($tableName)->updateOrInsert($whereData, $refactoringRow); $updateOrInsert++; } else { if($canModify && db($tableName)->where($whereData)->exists()) { db($tableName)->where($whereData)->update($refactoringRow); $update++; } } } } elseif($tableName == "m_t_o_s") { if(isset($row['id']) && !empty($row['id']) && is_numeric($row['id']) && $row['id'] > 0) { $whereData = ['id' => $row['id']]; // ID varsa sadece güncelleme yap if($canModify) { db($tableName)->where($whereData)->update($refactoringRow); $update++; } } elseif(isset($row['line'])) { if(isset($row['component_code_id'])) { $whereData = [ 'line' => $row['line'], 'component_code_id' => $row['component_code_id'], ]; if($canModifyAndWrite) { db($tableName)->updateOrInsert($whereData, $refactoringRow); $updateOrInsert++; } else { if($canModify && db($tableName)->where($whereData)->exists()) { db($tableName)->where($whereData)->update($refactoringRow); $update++; } } } } } else { // ID değerini güvenli bir şekilde kontrol et $hasValidId = !empty($row['id']) && is_numeric($row['id']) && $row['id'] > 0; if($hasValidId) { $whereData = ['id'=> $row['id']]; $existingRecord = db($tableName)->where($whereData)->first(); if($existingRecord) { $ids[] = ['id' => $existingRecord->id]; } if($existingRecord) { // Kayıt var - Update işlemi için modify yetkisi gerekli if($canModify) { // weld_logs tablosu için özel duplicate kontrol if($tableName == "weld_logs" && isset($refactoringRow['iso_number']) && isset($refactoringRow['no_of_the_joint_as_per_as_built_survey'])) { // Update edilecek değerlerle çakışma kontrolü $duplicateCheck = db($tableName) ->where('iso_number', $refactoringRow['iso_number']) ->where('no_of_the_joint_as_per_as_built_survey', $refactoringRow['no_of_the_joint_as_per_as_built_survey']) ->where('id', '!=', $existingRecord->id) // Kendisi hariç ->exists(); if($duplicateCheck) { // Duplicate bulundu - hata kaydet ve atla $errorRows[] = [ 'row' => $rowIndex + 1, 'error' => "Duplicate weld log entry: ISO '{$refactoringRow['iso_number']}' + Joint '{$refactoringRow['no_of_the_joint_as_per_as_built_survey']}' already exists", 'data' => $refactoringRow ]; $skippedRowNumbers[] = $rowIndex + 1; continue; // Sonraki satıra geç } } // Update işlemi $oldValues = []; foreach($refactoringRow as $column => $value) { // Önceki değerleri kaydet $oldValues[$column] = isset($existingRecord->$column) ? $existingRecord->$column : null; } db($tableName)->where($whereData)->update($refactoringRow); $update++; // Değişen alanlar için ColumnComment ekle foreach($refactoringRow as $column => $value) { // Sadece değişen kolonlar için ColumnComment oluştur if(isset($oldValues[$column]) && $oldValues[$column] != $value) { $columnCommentsToAdd[] = [ 'table_name' => $tableName, 'record_id' => $existingRecord->id, 'column_name' => $column, 'comment' => 'Updated via Excel batch', 'column_value' => $value, 'user_id' => u()->id, 'ip_address' => request()->ip(), 'created_at' => Carbon::now(), 'updated_at' => Carbon::now() ]; } } $updatedRowNumbers[] = $rowIndex + 1; } else { $skippedRowNumbers[] = $rowIndex + 1; } } else { // ID verilmiş ama kayıt bulunamadı - Insert işlemi için write yetkisi gerekli if($canWrite) { // weld_logs tablosu için insert öncesi duplicate kontrol if($tableName == "weld_logs" && isset($refactoringRow['iso_number']) && isset($refactoringRow['no_of_the_joint_as_per_as_built_survey'])) { $duplicateCheck = db($tableName) ->where('iso_number', $refactoringRow['iso_number']) ->where('no_of_the_joint_as_per_as_built_survey', $refactoringRow['no_of_the_joint_as_per_as_built_survey']) ->exists(); if($duplicateCheck) { // Duplicate bulundu - hata kaydet ve atla $errorRows[] = [ 'row' => $rowIndex + 1, 'error' => "Duplicate weld log entry: ISO '{$refactoringRow['iso_number']}' + Joint '{$refactoringRow['no_of_the_joint_as_per_as_built_survey']}' already exists", 'data' => $refactoringRow ]; $skippedRowNumbers[] = $rowIndex + 1; continue; // Sonraki satıra geç } } // Insert işlemi $newId = db($tableName)->insertGetId($refactoringRow); $ids[] = ['id' => $newId]; $insert++; // Yeni eklenen her alan için ColumnComment ekle foreach($refactoringRow as $column => $value) { if($value !== null && $value !== '' && !in_array($column, ['created_at', 'updated_at', 'deleted_at'])) { $columnCommentsToAdd[] = [ 'table_name' => $tableName, 'record_id' => $newId, 'column_name' => $column, 'comment' => 'Created via Excel batch', 'column_value' => $value, 'user_id' => u()->id, 'ip_address' => request()->ip(), 'created_at' => Carbon::now(), 'updated_at' => Carbon::now() ]; } } $insertedRowNumbers[] = $rowIndex + 1; } else { $skippedRowNumbers[] = $rowIndex + 1; } } } else { // ID yok veya geçersiz - Insert işlemi için write yetkisi gerekli if($canWrite && count($refactoringRow) != 0) { // weld_logs tablosu için insert öncesi duplicate kontrol if($tableName == "weld_logs" && isset($refactoringRow['iso_number']) && isset($refactoringRow['no_of_the_joint_as_per_as_built_survey'])) { $duplicateCheck = db($tableName) ->where('iso_number', $refactoringRow['iso_number']) ->where('no_of_the_joint_as_per_as_built_survey', $refactoringRow['no_of_the_joint_as_per_as_built_survey']) ->exists(); if($duplicateCheck) { // Duplicate bulundu - hata kaydet ve atla $errorRows[] = [ 'row' => $rowIndex + 1, 'error' => "Duplicate weld log entry: ISO '{$refactoringRow['iso_number']}' + Joint '{$refactoringRow['no_of_the_joint_as_per_as_built_survey']}' already exists", 'data' => $refactoringRow ]; $skippedRowNumbers[] = $rowIndex + 1; continue; // Sonraki satıra geç } } // Insert işlemi $newId = db($tableName)->insertGetId($refactoringRow); $ids[] = ['id' => $newId]; $insert++; // Yeni eklenen her alan için ColumnComment ekle foreach($refactoringRow as $column => $value) { if($value !== null && $value !== '' && !in_array($column, ['created_at', 'updated_at', 'deleted_at'])) { $columnCommentsToAdd[] = [ 'table_name' => $tableName, 'record_id' => $newId, 'column_name' => $column, 'comment' => 'Created via Excel batch', 'column_value' => $value, 'user_id' => u()->id, 'ip_address' => request()->ip(), 'created_at' => Carbon::now(), 'updated_at' => Carbon::now() ]; } } $insertedRowNumbers[] = $rowIndex + 1; } else { $skippedRowNumbers[] = $rowIndex + 1; } } } if(is_null($row['id'])) { $latestRecord = DB::table($tableName) ->latest('id') // id sütunu üzerinden son eklenen ->first(); $row['id'] = $latestRecord->id; } if (!in_array($row['id'], array_column($ids, 'id'))) { $ids[] = ['id' => $row['id']]; } $storedData++; } } $say++; if (!empty($columnCommentsToAdd)) { ColumnComment::insert($columnCommentsToAdd); $columnCommentsToAdd = []; // Diziyi temizle } // Bellek verimli çıkış - etkilenen satır sayılarını toplam olarak döndür, detaylar için limit kullan if($say % $commitSize == 0 && $say > 0) { if (!empty($columnCommentsToAdd)) { ColumnComment::insert($columnCommentsToAdd); $columnCommentsToAdd = []; // Diziyi temizle } DB::commit(); DB::beginTransaction(); } } catch (\Throwable $rowError) { // Her satır için hata yakalama $errorRows[] = [ 'row' => $rowIndex + 1, // Excel satır numarası (1-based) 'error' => $rowError->getMessage(), 'data' => $refactoringRow ]; continue; // Sonraki satıra geç } // Bellek kullanımını azaltmak için geçici değişkenleri temizle $refactoringRow = []; } // Kalan yorumları ekle if (!empty($columnCommentsToAdd)) { ColumnComment::insert($columnCommentsToAdd); $columnCommentsToAdd = []; // Diziyi temizle } DB::commit(); } catch (\Throwable $th) { DB::rollback(); $error = $th->getMessage(); } // ============================================================ // Tüm trigger'ları TEK BİR JOB ile kuyruğa gönder // Response'u yavaşlatmamak için sadece 1 dispatch çağrısı yapılır // ============================================================ $runTrigger = true; if(!empty($ids) && $runTrigger) { try { $requestData = request()->except(['data', 'columns']); // De-duplicate IDs to avoid redundant job dispatching for the same record $uniqueIds = []; $seenIds = []; foreach ($ids as $idData) { $id = $idData['id'] ?? null; if ($id && !isset($seenIds[$id])) { $uniqueIds[] = $idData; $seenIds[$id] = true; } } // Chunk bazında dispatch: 50'lik gruplar halinde job oluştur (N job yerine N/50 job) $chunkSize = 50; $chunks = array_chunk($uniqueIds, $chunkSize); $changedColumns = $columns ?? []; // Excel'den gelen sütunlar = değişen alanlar foreach ($chunks as $chunk) { ExecuteBatchExcelTriggersJob::dispatch($tableName, $chunk, $requestData, $changedColumns); } $triggerOutput .= count($uniqueIds) . " kayıt için " . count($chunks) . " trigger job kuyruğa eklendi (chunk: {$chunkSize})
"; } catch (\Throwable $th) { \Log::error('Batch Excel trigger dispatch error: ' . $th->getMessage(), [ 'table' => $tableName, ]); $triggerOutput .= "Trigger error: " . $th->getMessage() . "
"; } } $response = [ 'storedData' => $storedData, 'updateOrInsert' => $updateOrInsert, 'update' => $update, 'insert' => $insert, 'delete' => $delete, 'error' => $error, 'triggerInfo' => $triggerOutput, 'ids' => count($ids) > 100 ? array_slice($ids, 0, 100) : $ids, // ID listesini sınırla 'runTrigger' => $runTrigger, 'errorRows' => array_slice($errorRows, 0, $rowDetailsLimit), 'totalErrors' => count($errorRows), 'insertedRowNumbers' => array_slice($insertedRowNumbers, 0, $rowDetailsLimit), 'updatedRowNumbers' => array_slice($updatedRowNumbers, 0, $rowDetailsLimit), 'deletedRowNumbers' => array_slice($deletedRowNumbers, 0, $rowDetailsLimit), 'skippedRowNumbers' => array_slice($skippedRowNumbers, 0, $rowDetailsLimit), 'insertedRowCount' => count($insertedRowNumbers), 'updatedRowCount' => count($updatedRowNumbers), 'deletedRowCount' => count($deletedRowNumbers), 'skippedRowCount' => count($skippedRowNumbers), 'rowDetailsTruncated' => ( count($insertedRowNumbers) > $rowDetailsLimit || count($updatedRowNumbers) > $rowDetailsLimit || count($deletedRowNumbers) > $rowDetailsLimit || count($skippedRowNumbers) > $rowDetailsLimit || count($errorRows) > $rowDetailsLimit ), 'numericColumns' => $numericColumns, // Debug: Tespit edilen numeric sütunlar 'tableName' => $tableName // Debug: İşlenen tablo adı ]; echo json_encode_tr($response); ?>