Files
citrus-cms/resources/views/guide/weld-log-triggers-system.md
T
2026-04-28 21:15:09 +03:00

30 KiB
Raw Blame History

WeldLog Triggers System - Complete Documentation

Non-Technical Summary | Teknik Olmayan Özet

English: What Does WeldLog Trigger System Do?

The WeldLog Trigger System is an automatic synchronization system that activates whenever a welding record is saved or updated. Think of it as a smart assistant that automatically updates related documents and records across the system.

What It Updates:

  • 📋 Line Lists: Updates pipe line information with welding data
  • 🧪 NDE Matrix: Manages non-destructive testing requirements
  • 📅 Request Dates: Tracks when inspections and tests are requested
  • 🔧 Repair Logs: Records any repairs made to welds
  • 📊 NDE Projects: Updates project-wide testing information
  • 📦 Test Packages: Organizes welds into testing groups
  • 🎨 Paint Records: Updates painting schedules (both shop and field)
  • 🏗️ Construction Logs: Tracks construction progress
  • 📤 Handovers: Manages handover status to client
  • 🧹 Cleanup: Removes obsolete or duplicate records

How It Works:

  1. Engineer saves/updates a weld log in the system
  2. System automatically detects what changed
  3. Related tables are updated automatically (no manual work needed)
  4. Everything stays synchronized across the entire quality management system

Why It's Important:

  • ✅ Eliminates manual data entry errors
  • ✅ Ensures data consistency across all modules
  • ✅ Saves hundreds of hours of manual work
  • ✅ Real-time updates mean always current information
  • ✅ Reduces the risk of overlooked updates

Türkçe: WeldLog Trigger Sistemi Ne İşe Yarar?

WeldLog Trigger Sistemi, bir kaynak kaydı kaydedildiğinde veya güncellendiğinde otomatik olarak devreye giren akıllı bir senkronizasyon sistemidir. Bunu, sistemdeki ilgili tüm belge ve kayıtları otomatik olarak güncelleyen akıllı bir asistan olarak düşünebilirsiniz.

Neleri Günceller:

  • 📋 Hat Listeleri (Line Lists): Boru hattı bilgilerini kaynak verileriyle günceller
  • 🧪 NDE Matrisi: Tahribatsız muayene gereksinimlerini yönetir
  • 📅 Talep Tarihleri: Muayene ve test taleplerinin zamanını takip eder
  • 🔧 Tamir Kayıtları: Kaynaklarda yapılan onarımları kaydeder
  • 📊 NDE Projeleri: Proje genelindeki test bilgilerini günceller
  • 📦 Test Paketleri: Kaynakları test grupları halinde organize eder
  • 🎨 Boya Kayıtları: Boya programlarını günceller (hem atölye hem saha)
  • 🏗️ İnşaat Kayıtları: İnşaat ilerlemesini takip eder
  • 📤 Teslimler (Handovers): Müşteriye teslim durumunu yönetir
  • 🧹 Temizlik: Eski veya çift kayıtları siler

Nasıl Çalışır:

  1. Mühendis sistemde bir kaynak kaydı kaydeder/günceller
  2. Sistem neyin değiştiğini otomatik olarak algılar
  3. İlgili tablolar otomatik güncellenir (manuel çalışma gerekmez)
  4. Tüm kalite yönetim sistemi senkronize kalır

Neden Önemli:

  • ✅ Manuel veri girişi hatalarını ortadan kaldırır
  • ✅ Tüm modüller arasında veri tutarlılığı sağlar
  • ✅ Yüzlerce saatlik manuel işten tasarruf sağlar
  • ✅ Gerçek zamanlı güncellemeler = her zaman güncel bilgi
  • ✅ Gözden kaçan güncellemelerin riskini azaltır

Table of Contents

  1. Overview
  2. Architecture
  3. Directory Structure
  4. Core Components
  5. Available Triggers
  6. How It Works
  7. Adding New Triggers
  8. Best Practices
  9. Troubleshooting
  10. Migration Guide

Overview

The WeldLog Triggers System is a modular, service-based architecture that handles all post-save operations for weld log records. It replaces the monolithic 2435-line trigger file with 12 separate, maintainable trigger classes.

