Files
citrus-cms/app/Services/RegisterCreator/DocumentProcessors/DynamicMappingProcessor.php
T
2026-04-28 21:14:25 +03:00

234 lines
7.9 KiB
PHP

<?php
namespace App\Services\RegisterCreator\DocumentProcessors;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\DB;
class DynamicMappingProcessor extends AbstractDocumentProcessor
{
public function process(
array $weldLogData,
array $document,
Worksheet $sheet,
int &$currentRow,
array $settings
): int {
$this->initialize($weldLogData, $document, $sheet, $currentRow, $settings);
$this->log("Processing dynamic mapped document: {$document['title2']}");
// Check if this document has SQL query configuration
if (empty($document['sql_query'])) {
$this->log("No SQL query found for dynamic document", 'warning');
return $currentRow;
}
return $this->processSqlBasedMapping($currentRow);
}
private function processSqlBasedMapping(int &$currentRow): int
{
try {
// Execute SQL query with placeholder replacement
$results = $this->executeSqlQuery();
if (empty($results)) {
$this->log("SQL query returned no results", 'warning');
return $currentRow;
}
$this->log("Found " . count($results) . " records from SQL query");
// Process each result
foreach ($results as $result) {
try {
$identifier = $result['identifier'];
$recordData = $result['data'];
$documentDate = $result['document_date'];
// Generate row title using pattern
$rowTitle = $this->generateRowTitle($recordData);
// Generate file search pattern
$searchPattern = $this->generateFileSearchPattern($recordData);
$fullPath = "storage/documents/{$this->document['path']}/{$searchPattern}";
// Search for files
$files = $this->searchFiles($fullPath);
if (empty($files)) {
$this->log("No files found for: {$identifier} (pattern: {$searchPattern})", 'warning');
continue;
}
$this->log("✓ Found " . count($files) . " files for: {$identifier}");
// Update document titles
$this->document['title2'] = $identifier;
$this->document['title4'] = $rowTitle;
// Add row to Excel
$newRow = $this->addRowToExcel(
$files,
$identifier,
$documentDate
);
if ($newRow > $currentRow) {
$currentRow = $newRow;
}
$this->log("✓ Processed: {$identifier} (from SQL query)");
} catch (\Throwable $th) {
$this->log("Error processing SQL result: {$th->getMessage()}", 'error');
Log::error("Dynamic mapping result processing error", [
'identifier' => $result['identifier'] ?? 'unknown',
'error' => $th->getMessage(),
'trace' => $th->getTraceAsString()
]);
continue;
}
}
return $currentRow;
} catch (\Throwable $th) {
$this->log("SQL query execution error: {$th->getMessage()}", 'error');
Log::error("Dynamic mapping SQL execution error", [
'sql_query' => $this->document['sql_query'] ?? 'N/A',
'error' => $th->getMessage(),
'trace' => $th->getTraceAsString()
]);
throw $th;
}
}
/**
* Execute SQL query with placeholder replacement
*/
private function executeSqlQuery(): array
{
$sqlQuery = $this->document['sql_query'] ?? '';
if (empty($sqlQuery)) {
throw new \Exception("No SQL query defined for dynamic document");
}
// Replace placeholders
$executedQuery = $this->replacePlaceholders($sqlQuery);
Log::info("Executing dynamic SQL query", [
'original_query' => $sqlQuery,
'executed_query' => $executedQuery
]);
try {
$startTime = microtime(true);
$results = DB::select($executedQuery);
$executionTime = round((microtime(true) - $startTime) * 1000, 2);
Log::info("Dynamic SQL query executed successfully", [
'record_count' => count($results),
'execution_time' => $executionTime . 'ms'
]);
return $this->formatResults($results);
} catch (\Throwable $th) {
Log::error("Dynamic SQL query execution failed", [
'query' => $executedQuery,
'error' => $th->getMessage()
]);
throw $th;
}
}
/**
* Replace :placeholder with actual values from register data
*/
private function replacePlaceholders(string $query): string
{
$result = $query;
// Find all :placeholder patterns
preg_match_all('/:(\w+)/', $query, $matches);
foreach ($matches[1] as $placeholder) {
$value = $this->weldLogData[$placeholder] ?? null;
if ($value !== null) {
// Escape value for SQL
$escapedValue = DB::getPdo()->quote($value);
$result = str_replace(":{$placeholder}", $escapedValue, $result);
} else {
Log::warning("Placeholder value not found", [
'placeholder' => $placeholder,
'available_fields' => array_keys($this->weldLogData)
]);
}
}
return $result;
}
/**
* Format SQL results to standard structure
*/
private function formatResults(array $results): array
{
$identifierField = $this->document['identifier_field'] ?? 'identifier';
$dateField = $this->document['date_field'] ?? 'document_date';
$formatted = [];
foreach ($results as $result) {
$recordArray = (array) $result;
$identifier = $recordArray[$identifierField] ?? $recordArray['id'] ?? 'unknown';
$date = $recordArray[$dateField] ?? '';
$formatted[] = [
'identifier' => $identifier,
'document_date' => $date,
'data' => $recordArray
];
}
return $formatted;
}
/**
* Generate file search pattern with field replacements
*/
private function generateFileSearchPattern(array $recordData): string
{
$pattern = $this->document['file_search_pattern'] ?? '*{identifier}*.pdf';
// Replace {field_name} with actual values
foreach ($recordData as $key => $value) {
$pattern = str_replace("{{$key}}", $value, $pattern);
}
return $pattern;
}
/**
* Generate row title with pattern
*/
private function generateRowTitle(array $recordData): string
{
$pattern = $this->document['title4_pattern'] ?? '{identifier}';
// Replace {field_name} with actual values
foreach ($recordData as $key => $value) {
$pattern = str_replace("{{$key}}", $value, $pattern);
}
return $pattern;
}
}