Files
citrus-cms/resources/views/admin-ajax/report-builder-sql.blade.php
2026-04-28 21:15:09 +03:00

258 lines
10 KiB
PHP
Raw Permalink 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
/**
* @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);
}
?>