964 lines
46 KiB
PHP
964 lines
46 KiB
PHP
<?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;
|
||
}
|
||
|
||
?>
|
||
|