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

1097 lines
30 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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](#overview)
2. [Architecture](#architecture)
3. [Directory Structure](#directory-structure)
4. [Core Components](#core-components)
5. [Available Triggers](#available-triggers)
6. [How It Works](#how-it-works)
7. [Adding New Triggers](#adding-new-triggers)
8. [Best Practices](#best-practices)
9. [Troubleshooting](#troubleshooting)
10. [Migration Guide](#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**:
```php
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**:
```php
$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**:
```php
$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**:
```php
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
```php
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:
```php
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
```php
// 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
<?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`:
```php
protected function registerTriggers()
{
// ... existing triggers ...
$this->register(new MyNewTrigger()); // Add this line
}
```
### Step 3: Test
```php
// 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
```php
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
```php
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
```php
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:
```php
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:
```php
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**:
```php
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**:
```php
$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
```php
$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
```php
// 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**:
```php
Log::channel('single')->info("Force log", ['data' => $data]);
```
---
## Migration Guide
### From Old System to New System
#### Step 1: Backup
```bash
# 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
```bash
# 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
```bash
# 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:
```bash
# 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