Key Benefits

  • Modularity: Each trigger is a separate, focused class
  • Reusability: Trigger system can be adapted for other tables
  • Testability: Each trigger can be unit tested independently
  • Maintainability: Easy to locate and fix issues
  • Performance: Async execution support (future)
  • Logging: Standardized logging across all triggers
  • Flexibility: Easy to add, remove, or modify triggers

System Statistics

  • Original File: 2,435 lines in single file
  • New System: 12 trigger classes + 3 core classes
  • Total Triggers: 12 independent operations
  • Execution Order: Numbered 1-12 for consistency
  • Average Trigger Size: ~150-300 lines per trigger

Architecture

System Design Pattern

The system follows the Strategy Pattern combined with Registry Pattern:

┌─────────────────────────────────────────────┐
│          weld_logs.php (Entry Point)        │
│  - Detects changes                          │
│  - Initializes Manager & Registry           │
└──────────────────┬──────────────────────────┘
                   │
                   ▼
┌─────────────────────────────────────────────┐
│       WeldLogTriggerManager                 │
│  - Orchestrates trigger execution           │
│  - Handles timing & logging                 │
│  - Manages errors                           │
└──────────────────┬──────────────────────────┘
                   │
                   ▼
┌─────────────────────────────────────────────┐
│       WeldLogTriggerRegistry                │
│  - Stores all trigger instances             │
│  - Returns triggers in execution order      │
└──────────────────┬──────────────────────────┘
                   │
                   ▼
┌─────────────────────────────────────────────┐
│     Individual Trigger Classes (12)         │
│  - SpoolStatusChangerTrigger                │
│  - LineListsUpdateTrigger                   │
│  - NdeMatrixUpdateTrigger                   │
│  - ... (10 more triggers)                   │
└─────────────────────────────────────────────┘

Component Relationships

WeldLogTriggerInterface (Contract)
         ▲
         │ implements
         │
    BaseTrigger (Abstract Base Class)
         ▲
         │ extends
         │
    ┌────┴────┬────────┬─────────┐
    │         │        │         │
Trigger1  Trigger2  Trigger3  ... Trigger12

Directory Structure

app/Services/WeldLogTriggers/
├── Contracts/
│   └── WeldLogTriggerInterface.php      # Interface for all triggers
├── Base/
│   └── BaseTrigger.php                   # Base class with common functionality
├── Triggers/
│   ├── SpoolStatusChangerTrigger.php           # Order 1
│   ├── LineListsUpdateTrigger.php              # Order 2
│   ├── NdeMatrixUpdateTrigger.php              # Order 3
│   ├── RequestDateOperationsTrigger.php        # Order 4
│   ├── RepairLogsUpdateTrigger.php             # Order 5
│   ├── NdeProjectUpdateTrigger.php             # Order 6
│   ├── TestPackageOperationsTrigger.php        # Order 7
│   ├── ConstructionPaintLogsTrigger.php        # Order 8
│   ├── TestPackBaseStatusChangerTrigger.php    # Order 9
│   ├── PaintFollowUpsSyncTrigger.php           # Order 10
│   ├── HandoversSyncTrigger.php                # Order 11
│   └── TestPackCleanupTrigger.php              # Order 12
├── WeldLogTriggerRegistry.php            # Central trigger registry
└── WeldLogTriggerManager.php             # Trigger execution orchestrator

Core Components

1. WeldLogTriggerInterface

Purpose: Defines the contract that all triggers must implement

Location: app/Services/WeldLogTriggers/Contracts/WeldLogTriggerInterface.php

Methods:

interface WeldLogTriggerInterface
{
    public function getName(): string;
    public function getOrder(): int;
    public function shouldRun(array $changedFields, bool $isNewRecord): bool;
    public function getDependentFields(): array;
    public function execute($weldLogData, $beforeData, array $context): array;
    public function isAsync(): bool;
}

Key Concepts:

  • getName(): Human-readable trigger name for logging
  • getOrder(): Execution order (1-12)
  • shouldRun(): Determines if trigger should execute based on changes
  • getDependentFields(): List of fields this trigger depends on
  • execute(): Main trigger logic
  • isAsync(): Whether trigger can run asynchronously

