1485 lines
50 KiB
Markdown
1485 lines
50 KiB
Markdown
# Line List Triggers System - Complete Documentation
|
||
|
||
## Non-Technical Summary | Teknik Olmayan Özet
|
||
|
||
### English: What Does LineList Trigger System Do?
|
||
|
||
The LineList Trigger System is an **automatic data synchronization engine** that activates whenever a pipe line specification is saved or updated. It acts as a central coordinator that ensures all related quality control, inspection, and painting records stay up-to-date.
|
||
|
||
**What It Updates:**
|
||
- 👷 **Weld Logs**: Updates 15+ fields in all welding records for the line
|
||
- 🎨 **Paint Matrix**: Creates/updates painting specifications and color codes
|
||
- 🧪 **NDE Matrix**: Manages non-destructive testing requirements for each joint type
|
||
- 🎨 **Paint Systems**: Updates painting system standards and specifications
|
||
- 🏭 **Paint Follow-Ups**: Creates records for both workshop (SHOP) and field (FIELD) painting
|
||
- 🏗️ **Construction Paint Logs**: Tracks painting progress for each spool
|
||
- 📊 **Color Systems**: Manages fluid code colors and RAL color mappings
|
||
- 🔄 **Spool Status**: Automatically updates spool completion status
|
||
- 🧹 **Cleanup**: Removes orphaned paint records
|
||
|
||
**Special Features:**
|
||
- 🛡️ **Date Protection**: Never overwrites records where work has already started (dates are filled)
|
||
- 🔄 **Painting Cycle Changes**: When paint specs change, old records are preserved (marked as HOLD) and new ones created
|
||
- 🌡️ **Temperature Calculations**: Automatically calculates substrate and ambient temperatures
|
||
- 📏 **Volume Calculations**: Computes paint volumes for both shop and field work
|
||
- 🎨 **RAL to Russian**: Converts RAL color codes to Russian color descriptions
|
||
|
||
**How It Works:**
|
||
1. Engineer updates a line specification (e.g., changes painting cycle)
|
||
2. System detects which fields changed
|
||
3. Automatically synchronizes data to 8+ related tables
|
||
4. Protects completed work (records with dates) from being overwritten
|
||
5. Creates new records for new specifications while preserving old work
|
||
|
||
**Why It's Important:**
|
||
- ✅ Each change automatically updates only the relevant related records
|
||
- ✅ Prevents accidental data loss (completed work is protected)
|
||
- ✅ Maintains complete history when specifications change
|
||
- ✅ Eliminates need for manual updates across multiple modules
|
||
- ✅ Ensures painting, testing, and welding records are always synchronized
|
||
|
||
---
|
||
|
||
### Türkçe: LineList Trigger Sistemi Ne İşe Yarar?
|
||
|
||
LineList Trigger Sistemi, bir boru hattı spesifikasyonu kaydedildiğinde veya güncellendiğinde otomatik olarak devreye giren **merkezi bir veri senkronizasyon motoru**dur. İlgili tüm kalite kontrol, muayene ve boya kayıtlarının güncel kalmasını sağlayan merkezi bir koordinatör görevi görür.
|
||
|
||
**Neleri Günceller:**
|
||
- 👷 **Kaynak Kayıtları (Weld Logs)**: Hat için tüm kaynak kayıtlarında 15+ alanı günceller
|
||
- 🎨 **Boya Matrisi (Paint Matrix)**: Boya spesifikasyonlarını ve renk kodlarını oluşturur/günceller
|
||
- 🧪 **NDE Matrisi**: Her ek tipi için tahribatsız muayene gereksinimlerini yönetir
|
||
- 🎨 **Boya Sistemleri**: Boya sistemi standartlarını ve spesifikasyonlarını günceller
|
||
- 🏭 **Boya Takip (Paint Follow-Ups)**: Hem atölye (SHOP) hem saha (FIELD) boyama için kayıtlar oluşturur
|
||
- 🏗️ **İnşaat Boya Kayıtları**: Her spool için boyama ilerlemesini takip eder
|
||
- 📊 **Renk Sistemleri**: Akışkan kodu renklerini ve RAL renk eşleştirmelerini yönetir
|
||
- 🔄 **Spool Durumu**: Spool tamamlanma durumunu otomatik günceller
|
||
- 🧹 **Temizlik**: Sahipsiz boya kayıtlarını siler
|
||
|
||
**Özel Özellikler:**
|
||
- 🛡️ **Tarih Koruması**: İş başlamış kayıtların (tarihler dolmuş) üzerine asla yazmaz
|
||
- 🔄 **Boya Döngüsü Değişiklikleri**: Boya spesifikasyonları değiştiğinde, eski kayıtlar korunur (HOLD işaretlenir) ve yenileri oluşturulur
|
||
- 🌡️ **Sıcaklık Hesaplamaları**: Substrat ve ortam sıcaklıklarını otomatik hesaplar
|
||
- 📏 **Hacim Hesaplamaları**: Hem atölye hem saha işi için boya hacimlerini hesaplar
|
||
- 🎨 **RAL'dan Rusça'ya**: RAL renk kodlarını Rusça renk tanımlarına dönüştürür
|
||
|
||
**Nasıl Çalışır:**
|
||
1. Mühendis bir hat spesifikasyonunu günceller (örn. boya döngüsünü değiştirir)
|
||
2. Sistem hangi alanların değiştiğini algılar
|
||
3. Otomatik olarak 8+ ilgili tabloya veri senkronize eder
|
||
4. Tamamlanmış işleri korur (tarihi olan kayıtların üzerine yazmaz)
|
||
5. Yeni spesifikasyonlar için yeni kayıtlar oluştururken eski işleri korur
|
||
|
||
**Neden Önemli:**
|
||
- ✅ Her değişiklik sadece ilgili kayıtları otomatik günceller
|
||
- ✅ Kazara veri kaybını önler (tamamlanmış iş korunur)
|
||
- ✅ Spesifikasyonlar değiştiğinde tam geçmiş tutar
|
||
- ✅ Birden fazla modülde manuel güncelleme ihtiyacını ortadan kaldırır
|
||
- ✅ Boya, test ve kaynak kayıtlarının her zaman senkronize olmasını sağlar
|
||
|
||
---
|
||
|
||
## Quick Reference: What Happens in Each Column / Table
|
||
|
||
This section provides a simple, non-technical overview of what each trigger does, which tables it affects, and in what order.
|
||
|
||
### Execution Order Summary
|
||
|
||
| Order | Trigger Name | Tables Affected | Operation Type | When It Runs |
|
||
|-------|-------------|-----------------|----------------|--------------|
|
||
| 1 | Paint Cycle Change | `weld_logs`, `construction_paint_logs` | UPDATE, DELETE | When painting_cycle changes |
|
||
| 2 | WeldLog Fields Sync | `weld_logs` | UPDATE | Always (syncs 15+ fields) |
|
||
| 3 | Paint System Sync | `paint_systems`, `color_systems` | CREATE/UPDATE | When painting_cycle or fluid_code changes |
|
||
| 4 | Construction Paint Logs Sync | `construction_paint_logs` | CREATE/UPDATE | When line has painting_cycle and shop joints |
|
||
| 5 | Paint Follow Ups Sync | `paint_follow_ups`, `paint_matrices` | CREATE/UPDATE | When line has painting_cycle |
|
||
| 6 | Paint Matrix Operations | `paint_matrices`, `paint_follow_ups` | CREATE/UPDATE | When painting_cycle changes |
|
||
| 7 | NDE Matrix Sync | `nde_matrices` | CREATE/UPDATE | When line_no or fluid_code changes |
|
||
| 8 | Painting Cycle Deletion | `paint_matrices`, `paint_follow_ups`, `construction_paint_logs`, `nde_matrices` | DELETE | When painting_cycle is deleted |
|
||
| 9 | Spool Status Changer | `weld_logs` | UPDATE | When line_no changes |
|
||
| 10 | Paint System To Matrix | `paint_matrices` | UPDATE | When painting_cycle changes |
|
||
| 11 | Cleanup Operations | `paint_follow_ups` | DELETE | When line_no changes |
|
||
|
||
### Trigger 1: Paint Cycle Change (When painting_cycle changes)
|
||
|
||
**What it does**: When engineer changes painting cycle specification, updates all related welding records and removes old painting records.
|
||
|
||
**Tables Updated**:
|
||
- `weld_logs` → Updates `painting_cycle` column for all welds on this line
|
||
- `construction_paint_logs` → Deletes records that haven't started work yet (no dates filled)
|
||
|
||
**Columns Changed in weld_logs**:
|
||
- `painting_cycle` = new value from line_lists
|
||
|
||
**Business Logic**:
|
||
- If painting_cycle becomes EMPTY → Deletes construction_paint_logs (only if blasting/painting hasn't started)
|
||
- If painting_cycle has NEW VALUE → Updates all weld logs with new painting cycle
|
||
|
||
---
|
||
|
||
### Trigger 2: WeldLog Fields Sync (Always runs)
|
||
|
||
**What it does**: Copies 17 specification fields from line specification to all welding records.
|
||
|
||
**Tables Updated**:
|
||
- `weld_logs` → Updates all records matching this line number
|
||
|
||
**Columns Changed in weld_logs**:
|
||
```
|
||
painting_cycle ← line_lists.painting_cycle
|
||
main_nps ← line_lists.dn
|
||
fluid_code ← line_lists.fluid_code
|
||
service_category ← line_lists.category
|
||
fluid_group ← line_lists.fluid_group
|
||
piping_class ← line_lists.pipe_material_class
|
||
external_finish_type ← line_lists.external_finish_type
|
||
circuit_number ← line_lists.circuit_number
|
||
p_id ← line_lists.p_id
|
||
type_of_test ← line_lists.test_media
|
||
test_pressure ← line_lists.test_pressure_mpa
|
||
line_specification ← line_lists.line_specification
|
||
design_pressure_mpa ← line_lists.design_pressure_mpa
|
||
design_temperature_s ← line_lists.design_temperature
|
||
operating_pressure_mpa ← line_lists.working_pressure_mpa
|
||
operating_temperature_s← line_lists.working_temperature
|
||
ndt_percent ← line_lists.ndt
|
||
```
|
||
|
||
---
|
||
|
||
### Trigger 3: Paint System Sync (When painting_cycle or fluid_code changes)
|
||
|
||
**What it does**: Creates or updates paint system standards and color system specifications.
|
||
|
||
**Tables Updated**:
|
||
- `paint_systems` → Creates/updates one record per painting_cycle
|
||
- `color_systems` → Creates/updates one record per fluid_code
|
||
|
||
**Columns Changed in paint_systems**:
|
||
- `paint_cycle` = line_lists.painting_cycle
|
||
- `revision` = line_lists.rev
|
||
|
||
**Columns Changed in color_systems**:
|
||
- `fluid_code_description` = line_lists.fluid_ru
|
||
- `fluid_code` = line_lists.fluid_code
|
||
- `design_temperature` = line_lists.design_temperature
|
||
- `working_temperature` = line_lists.working_temperature
|
||
- `unit` = line_lists.unit
|
||
|
||
---
|
||
|
||
### Trigger 4: Construction Paint Logs Sync (When painting_cycle exists)
|
||
|
||
**What it does**: Creates painting tracking records for each spool that has shop joints.
|
||
|
||
**Tables Updated**:
|
||
- `construction_paint_logs` → Creates/updates one record per spool (only spools with shop joints)
|
||
|
||
**Columns Created/Updated**:
|
||
```
|
||
construction_report_no ← weld_logs.weld_map_no
|
||
test_package ← weld_logs.test_package_no
|
||
rev ← line_lists.rev
|
||
engineering ← line_lists.engineering
|
||
area ← weld_logs.project
|
||
unit ← weld_logs.design_area
|
||
line ← line_lists.line_no
|
||
iso_drawings ← weld_logs.iso_number
|
||
fluid_code ← line_lists.fluid_code
|
||
fluid_code_description ← line_lists.fluid_ru
|
||
isolation_info ← line_lists.external_finish_type
|
||
spool ← weld_logs.spool_number
|
||
spool_status ← weld_logs.spool_status (default: 'Waiting')
|
||
painting_system_type_1 ← paint_matrices.paint_cycle
|
||
painting_system_type_2 ← paint_matrices.paint_cycle
|
||
brend_name_1/2/3 ← paint_matrices (3 coat brands)
|
||
ral_1/2/3 ← paint_matrices (3 RAL codes)
|
||
color_1/2/3 ← paint_matrices (3 Russian colors)
|
||
thickness_1/2/3 ← paint_matrices (3 coat thicknesses)
|
||
dn_1/2/3 ← weld_logs (pipe diameters)
|
||
```
|
||
|
||
**Business Logic**:
|
||
- Only creates records for spools with `type_of_joint = 'S'` (shop joints)
|
||
- Protects records where painting has started (date fields are not null)
|
||
|
||
---
|
||
|
||
### Trigger 5: Paint Follow Ups Sync (When painting_cycle exists)
|
||
|
||
**What it does**: Creates detailed painting follow-up records for both shop and field work. Most complex trigger with temperature and volume calculations.
|
||
|
||
**Tables Updated**:
|
||
- `paint_matrices` → Creates if doesn't exist
|
||
- `paint_follow_ups` → Creates two types of records: SHOP and FIELD
|
||
|
||
**For SHOP Records** (one per spool):
|
||
```
|
||
location = 'SHOP'
|
||
spool_no_joint_no ← weld_logs.spool_number
|
||
project ← weld_logs.project
|
||
area ← line_lists.unit
|
||
line ← line_lists.line_no
|
||
iso_number ← weld_logs.iso_number
|
||
fluid_code ← line_lists.fluid_code
|
||
fluid_code_description ← line_lists.fluid_ru
|
||
cycle ← line_lists.painting_cycle
|
||
surface_roughness ← paint_matrices.surface_preparation
|
||
|
||
# 3 paint coats (primer, intermediate, final)
|
||
primer_coat_name_1 ← paint_matrices.primer_coat
|
||
brend_name_1 ← paint_matrices.brend_name_1
|
||
colour_1 ← paint_matrices.colour_1 (Russian)
|
||
ral_code_1 ← paint_matrices.ral_code_1
|
||
thickness_1 ← paint_matrices.thickness_1
|
||
(same pattern for coat 2 and 3)
|
||
|
||
# Calculated fields
|
||
substrate_temprature ← calculated from temperature settings (shop)
|
||
ambient_temprature ← calculated from temperature settings (shop)
|
||
volume_1/2/3 ← calculated from MTO table
|
||
total_volume = volume_1 + volume_2 + volume_3
|
||
status = 'In Progress'
|
||
```
|
||
|
||
**For FIELD Records** (one per joint):
|
||
```
|
||
location = 'FIELD'
|
||
spool_no_joint_no ← weld_logs.no_of_the_joint_as_per_as_built_survey
|
||
(same fields as SHOP, but different values)
|
||
surface_roughness ← paint_matrices.touch_up_of_damaged_parts
|
||
substrate_temprature ← calculated from temperature settings (field)
|
||
ambient_temprature ← calculated from temperature settings (field)
|
||
volume_1/2/3 ← calculated: π * (avg_nps)² * 200
|
||
```
|
||
|
||
**Business Logic**:
|
||
- **Date Protection**: If ANY date field is filled (primer_coating_start_date, etc.), keeps existing record
|
||
- **Painting Cycle Changes**:
|
||
- If dates filled → Marks old record as 'HOLD', creates new record
|
||
- If dates empty → Updates existing record to new cycle
|
||
- **Temperature Calculation**: Based on blasting_date and day of year from settings
|
||
- **Volume Calculation**: Different formulas for SHOP (from MTO) vs FIELD (from pipe diameter)
|
||
|
||
---
|
||
|
||
### Trigger 6: Paint Matrix Operations (When painting_cycle changes)
|
||
|
||
**What it does**: Creates/updates paint matrix (master painting specification) and syncs paint details to follow-up records.
|
||
|
||
**Tables Updated**:
|
||
- `paint_matrices` → Creates/updates one record per line + fluid_code
|
||
- `paint_follow_ups` → Updates surface roughness for all records
|
||
|
||
**Columns Created/Updated in paint_matrices**:
|
||
```
|
||
project ← weld_logs.project (zone info)
|
||
area ← line_lists.unit
|
||
description = 'PIPE'
|
||
line ← line_lists.line_no
|
||
fluid_code_description ← line_lists.fluid_ru
|
||
fluid_code ← line_lists.fluid_code
|
||
design_temperature ← line_lists.design_temperature
|
||
operation_temperature ← line_lists.working_temperature
|
||
paint_cycle ← line_lists.painting_cycle
|
||
```
|
||
|
||
**Columns Updated in paint_follow_ups**:
|
||
```
|
||
surface_roughness ← paint_matrices.surface_preparation (if spool starts with 'SPL')
|
||
← paint_matrices.touch_up_of_damaged_parts (if joint number)
|
||
cycle ← paint_matrices.paint_cycle
|
||
primer_coat_name_1 ← paint_matrices.primer_coat
|
||
brend_name_1/2/3 ← paint_matrices (3 coat brands)
|
||
colour_1/2/3 ← paint_matrices (3 coat colors)
|
||
ral_code_1/2/3 ← paint_matrices (3 RAL codes)
|
||
thickness_1/2/3 ← paint_matrices (3 coat thicknesses)
|
||
```
|
||
|
||
**Business Logic**:
|
||
- Only updates paint_follow_ups if ALL date fields are null (hasn't started work)
|
||
- Distinguishes SHOP records (SPL prefix) from FIELD records for surface roughness
|
||
|
||
---
|
||
|
||
### Trigger 7: NDE Matrix Sync (When line_no or fluid_code changes)
|
||
|
||
**What it does**: Creates testing requirement records for each type of weld joint on the line.
|
||
|
||
**Tables Updated**:
|
||
- `nde_matrices` → Creates/updates one record per unique combination of (line + joint_type + fluid_code)
|
||
|
||
**Columns Created/Updated**:
|
||
```
|
||
design_area ← line_lists.unit
|
||
fluid ← line_lists.fluid_code
|
||
line ← line_lists.line_no
|
||
line_spec ← line_lists.line_specification
|
||
operation_temp ← line_lists.working_temperature
|
||
operations_pressure_kg ← line_lists.working_pressure_mpa
|
||
pipe_material_class ← line_lists.pipe_material_class
|
||
type_of_joint ← weld_logs.type_of_welds (collected from all welds)
|
||
pwht ← line_lists.pwht
|
||
pwht_field ← line_lists.pwht
|
||
ht = 100 if pwht='YES', else 0
|
||
ndt ← line_lists.ndt
|
||
piping_class_according_to_gost ← line_lists.category
|
||
piping_group ← line_lists.fluid_group
|
||
rev ← line_lists.rev
|
||
```
|
||
|
||
**Business Logic**:
|
||
- Collects unique joint types from weld_logs (e.g., 'BW', 'SW', 'FW')
|
||
- Creates one nde_matrices record for each joint type
|
||
- Calculates ht (heat treatment) = 100 if PWHT required, else 0
|
||
|
||
---
|
||
|
||
### Trigger 8: Painting Cycle Deletion (When painting_cycle deleted)
|
||
|
||
**What it does**: Removes all painting-related records when painting cycle is removed from line specification.
|
||
|
||
**Tables Updated** (ALL DELETE operations):
|
||
- `paint_matrices` → Deletes records for this line + fluid_code
|
||
- `paint_follow_ups` → Deletes records (only if no dates filled)
|
||
- `construction_paint_logs` → Deletes records (only if no dates filled)
|
||
- `nde_matrices` → Deletes records for this line
|
||
|
||
**Conditions for Deletion**:
|
||
- paint_follow_ups: Only deletes if ALL these are NULL:
|
||
- primer_coating_start_date, primer_coating_finish_date
|
||
- start_intermediate_date2, finish_intermediate_date2
|
||
- final_coat_start_date3, final_coat_finish_date3
|
||
|
||
- construction_paint_logs: Only deletes if ALL these are NULL:
|
||
- blasting_date, blasting_finish_date
|
||
- painting_date_1, painting_finish_date_1
|
||
- painting_date_2, painting_finish_date_2
|
||
- painting_date_3, painting_finish_date_3
|
||
|
||
**Business Logic**: Protects completed work - never deletes records where work has started
|
||
|
||
---
|
||
|
||
### Trigger 9: Spool Status Changer (When line_no changes)
|
||
|
||
**What it does**: Recalculates completion status for each spool based on all testing and painting results.
|
||
|
||
**Tables Updated**:
|
||
- `weld_logs` → Updates `spool_status` column for all spools
|
||
|
||
**Business Logic**:
|
||
- Uses complex view logic (cron.spool-status-changer)
|
||
- Checks NDT results, painting completion, testing status
|
||
- Updates spool_status to values like: 'Waiting', 'In Progress', 'Completed', 'Failed'
|
||
|
||
---
|
||
|
||
### Trigger 10: Paint System To Matrix Sync (When painting_cycle changes)
|
||
|
||
**What it does**: Syncs detailed paint specifications from paint_systems and color_systems tables to paint_matrices.
|
||
|
||
**Tables Updated**:
|
||
- `paint_matrices` → Updates all records matching this painting_cycle
|
||
|
||
**Columns Updated**:
|
||
```
|
||
# From paint_systems
|
||
surface_preparation ← paint_systems.surface_preparation
|
||
touch_up_of_damaged_parts ← paint_systems.surface_roughness
|
||
primer_coat ← paint_systems.primer_coat_name_1
|
||
brend_name_1 ← paint_systems.brand_name_1
|
||
thickness_1 ← paint_systems.thickness_1
|
||
intermediate_coat ← paint_systems.primer_coat_name_2
|
||
brend_name_2 ← paint_systems.brand_name_2
|
||
thickness_2 ← paint_systems.thickness_2
|
||
final_coat ← paint_systems.primer_coat_name_3
|
||
brend_name_3 ← paint_systems.brand_name_3
|
||
thickness_3 ← paint_systems.thickness_3
|
||
total_thickness = thickness_1 + thickness_2 + thickness_3
|
||
|
||
# From color_systems
|
||
fluid_code_description ← color_systems.fluid_code_description
|
||
design_temperature ← color_systems.design_temperature
|
||
operation_temperature ← color_systems.working_temperature
|
||
ral_code_1/2/3 ← color_systems.ral_1/2/3
|
||
colour_1/2/3 ← Converted from RAL codes to Russian descriptions
|
||
```
|
||
|
||
**Business Logic**:
|
||
- Converts RAL codes to Russian color names using setting("ral-codes")
|
||
- Example: RAL 5015 → "Синий небесный" (Sky Blue in Russian)
|
||
|
||
---
|
||
|
||
### Trigger 11: Cleanup Operations (Non-critical cleanup)
|
||
|
||
**What it does**: Removes orphaned paint follow-up records that are no longer needed.
|
||
|
||
**Tables Updated**:
|
||
- `paint_follow_ups` → Deletes orphaned records
|
||
|
||
**Business Logic**:
|
||
- Uses view logic (cron.delete-no-paint-followup)
|
||
- Non-critical operation - logs warning if fails but doesn't stop execution
|
||
|
||
---
|
||
|
||
## Complete Data Flow Summary
|
||
|
||
```
|
||
Line List Save
|
||
↓
|
||
1. Paint Cycle Change (if painting_cycle changed)
|
||
→ weld_logs.painting_cycle = NEW VALUE
|
||
→ construction_paint_logs DELETE (if no dates)
|
||
↓
|
||
2. WeldLog Fields Sync (always)
|
||
→ weld_logs: 17 columns updated
|
||
↓
|
||
3. Paint System Sync
|
||
→ paint_systems: CREATE/UPDATE
|
||
→ color_systems: CREATE/UPDATE
|
||
↓
|
||
4. Construction Paint Logs Sync
|
||
→ construction_paint_logs: CREATE/UPDATE (per spool with shop joints)
|
||
↓
|
||
5. Paint Follow Ups Sync
|
||
→ paint_matrices: CREATE if missing
|
||
→ paint_follow_ups: CREATE SHOP records (per spool)
|
||
→ paint_follow_ups: CREATE FIELD records (per joint)
|
||
↓
|
||
6. Paint Matrix Operations
|
||
→ paint_matrices: CREATE/UPDATE
|
||
→ paint_follow_ups: UPDATE surface_roughness + paint details
|
||
↓
|
||
7. NDE Matrix Sync
|
||
→ nde_matrices: CREATE/UPDATE (per joint type)
|
||
↓
|
||
8. Painting Cycle Deletion (if painting_cycle deleted)
|
||
→ paint_matrices: DELETE
|
||
→ paint_follow_ups: DELETE (if no dates)
|
||
→ construction_paint_logs: DELETE (if no dates)
|
||
→ nde_matrices: DELETE
|
||
↓
|
||
9. Spool Status Changer
|
||
→ weld_logs.spool_status: UPDATE (recalculate)
|
||
↓
|
||
10. Paint System To Matrix Sync
|
||
→ paint_matrices: UPDATE (detailed specs + RAL to Russian)
|
||
↓
|
||
11. Cleanup Operations
|
||
→ paint_follow_ups: DELETE orphaned records
|
||
```
|
||
|
||
---
|
||
|
||
## Table of Contents
|
||
1. [Introduction](#introduction)
|
||
2. [Architecture Overview](#architecture-overview)
|
||
3. [System Components](#system-components)
|
||
4. [Trigger Breakdown](#trigger-breakdown)
|
||
5. [Execution Flow](#execution-flow)
|
||
6. [Data Flow Diagrams](#data-flow-diagrams)
|
||
7. [Key Concepts](#key-concepts)
|
||
8. [Development Guide](#development-guide)
|
||
9. [Troubleshooting](#troubleshooting)
|
||
10. [Performance Optimization](#performance-optimization)
|
||
|
||
---
|
||
|
||
## Introduction
|
||
|
||
The Line List Triggers System is a modular, service-based architecture designed to handle complex business logic when Line List records are created or updated. It replaces a monolithic 2070-line trigger file with 11 independent, testable, and maintainable trigger classes.
|
||
|
||
### Problem Solved
|
||
|
||
**Before**: A single 2070-line file with 11 different operations mixed together, making it:
|
||
- Difficult to understand and maintain
|
||
- Hard to test individual operations
|
||
- Prone to bugs due to tight coupling
|
||
- Challenging to extend with new features
|
||
|
||
**After**: 11 independent trigger classes, each with:
|
||
- Single Responsibility Principle
|
||
- Clear dependencies and execution order
|
||
- Comprehensive logging
|
||
- Easy to test and extend
|
||
|
||
---
|
||
|
||
## Architecture Overview
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ LineList Save Event │
|
||
└──────────────────────┬──────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ line_lists.php (Entry Point) │
|
||
│ - Detects changed fields │
|
||
│ - Determines if new record │
|
||
└──────────────────────┬──────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ LineListTriggerManager (Orchestrator) │
|
||
│ - Initializes registry │
|
||
│ - Gets triggers in order │
|
||
│ - Executes shouldRun() for each │
|
||
│ - Calls execute() for enabled triggers │
|
||
│ - Logs results │
|
||
└──────────────────────┬──────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ LineListTriggerRegistry (Trigger Manager) │
|
||
│ - Registers all 11 triggers │
|
||
│ - Provides triggers sorted by order │
|
||
└──────────────────────┬──────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ Individual Trigger Classes │
|
||
│ (11 triggers executed in sequence) │
|
||
│ │
|
||
│ 1. Paint Cycle Change │
|
||
│ 2. Painting Cycle Deletion │
|
||
│ 3. WeldLog Fields Sync │
|
||
│ 4. Paint Matrix Operations │
|
||
│ 5. NDE Matrix Sync │
|
||
│ 6. Paint System Sync │
|
||
│ 7. Paint System To Matrix Sync │
|
||
│ 8. Construction Paint Logs Sync │
|
||
│ 9. Paint Follow Ups Sync │
|
||
│ 10. Spool Status Changer Final │
|
||
│ 11. Cleanup Operations │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## System Components
|
||
|
||
### 1. LineListTriggerInterface
|
||
|
||
**Location**: `app/Services/LineListTriggers/Contracts/LineListTriggerInterface.php`
|
||
|
||
Defines the contract that all triggers must implement:
|
||
|
||
```php
|
||
interface LineListTriggerInterface
|
||
{
|
||
public function getName(): string;
|
||
public function getOrder(): int;
|
||
public function shouldRun(array $changedFields, bool $isNewRecord): bool;
|
||
public function getDependentFields(): array;
|
||
public function execute($lineListData, $beforeData = null, array $context = []): array;
|
||
public function isAsync(): bool;
|
||
}
|
||
```
|
||
|
||
### 2. BaseLineListTrigger
|
||
|
||
**Location**: `app/Services/LineListTriggers/Base/BaseLineListTrigger.php`
|
||
|
||
Provides common functionality:
|
||
- Execution timing
|
||
- Logging (start/end with duration)
|
||
- Default `shouldRun()` implementation
|
||
- Error handling
|
||
|
||
### 3. LineListTriggerRegistry
|
||
|
||
**Location**: `app/Services/LineListTriggers/LineListTriggerRegistry.php`
|
||
|
||
- Registers all triggers
|
||
- Provides sorted trigger list
|
||
- Enables/disables triggers
|
||
|
||
### 4. LineListTriggerManager
|
||
|
||
**Location**: `app/Services/LineListTriggers/LineListTriggerManager.php`
|
||
|
||
- Orchestrates trigger execution
|
||
- Handles `shouldRun` checks
|
||
- Provides overall logging
|
||
- Manages errors
|
||
|
||
---
|
||
|
||
## Trigger Breakdown
|
||
|
||
### Trigger 1: Paint Cycle Change Operations
|
||
|
||
**File**: `PaintCycleChangeTrigger.php`
|
||
**Order**: 1
|
||
**Execution Condition**: `painting_cycle` has changed
|
||
|
||
**Purpose**: Handles comprehensive operations when the painting cycle is modified
|
||
|
||
**Operations**:
|
||
1. **Spool Status Changer Trigger**
|
||
- Finds all weld logs with shop joints for this line
|
||
- Triggers spool-status-changer view for each unique spool
|
||
|
||
2. **WeldLogs Painting Cycle Update**
|
||
- Updates `painting_cycle` field in all weld logs for this line
|
||
|
||
3. **Comprehensive Paint Sync**
|
||
- Creates/updates Paint Follow Ups (SHOP and FIELD records)
|
||
- Creates/updates Construction Paint Logs
|
||
- Uses Paint Matrix and Paint System data
|
||
|
||
**Key Logic**:
|
||
- Only runs if `beforeData` exists and `painting_cycle` changed
|
||
- Processes both SHOP (spool-based) and FIELD (joint-based) records
|
||
- Pulls data from `paint_matrices` and `paint_systems` tables
|
||
|
||
---
|
||
|
||
### Trigger 2: Painting Cycle Deletion
|
||
|
||
**File**: `PaintingCycleDeletionTrigger.php`
|
||
**Order**: 2
|
||
**Execution Condition**: `painting_cycle` was deleted (changed from value to empty)
|
||
|
||
**Purpose**: Cleanup operations when painting cycle is removed
|
||
|
||
**Operations**:
|
||
1. Delete `paint_matrices` records
|
||
2. Delete `paint_follow_ups` records (only if date fields are null)
|
||
3. Delete `construction_paint_logs` records (only if date fields are null)
|
||
4. Delete `nde_matrices` records
|
||
|
||
**Date Field Protection**: Does NOT delete records if any of these date fields are filled:
|
||
- `primer_coating_start_date`, `primer_coating_finish_date`
|
||
- `start_intermediate_date2`, `finish_intermediate_date2`
|
||
- `final_coat_start_date3`, `final_coat_finish_date3`
|
||
- (for construction_paint_logs: blasting dates, painting dates, rfi dates)
|
||
|
||
---
|
||
|
||
### Trigger 3: WeldLog Fields Sync
|
||
|
||
**File**: `WeldLogFieldsSyncTrigger.php`
|
||
**Order**: 3
|
||
**Execution Condition**: Always runs
|
||
|
||
**Purpose**: Synchronize 15+ fields from line_lists to weld_logs
|
||
|
||
**Fields Synchronized**:
|
||
```php
|
||
- painting_cycle
|
||
- main_nps (from dn)
|
||
- fluid_code
|
||
- service_category (from category)
|
||
- fluid_group
|
||
- piping_class (from pipe_material_class)
|
||
- external_finish_type
|
||
- circuit_number
|
||
- p_id
|
||
- type_of_test (from test_media)
|
||
- test_pressure (from test_pressure_mpa)
|
||
- line_specification
|
||
- design_pressure_mpa
|
||
- design_temperature_s (from design_temperature)
|
||
- operating_pressure_mpa (from working_pressure_mpa)
|
||
- operating_temperature_s (from working_temperature)
|
||
- ndt_percent (from ndt)
|
||
```
|
||
|
||
**Logic**: Updates all `weld_logs` records where `line_number` matches `line_lists.line_no`
|
||
|
||
---
|
||
|
||
### Trigger 4: Paint Matrix Operations
|
||
|
||
**File**: `PaintMatrixOperationsTrigger.php`
|
||
**Order**: 4
|
||
**Execution Condition**: `painting_cycle`, `line_no`, `fluid_code`, or `unit` changed
|
||
|
||
**Purpose**: Create/update Paint Matrix and sync to Paint Follow Ups
|
||
|
||
**Operations**:
|
||
1. **Get Zone Information**
|
||
- Fetches `project` field from weld logs for zone assignment
|
||
|
||
2. **Create/Update Paint Matrix**
|
||
- Unique constraint: `line + fluid_code`
|
||
- Updates or creates paint matrix record
|
||
|
||
3. **Surface Preparation Sync**
|
||
- Syncs `surface_preparation` (for SHOP) and `touch_up_of_damaged_parts` (for FIELD)
|
||
- From `paint_matrices` to `paint_follow_ups`
|
||
|
||
4. **Paint Coat Details Sync**
|
||
- Syncs 3 coats (primer, intermediate, final)
|
||
- Brand names, colors, RAL codes, thickness
|
||
- Only updates if ALL date fields are empty
|
||
|
||
**Key Data Structures**:
|
||
```php
|
||
$whereData = ['line' => $line_no, 'fluid_code' => $fluid_code];
|
||
$updateData = [
|
||
'project', 'area', 'description', 'line', 'fluid_code_description',
|
||
'fluid_code', 'design_temperature', 'operation_temperature', 'paint_cycle'
|
||
];
|
||
```
|
||
|
||
---
|
||
|
||
### Trigger 5: NDE Matrix Sync
|
||
|
||
**File**: `NdeMatrixSyncTrigger.php`
|
||
**Order**: 5
|
||
**Execution Condition**: Multiple fields (line_no, fluid_code, unit, etc.)
|
||
|
||
**Purpose**: Comprehensive NDE Matrix synchronization from WeldLogs and LineList
|
||
|
||
**Operations**:
|
||
1. **Collect Spec Joint Types**
|
||
- Reads all weld logs for this line
|
||
- Groups by `fluid_code`, `line_number`, and `type_of_welds`
|
||
- Creates array: `$specJointTypes[$fluid_code][$line_no][] = type_of_welds`
|
||
|
||
2. **Update Fluid Codes in WeldLogs**
|
||
- If weld log has empty fluid_code, copies from line list
|
||
|
||
3. **Create/Update NDE Matrices**
|
||
- Unique constraint: `line + type_of_joint + fluid`
|
||
- For each spec joint type, creates or updates NDE matrix
|
||
- Calculates `ht` (100 if pwht is "YES", else 0)
|
||
|
||
**PWHT Logic**:
|
||
```php
|
||
$ht = 0;
|
||
if($lineListData->pwht == "YES") $ht = 100;
|
||
```
|
||
|
||
**Data Fields**:
|
||
```php
|
||
$data = [
|
||
'design_area', 'fluid', 'line', 'line_spec', 'operation_temp',
|
||
'operations_pressure_kg', 'pipe_material_class', 'type_of_joint',
|
||
'pwht', 'pwht_field', 'ht', 'ndt',
|
||
'piping_class_according_to_gost', 'piping_group', 'rev'
|
||
];
|
||
```
|
||
|
||
---
|
||
|
||
### Trigger 6: Paint System Sync
|
||
|
||
**File**: `PaintSystemSyncTrigger.php`
|
||
**Order**: 6
|
||
**Execution Condition**: `painting_cycle`, `rev`, `fluid_code`, etc. changed
|
||
|
||
**Purpose**: Sync to paint_systems and color_systems tables
|
||
|
||
**Operations**:
|
||
1. **Paint Systems**
|
||
- Updates or inserts into `paint_systems` table
|
||
- Key: `paint_cycle`
|
||
- Data: `paint_cycle`, `revision`
|
||
|
||
2. **Color Systems**
|
||
- Updates or inserts into `color_systems` table
|
||
- Key: `fluid_code`
|
||
- Data: `fluid_code_description`, `fluid_code`, `design_temperature`,
|
||
`working_temperature`, `unit`
|
||
|
||
---
|
||
|
||
### Trigger 7: Paint System To Matrix Sync
|
||
|
||
**File**: `PaintSystemToMatrixSyncTrigger.php`
|
||
**Order**: 7
|
||
**Execution Condition**: `painting_cycle`, `fluid_code`, `line_no` changed
|
||
|
||
**Purpose**: Sync paint_systems + color_systems data to paint_matrices
|
||
|
||
**Operations**:
|
||
1. **Get Paint System and Color System**
|
||
- Fetches from respective tables
|
||
|
||
2. **RAL Code to Russian Color Mapping**
|
||
- Uses `setting("ral-codes")` JSON
|
||
- Maps `ral_1`, `ral_2`, `ral_3` to Russian color descriptions
|
||
|
||
3. **Update Paint Matrices**
|
||
- Finds all paint matrices with matching `paint_cycle`
|
||
- Updates with:
|
||
- Surface preparation data
|
||
- 3 coat details (primer, intermediate, final)
|
||
- Brand names, thickness, total thickness
|
||
- RAL codes and Russian color descriptions
|
||
|
||
**RAL Mapping Logic**:
|
||
```php
|
||
foreach ($ralCodes as $entry) {
|
||
if (isset($entry['ral_code']) && $entry['ral_code'] == $ralCode && isset($entry['ru'])) {
|
||
return $entry['ru'];
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### Trigger 8: Construction Paint Logs Sync
|
||
|
||
**File**: `ConstructionPaintLogsSyncTrigger.php`
|
||
**Order**: 8
|
||
**Execution Condition**: `line_no`, `painting_cycle`, `fluid_code`, etc. changed
|
||
|
||
**Purpose**: Comprehensive Construction Paint Logs synchronization
|
||
|
||
**Operations**:
|
||
1. **Get Paint Matrix and Paint System**
|
||
- Fetches related data for RAL values and paint system details
|
||
|
||
2. **Process Each Weld Log**
|
||
- Only processes spools with shop joints
|
||
- Creates unique constraint: `line + spool + unit + painting_system_type_1`
|
||
|
||
3. **Handle Painting Cycle Changes**
|
||
- **If record with same painting cycle exists**: Update it
|
||
- **If records with different painting cycles exist**:
|
||
- Check if any date fields are filled
|
||
- If dates filled: Keep old record with current status (protect completed work)
|
||
- If dates empty: Update old record to new painting cycle
|
||
|
||
4. **Create New Records**
|
||
- Only if no existing record can be updated
|
||
- Sets all date fields to null
|
||
|
||
**Date Fields Checked**:
|
||
```php
|
||
$hasAnyDateFilled = !empty($blasting_date) ||
|
||
!empty($blasting_finish_date) ||
|
||
!empty($painting_date_1) || !empty($painting_finish_date_1) ||
|
||
!empty($painting_date_2) || !empty($painting_finish_date_2) ||
|
||
!empty($painting_date_3) || !empty($painting_finish_date_3) ||
|
||
!empty($rfi_date_1) || !empty($rfi_date_2) || !empty($rfi_date_3);
|
||
```
|
||
|
||
---
|
||
|
||
### Trigger 9: Paint Follow Ups Sync
|
||
|
||
**File**: `PaintFollowUpsSyncTrigger.php`
|
||
**Order**: 9
|
||
**Execution Condition**: `line_no`, `painting_cycle`, `fluid_code`, etc. changed
|
||
|
||
**Purpose**: Most complex trigger - comprehensive Paint Follow Ups synchronization
|
||
|
||
**Operations**:
|
||
1. **Get or Create Paint Matrix**
|
||
- Ensures paint matrix exists for this line
|
||
|
||
2. **Temperature Calculations**
|
||
- Loads temperature settings from system settings
|
||
- Gets blasting_date from construction_paint_logs
|
||
- Calculates day of year and looks up temperature data
|
||
|
||
3. **Volume Calculations**
|
||
- **F Volume** (Field): `π * (avg_nps)² * 200`
|
||
- **S Volume** (Shop): Sum from MTO table
|
||
|
||
4. **Process SHOP Records**
|
||
- Based on `spool_number`
|
||
- Only if shop joint exists for this spool
|
||
- Unique constraint: `line + spool_no_joint_no + cycle + location`
|
||
- Handles painting cycle changes with date protection
|
||
|
||
5. **Process FIELD Records**
|
||
- Based on `no_of_the_joint_as_per_as_built_survey`
|
||
- Unique constraint: `line + spool_no_joint_no + cycle + location`
|
||
- Handles painting cycle changes with date protection
|
||
|
||
**Date Protection Logic**:
|
||
```php
|
||
$hasAllEmptyDates = empty($primer_coating_start_date) &&
|
||
empty($primer_coating_finish_date) &&
|
||
empty($start_intermediate_date2) &&
|
||
empty($finish_intermediate_date2) &&
|
||
empty($final_coat_start_date3) &&
|
||
empty($final_coat_finish_date3);
|
||
|
||
if ($hasAllEmptyDates) {
|
||
// Full update allowed
|
||
} else {
|
||
// Only update temperature and volume if empty
|
||
}
|
||
```
|
||
|
||
**Temperature and Volume Updates**:
|
||
- Even if dates are filled, updates temp/volume fields if they are empty
|
||
- SHOP: Uses `temp_material_shop`, `shop_ambient`
|
||
- FIELD: Uses `temp_material_field`, `field_ambient`
|
||
|
||
---
|
||
|
||
### Trigger 10: Spool Status Changer Final
|
||
|
||
**File**: `SpoolStatusChangerFinalTrigger.php`
|
||
**Order**: 10
|
||
**Execution Condition**: `line_no` changed
|
||
|
||
**Purpose**: Final spool status changer after all syncs
|
||
|
||
**Operations**:
|
||
- Renders `cron.spool-status-changer` view
|
||
- Re-calculates spool statuses based on all updated data
|
||
|
||
---
|
||
|
||
### Trigger 11: Cleanup Operations
|
||
|
||
**File**: `CleanupOperationsTrigger.php`
|
||
**Order**: 11
|
||
**Execution Condition**: `line_no` changed
|
||
|
||
**Purpose**: Non-critical cleanup operations
|
||
|
||
**Operations**:
|
||
- Renders `cron.delete-no-paint-followup` view
|
||
- Deletes orphaned paint follow up records
|
||
|
||
**Error Handling**: Non-critical - logs warning if fails, doesn't throw exception
|
||
|
||
---
|
||
|
||
## Execution Flow
|
||
|
||
### Step-by-Step Flow
|
||
|
||
1. **LineList Save Triggered**
|
||
```php
|
||
// AdminController or DevExtreme save operation
|
||
$lineList->save();
|
||
```
|
||
|
||
2. **Trigger File Called**
|
||
```php
|
||
// app/Http/Controllers/SaveTrigger/line_lists.php
|
||
$id = $request['key'];
|
||
$lineList = db($tableName)->where("id", $id)->first();
|
||
```
|
||
|
||
3. **Detect Changes**
|
||
```php
|
||
$isNewRecord = is_null($beforeData);
|
||
$changedFields = detectChangedFields($lineList, $beforeData);
|
||
```
|
||
|
||
4. **Initialize Manager**
|
||
```php
|
||
$registry = new LineListTriggerRegistry();
|
||
$manager = new LineListTriggerManager($registry);
|
||
```
|
||
|
||
5. **Execute Triggers**
|
||
```php
|
||
$results = $manager->executeTriggers(
|
||
$lineList,
|
||
$beforeData,
|
||
$changedFields,
|
||
$isNewRecord
|
||
);
|
||
```
|
||
|
||
6. **For Each Trigger**:
|
||
- Check `shouldRun()`
|
||
- If true, call `execute()`
|
||
- Log start time
|
||
- Run `process()` method
|
||
- Log completion with duration
|
||
- Return results
|
||
|
||
7. **Log Overall Completion**
|
||
- Total execution time
|
||
- Peak memory usage
|
||
- Results summary
|
||
|
||
---
|
||
|
||
## Data Flow Diagrams
|
||
|
||
### Paint Cycle Change Flow
|
||
|
||
```
|
||
LineList.painting_cycle changed
|
||
│
|
||
├─> Trigger Spool Status Changer
|
||
│ └─> For each spool with shop joint
|
||
│ └─> view('cron.spool-status-changer')
|
||
│
|
||
├─> Update WeldLogs
|
||
│ └─> UPDATE weld_logs SET painting_cycle = ?
|
||
│
|
||
└─> Comprehensive Paint Sync
|
||
├─> Get Paint Matrix data
|
||
├─> Get Paint System data
|
||
│
|
||
├─> Paint Follow Ups
|
||
│ ├─> SHOP records (spool-based)
|
||
│ └─> FIELD records (joint-based)
|
||
│
|
||
└─> Construction Paint Logs
|
||
└─> For each spool with shop joint
|
||
```
|
||
|
||
### Paint Follow Ups Sync Flow
|
||
|
||
```
|
||
LineList saved
|
||
│
|
||
├─> Get/Create Paint Matrix
|
||
│
|
||
├─> Load Temperature Settings
|
||
│ └─> Get blasting_date from construction_paint_logs
|
||
│ └─> Calculate day of year
|
||
│ └─> Lookup temperature data
|
||
│
|
||
├─> Calculate Volumes
|
||
│ ├─> F Volume = π * (avg_nps)² * 200
|
||
│ └─> S Volume = SUM from MTO table
|
||
│
|
||
├─> For each Weld Log
|
||
│ │
|
||
│ ├─> SHOP Record Processing
|
||
│ │ ├─> Check if shop joint exists
|
||
│ │ ├─> Build base data + temp + volume
|
||
│ │ ├─> Check unique constraint
|
||
│ │ ├─> Find existing record with same cycle
|
||
│ │ ├─> Find records with different cycles
|
||
│ │ │
|
||
│ │ ├─> IF existing record with same cycle
|
||
│ │ │ ├─> IF all dates empty → Full update
|
||
│ │ │ └─> IF dates filled → Update only empty temp/volume
|
||
│ │ │
|
||
│ │ └─> IF no existing record with same cycle
|
||
│ │ ├─> Handle old records with different cycles
|
||
│ │ │ ├─> IF dates filled → Mark as HOLD
|
||
│ │ │ └─> IF dates empty → Update to new cycle
|
||
│ │ └─> Create new record
|
||
│ │
|
||
│ └─> FIELD Record Processing
|
||
│ └─> (Same logic as SHOP, but for joint_no)
|
||
│
|
||
└─> Return results
|
||
```
|
||
|
||
---
|
||
|
||
## Key Concepts
|
||
|
||
### 1. Unique Constraints
|
||
|
||
Different tables have different unique constraints:
|
||
|
||
**NDE Matrix**: `line + type_of_joint + fluid`
|
||
|
||
**Paint Follow Ups**: `line + spool_no_joint_no + cycle + location`
|
||
|
||
**Construction Paint Logs**: `line + spool + unit + painting_system_type_1`
|
||
|
||
**Paint Matrix**: `line + fluid_code`
|
||
|
||
### 2. Date Field Protection
|
||
|
||
When painting cycles change, the system protects records where work has already started (date fields filled):
|
||
|
||
**Paint Follow Ups Date Fields**:
|
||
- `primer_coating_start_date`, `primer_coating_finish_date`
|
||
- `start_intermediate_date2`, `finish_intermediate_date2`
|
||
- `final_coat_start_date3`, `final_coat_finish_date3`
|
||
|
||
**Construction Paint Logs Date Fields**:
|
||
- `blasting_date`, `blasting_finish_date`
|
||
- `painting_date_1`, `painting_finish_date_1`
|
||
- `painting_date_2`, `painting_finish_date_2`
|
||
- `painting_date_3`, `painting_finish_date_3`
|
||
- `rfi_date_1`, `rfi_date_2`, `rfi_date_3`
|
||
|
||
**Protection Logic**:
|
||
- If **ALL dates empty**: Full record update allowed
|
||
- If **ANY date filled**:
|
||
- Keep existing record
|
||
- Mark as HOLD or keep current status
|
||
- Create new record for new painting cycle
|
||
- Only update empty temperature/volume fields
|
||
|
||
### 3. SHOP vs FIELD Records
|
||
|
||
**SHOP Records**:
|
||
- Based on `spool_number`
|
||
- Location: 'SHOP'
|
||
- Only created if shop joint (type_of_joint = 'S') exists for spool
|
||
- Uses S Volume
|
||
- Uses shop temperature data
|
||
|
||
**FIELD Records**:
|
||
- Based on `no_of_the_joint_as_per_as_built_survey` (joint number)
|
||
- Location: 'FIELD'
|
||
- Created for every joint with a joint number
|
||
- Uses F Volume
|
||
- Uses field temperature data
|
||
|
||
### 4. Temperature and Volume Calculations
|
||
|
||
**Temperature Data**:
|
||
- Stored in system settings as JSON
|
||
- Indexed by day of year (0-365)
|
||
- Includes: `temp_material_shop`, `shop_ambient`, `temp_material_field`, `field_ambient`
|
||
- Based on `blasting_date` from construction_paint_logs
|
||
|
||
**Volume Calculations**:
|
||
```php
|
||
// F Volume (Field)
|
||
$fAvgNps = weld_logs->where("type_of_joint", "F")->avg("nps_1");
|
||
$fVolume = round(π * pow($fAvgNps, 2) * 200, 2);
|
||
|
||
// S Volume (Shop)
|
||
$mtoTotal = SUM(quantity * POWER(odmm_1/2000, 2) * π) from m_t_o_s;
|
||
$sVolume = round($mtoTotal, 2);
|
||
```
|
||
|
||
---
|
||
|
||
## Development Guide
|
||
|
||
### Adding a New Trigger
|
||
|
||
1. **Create Trigger Class**
|
||
|
||
```php
|
||
<?php
|
||
|
||
namespace App\Services\LineListTriggers\Triggers;
|
||
|
||
use App\Services\LineListTriggers\Base\BaseLineListTrigger;
|
||
use Illuminate\Support\Facades\Log;
|
||
|
||
class MyNewTrigger extends BaseLineListTrigger
|
||
{
|
||
public function getName(): string
|
||
{
|
||
return 'My New Trigger';
|
||
}
|
||
|
||
public function getOrder(): int
|
||
{
|
||
return 12; // Choose appropriate order
|
||
}
|
||
|
||
public function getDependentFields(): array
|
||
{
|
||
return ['field1', 'field2']; // Fields this trigger cares about
|
||
}
|
||
|
||
protected function process($lineListData, $beforeData, array $context): array
|
||
{
|
||
// Your logic here
|
||
Log::debug("My trigger is processing", [
|
||
'line_no' => $lineListData->line_no
|
||
]);
|
||
|
||
// Do your operations
|
||
|
||
return [
|
||
'success' => true,
|
||
'records_processed' => 10
|
||
];
|
||
}
|
||
}
|
||
```
|
||
|
||
2. **Register in Registry**
|
||
|
||
```php
|
||
// app/Services/LineListTriggers/LineListTriggerRegistry.php
|
||
|
||
protected function registerTriggers()
|
||
{
|
||
// ... existing triggers ...
|
||
$this->register(new MyNewTrigger());
|
||
}
|
||
```
|
||
|
||
3. **Test**
|
||
- Create a test line list record
|
||
- Modify dependent fields
|
||
- Check logs
|
||
- Verify operations
|
||
|
||
### Modifying Existing Trigger
|
||
|
||
1. **Find the Trigger Class**
|
||
- Navigate to `app/Services/LineListTriggers/Triggers/`
|
||
- Open the appropriate trigger file
|
||
|
||
2. **Modify `process()` Method**
|
||
- Make your changes
|
||
- Add logging for debugging
|
||
- Return results array
|
||
|
||
3. **Update Documentation**
|
||
- Update this guide if logic changed
|
||
- Update trigger README if needed
|
||
|
||
### Testing
|
||
|
||
**Unit Testing** (Recommended):
|
||
```php
|
||
use App\Services\LineListTriggers\Triggers\MyTrigger;
|
||
|
||
$trigger = new MyTrigger();
|
||
|
||
$lineList = (object) [
|
||
'line_no' => 'TEST-001',
|
||
'painting_cycle' => 'PC-01'
|
||
];
|
||
|
||
$result = $trigger->execute($lineList, null, []);
|
||
|
||
$this->assertTrue($result['success']);
|
||
```
|
||
|
||
**Integration Testing**:
|
||
1. Create test line list record in database
|
||
2. Modify fields
|
||
3. Check logs in `storage/logs/laravel.log`
|
||
4. Verify database changes
|
||
|
||
---
|
||
|
||
## Troubleshooting
|
||
|
||
### Common Issues
|
||
|
||
#### 1. Trigger Not Running
|
||
|
||
**Symptoms**: Trigger not executing when expected
|
||
|
||
**Diagnosis**:
|
||
- Check `shouldRun()` logic
|
||
- Verify dependent fields are actually changing
|
||
- Check logs for "Skipping trigger" messages
|
||
|
||
**Solution**:
|
||
```php
|
||
// Override shouldRun for debugging
|
||
public function shouldRun(array $changedFields, bool $isNewRecord): bool
|
||
{
|
||
Log::debug("shouldRun check", [
|
||
'trigger' => $this->getName(),
|
||
'changedFields' => $changedFields,
|
||
'dependentFields' => $this->getDependentFields(),
|
||
'isNewRecord' => $isNewRecord
|
||
]);
|
||
|
||
return parent::shouldRun($changedFields, $isNewRecord);
|
||
}
|
||
```
|
||
|
||
#### 2. Date Fields Not Protected
|
||
|
||
**Symptoms**: Records with filled dates being overwritten
|
||
|
||
**Diagnosis**:
|
||
- Check `hasAllEmptyDates()` logic
|
||
- Verify date field names match database
|
||
|
||
**Solution**:
|
||
```php
|
||
// Add detailed logging
|
||
$hasAllEmptyDates = $this->hasAllEmptyDates($record);
|
||
Log::debug("Date protection check", [
|
||
'record_id' => $record->id,
|
||
'hasAllEmptyDates' => $hasAllEmptyDates,
|
||
'date_fields' => [
|
||
'primer_coating_start_date' => $record->primer_coating_start_date,
|
||
'primer_coating_finish_date' => $record->primer_coating_finish_date,
|
||
// ... other dates
|
||
]
|
||
]);
|
||
```
|
||
|
||
#### 3. Duplicate Records Created
|
||
|
||
**Symptoms**: Multiple records with same unique constraint
|
||
|
||
**Diagnosis**:
|
||
- Check unique constraint conditions
|
||
- Verify `whereCondition` vs `uniqueConstraintCondition`
|
||
|
||
**Solution**:
|
||
```php
|
||
// Add logging before insert
|
||
Log::debug("Checking for existing record", [
|
||
'uniqueConstraint' => $uniqueConstraintCondition,
|
||
'existing' => $existingRecord ? $existingRecord->id : 'none'
|
||
]);
|
||
```
|
||
|
||
#### 4. Performance Issues
|
||
|
||
**Symptoms**: Trigger execution takes too long
|
||
|
||
**Diagnosis**:
|
||
- Check logs for execution duration
|
||
- Identify slow triggers
|
||
|
||
**Solution**:
|
||
- Add indexes to frequently queried fields
|
||
- Optimize database queries
|
||
- Consider caching
|
||
|
||
### Debugging Tips
|
||
|
||
1. **Enable Detailed Logging**:
|
||
```php
|
||
// Add at start of process() method
|
||
Log::debug("=== {$this->getName()} DETAILED DEBUG ===", [
|
||
'lineList' => $lineListData,
|
||
'beforeData' => $beforeData,
|
||
'context' => $context
|
||
]);
|
||
```
|
||
|
||
2. **Check Execution Order**:
|
||
```php
|
||
// In LineListTriggerManager
|
||
Log::debug("Executing triggers in order", [
|
||
'triggers' => array_map(fn($t) => [
|
||
'name' => $t->getName(),
|
||
'order' => $t->getOrder()
|
||
], $triggers)
|
||
]);
|
||
```
|
||
|
||
3. **Monitor Database Changes**:
|
||
```sql
|
||
-- Check recent changes
|
||
SELECT * FROM paint_follow_ups
|
||
WHERE updated_at > NOW() - INTERVAL 1 MINUTE
|
||
ORDER BY updated_at DESC;
|
||
```
|
||
|
||
---
|
||
|
||
## Performance Optimization
|
||
|
||
### Current Performance
|
||
|
||
- **Total Execution Time**: ~2-5 seconds for typical line list save
|
||
- **Memory Usage**: ~50-100 MB peak
|
||
- **Database Queries**: ~50-100 queries per save
|
||
|
||
### Optimization Strategies
|
||
|
||
#### 1. Query Optimization
|
||
|
||
**Before**:
|
||
```php
|
||
foreach ($weldLogs as $weldLog) {
|
||
$hasShopJoint = db("weld_logs")
|
||
->where('line_number', $lineList->line_no)
|
||
->where('spool_number', $weldLog->spool_number)
|
||
->where('type_of_joint', 'S')
|
||
->exists();
|
||
}
|
||
// N+1 query problem
|
||
```
|
||
|
||
**After**:
|
||
```php
|
||
$spoolsWithShopJoints = db("weld_logs")
|
||
->where('line_number', $lineList->line_no)
|
||
->where('type_of_joint', 'S')
|
||
->pluck('spool_number')
|
||
->toArray();
|
||
|
||
foreach ($weldLogs as $weldLog) {
|
||
$hasShopJoint = in_array($weldLog->spool_number, $spoolsWithShopJoints);
|
||
}
|
||
// Single query
|
||
```
|
||
|
||
#### 2. Caching
|
||
|
||
```php
|
||
// Cache paint matrix for this line
|
||
$cacheKey = "paint_matrix_{$lineList->line_no}_{$lineList->fluid_code}";
|
||
$paintMatrix = Cache::remember($cacheKey, 60, function() use ($lineList) {
|
||
return PaintMatrix::where('line', $lineList->line_no)
|
||
->where('fluid_code', $lineList->fluid_code)
|
||
->first();
|
||
});
|
||
```
|
||
|
||
#### 3. Batch Operations
|
||
|
||
```php
|
||
// Instead of individual inserts
|
||
foreach ($data as $item) {
|
||
db("paint_follow_ups")->insert($item);
|
||
}
|
||
|
||
// Use batch insert
|
||
db("paint_follow_ups")->insert($dataArray);
|
||
```
|
||
|
||
#### 4. Conditional Execution
|
||
|
||
```php
|
||
// Skip expensive operations if data hasn't changed
|
||
if (!in_array('painting_cycle', $changedFields)) {
|
||
return ['skipped' => true, 'reason' => 'painting_cycle_unchanged'];
|
||
}
|
||
```
|
||
|
||
### Monitoring
|
||
|
||
**Add Performance Logging**:
|
||
```php
|
||
protected function process($lineListData, $beforeData, array $context): array
|
||
{
|
||
$queryCount = DB::getQueryLog();
|
||
$memoryStart = memory_get_usage();
|
||
|
||
// Your logic here
|
||
|
||
$memoryEnd = memory_get_usage();
|
||
$memoryUsed = $memoryEnd - $memoryStart;
|
||
|
||
Log::info("Performance metrics", [
|
||
'trigger' => $this->getName(),
|
||
'queries_executed' => count(DB::getQueryLog()) - count($queryCount),
|
||
'memory_used_mb' => round($memoryUsed / 1024 / 1024, 2)
|
||
]);
|
||
|
||
return $results;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Conclusion
|
||
|
||
The Line List Triggers System provides a robust, maintainable, and extensible architecture for handling complex business logic. By breaking down the monolithic trigger file into 11 independent classes, we've achieved:
|
||
|
||
✅ **Better Maintainability**: Each trigger has a single responsibility
|
||
✅ **Improved Testability**: Easy to unit test individual triggers
|
||
✅ **Clear Documentation**: Each trigger is well-documented
|
||
✅ **Enhanced Logging**: Detailed execution tracking
|
||
✅ **Easy Extension**: Simple to add new triggers
|
||
✅ **Performance Monitoring**: Built-in execution time tracking
|
||
|
||
For questions or issues, please refer to:
|
||
- [Service README](../../app/Services/LineListTriggers/README.md)
|
||
- [WeldLog Triggers System](weld-log-triggers-system.md)
|
||
- DevQMS Developer Documentation
|
||
|