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

230 lines
8.9 KiB
PHP

<?php
namespace App\Services\RegisterCreator\DocumentProcessors;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
use Illuminate\Support\Facades\Log;
class WpsNaksTechnologyProcessor extends AbstractDocumentProcessor
{
/**
* Search files using the same algorithm as pdf-db-naks-technology-sync
* This algorithm handles zero-prefix patterns and multiple search strategies
*/
private function searchFilesWithFallback(string $basePath, string $certificateNo): array
{
$files = [];
// Parse certificate number to extract short_number and cert_no parts
// Format examples: АЦСТ-20-01934, АЦСТ-161-00050
$certParts = explode('-', $certificateNo);
if (count($certParts) >= 2) {
$shortNumber = $certParts[0]; // e.g., АЦСТ
$certNumber = isset($certParts[1]) ? $certParts[1] : '';
// If there's a third part, combine with second
if (count($certParts) >= 3) {
$certNumber = $certParts[1]; // e.g., 20 or 161
$thirdPart = $certParts[2]; // e.g., 01934 or 00050
// Generate certificate patterns with different zero prefixes
$certPatterns = [$thirdPart];
// Clean leading zeros and generate additional search patterns
$trimmedCertNo = ltrim($thirdPart, '0');
if ($trimmedCertNo != $thirdPart && $trimmedCertNo != '') {
$certPatterns[] = $trimmedCertNo;
// Add versions with different numbers of leading zeros
for ($i = 1; $i <= 5; $i++) {
$certPatterns[] = str_pad($trimmedCertNo, $i, '0', STR_PAD_LEFT);
}
}
// Try each pattern until we find a match
foreach ($certPatterns as $certPattern) {
// Format: short_number-certNumber-certPattern
$searchData = "*{$shortNumber}-{$certNumber}-{$certPattern}*";
$searchData = str_replace("/", "*", $searchData);
$searchData = str_replace(" ", "*", $searchData);
$searchData = str_replace("\\", "*", $searchData);
$path = "{$basePath}/{$searchData}";
$searchPDF = glob($path);
if (!empty($searchPDF)) {
Log::debug("Found with pattern", [
'pattern' => $searchData,
'files' => count($searchPDF)
]);
return $searchPDF;
}
}
} else {
// Format with only 2 parts: АЦСТ-161
$certPatterns = [$certNumber];
$trimmedCertNo = ltrim($certNumber, '0');
if ($trimmedCertNo != $certNumber && $trimmedCertNo != '') {
$certPatterns[] = $trimmedCertNo;
for ($i = 1; $i <= 5; $i++) {
$certPatterns[] = str_pad($trimmedCertNo, $i, '0', STR_PAD_LEFT);
}
}
foreach ($certPatterns as $certPattern) {
$searchData = "*{$shortNumber}-{$certPattern}*";
$searchData = str_replace("/", "*", $searchData);
$searchData = str_replace(" ", "*", $searchData);
$searchData = str_replace("\\", "*", $searchData);
$path = "{$basePath}/{$searchData}";
$searchPDF = glob($path);
if (!empty($searchPDF)) {
Log::debug("Found with 2-part pattern", [
'pattern' => $searchData,
'files' => count($searchPDF)
]);
return $searchPDF;
}
}
}
// Fallback: Try just the short_number
$searchData = "*{$shortNumber}*";
$searchData = str_replace("/", "*", $searchData);
$searchData = str_replace(" ", "*", $searchData);
$searchData = str_replace("\\", "*", $searchData);
$path = "{$basePath}/{$searchData}";
$searchPDF = glob($path);
if (!empty($searchPDF)) {
Log::debug("Found with short_number fallback", [
'pattern' => $searchData,
'files' => count($searchPDF)
]);
return $searchPDF;
}
}
// Final fallback: Try exact certificate number
$searchData = "*{$certificateNo}*";
$searchData = str_replace("/", "*", $searchData);
$searchData = str_replace(" ", "*", $searchData);
$searchData = str_replace("\\", "*", $searchData);
$path = "{$basePath}/{$searchData}";
$searchPDF = glob($path);
if (!empty($searchPDF)) {
Log::debug("Found with exact match", [
'pattern' => $searchData,
'files' => count($searchPDF)
]);
return $searchPDF;
}
Log::warning("No files found for certificate", [
'certificate' => $certificateNo,
'base_path' => $basePath
]);
return $files;
}
public function process(
array $weldLogData,
array $document,
Worksheet $sheet,
int &$currentRow,
array $settings
): int {
$this->initialize($weldLogData, $document, $sheet, $currentRow, $settings);
$wpsData = $settings['wps_data'] ?? null;
if (!$wpsData || empty($wpsData->naks_certificate_no)) {
$this->log("WPS Naks certificate not found", 'warning');
return $currentRow;
}
$naksCertificates = explode(" + ", $wpsData->naks_certificate_no);
// Prepare certificates with dates for sorting
$certificatesWithDates = [];
foreach ($naksCertificates as $naksCertificate) {
$certInfo = db("naks_certificates")->where("certificate_no", $naksCertificate)->first();
$certificatesWithDates[] = [
'certificate_no' => $naksCertificate,
'date' => $certInfo->valid_from ?? ''
];
}
// Sort by valid_from date (oldest first) - reverse insertion order
usort($certificatesWithDates, function($a, $b) {
$timestampA = !empty($a['date']) ? strtotime($a['date']) : 0;
$timestampB = !empty($b['date']) ? strtotime($b['date']) : 0;
return $timestampA <=> $timestampB;
});
$this->log("Certificates sorted by date (oldest first for reverse insertion)");
foreach ($certificatesWithDates as $certData) {
$naksCertificate = $certData['certificate_no'];
try {
Log::debug("Processing Naks certificate: " . $naksCertificate);
// Try multiple search strategies for Cyrillic characters and URL encoding
$search = [];
$basePath = "storage/documents/{$document['path']}";
// Strategy 1: Try with URL decoded path
$decodedPath = urldecode($basePath);
$files = $this->searchFilesWithFallback($decodedPath, $naksCertificate);
if (!empty($files)) {
$search = $files;
Log::debug("Found files with decoded path", ['count' => count($files), 'path' => $decodedPath]);
}
// Strategy 2: Try with original path if first strategy failed
if (empty($search) && $decodedPath !== $basePath) {
$files = $this->searchFilesWithFallback($basePath, $naksCertificate);
if (!empty($files)) {
$search = $files;
Log::debug("Found files with original path", ['count' => count($files), 'path' => $basePath]);
}
}
$document['title2'] = $naksCertificate;
$this->document = $document;
$newRow = $this->addRowToExcel(
$search,
$naksCertificate,
$certData['date']
);
if ($newRow > $currentRow) {
$currentRow = $newRow;
}
} catch (\Throwable $th) {
$this->log("Error: {$th->getMessage()}", 'error');
continue;
}
}
return $currentRow;
}
}