2. BaseTrigger

Purpose: Abstract base class providing common functionality

Location: app/Services/WeldLogTriggers/Base/BaseTrigger.php

Features:

  • Automatic timing and performance tracking
  • Standardized logging format
  • Error handling wrapper
  • Default shouldRun() implementation
  • Success/failure status tracking

Usage: All trigger classes extend BaseTrigger and implement:

  • getName()
  • getOrder()
  • getDependentFields()
  • process() (protected method with actual logic)

3. WeldLogTriggerRegistry

Purpose: Central registry for all trigger instances

Location: app/Services/WeldLogTriggers/WeldLogTriggerRegistry.php

Key Methods:

$registry = new WeldLogTriggerRegistry();

// Get all triggers in execution order
$triggers = $registry->getTriggersInOrder();

// Get specific trigger by name
$trigger = $registry->getTrigger('Spool Status Changer');

// Get all trigger names
$names = $registry->getTriggerNames();

// Count registered triggers
$count = $registry->count();

Auto-Registration: All triggers are automatically registered in the constructor. No manual registration needed.


4. WeldLogTriggerManager

Purpose: Orchestrates trigger execution

Location: app/Services/WeldLogTriggers/WeldLogTriggerManager.php

Responsibilities:

  • Execute triggers in correct order
  • Check if each trigger should run
  • Handle errors gracefully
  • Log execution statistics
  • Manage async execution (future)
  • Set database timeouts and memory limits

Usage:

$registry = new WeldLogTriggerRegistry();
$manager = new WeldLogTriggerManager($registry);

$results = $manager->executeTriggers(
    $weldLogData,
    $beforeData,
    $changedFields,
    $isNewRecord
);

Available Triggers

Trigger 1: SpoolStatusChangerTrigger

Order: 1
Purpose: Updates spool status when spool_number, iso_number, or type_of_joint changes

Dependent Fields:

  • spool_number
  • iso_number
  • type_of_joint
  • line_number
  • project
  • design_area

Operations:

  1. Triggers spool-status-changer cron view for new values
  2. Triggers spool-status-changer for old values (if changed)
  3. Sets spool_status to 'Waiting' when type_of_joint changes

Views Called:

  • cron.spool-status-changer

Trigger 2: LineListsUpdateTrigger

Order: 2
Purpose: Updates line_lists table and syncs data from line_lists to weld_logs

Dependent Fields:

  • line_number
  • design_area
  • fluid_code
  • type_of_welds

Operations:

  1. Updates line_lists.updated_at for cron tracking
  2. Syncs data from line_lists to weld_logs

Views Called:

  • cron.line_lists-sync-from-linelists-to-weldlog

Trigger 3: NdeMatrixUpdateTrigger

Order: 3
Purpose: Syncs data between Line Lists, NDE Matrix, and WeldLogs

Dependent Fields:

  • type_of_welds
  • fluid_code
  • type_of_joint
  • line_number
  • design_area
  • project

Operations:

  1. Syncs line_lists to nde_matrices
  2. Handles type_of_welds changes (cleanup old types)
  3. Syncs nde_matrices to weld_logs (scope percentages)

Special Logic:

  • Deletes old NDE matrix records only if no other weld logs use them
  • Uses TransactionHelper for deadlock prevention
  • Processes in chunks (10 records per batch)

Views Called:

  • cron.line_lists-sync-from-linelists-nde-matrix

Trigger 4: RequestDateOperationsTrigger

Order: 4
Purpose: Generates and manages request numbers for all test types

Dependent Fields:

  • iso_number
  • no_of_the_joint_as_per_as_built_survey
  • rt/ut/mt/pt/vt/pwht/ferrite/pmi (request_date, request_no, test_laboratory)

Operations:

  1. Processes all test types (RT, UT, MT, PT, VT, PWHT, Ferrite, PMI)
  2. Generates request numbers using pattern from settings
  3. Reuses existing request numbers for same date/company
  4. Updates both weld_logs and test-specific tables

Request Number Pattern: Uses logs_request_number_pattern setting:

  • {company_code} - Subcontractor company code
  • {log_name} - Test type (RT, UT, etc.)
  • {number} - Sequential counter

