414 lines
18 KiB
PHP
414 lines
18 KiB
PHP
<?php
|
|
|
|
namespace App\Services\LineListTriggers\Triggers;
|
|
|
|
use App\Services\LineListTriggers\Base\BaseLineListTrigger;
|
|
use App\Models\PaintMatrix;
|
|
use App\Helpers\TransactionHelper;
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
/**
|
|
* Construction Paint Logs Sync Trigger
|
|
*
|
|
* Syncs data from Line Lists + Weld Logs + Paint Systems to Construction Paint Logs:
|
|
* - Creates/updates construction_paint_logs for each spool with shop joint
|
|
* - Handles painting cycle changes
|
|
* - Similar approach to WeldLog trigger for consistency
|
|
*/
|
|
class ConstructionPaintLogsSyncTrigger extends BaseLineListTrigger
|
|
{
|
|
public function getName(): string
|
|
{
|
|
return 'Construction Paint Logs Sync';
|
|
}
|
|
|
|
public function getDependentFields(): array
|
|
{
|
|
return [
|
|
|
|
];
|
|
}
|
|
|
|
protected function process($lineListData, $beforeData, array $context): array
|
|
{
|
|
$lineList = $lineListData;
|
|
|
|
// Skip processing if essential fields are missing
|
|
if (empty($lineList->line_no)) {
|
|
Log::debug("Skipping Construction Paint Logs sync - missing line number");
|
|
return ['skipped' => true, 'reason' => 'line_no_empty'];
|
|
}
|
|
|
|
// Skip processing if painting_cycle is empty
|
|
// Construction Paint Logs should only exist when there is a painting cycle
|
|
if (empty($lineList->painting_cycle)) {
|
|
Log::debug("Skipping Construction Paint Logs sync - painting_cycle is empty", [
|
|
'line_no' => $lineList->line_no
|
|
]);
|
|
return ['skipped' => true, 'reason' => 'painting_cycle_empty'];
|
|
}
|
|
|
|
// Check if matching weld_logs record exists with same unit + line + fluid_code
|
|
// Construction paint logs should only be created if there's a corresponding weld log
|
|
$matchingWeldLogExists = db("weld_logs")
|
|
->where("line_number", $lineList->line_no)
|
|
->where("design_area", $lineList->unit)
|
|
->where("fluid_code", $lineList->fluid_code)
|
|
->exists();
|
|
|
|
if (!$matchingWeldLogExists) {
|
|
Log::debug("Skipping Construction Paint Logs sync - no matching weld_logs record found", [
|
|
'line_no' => $lineList->line_no,
|
|
'unit' => $lineList->unit,
|
|
'fluid_code' => $lineList->fluid_code
|
|
]);
|
|
return ['skipped' => true, 'reason' => 'no_matching_weld_log'];
|
|
}
|
|
|
|
// Retrieve all weld logs with the same line number, unit and fluid_code
|
|
$allWeldLogs = db("weld_logs")
|
|
->where("line_number", $lineList->line_no)
|
|
->where("design_area", $lineList->unit)
|
|
->where("fluid_code", $lineList->fluid_code)
|
|
->orderBy('id', 'ASC') // Deadlock prevention
|
|
->get();
|
|
|
|
Log::debug("Syncing Construction Paint Logs for line: " . $lineList->line_no, [
|
|
'weld_log_count' => count($allWeldLogs),
|
|
'painting_cycle' => $lineList->painting_cycle
|
|
]);
|
|
|
|
$createdCount = 0;
|
|
$updatedCount = 0;
|
|
|
|
// Track processed spools to avoid duplicates
|
|
$processedSpools = [];
|
|
|
|
// Process weld logs in chunks with TransactionHelper
|
|
TransactionHelper::chunkTransaction(
|
|
$allWeldLogs,
|
|
function ($weldLogChunk) use ($lineList, &$updatedCount, &$createdCount, &$processedSpools) {
|
|
foreach ($weldLogChunk as $weldLogData) {
|
|
// Skip if spool is empty
|
|
if (empty($weldLogData->spool_number)) {
|
|
Log::debug("Skipping weld log - empty spool_number", ['weld_log_id' => $weldLogData->id]);
|
|
continue;
|
|
}
|
|
|
|
// Skip if already processed this spool
|
|
if (in_array($weldLogData->spool_number, $processedSpools)) {
|
|
Log::debug("Skipping weld log - spool already processed", [
|
|
'weld_log_id' => $weldLogData->id,
|
|
'spool' => $weldLogData->spool_number
|
|
]);
|
|
continue;
|
|
}
|
|
|
|
// Shop joint check - only process spools with shop joints
|
|
$hasShopJoint = db("weld_logs")
|
|
->where('line_number', $lineList->line_no)
|
|
->where('spool_number', $weldLogData->spool_number)
|
|
->where('type_of_joint', 'S')
|
|
->exists();
|
|
|
|
if (!$hasShopJoint) {
|
|
Log::debug("Skipping spool - no shop joint found", [
|
|
'line' => $lineList->line_no,
|
|
'spool' => $weldLogData->spool_number
|
|
]);
|
|
continue;
|
|
}
|
|
|
|
Log::debug("Processing spool for Construction Paint Log", [
|
|
'line' => $lineList->line_no,
|
|
'spool' => $weldLogData->spool_number,
|
|
'weld_log_id' => $weldLogData->id
|
|
]);
|
|
|
|
// Process this spool
|
|
$this->processWeldLogRecord($weldLogData, $lineList, $updatedCount, $createdCount);
|
|
|
|
// Mark this spool as processed
|
|
$processedSpools[] = $weldLogData->spool_number;
|
|
}
|
|
return $weldLogChunk->count();
|
|
},
|
|
1, // Chunk size
|
|
10000 // 10ms delay
|
|
);
|
|
|
|
Log::debug("Construction Paint Logs sync completed", [
|
|
'line_no' => $lineList->line_no,
|
|
'created' => $createdCount,
|
|
'updated' => $updatedCount
|
|
]);
|
|
|
|
return [
|
|
'success' => true,
|
|
'created' => $createdCount,
|
|
'updated' => $updatedCount
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Process a single weld log record for construction paint logs
|
|
* Same structure as WeldLog trigger
|
|
*/
|
|
protected function processWeldLogRecord($currentWeldLog, $lineList, &$updatedCount, &$createdCount)
|
|
{
|
|
Log::debug("Starting processWeldLogRecord", [
|
|
'line' => $lineList->line_no,
|
|
'spool' => $currentWeldLog->spool_number,
|
|
'painting_cycle' => $lineList->painting_cycle,
|
|
'fluid_code' => $lineList->fluid_code
|
|
]);
|
|
|
|
// Get paint matrix data for paint system information
|
|
$paintMatrix = PaintMatrix::where('line', $lineList->line_no)
|
|
->where('fluid_code', $lineList->fluid_code)
|
|
->first();
|
|
|
|
Log::debug("Paint Matrix lookup result", [
|
|
'found' => $paintMatrix !== null,
|
|
'line' => $lineList->line_no,
|
|
'fluid_code' => $lineList->fluid_code
|
|
]);
|
|
|
|
// Base data for construction paint log
|
|
$baseConstructionPaintLogData = [
|
|
// Report Information
|
|
'construction_report_no' => $currentWeldLog->weld_map_no ?? '',
|
|
'test_package' => $currentWeldLog->test_package_no ?? '',
|
|
'rev' => $lineList->rev ?? '',
|
|
|
|
// Project Information
|
|
'engineering' => $lineList->engineering ?? '',
|
|
'area' => $currentWeldLog->project ?? '',
|
|
'unit' => $currentWeldLog->design_area ?? '',
|
|
|
|
// Line Details
|
|
'line' => $lineList->line_no,
|
|
'iso_drawings' => $currentWeldLog->iso_number ?? '',
|
|
'fluid_code' => $lineList->fluid_code ?? '',
|
|
'fluid_code_description' => $lineList->fluid_ru ?? '',
|
|
'isolation_info' => $lineList->external_finish_type ?? '',
|
|
];
|
|
|
|
// Add paint system data if available
|
|
if ($paintMatrix) {
|
|
$paintSystemData = [
|
|
'painting_system_type_1' => $paintMatrix->paint_cycle ?? '',
|
|
'painting_system_type_2' => $paintMatrix->paint_cycle ?? '',
|
|
|
|
// First coat (Primer)
|
|
'brend_name_1' => $paintMatrix->brend_name_1 ?? '',
|
|
'ral_1' => $paintMatrix->ral_code_1 ?? '',
|
|
'color_1' => $paintMatrix->colour_1 ?? '', // Russian color description
|
|
'thickness_1' => $paintMatrix->thickness_1 ?? '',
|
|
|
|
// Second coat (Intermediate)
|
|
'brend_name_2' => $paintMatrix->brend_name_2 ?? '',
|
|
'ral_2' => $paintMatrix->ral_code_2 ?? '',
|
|
'color_2' => $paintMatrix->colour_2 ?? '', // Russian color description
|
|
'thickness_2' => $paintMatrix->thickness_2 ?? '',
|
|
|
|
// Third coat (Final)
|
|
'brend_name_3' => $paintMatrix->brend_name_3 ?? '',
|
|
'ral_3' => $paintMatrix->ral_code_3 ?? '',
|
|
'color_3' => $paintMatrix->colour_3 ?? '', // Russian color description
|
|
'thickness_3' => $paintMatrix->thickness_3 ?? '',
|
|
];
|
|
$baseConstructionPaintLogData = array_merge($baseConstructionPaintLogData, $paintSystemData);
|
|
}
|
|
|
|
// Add timestamp
|
|
$baseConstructionPaintLogData['updated_at'] = now();
|
|
|
|
// Process only the specific spool
|
|
$constructionPaintLogData = $baseConstructionPaintLogData;
|
|
|
|
// Add spool-specific data
|
|
$constructionPaintLogData['test_package'] = $currentWeldLog->test_package_no ?? '';
|
|
$constructionPaintLogData['spool'] = $currentWeldLog->spool_number ?? '';
|
|
$constructionPaintLogData['spool_status'] = $currentWeldLog->spool_status ?? 'Waiting';
|
|
|
|
// Generate unique report number for the spool
|
|
$constructionPaintLogData['report_no'] = '';
|
|
|
|
// Add dimensions
|
|
$constructionPaintLogData['dn_1'] = $currentWeldLog->nps_1 ?? '';
|
|
$constructionPaintLogData['dn_2'] = $currentWeldLog->nps_2 ?? '';
|
|
$constructionPaintLogData['dn_3'] = '';
|
|
|
|
// UNIQUE CONSTRAINT: line + spool + painting_system_type_1 (paint cycle)
|
|
// This allows multiple records for same spool with different paint cycles
|
|
$uniqueConstraintCondition = [
|
|
'line' => $lineList->line_no,
|
|
'spool' => $currentWeldLog->spool_number,
|
|
'painting_system_type_1' => $paintMatrix->paint_cycle ?? ''
|
|
];
|
|
|
|
// WHERE condition without cycle (to find records with different cycles)
|
|
$whereCondition = [
|
|
'line' => $lineList->line_no,
|
|
'spool' => $currentWeldLog->spool_number
|
|
];
|
|
|
|
// Find existing record with SAME painting cycle
|
|
$existingRecordSameCycle = db("construction_paint_logs")
|
|
->where($uniqueConstraintCondition)
|
|
->first();
|
|
|
|
// Find records with DIFFERENT painting cycle
|
|
$recordsWithDifferentPaintCycle = db("construction_paint_logs")
|
|
->where($whereCondition)
|
|
->where('painting_system_type_1', '!=', $paintMatrix->paint_cycle ?? '')
|
|
->get();
|
|
|
|
Log::debug('LineList ConstructionPaintLogsTrigger: Record check', [
|
|
'line' => $lineList->line_no,
|
|
'spool' => $currentWeldLog->spool_number,
|
|
'currentPaintCycle' => $paintMatrix->paint_cycle ?? '',
|
|
'existingSameCycle' => (bool) $existingRecordSameCycle,
|
|
'differentCycleCount' => $recordsWithDifferentPaintCycle->count()
|
|
]);
|
|
|
|
try {
|
|
if ($existingRecordSameCycle) {
|
|
// Record with same paint cycle exists
|
|
$hasAllEmptyDates = $this->hasAllEmptyDates($existingRecordSameCycle);
|
|
|
|
if ($hasAllEmptyDates) {
|
|
// All dates are empty - safe to update completely
|
|
Log::debug('LineList ConstructionPaintLogsTrigger: Updating record (all dates empty)', [
|
|
'recordId' => $existingRecordSameCycle->id,
|
|
'paintCycle' => $paintMatrix->paint_cycle ?? ''
|
|
]);
|
|
|
|
db("construction_paint_logs")
|
|
->where('id', $existingRecordSameCycle->id)
|
|
->update($constructionPaintLogData);
|
|
$updatedCount++;
|
|
|
|
Log::info("✓ Updated Construction Paint Log (same cycle)", [
|
|
'record_id' => $existingRecordSameCycle->id,
|
|
'line' => $lineList->line_no,
|
|
'spool' => $currentWeldLog->spool_number,
|
|
'painting_cycle' => $lineList->painting_cycle
|
|
]);
|
|
} else {
|
|
// Some dates are filled - preserve completed work
|
|
Log::debug('LineList ConstructionPaintLogsTrigger: Skipping update (dates filled)', [
|
|
'recordId' => $existingRecordSameCycle->id,
|
|
'paintCycle' => $paintMatrix->paint_cycle ?? ''
|
|
]);
|
|
}
|
|
} else {
|
|
// No record with same paint cycle exists
|
|
|
|
// Handle records with different paint cycles
|
|
if ($recordsWithDifferentPaintCycle->count() > 0) {
|
|
foreach ($recordsWithDifferentPaintCycle as $oldRecord) {
|
|
$hasAnyDateFilled = !$this->hasAllEmptyDates($oldRecord);
|
|
|
|
if ($hasAnyDateFilled) {
|
|
// Dates are filled - keep old record, will create new one
|
|
Log::debug('LineList ConstructionPaintLogsTrigger: Old paint cycle record has dates, keeping it', [
|
|
'oldRecordId' => $oldRecord->id,
|
|
'oldPaintCycle' => $oldRecord->painting_system_type_1,
|
|
'newPaintCycle' => $paintMatrix->paint_cycle ?? ''
|
|
]);
|
|
} else {
|
|
// Dates are empty - update to new paint cycle instead of creating new
|
|
Log::debug('LineList ConstructionPaintLogsTrigger: Updating old record to new paint cycle', [
|
|
'oldRecordId' => $oldRecord->id,
|
|
'oldPaintCycle' => $oldRecord->painting_system_type_1,
|
|
'newPaintCycle' => $paintMatrix->paint_cycle ?? ''
|
|
]);
|
|
|
|
db("construction_paint_logs")
|
|
->where('id', $oldRecord->id)
|
|
->update($constructionPaintLogData);
|
|
$updatedCount++;
|
|
|
|
Log::info("✓ Updated Construction Paint Log (cycle changed, no dates)", [
|
|
'record_id' => $oldRecord->id,
|
|
'line' => $lineList->line_no,
|
|
'spool' => $currentWeldLog->spool_number,
|
|
'old_cycle' => $oldRecord->painting_system_type_1,
|
|
'new_cycle' => $lineList->painting_cycle
|
|
]);
|
|
return; // Don't create new record
|
|
}
|
|
}
|
|
}
|
|
|
|
// Create new record (either no record exists, or old one has dates)
|
|
Log::debug('LineList ConstructionPaintLogsTrigger: Creating new record', [
|
|
'line' => $lineList->line_no,
|
|
'spool' => $currentWeldLog->spool_number,
|
|
'paintCycle' => $paintMatrix->paint_cycle ?? '',
|
|
'reason' => $recordsWithDifferentPaintCycle->count() > 0
|
|
? 'different_cycle_with_dates'
|
|
: 'no_existing_record'
|
|
]);
|
|
|
|
$constructionPaintLogData['created_at'] = now();
|
|
$insertedId = db("construction_paint_logs")->insertGetId($constructionPaintLogData);
|
|
$createdCount++;
|
|
|
|
Log::info("✓ Created Construction Paint Log", [
|
|
'record_id' => $insertedId,
|
|
'line' => $lineList->line_no,
|
|
'spool' => $currentWeldLog->spool_number,
|
|
'painting_cycle' => $lineList->painting_cycle,
|
|
'reason' => $recordsWithDifferentPaintCycle->count() > 0
|
|
? 'different_cycle_with_dates'
|
|
: 'no_existing_record'
|
|
]);
|
|
}
|
|
} catch (\Exception $e) {
|
|
Log::error("✗ Failed to save Construction Paint Log", [
|
|
'error' => $e->getMessage(),
|
|
'line' => $lineList->line_no,
|
|
'spool' => $currentWeldLog->spool_number,
|
|
'file' => $e->getFile(),
|
|
'line_number' => $e->getLine()
|
|
]);
|
|
throw $e;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if all date fields are empty in a construction paint log record
|
|
*
|
|
* @param object $record Construction paint log record
|
|
* @return bool True if all date fields are empty
|
|
*/
|
|
protected function hasAllEmptyDates($record): bool
|
|
{
|
|
$dateFields = [
|
|
'blasting_date',
|
|
'blasting_finish_date',
|
|
'painting_date_1',
|
|
'painting_finish_date_1',
|
|
'rfi_date_1',
|
|
'painting_date_2',
|
|
'painting_finish_date_2',
|
|
'rfi_date_2',
|
|
'painting_date_3',
|
|
'painting_finish_date_3',
|
|
'rfi_date_3'
|
|
];
|
|
|
|
foreach ($dateFields as $field) {
|
|
if (!empty($record->$field)) {
|
|
return false; // Found a filled date
|
|
}
|
|
}
|
|
|
|
return true; // All dates are empty
|
|
}
|
|
}
|
|
|