Files
citrus-cms/resources/views/admin-ajax/batch-excel-save.blade.php
T
2026-04-28 21:15:09 +03:00

1237 lines
65 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;
use App\Models\ColumnComment;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Schema;
use App\Jobs\ExecuteBatchExcelTriggersJob;
set_time_limit(-1);
ini_set('upload_max_filesize', '2G'); // Maksimum dosya boyutu arttırıldı
ini_set('post_max_size', '2G'); // Maksimum POST verisi arttırıldı
ini_set('memory_limit', '8G'); // Bellek limiti arttırıldı
ini_set('max_execution_time', 0); // Sınırsız süre
$dateColumns = [
'planned_test',
];
// Request'ten verileri al
$tableName = request()->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})<br>";
} catch (\Throwable $th) {
\Log::error('Batch Excel trigger dispatch error: ' . $th->getMessage(), [
'table' => $tableName,
]);
$triggerOutput .= "Trigger error: " . $th->getMessage() . "<br>";
}
}
$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);
?>