Trigger 5: RepairLogsUpdateTrigger

Order: 5
Purpose: Updates repair logs based on test results

Dependent Fields:

  • iso_number
  • no_of_the_joint_as_per_as_built_survey
  • welding_date
  • All test result fields (vt_result, rt_result, etc.)

Operations:

  1. Checks all test result fields
  2. Determines repair status:
    • "Not Done" - All fields empty OR RT & UT both empty
    • "Done" - No repair/cut results
    • "Repair" - Contains repair or cut results

Status Logic:

if (allFieldsEmpty || rtAndUtEmpty) {
    status = "Not Done"
} else if (!hasRepairOrCut) {
    status = "Done"
} else {
    status = "Repair"
}

Trigger 6: NdeProjectUpdateTrigger

Order: 6
Purpose: Updates NDE Matrix project field from weld_logs when null

Dependent Fields:

  • line_number
  • project

Operations:

  1. Joins nde_matrices with weld_logs
  2. Updates null project fields in nde_matrices
  3. Uses DB facade for efficient join update

Trigger 7: TestPackageOperationsTrigger

Order: 7
Purpose: Comprehensive test package management

Dependent Fields:

  • test_package_no, iso_number, nps_1, nps_2
  • line_number, project, design_area
  • piping_type, circuit_number, p_id
  • type_of_test, test_pressure, quantity_of_iso
  • welding_date, all test dates
  • no_of_the_joint_as_per_as_built_survey

Operations:

  1. Updates support weld_or_assembled_date
  2. Calculates support statistics
  3. Calculates punch list statistics
  4. Calculates weld log statistics (WDI, golden joints, backlogs)
  5. Gets NDT calculations
  6. Updates test_packages and test_pack_base_statuses

Complex Calculations:

  • WDI (Weld Diameter Inch) totals
  • Welding progress percentages
  • Shop vs Field weld tracking
  • Golden joints counting
  • Backlog calculations for all test types

Views Called:

  • admin-ajax.ndt-calculation
  • cron.weld_logs-sync-from-weldlog-to-test-pack

Trigger 8: ConstructionPaintLogsTrigger

Order: 8
Purpose: Syncs paint data from WeldLogs to Construction Paint Logs with LineList parity

Dependent Fields:

  • line_number, spool_number, type_of_joint
  • project, design_area, iso_number
  • fluid_code, test_package_no
  • nps_1, nps_2, spool_status, weld_map_no

Operations:

  1. Requires matching Line List + painting_cycle (skips when empty)
  2. Loads weld logs filtered by line/unit/fluid_code
  3. Deduplicates spool processing and validates shop joints
  4. Creates/updates construction paint logs for shop joints only
  5. Cleans up orphan spools when source data no longer exists

Special Logic:

  • Only processes if at least one 'S' type joint exists
  • Guards completed records (date fields) during updates
  • Uses TransactionHelper with chunk processing (10 per batch)
  • Deletes empty records for spools removed from weld_logs

Trigger 9: TestPackBaseStatusChangerTrigger

Order: 9
Purpose: Updates test package base statuses including WDI and repair statistics

Dependent Fields:

  • test_package_no, iso_number, line_number
  • welding_date, type_of_joint, nps_1

Operations:

  1. Gets test packages, weld logs, repair logs, supports
  2. Calculates support statistics
  3. Calculates repair summaries
  4. Calculates WDI totals (total, shop, field)
  5. Calculates welding progress
  6. Updates test_pack_base_statuses
  7. Updates test_packages

WDI Calculations:

  • total_wdi: Sum of all nps_1 values
  • total_complated_wdi: Sum where welding_date is not rejected
  • total_shop_wdi: Sum where type_of_joint = 'S'
  • total_field_wdi: Sum where type_of_joint = 'F'
  • welding_progress: (total_complated_wdi / total_wdi) * 100

Trigger 10: PaintFollowUpsSyncTrigger

Order: 10
Purpose: Comprehensive sync from WeldLogs to Paint Follow Ups (LineList parity)

Dependent Fields:

  • line_number, spool_number
  • no_of_the_joint_as_per_as_built_survey
  • fluid_code, iso_number
  • project, design_area, type_of_joint

