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);
?>