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

964 lines
46 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 App\Models\WelderTest;
use Barryvdh\DomPDF\Facade\Pdf;
use Carbon\Carbon;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
set_time_limit(-1);
ini_set('max_execution_time', -1);
ini_set('memory_limit', '2G'); // Bellek sınırını artır
setlocale(LC_ALL, 'ru_RU.utf8');
App::setLocale("ru");
try {
$startTime = microtime(true);
Log::debug('🚦 [START] PDF generation process', ['timestamp' => now()->format('Y-m-d H:i:s')]);
logProcessInfo('PDF generation process started', [
'request_data' => $_POST,
'user' => auth()?->user()?->name ?? 'System'
]);
$templateRowNo = post("templateRowNo");
$repeatedRows = post("repeatedRows");
$isMultipleMode = post("isMultipleMode") == "true";
$documentInfo = document_template(post("documentId"));
Log::debug('📄 [START] Template settings loaded', ['timestamp' => now()->format('Y-m-d H:i:s')]);
logProcessInfo('Template settings loaded', [
'template_row_no' => $templateRowNo,
'is_multiple_mode' => $isMultipleMode,
'document_info' => $documentInfo->kid
]);
$sqlCodeMaster = post("sqlCodeMaster");
$sqlCodeDetail = post("sqlCodeDetail");
$j = j($documentInfo->json);
$temperatures = j(setting("temperatures"));
if(postisset("rowData"))
{
$resultMaster[] = $_POST['rowData'];
Log::debug('🟢 [START] Using provided row data', ['timestamp' => now()->format('Y-m-d H:i:s')]);
logProcessInfo('Using provided row data');
Log::debug('🟢 [END] Using provided row data', ['timestamp' => now()->format('Y-m-d H:i:s')]);
} else {
Log::debug('🟢 [START] Executing master SQL query', ['timestamp' => now()->format('Y-m-d H:i:s')]);
logProcessInfo('Executing master SQL query');
$resultMaster = ($sqlCodeMaster && stripos(trim($sqlCodeMaster), 'SELECT') === 0)
? DB::select($sqlCodeMaster)
: [];
logProcessInfo('Master SQL query completed', [
'rows_count' => count($resultMaster)
]);
Log::debug('🟢 [END] Executing master SQL query', ['timestamp' => now()->format('Y-m-d H:i:s')]);
}
// Master verisindeki tarih alanlarını formatla
foreach($resultMaster as &$master) {
$master = formatDateColumns($master);
}
// Batch işleme için veriyi böl
$batchSize = 100; // Her batch'te 100 satır işle (performans için artırıldı)
$totalCount = count($resultMaster);
$processedCount = 0;
logProcessInfo('Starting batch processing', [
'total_records' => $totalCount,
'batch_size' => $batchSize,
'estimated_batches' => ceil($totalCount / $batchSize)
]);
for ($batchIndex = 0; $batchIndex < ceil($totalCount / $batchSize); $batchIndex++) {
$batchStart = $batchIndex * $batchSize;
$batchEnd = min($batchStart + $batchSize, $totalCount);
$batchData = array_slice($resultMaster, $batchStart, $batchSize, true);
// logProcessInfo('Processing batch', [
// 'batch_index' => $batchIndex + 1,
// 'batch_start' => $batchStart,
// 'batch_end' => $batchEnd,
// 'batch_count' => count($batchData),
// 'memory_before_batch' => round(memory_get_usage() / 1024 / 1024, 2) . ' MB'
// ]);
foreach($batchData AS $masterIndex => $master) {
$processingStart = microtime(true);
$processedCount++;
// Progress hesapla
$progressPercent = round(($processedCount / $totalCount) * 100, 2);
//Log::debug('🔄 [START] Processing master row', ['index' => $masterIndex, 'timestamp' => now()->format('Y-m-d H:i:s')]);
/*
logProcessInfo('Processing master row', [
'index' => $masterIndex,
'processed_count' => $processedCount,
'total_masters' => $totalCount,
'progress_percent' => $progressPercent,
'batch_index' => $batchIndex + 1,
'memory_current' => round(memory_get_usage() / 1024 / 1024, 2) . ' MB'
]);
*/
// Her 500 kayıtta bir progress göster (performans için artırıldı)
if ($processedCount % 500 == 0 || $processedCount == 1) {
echo "Progress: {$processedCount}/{$totalCount} ({$progressPercent}%)\n";
flush(); // Output buffer'ı temizle
}
try {
// Load your Excel template file
// Log::debug('📥 [START] Load Excel template', ['master_index' => $masterIndex, 'timestamp' => now()->format('Y-m-d H:i:s')]);
$templatePath = 'storage/documents/' . $documentInfo->files;
if (!file_exists($templatePath)) {
throw new Exception("Template file not found: {$templatePath}");
}
$spreadsheet = IOFactory::load($templatePath);
// logProcessInfo('Excel template loaded successfully', [
// 'master_index' => $masterIndex,
// 'template_path' => $templatePath,
// 'memory_after_load' => round(memory_get_usage() / 1024 / 1024, 2) . ' MB'
// ]);
// Log::debug('📥 [END] Load Excel template', ['master_index' => $masterIndex, 'timestamp' => now()->format('Y-m-d H:i:s')]);
// Spreadsheet türünü kontrol et
// echo "Yüklenen Excel türü: " . get_class($spreadsheet) . "\n";
$sheet = $spreadsheet->getActiveSheet();
$fileName = post("fileNameTemplate");
$fileName = replacePlaceholdersFileName($fileName, $master);
// Dosya adında da converter-map çevirisini uygula
$fileName = converterMapStringReplacer($fileName);
// İlk sonucu al (birden fazla kayıt varsa foreach kullanabilirsiniz)
$masterData = is_array($master) ? $master : (array)$master;
// Başlangıçta boş bir replacements dizisi tanımla
$replacements = [];
try {
// logProcessInfo('Starting workPermitReplacerExcel2 function call', [
// 'function' => 'workPermitReplacerExcel2',
// 'spreadsheet_type' => get_class($spreadsheet),
// 'document_id' => $documentInfo->kid,
// 'master_data_keys' => array_keys((array)$master),
// 'replacer_type' => 'replacer',
// 'memory_before' => round(memory_get_usage() / 1024 / 1024, 2) . ' MB'
// ]);
$result = workPermitReplacerExcel2($spreadsheet, $master, $documentInfo, "replacer");
// logProcessInfo('workPermitReplacerExcel2 function completed', [
// 'result_type' => is_null($result) ? 'NULL' : (is_object($result) ? get_class($result) : gettype($result)),
// 'is_valid_spreadsheet' => ($result !== null && $result instanceof PhpOffice\PhpSpreadsheet\Spreadsheet),
// 'memory_after' => round(memory_get_usage() / 1024 / 1024, 2) . ' MB'
// ]);
// Eğer fonksiyon null döndürmüşse, orijinal spreadsheet'i kullan
if ($result !== null && $result instanceof PhpOffice\PhpSpreadsheet\Spreadsheet) {
// logProcessInfo('Using replacement result spreadsheet', [
// 'action' => 'spreadsheet_replaced',
// 'new_spreadsheet_type' => get_class($result)
// ]);
$spreadsheet = $result;
} else {
// logProcessInfo('Using original spreadsheet - replacement failed or returned invalid result', [
// 'action' => 'keep_original_spreadsheet',
// 'result_received' => is_null($result) ? 'NULL' : gettype($result),
// 'warning' => 'workPermitReplacerExcel2 did not return valid spreadsheet'
// ], 'warning');
}
// Converter-map replacement'i uygula
try {
// logProcessInfo('Starting converterMapReplacer function call', [
// 'function' => 'converterMapReplacer',
// 'spreadsheet_type' => get_class($spreadsheet),
// 'replacer_type' => 'replacer',
// 'memory_before' => round(memory_get_usage() / 1024 / 1024, 2) . ' MB'
// ]);
$converterResult = converterMapReplacer($spreadsheet, "replacer");
// logProcessInfo('converterMapReplacer function completed', [
// 'result_type' => is_null($converterResult) ? 'NULL' : (is_object($converterResult) ? get_class($converterResult) : gettype($converterResult)),
// 'is_valid_spreadsheet' => ($converterResult !== null && $converterResult instanceof PhpOffice\PhpSpreadsheet\Spreadsheet),
// 'memory_after' => round(memory_get_usage() / 1024 / 1024, 2) . ' MB'
// ]);
// Eğer fonksiyon geçerli bir spreadsheet döndürmüşse, onu kullan
if ($converterResult !== null && $converterResult instanceof PhpOffice\PhpSpreadsheet\Spreadsheet) {
// logProcessInfo('Using converter map replacement result spreadsheet', [
// 'action' => 'spreadsheet_replaced_with_converter_map',
// 'new_spreadsheet_type' => get_class($converterResult)
// ]);
$spreadsheet = $converterResult;
} else {
// logProcessInfo('Using original spreadsheet - converter map replacement failed or returned invalid result', [
// 'action' => 'keep_original_spreadsheet_after_converter_map',
// 'result_received' => is_null($converterResult) ? 'NULL' : gettype($converterResult),
// 'warning' => 'converterMapReplacer did not return valid spreadsheet'
// ], 'warning');
}
} catch (\Throwable $th) {
// logProcessInfo('Critical error in converterMapReplacer', [
// 'error_type' => get_class($th),
// 'error_message' => $th->getMessage(),
// 'error_file' => $th->getFile(),
// 'error_line' => $th->getLine(),
// 'error_code' => $th->getCode(),
// 'function_context' => 'converterMapReplacer',
// 'document_id' => $documentInfo->kid ?? 'unknown',
// 'master_index' => $masterIndex ?? 'unknown',
// 'memory_usage' => round(memory_get_usage() / 1024 / 1024, 2) . ' MB',
// 'stack_trace' => $th->getTraceAsString()
// ], 'error');
}
} catch (\Throwable $th) {
// logProcessInfo('Critical error in workPermitReplacerExcel2', [
// 'error_type' => get_class($th),
// 'error_message' => $th->getMessage(),
// 'error_file' => $th->getFile(),
// 'error_line' => $th->getLine(),
// 'error_code' => $th->getCode(),
// 'function_context' => 'workPermitReplacerExcel2',
// 'document_id' => $documentInfo->kid ?? 'unknown',
// 'master_index' => $masterIndex ?? 'unknown',
// 'memory_usage' => round(memory_get_usage() / 1024 / 1024, 2) . ' MB',
// 'stack_trace' => $th->getTraceAsString()
// ], 'error');
}
// Spreadsheet türünü tekrar kontrol et
// echo "İşlemden sonraki Excel türü: " . (is_object($spreadsheet) ? get_class($spreadsheet) : gettype($spreadsheet)) . "\n";
// Master verisinden placeholder değerleri oluştur
foreach($masterData AS $field => $value)
{
$replacements['{'.$field.'}'] = $value;
}
// Sıcaklık değerlerini hesapla ve placeholderlara ekle
if (isset($masterData['welding_date']) && isset($masterData['type_of_joint'])) {
$tempData = $temperatures[date("z", strtotime($masterData['welding_date']))];
if ($masterData['type_of_joint'] == "S") {
$thisTempData = $tempData['shop_ambient'];
$thisTempData2 = $tempData['temp_material_shop'];
} else {
$thisTempData = $tempData['field_ambient'];
$thisTempData2 = $tempData['temp_material_field'];
}
// Sıcaklık placeholder'larını ekle
$replacements['{temp_data_ambient}'] = "{$masterData['welding_date']} \n $thisTempData °С";
$replacements['{temp_data_material}'] = "{$masterData['welding_date']} \n $thisTempData2 °С";
}
foreach ($sheet->getRowIterator() as $row) {
foreach ($row->getCellIterator() as $cell) {
$cellValue = $cell->getValue();
if (is_string($cellValue)) {
foreach ($replacements as $placeholder => $replacement) {
if (strpos($cellValue, $placeholder) !== false) {
$newValue = str_replace($placeholder, $replacement, $cellValue);
$cell->setValue($newValue);
}
}
// Hücre değerinde converter-map çevirisini de uygula
$originalCellValue = $cell->getValue();
if (is_string($originalCellValue)) {
$convertedValue = converterMapStringReplacer($originalCellValue);
if ($convertedValue !== $originalCellValue) {
$cell->setValue($convertedValue);
}
}
}
}
}
// Regex ile SQL'deki bind parametrelerini yakala (örn. :iso_number, :joint_no)
preg_match_all('/:\w+/', $sqlCodeDetail, $matches);
$params = [];
// Parametreleri dolaş ve masterData'daki karşılık gelen anahtarlarla eşleştir
foreach ($matches[0] as $param) {
// ":" işaretini kaldır (örneğin, :iso_number => iso_number)
$paramName = ltrim($param, ':');
// Master verisinden bu parametreye karşılık gelen değeri al
if (array_key_exists($paramName, $masterData)) {
$params[$paramName] = $masterData[$paramName];
} else {
throw new Exception("Master sorgusunda {$paramName} bulunamadı.");
}
}
// Detail sorgusunu parametrelerle çalıştır
$resultDetail = [];
if (!empty($sqlCodeDetail)) {
// logProcessInfo('Executing detail SQL query', [
// 'master_index' => $masterIndex,
// 'sql_params' => $params,
// 'memory_before_query' => round(memory_get_usage() / 1024 / 1024, 2) . ' MB'
// ]);
try {
$resultDetail = DB::select($sqlCodeDetail, $params);
// logProcessInfo('Detail SQL query completed', [
// 'master_index' => $masterIndex,
// 'detail_count' => count($resultDetail),
// 'memory_after_query' => round(memory_get_usage() / 1024 / 1024, 2) . ' MB'
// ]);
// Detail verisindeki tarih alanlarını formatla
foreach($resultDetail as &$detail) {
$detail = formatDateColumns($detail);
}
} catch (\Exception $e) {
// logProcessInfo('Error in detail SQL query', [
// 'master_index' => $masterIndex,
// 'error' => $e->getMessage(),
// 'sql_params' => $params
// ], 'error');
throw $e;
}
} else {
// logProcessInfo('No detail SQL query provided', [
// 'master_index' => $masterIndex
// ]);
}
if(!empty($resultDetail)) {
if($isMultipleMode && !empty($repeatedRows)) {
// Multiple repeated rows işleme
$repeatedRowsArray = json_decode($repeatedRows, true);
// logProcessInfo('Processing multiple repeated rows', [
// 'repeated_rows_count' => count($repeatedRowsArray)
// ]);
// Detail verilerini section'lara göre grupla
$sectionedDetails = [];
foreach($resultDetail as $detail) {
// SQL sorgusundan gelen veriyi kontrol et ve dönüştür
$sectionValue = null;
if (is_object($detail)) {
$sectionValue = isset($detail->section) ? $detail->section : null;
} elseif (is_array($detail)) {
$sectionValue = isset($detail['section']) ? $detail['section'] : null;
}
$section = intval($sectionValue);
// logProcessInfo('Processing detail row section data', [
// 'raw_section' => $sectionValue,
// 'converted_section' => $section,
// 'detail_data' => json_encode($detail, JSON_PRETTY_PRINT)
// ]);
if (!in_array($section, [1, 2, 3])) {
// logProcessInfo('Invalid section value', [
// 'section' => $section,
// 'expected' => [1, 2, 3]
// ], 'error');
continue;
}
if (!isset($sectionedDetails[$section])) {
$sectionedDetails[$section] = [];
}
$sectionedDetails[$section][] = $detail;
}
// logProcessInfo('Grouped details by section', [
// 'sections_found' => array_keys($sectionedDetails),
// 'counts_per_section' => array_map('count', $sectionedDetails)
// ]);
// Her bir tekrarlanan satır için işlem yap
$totalAddedRows = 0; // Önceki section'larda eklenen toplam satır sayısı
foreach($repeatedRowsArray as $rowIndex => $rowNumber) {
$currentSection = $rowIndex + 1;
$originalStartRow = intval($rowNumber);
// Önceki section'larda eklenen satır sayısı kadar kaydır
$startRow = $originalStartRow + $totalAddedRows;
// logProcessInfo('Processing repeated row with offset', [
// 'row_index' => $rowIndex,
// 'current_section' => $currentSection,
// 'original_template_row' => $originalStartRow,
// 'adjusted_template_row' => $startRow,
// 'total_added_rows' => $totalAddedRows,
// 'has_section_data' => isset($sectionedDetails[$currentSection])
// ]);
// Template satırından hücre değerlerini al
$templateRowCells = [];
$templateFormulas = [];
try {
foreach ($sheet->getRowIterator($startRow)->current()->getCellIterator() as $cell) {
$templateRowCells[] = $cell->getValue();
if ($cell->isFormula()) {
$colIndex = $cell->getColumn();
$templateFormulas[$colIndex] = $cell->getValue();
}
}
} catch (\Exception $e) {
// logProcessInfo('Error reading template row', [
// 'original_row' => $originalStartRow,
// 'adjusted_row' => $startRow,
// 'error' => $e->getMessage()
// ], 'error');
continue;
}
// Birleştirilmiş hücreleri kaydet
$mergedCells = [];
foreach ($sheet->getMergeCells() as $mergeRange) {
list($startCell, $endCell) = explode(':', $mergeRange);
$startCoordinates = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::coordinateFromString($startCell);
$startRowNum = intval($startCoordinates[1]);
if ($startRowNum == $startRow) {
$mergedCells[] = [
'range' => $mergeRange,
'start' => $startCell,
'end' => $endCell
];
}
}
// Section verilerini işle
$sectionDetails = isset($sectionedDetails[$currentSection]) ? $sectionedDetails[$currentSection] : [];
$hasData = !empty($sectionDetails);
$addedRowsInCurrentSection = 0; // Bu section'da eklenen satır sayısı
// Her durumda en az bir satır ekle (veri varsa veya yoksa)
$newRowIndex = $startRow;
$sheet->insertNewRowBefore($newRowIndex + 1, 1);
$newRow = $sheet->getRowIterator($newRowIndex + 1)->current();
$addedRowsInCurrentSection++;
if ($hasData) {
// Section verisi varsa normal işleme devam et
foreach($sectionDetails as $index => $detail) {
if ($index > 0) {
// İlk satırdan sonraki satırlar için yeni satır ekle
$newRowIndex++;
$sheet->insertNewRowBefore($newRowIndex + 1, 1);
$newRow = $sheet->getRowIterator($newRowIndex + 1)->current();
$addedRowsInCurrentSection++;
}
// Detail verilerini hazırla
$detailData = (array)$detail;
$detailData['row_index'] = $index + 1;
// Yeni satıra değerleri yerleştir
$cellIndex = 0;
foreach ($newRow->getCellIterator() as $newCell) {
$newCellValue = $templateRowCells[$cellIndex];
$colLetter = $newCell->getColumn();
if (isset($templateFormulas[$colLetter])) {
$formula = $templateFormulas[$colLetter];
// Formüldeki tüm hücre referanslarını güncelle
// (1) Standart referanslar: A1, B2, C3 vb.
// (2) İşlem içindekiler: +A1, -B2, *C3 vb.
// (3) Fonksiyon içindekiler: SUM(A1:A10), AVERAGE(B1:B10) vb.
// (4) Türkçe formül içindekiler: BİRLEŞTİR(A1;" "), EĞER(A1>0;A2;A3) vb.
// Satır bazlı formül güncelleme fonksiyonu
$updateRowReferences = function($formula, $rowOffset) {
// Tüm olası hücre referanslarını bul ve güncelle
return preg_replace_callback(
'/([A-Z]+)(\d+)/',
function($matches) use ($rowOffset) {
$col = $matches[1];
$row = intval($matches[2]);
// Satır numarasını offset kadar artır
$row += $rowOffset;
return $col . $row;
},
$formula
);
};
// İndeks değerine göre satır numaralarını artıralım
// Burada her yeni eklenen satır için formülleri güncelleyeceğiz
$rowOffset = $index + 1; // İndekse göre satır numarasını artır
// Formülü güncelle
$updatedFormula = $updateRowReferences($formula, $rowOffset);
// Formülü hücreye uygula
$newCell->setValue($updatedFormula);
} else {
// Placeholder değişimlerini yap
foreach($detailData as $field => $value) {
$newCellValue = str_replace('{'.$field.'}', $value ?? '', $newCellValue);
}
// Kalan placeholder'ları temizle
$newCellValue = preg_replace('/\{[^}]+\}/', '', $newCellValue);
// Converter-map çevirisini uygula
$newCellValue = converterMapStringReplacer($newCellValue);
$newCell->setValue($newCellValue);
}
$cellIndex++;
}
// Birleştirilmiş hücreleri yeni satıra uygula
foreach ($mergedCells as $mergeInfo) {
$originalRange = $mergeInfo['range'];
list($startCell, $endCell) = explode(':', $originalRange);
$newStartCell = preg_replace('/\d+/', $newRowIndex + 1, $startCell);
$newEndCell = preg_replace('/\d+/', $newRowIndex + 1, $endCell);
$newRange = $newStartCell . ':' . $newEndCell;
try {
$sheet->mergeCells($newRange);
} catch (\Exception $e) {
// logProcessInfo('Merge cells error', [
// 'error' => $e->getMessage(),
// 'range' => $newRange
// ], 'error');
}
}
}
} else {
// Section verisi yoksa placeholder'ları temizle ve boş satır ekle
$cellIndex = 0;
foreach ($newRow->getCellIterator() as $newCell) {
$newCellValue = $templateRowCells[$cellIndex];
// Tüm placeholder'ları temizle
$newCellValue = preg_replace('/\{[^}]+\}/', '', $newCellValue);
// Converter-map çevirisini uygula
$newCellValue = converterMapStringReplacer($newCellValue);
$newCell->setValue($newCellValue);
$cellIndex++;
}
// Birleştirilmiş hücreleri yeni satıra uygula
foreach ($mergedCells as $mergeInfo) {
$originalRange = $mergeInfo['range'];
list($startCell, $endCell) = explode(':', $originalRange);
$newStartCell = preg_replace('/\d+/', $newRowIndex + 1, $startCell);
$newEndCell = preg_replace('/\d+/', $newRowIndex + 1, $endCell);
$newRange = $newStartCell . ':' . $newEndCell;
try {
$sheet->mergeCells($newRange);
} catch (\Exception $e) {
// logProcessInfo('Merge cells error', [
// 'error' => $e->getMessage(),
// 'range' => $newRange
// ], 'error');
}
}
}
// Template satırını sil
try {
$sheet->removeRow($startRow);
// logProcessInfo('Template row removed', [
// 'section' => $currentSection,
// 'original_row' => $originalStartRow,
// 'adjusted_row' => $startRow,
// 'added_rows' => $addedRowsInCurrentSection,
// 'had_data' => $hasData
// ]);
} catch (\Exception $e) {
// logProcessInfo('Error removing template row', [
// 'section' => $currentSection,
// 'row' => $startRow,
// 'error' => $e->getMessage()
// ], 'error');
}
// Toplam eklenen satır sayısını güncelle
$totalAddedRows += ($addedRowsInCurrentSection - 1); // Template satırı silindiği için 1 çıkar
// logProcessInfo('Section processing completed', [
// 'section' => $currentSection,
// 'added_rows_in_section' => $addedRowsInCurrentSection,
// 'total_added_rows' => $totalAddedRows
// ]);
}
} else {
// Mevcut single repeated row işleme kodu
$startRow = $templateRowNo;
$templateRowCells = [];
$templateFormulas = [];
// Iterate through the template row and save cell values and merge information
foreach ($sheet->getRowIterator($startRow)->current()->getCellIterator() as $cell) {
$templateRowCells[] = $cell->getValue();
// Formül varsa orijinal formülü de kaydedelim
if ($cell->isFormula()) {
$colIndex = $cell->getColumn();
$templateFormulas[$colIndex] = $cell->getValue();
}
}
// Loop through all the cells in the sheet and replace placeholders
foreach($resultDetail AS $index => $detailRowData) {
// Save the template row's cell values and merge information
$mergedCells = [];
// Save merged cell ranges in the template row
foreach ($sheet->getMergeCells() as $mergeRange) {
// Check if the merge range starts in the template row
if (preg_match('/^\D*'.$startRow.'$/', explode(':', $mergeRange)[0])) {
$mergedCells[] = $mergeRange;
}
}
// Insert a new row before the next one (clone the template row)
$sheet->insertNewRowBefore($startRow + 1, 1);
// Get the newly inserted row
$newRow = $sheet->getRowIterator($startRow + 1)->current();
// Copy template row's values to the new row
$cellIndex = 0; // To keep track of which cell we're on
foreach ($newRow->getCellIterator() as $newCell) {
// Set the template value to the new cell
$newCellValue = $templateRowCells[$cellIndex];
$colLetter = $newCell->getColumn();
// Eğer bu hücrede bir formül varsa
if (isset($templateFormulas[$colLetter])) {
$formula = $templateFormulas[$colLetter];
// Formüldeki tüm hücre referanslarını güncelle
// (1) Standart referanslar: A1, B2, C3 vb.
// (2) İşlem içindekiler: +A1, -B2, *C3 vb.
// (3) Fonksiyon içindekiler: SUM(A1:A10), AVERAGE(B1:B10) vb.
// (4) Türkçe formül içindekiler: BİRLEŞTİR(A1;" "), EĞER(A1>0;A2;A3) vb.
// Satır bazlı formül güncelleme fonksiyonu
$updateRowReferences = function($formula, $rowOffset) {
// Tüm olası hücre referanslarını bul ve güncelle
return preg_replace_callback(
'/([A-Z]+)(\d+)/',
function($matches) use ($rowOffset) {
$col = $matches[1];
$row = intval($matches[2]);
// Satır numarasını offset kadar artır
$row += $rowOffset;
return $col . $row;
},
$formula
);
};
// İndeks değerine göre satır numaralarını artıralım
// Burada her yeni eklenen satır için formülleri güncelleyeceğiz
$rowOffset = $index + 1; // İndekse göre satır numarasını artır
// Formülü güncelle
$updatedFormula = $updateRowReferences($formula, $rowOffset);
// Formülü hücreye uygula
$newCell->setValue($updatedFormula);
} else {
// Formül değilse, normal placeholder değişimini yap
// Detail için sıcaklık değerlerini hesapla
$detailData = (array) $detailRowData;
// logProcessInfo('index', [
// 'index' => $index,
// ]);
// Satır indeksi ekle - burada 1'den başlıyoruz çünkü kullanıcılar genelde 0'dan başlayan indeksleri değil 1'den başlayan satır numaralarını bekler
$detailData['row_index'] = $index + 1;
if (isset($detailData['welding_date']) && isset($detailData['type_of_joint'])) {
$tempData = $temperatures[date("z", strtotime($detailData['welding_date']))];
if ($detailData['type_of_joint'] == "S") {
$thisTempData = $tempData['shop_ambient'];
$thisTempData2 = $tempData['temp_material_shop'];
} else {
$thisTempData = $tempData['field_ambient'];
$thisTempData2 = $tempData['temp_material_field'];
}
// Sıcaklık placeholder'larını ekle
$detailData['temp_data_ambient'] = "{$detailData['welding_date']} \n $thisTempData °С";
$detailData['temp_data_material'] = "{$detailData['welding_date']} \n $thisTempData2 °С";
}
foreach($detailData AS $field => $value)
{
$newCellValue = str_replace('{'.$field.'}', $value, $newCellValue);
}
// Converter-map çevirisini uygula
$newCellValue = converterMapStringReplacer($newCellValue);
// Set the new value in the cell
$newCell->setValue($newCellValue);
}
$cellIndex++; // Move to the next cell
}
// Apply merged cells to the new row
foreach ($mergedCells as $mergeRange) {
// Adjust the merge range to the new row
$adjustedMergeRange = preg_replace_callback('/\d+/', function($matches) use ($startRow) {
return $matches[0] + 1; // Shift row numbers by 1 for the newly inserted row
}, $mergeRange);
// Apply the adjusted merge range to the new row
$sheet->mergeCells($adjustedMergeRange);
}
// Move to the next row for the next weld log entry
$startRow++;
}
// After inserting all new rows, remove the original template row
$sheet->removeRow(intval($templateRowNo));
}
}
$path = $documentInfo->kid; //"005_PTO/06_Прочность и плотность";
$fileName = str_replace("/", "-", $fileName);
$path = "storage/documents/$path/$fileName.xlsx";
if (!file_exists(dirname($path))) {
mkdir(dirname($path), 0777, true);
// logProcessInfo('Created directory structure', [
// 'path' => dirname($path)
// ]);
}
// Save the modified spreadsheet
try {
// Dosya yazılmadan önce debug çıktısı
// echo "Excel dosyası yazılmaya başlanıyor. Bellek kullanımı: " . (memory_get_usage(true) / 1024 / 1024) . " MB\n";
// Daha hafif yazıcı seçeneği kullanabiliriz
$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
// $writer->setPreCalculateFormulas(false); // Formülleri önceden hesaplama - performans artışı
// Yazma işlemi
$writer->save($path);
// echo "Excel dosyası yazıldı. Bellek kullanımı: " . (memory_get_usage(true) / 1024 / 1024) . " MB\n";
} catch (\Exception $e) {
// echo "Hata oluştu: " . $e->getMessage();
// dd($e); // Detaylı hata bilgisi
}
// Belleği temizle
// logProcessInfo('Cleaning up spreadsheet memory', [
// 'master_index' => $masterIndex,
// 'memory_before_cleanup' => round(memory_get_usage() / 1024 / 1024, 2) . ' MB'
// ]);
$spreadsheet->disconnectWorksheets();
unset($spreadsheet);
gc_collect_cycles();
// logProcessInfo('Memory cleanup completed', [
// 'master_index' => $masterIndex,
// 'memory_after_cleanup' => round(memory_get_usage() / 1024 / 1024, 2) . ' MB'
// ]);
$processingEnd = microtime(true);
// logProcessInfo('Excel file saved successfully', [
// 'master_index' => $masterIndex,
// 'file_path' => $path,
// 'processing_time' => round($processingEnd - $processingStart, 2) . ' seconds',
// 'memory_peak' => round(memory_get_peak_usage() / 1024 / 1024, 2) . ' MB'
// ]);
// Log::debug('🟦 [START] PDF Generation', ['master_index' => $masterIndex, 'timestamp' => now()->format('Y-m-d H:i:s')]);
try {
$pdfResult = xlsx_to_pdf($path, "storage/documents/{$documentInfo->kid}");
if ($pdfResult['success']) {
// PDF başarıyla oluşturuldu
// logProcessInfo('PDF generation completed', [
// 'master_index' => $masterIndex,
// 'pdf_path' => $pdfResult['output_file'],
// 'message' => $pdfResult['message'],
// 'memory_after_pdf' => round(memory_get_usage() / 1024 / 1024, 2) . ' MB'
// ]);
// Log::debug('🟦 [END] PDF Generation', [
// 'master_index' => $masterIndex,
// 'timestamp' => now()->format('Y-m-d H:i:s'),
// 'pdf_file' => $pdfResult['output_file']
// ]);
echo "✅ PDF başarıyla oluşturuldu: " . ($pdfResult['output_file']) . "\n";
// PDF dosya yolunu döndür (diğer işlemler için)
$pdfPath = $pdfResult['output_file'];
} else {
// PDF oluşturulamadı
// logProcessInfo('PDF generation failed', [
// 'master_index' => $masterIndex,
// 'excel_path' => $path,
// 'error' => $pdfResult['error'],
// 'memory_after_pdf' => round(memory_get_usage() / 1024 / 1024, 2) . ' MB'
// ], 'error');
// Log::debug('🟦 [ERROR] PDF Generation', [
// 'master_index' => $masterIndex,
// 'timestamp' => now()->format('Y-m-d H:i:s'),
// 'error' => $pdfResult['error']
// ]);
echo "❌ PDF oluşturulamadı: " . $pdfResult['error'] . "\n";
// Hata durumunda null döndür
$pdfPath = null;
}
} catch (\Exception $e) {
// logProcessInfo('Error in PDF generation', [
// 'master_index' => $masterIndex,
// 'excel_path' => $path,
// 'error' => $e->getMessage()
// ], 'error');
// Exception durumunda PDF path'i null yap
$pdfPath = null;
throw $e;
}
// PDF başarıyla oluşturulduysa ek işlemler yapılabilir
if ($pdfPath !== null) {
// PDF dosyası başarıyla oluşturuldu, gerekirse ek işlemler burada yapılabilir
// Örneğin: veritabanına kaydetme, email gönderme, vb.
// logProcessInfo('PDF post-processing started', [
// 'master_index' => $masterIndex,
// 'pdf_path' => $pdfPath,
// 'file_size' => file_exists($pdfPath) ? round(filesize($pdfPath) / 1024, 2) . ' KB' : 'N/A'
// ]);
}
} catch (\Exception $e) {
// logProcessInfo('Error in master row processing', [
// 'master_index' => $masterIndex,
// 'processed_count' => $processedCount,
// 'error' => $e->getMessage(),
// 'trace' => $e->getTraceAsString()
// ], 'error');
throw $e;
}
}
// Batch sonunda bellek temizleme
// logProcessInfo('Batch completed', [
// 'batch_index' => $batchIndex + 1,
// 'processed_count' => $processedCount,
// 'memory_after_batch' => round(memory_get_usage() / 1024 / 1024, 2) . ' MB'
// ]);
// Agresif bellek temizleme
gc_collect_cycles();
// Bellek kullanımını kontrol et
$memoryUsageMB = round(memory_get_usage() / 1024 / 1024, 2);
$memoryLimitMB = 1500; // 1.5GB limit
if ($memoryUsageMB > $memoryLimitMB) {
// logProcessInfo('High memory usage detected, forcing cleanup', [
// 'batch_index' => $batchIndex + 1,
// 'memory_usage' => $memoryUsageMB . ' MB',
// 'memory_limit' => $memoryLimitMB . ' MB'
// ], 'warning');
// Agresif temizleme
if (function_exists('opcache_reset')) {
opcache_reset();
}
gc_collect_cycles();
// logProcessInfo('Forced memory cleanup completed', [
// 'memory_after_cleanup' => round(memory_get_usage() / 1024 / 1024, 2) . ' MB'
// ]);
}
// Her 10 batch'te bir daha agresif temizleme
if (($batchIndex + 1) % 10 == 0) {
// logProcessInfo('Deep memory cleanup after 10 batches', [
// 'batch_index' => $batchIndex + 1,
// 'memory_before_cleanup' => round(memory_get_usage() / 1024 / 1024, 2) . ' MB'
// ]);
if (function_exists('opcache_reset')) {
opcache_reset();
}
// logProcessInfo('Deep memory cleanup completed', [
// 'memory_after_cleanup' => round(memory_get_usage() / 1024 / 1024, 2) . ' MB'
// ]);
}
}
$endTime = microtime(true);
// Log::debug('🏁 [END] Complete process', [
// 'timestamp' => now()->format('Y-m-d H:i:s'),
// 'total_time' => round($endTime - $startTime, 2) . ' seconds',
// 'memory_peak' => round(memory_get_peak_usage() / 1024 / 1024, 2) . ' MB'
// ]);
logProcessInfo('Complete process finished', [
'total_time' => round($endTime - $startTime, 2) . ' MB'
]);
} catch (\Exception $e) {
// logProcessInfo('Fatal error in PDF generation process', [
// 'error' => $e->getMessage(),
// 'trace' => $e->getTraceAsString()
// ], 'error');
throw $e;
}
?>