Operations:

  1. Validates Line List + painting_cycle; skips when empty or no matching weld logs exist
  2. Loads weld logs filtered by line/unit/fluid, removes cloned joints, and honours repair (R) joint overrides
  3. Loads/creates Paint Matrix aligned to the active painting cycle and computes temperature & volume references
  4. Creates/updates SHOP (spool) and FIELD (joint) records with cycle-aware uniqueness, HOLD handling, and date protection
  5. Cleans orphaned entries when spool/joint numbers change and purges records without backing weld logs

Key Enhancements:

  • Temperature/volume backfill without overwriting completed dates
  • HOLD status applied when painting cycle changes but work is complete
  • TransactionHelper chunk execution with deadlock retries
  • Two-phase cleanup: targeted orphan deletion + non-matching purge at line scope

Trigger 11: HandoversSyncTrigger

Order: 11
Purpose: Syncs data from WeldLogs to Handovers table

Dependent Fields:

  • line_number
  • project
  • design_area
  • piping_type

Operations:

  1. Gets all weld logs for line_number
  2. Groups by line (handovers stored per line)
  3. Creates/updates handover records

Field Mapping:

  • line_number → project (in handovers)
  • project → object
  • design_area → location
  • piping_type → work_type (defaults to 'ТРУБКА')

Trigger 12: TestPackCleanupTrigger

Order: 12
Purpose: Deletes non-matching test pack statuses

Dependent Fields:

  • test_package_no
  • iso_number

Operations:

  1. Calls cleanup view to remove orphaned test pack statuses

