ikinci temizlik tamamlandı

This commit is contained in:
Ümit Tunç
2026-04-28 21:15:09 +03:00
parent f80443aec0
commit 37e7296527
8313 changed files with 2400677 additions and 0 deletions
@@ -0,0 +1,258 @@
<?php
/**
* @api-readonly
* Executes report builder SQL queries
*/
try {
// İşlem başlangıç zamanını kaydet
$startTime = microtime(true);
Log::info("Report Builder SQL başlatıldı - ".date('Y-m-d H:i:s'));
$sqlCodeMaster = post("sqlCodeMaster");
$sqlCodeDetail = post("sqlCodeDetail");
$documentId = post("documentId");
$documentInfo = document_template($documentId);
$temperatures = j(setting("temperatures"));
// Mode kontrolü: 'live', 'cache_only'
$mode = post("mode");
if (!$mode) {
$mode = post("fast") == "ok" ? "cache_only" : "live"; // Geriye dönük uyumluluk
}
$cacheMinutes = 60; // Cache süresi (dakika cinsinden)
// Full Response Cache Key
// Bu key, tüm işlem sonucunu (master, detail, columns, placeholders) saklar.
$fullCacheKey = 'report_full_response_' . md5($documentId . $sqlCodeMaster . $sqlCodeDetail);
if ($mode == 'cache_only') {
Log::info("Cache Only modu aktif. Full cache kontrol ediliyor: $fullCacheKey");
$cachedResponse = Cache::get($fullCacheKey);
if ($cachedResponse !== null) {
Log::info("Full cache bulundu, direkt döndürülüyor.");
echo json_encode_tr($cachedResponse);
exit;
} else {
Log::info("Full cache bulunamadı. Boş yanıt döndürülüyor (Hesaplama yapılmayacak).");
// Cache yoksa, kullanıcıya boş ama geçerli bir yapı dönüyoruz ki hata almasın
// Kullanıcı "Run SQL" butonuna basarak veriyi oluşturabilir.
echo json_encode_tr([
'success' => true,
'resultMaster' => [],
'resultDetail' => [],
'columnsMaster' => [],
'columnsDetail' => [],
'message' => 'Cached data not found. Please click "RUN SQL" to generate report.',
'from_cache' => false
]);
exit;
}
}
// SQL sorguları için gelişmiş loglama fonksiyonu
function logSqlQuery($logPrefix, $sqlCode, $logLevel = 'debug') {
// Yeni satır karakterlerini boşluk ile değiştir
$cleanSql = str_replace(["\r", "\n", "\t"], [" ", " ", " "], $sqlCode);
// Çoklu boşlukları tek boşluğa çevir
$cleanSql = preg_replace('/\s+/', ' ', $cleanSql);
// Log mesajı uzunluk limiti
$maxLogLength = 1000;
if (strlen($cleanSql) <= $maxLogLength) {
// Sorgu kısaysa tek parça olarak logla
Log::$logLevel("{$logPrefix}: {$cleanSql}");
} else {
// Uzun sorguları parçalara bölerek logla
Log::$logLevel("{$logPrefix} (uzun sorgu - toplam uzunluk: " . strlen($cleanSql) . " karakter)");
$chunks = str_split($cleanSql, $maxLogLength);
foreach ($chunks as $index => $chunk) {
Log::$logLevel("{$logPrefix} [Parça " . ($index + 1) . "/" . count($chunks) . "]: {$chunk}");
}
}
}
// Giriş parametrelerini logla
Log::info("Report Builder SQL parametreleri:", [
'document_id' => $documentId,
'sql_master_length' => strlen($sqlCodeMaster),
'sql_detail_length' => strlen($sqlCodeDetail),
'mode' => $mode
]);
// Maksimum sorgu çalışma süresi (saniye)
$queryTimeout = 300;
// Master Query Çalıştırma
if ($sqlCodeMaster && stripos(trim($sqlCodeMaster), 'SELECT') === 0) {
$masterQueryStart = microtime(true);
Log::info("Master sorgu başlatıldı");
logSqlQuery("Master sorgu", $sqlCodeMaster, "debug");
// Master query için de ayrı bir cache mekanizması (DB seviyesinde) kullanabiliriz
// Ancak full response cache zaten en üstte var. Buradaki cache sadece live modda
// tekrar eden sorguları hızlandırmak için kalabilir.
$masterCacheKey = 'report_sql_master_' . md5($sqlCodeMaster);
$resultMaster = Cache::get($masterCacheKey);
if ($resultMaster === null) {
try {
$resultMaster = DB::select($sqlCodeMaster);
Cache::put($masterCacheKey, $resultMaster, now()->addMinutes($cacheMinutes));
$masterQueryDuration = microtime(true) - $masterQueryStart;
Log::info("Master sorgu tamamlandı", [
'duration' => round($masterQueryDuration, 2) . " saniye",
'row_count' => count($resultMaster)
]);
} catch (\Exception $queryEx) {
Log::error("Master sorgu hatası: " . $queryEx->getMessage());
throw $queryEx;
}
} else {
Log::info("Master sorgu cache'den getirildi");
}
} else {
$resultMaster = [];
}
// Detail Query Çalıştırma
if ($sqlCodeDetail != "")
{
if (!empty($resultMaster)) {
$detailQueryStart = microtime(true);
// İlk sonucu al
$masterData = (array)$resultMaster[0];
// Regex ile SQL'deki bind parametrelerini yakala
preg_match_all('/:\w+/', $sqlCodeDetail, $matches);
$params = [];
// Parametreleri dolaş ve eşleştir
foreach ($matches[0] as $param) {
$paramName = ltrim($param, ':');
if (array_key_exists($paramName, $masterData)) {
$params[$paramName] = $masterData[$paramName];
} else {
throw new Exception("Master sorgusunda {$paramName} bulunamadı.");
}
}
$detailCacheKey = 'report_sql_detail_' . md5($sqlCodeDetail . json_encode($params));
$resultDetail = Cache::get($detailCacheKey);
if ($resultDetail === null) {
try {
$resultDetail = DB::select($sqlCodeDetail, $params);
Cache::put($detailCacheKey, $resultDetail, now()->addMinutes($cacheMinutes));
} catch (\Exception $queryEx) {
Log::error("Detail sorgu hatası: " . $queryEx->getMessage());
throw $queryEx;
}
}
} else {
$resultDetail = [];
}
} else {
$resultDetail = [];
}
function extractFormattedColumnNames($result) {
return !empty($result) ? array_map(function($column) {
return '{' . $column . '}';
}, array_keys(get_object_vars($result[0]))) : [];
}
// Extract column names for both master and detail results
$columnsMaster = extractFormattedColumnNames($resultMaster);
$columnsDetail = extractFormattedColumnNames($resultDetail);
$data = [];
$data['success'] = true;
$data['resultMaster'] = $resultMaster;
try {
$workPermitReplacerStart = microtime(true);
$workPermitReplacer = workPermitReplacerExcel2(null, !empty($resultMaster) ? $resultMaster[0] : null, $documentInfo, "");
if ($workPermitReplacer === null) {
$workPermitReplacer = [];
}
// Ek olarak, her satır için placeholder'ları ayrı ayrı hesaplayalım
$masterRowPlaceholders = [];
if (!empty($resultMaster)) {
foreach ($resultMaster as $rowIndex => $rowData) {
try {
$rowPlaceholders = workPermitReplacerExcel2(null, $rowData, $documentInfo, "");
if ($rowPlaceholders === null) $rowPlaceholders = [];
$masterRowPlaceholders[$rowIndex] = $rowPlaceholders;
} catch (\Throwable $rowEx) {
$masterRowPlaceholders[$rowIndex] = [];
}
}
}
$data['masterRowPlaceholders'] = $masterRowPlaceholders;
} catch (\Throwable $th) {
$workPermitReplacer = [];
$data['message'] = $th->getMessage();
echo json_encode_tr($data);
exit;
}
$data['resultDetail'] = $resultDetail;
if (!is_array($columnsMaster)) $columnsMaster = [];
if (!is_array($workPermitReplacer)) $workPermitReplacer = [];
$data['columnsMaster'] = array_merge($columnsMaster, $workPermitReplacer);
// Sıcaklık placeholder'larını ekle
if (!empty($resultMaster) && array_key_exists('welding_date', get_object_vars($resultMaster[0])) && array_key_exists('type_of_joint', get_object_vars($resultMaster[0]))) {
$customPlaceholders = [];
$customPlaceholders[] = '{temp_data_ambient}';
$customPlaceholders[] = '{temp_data_material}';
if (!is_array($data['columnsMaster'])) $data['columnsMaster'] = [];
$data['columnsMaster'] = array_merge($data['columnsMaster'], $customPlaceholders);
}
$data['columnsDetail'] = $columnsDetail;
// Detail kolonları için de sıcaklık placeholder'larını ekle
if (!empty($resultDetail)) {
$customPlaceholders = [];
$customPlaceholders[] = '{temp_data_ambient}';
$customPlaceholders[] = '{temp_data_material}';
$customPlaceholders[] = '{row_index}';
if (!is_array($data['columnsDetail'])) $data['columnsDetail'] = [];
$data['columnsDetail'] = array_merge($data['columnsDetail'], $customPlaceholders);
}
// FULL RESPONSE CACHE KAYDETME
// Tüm işlem bittikten sonra sonucu cache'e atıyoruz.
Cache::put($fullCacheKey, $data, now()->addMinutes($cacheMinutes));
Log::info("Full response cache'e yazıldı: $fullCacheKey");
$endTime = microtime(true);
Log::info("Report Builder SQL tamamlandı", [
'total_duration' => round($endTime - $startTime, 2) . " saniye"
]);
echo json_encode_tr($data);
} catch (Exception $e) {
$data = [];
$data['success'] = false;
$data['message'] = $e->getMessage();
Log::error("Report Builder SQL Hatası: " . $e->getMessage());
echo json_encode_tr($data);
}
?>