Special Notes:

  • Non-critical operation (doesn't throw exceptions)
  • Logs errors but continues execution

Views Called:

  • cron.weld_logs-delete-non-matching-test-pack-statuses

How It Works

Execution Flow

1. WeldLog saved
   ↓
2. SaveTrigger called (weld_logs.php)
   ↓
3. Detect changes (detectChangedFields())
   ↓
4. Initialize Registry & Manager
   ↓
5. Manager.executeTriggers()
   ↓
6. For each trigger (order 1-12):
   ├─ Check shouldRun()
   ├─ If NO → Skip, log, continue
   ├─ If YES → Execute trigger
   │   ├─ Log START
   │   ├─ Run process()
   │   ├─ Log COMPLETION
   │   └─ Return results
   └─ Continue to next trigger
   ↓
7. Log overall statistics
   ↓
8. Return all results

Change Detection Logic

function detectChangedFields($data, $beforeData): array
{
    if (is_null($beforeData)) {
        // New record - all fields changed
        return array_keys((array) $data);
    }
    
    $changedFields = [];
    foreach ((array) $data as $key => $value) {
        $oldValue = $beforeData->$key ?? null;
        if ($oldValue !== $value) {
            $changedFields[] = $key;
        }
    }
    
    return $changedFields;
}

Should Run Logic

Each trigger checks if it should run:

public function shouldRun(array $changedFields, bool $isNewRecord): bool
{
    if ($isNewRecord) {
        return true; // Always run for new records
    }
    
    $dependentFields = $this->getDependentFields();
    
    // Run if any changed field is in dependent fields
    return !empty(array_intersect($changedFields, $dependentFields));
}

Example: Trigger Execution

// Original weld log data
$beforeData = (object)[
    'id' => 1,
    'spool_number' => 'SP-001',
    'iso_number' => 'ISO-100',
    'type_of_joint' => 'S'
];

// Updated weld log data
$data = (object)[
    'id' => 1,
    'spool_number' => 'SP-002', // CHANGED
    'iso_number' => 'ISO-100',
    'type_of_joint' => 'S'
];

// Changed fields: ['spool_number']

// SpoolStatusChangerTrigger depends on:
// ['spool_number', 'iso_number', 'type_of_joint', ...]

// array_intersect(['spool_number'], ['spool_number', 'iso_number', ...])
// = ['spool_number'] (not empty)

// Result: shouldRun() returns TRUE, trigger executes

Adding New Triggers

Step 1: Create Trigger Class

<?php

namespace App\Services\WeldLogTriggers\Triggers;

use App\Services\WeldLogTriggers\Base\BaseTrigger;
use Illuminate\Support\Facades\Log;

class MyNewTrigger extends BaseTrigger
{
    public function getName(): string
    {
        return 'My New Trigger';
    }
    
    public function getOrder(): int
    {
        return 14; // Next available order
    }
    
    public function getDependentFields(): array
    {
        return [
            'field1',
            'field2',
            'field3'
        ];
    }
    
    protected function process($data, $beforeData, array $context): array
    {
        // Your trigger logic here
        
        Log::info("My New Trigger processing", [
            'weld_log_id' => $data->id
        ]);
        
        // Do something...
        
        return [
            'success' => true,
            'records_processed' => 10
        ];
    }
}

Step 2: Register in Registry

Edit app/Services/WeldLogTriggers/WeldLogTriggerRegistry.php:

protected function registerTriggers()
{
    // ... existing triggers ...
    
    $this->register(new MyNewTrigger()); // Add this line
}

Step 3: Test

// Trigger will automatically execute when fields change
// Check logs for execution confirmation

Best Practices

1. Naming Conventions

  • Trigger Classes: {Purpose}Trigger.php (e.g., SpoolStatusChangerTrigger.php)
  • Method Names: Clear, descriptive verbs (e.g., processWeldLogRecord, calculateStatistics)
  • Variables: Descriptive names (avoid $data1, $data2)

2. Error Handling

protected function process($data, $beforeData, array $context): array
{
    try {
        // Main logic
        
        return ['success' => true];
    } catch (\Throwable $th) {
        Log::error("Error in trigger", [
            'error' => $th->getMessage(),
            'weld_log_id' => $data->id
        ]);
        
        // Re-throw if critical, or handle gracefully
        throw $th;
    }
}

3. Logging

Always log:

  • Start of processing
  • Key decisions
  • Errors
  • Completion with statistics
Log::info("Processing started", [
    'weld_log_id' => $data->id,
    'record_count' => $records->count()
]);

// ... processing ...

Log::info("Processing completed", [
    'weld_log_id' => $data->id,
    'processed' => $processedCount,
    'skipped' => $skippedCount
]);

4. Performance

  • Use chunk processing for large datasets
  • Use TransactionHelper for database operations
  • Add appropriate delays between chunks (10ms recommended)
  • Order records by 'id ASC' to prevent deadlocks
TransactionHelper::chunkTransaction(
    $collection,
    function ($chunk) use (&$count) {
        // Process chunk
        return $chunk->count();
    },
    10,    // Chunk size
    10000  // 10ms delay
);

5. Field Dependencies

Be explicit about dependencies:

public function getDependentFields(): array
{
    return [
        'field1',    // Primary field
        'field2',    // Related field
        'field3',    // Supporting field
        // ... with comments if complex
    ];
}

6. Return Values

Always return structured data:

return [
    'success' => true,
    'records_processed' => 100,
    'records_skipped' => 5,
    'error' => null,
    // ... other relevant data
];

Troubleshooting

Trigger Not Executing

Symptom: Trigger doesn't run when expected

Checks:

  1. Check if fields are in getDependentFields()
  2. Check logs for "Skipping trigger" messages
  3. Verify field actually changed
  4. Check if trigger is registered in Registry

Debug:

Log::info("Debug shouldRun", [
    'trigger' => $this->getName(),
    'changed_fields' => $changedFields,
    'dependent_fields' => $this->getDependentFields(),
    'intersection' => array_intersect($changedFields, $this->getDependentFields())
]);

Trigger Execution Too Slow

Symptom: Trigger takes too long to execute

Solutions:

  1. Add chunk processing
  2. Increase chunk size (but not too much)
  3. Add indexes to database tables
  4. Use eager loading for relationships
  5. Consider making trigger async (future)

Measure performance:

$startTime = microtime(true);
// ... processing ...
$duration = round((microtime(true) - $startTime) * 1000, 2);
Log::info("Performance", ['duration_ms' => $duration]);

Database Deadlocks

Symptom: "Deadlock found when trying to get lock"

Solutions:

  1. Always order queries by 'id ASC'
  2. Use TransactionHelper with retry logic
  3. Reduce chunk size
  4. Add delays between chunks
$query->orderBy('id', 'ASC') // Prevents deadlocks
     ->lockForUpdate()        // Explicit locking
     ->get();

Memory Issues

Symptom: "Allowed memory size exhausted"

Solutions:

  1. Use chunk processing
  2. Unset large variables after use
  3. Use cursor() instead of get() for very large datasets
  4. Increase memory_limit temporarily
// Instead of:
$allRecords = Model::all(); // Loads everything into memory

// Use:
Model::chunk(100, function($chunk) {
    // Process chunk
});

Missing Logs

Symptom: Expected log entries not appearing

Checks:

  1. Check log level in config
  2. Verify Log facade is imported
  3. Check storage/logs/laravel.log permissions
  4. Check if logs are being rotated

Force logging:

Log::channel('single')->info("Force log", ['data' => $data]);

Migration Guide

From Old System to New System

Step 1: Backup

# Backup old trigger file
cp app/Http/Controllers/SaveTrigger/weld_logs.php \
   app/Http/Controllers/SaveTrigger/weld_logs_backup.php

Step 2: Verify New System

# Check all trigger files exist
ls -la app/Services/WeldLogTriggers/Triggers/

# Should show 12 trigger files

Step 3: Test in Development

  1. Use weld_logs_new.php initially
  2. Test all trigger scenarios
  3. Compare results with old system
  4. Check logs for any errors

Step 4: Switch to New System

# Once tested, replace old with new
mv app/Http/Controllers/SaveTrigger/weld_logs.php \
   app/Http/Controllers/SaveTrigger/weld_logs_old.php

mv app/Http/Controllers/SaveTrigger/weld_logs_new.php \
   app/Http/Controllers/SaveTrigger/weld_logs.php

Step 5: Monitor

  • Check logs for first 24 hours
  • Monitor execution times
  • Verify all triggers executing correctly
  • Check database consistency

Rollback Plan

If issues occur:

# Restore old system
mv app/Http/Controllers/SaveTrigger/weld_logs.php \
   app/Http/Controllers/SaveTrigger/weld_logs_failed.php

mv app/Http/Controllers/SaveTrigger/weld_logs_old.php \
   app/Http/Controllers/SaveTrigger/weld_logs.php

Comparison Test

To verify new system works identically:

  1. Clone development environment
  2. Run old system, capture logs and database state
  3. Reset database
  4. Run new system with same data
  5. Compare results

Performance Considerations

Execution Times (Average)

Trigger Average Time Notes
1. Spool Status Changer 50-100ms Fast, minimal DB operations
2. Line Lists Update 100-200ms Depends on line size
3. NDE Matrix Update 200-500ms Chunk processing
4. Request Date Operations 100-300ms Per test type
5. Repair Logs Update 50-100ms Simple logic
6. NDE Project Update 50-100ms Single query
7. Test Package Operations 500-2000ms Most complex
8. Construction Paint Logs 200-400ms Chunk processing + lineage checks
9. Test Pack Base Status 300-600ms WDI calculations
10. Paint Follow Ups Sync 250-450ms SHOP + FIELD harmonization
11. Handovers Sync 100-200ms Simple sync
12. Test Pack Cleanup 50-100ms Non-critical

Total Average: 2-4 seconds per weld log save

Optimization Tips

  1. Database Indexes: Ensure indexes exist on frequently queried fields
  2. Chunk Sizes: Tune based on your data volume
  3. Async Execution: Consider for non-critical triggers (future)
  4. Caching: Cache lookup data (subcontractors, paint matrices)
  5. Batch Processing: Group multiple saves if possible

Conclusion

The WeldLog Triggers System provides a robust, maintainable, and scalable solution for handling post-save operations. By breaking down the monolithic trigger file into 12 focused classes, we've achieved:

✅ Better code organization
✅ Easier debugging and maintenance
✅ Improved testability
✅ Clear execution flow
✅ Comprehensive logging
✅ Performance optimization opportunities

For questions or issues, refer to the logs or contact the development team.


Document Version: 1.0
Last Updated: October 30, 2025
Author: DevQMS Development Team