TGM Expert provides comprehensive maintenance management through a unified Maintenance Record system, along with failures, preventive maintenance planning, and root cause analysis.

Table of Contents


Overview

Unified Maintenance Record Model

As of V86, inspections, interventions, and work orders have been unified into a single maintenance_records table with a record_type discriminator. This simplifies the data model, reduces code duplication, and provides a consistent API surface.

                    MaintenanceRecord
                   ┌─────────────────┐
                   │  record_type:   │
                   │  INSPECTION  or │
                   │  INTERVENTION   │
                   └────────┬────────┘
                            │
              ┌─────────────┼─────────────┐
              │             │             │
         Inspections   Interventions   Shared
         (diagnostic)  (corrective)    fields

Maintenance Workflow

  Maintenance Plan (scheduled)
         │
         ▼
  MaintenanceRecord (INSPECTION)
         │
    Issue Found? ────────> Failure Record
         │                      │
         ▼                      ▼
  MaintenanceRecord         RCA (if major)
    (INTERVENTION)
         │
         ▼
     Completed

Maintenance Types

Type Description
Preventive Scheduled, time-based maintenance
Predictive Condition-based, using sensor data
Corrective Reactive, fixing failures
Emergency Urgent unplanned repairs

Maintenance Records

Entity Structure

The MaintenanceRecord entity unifies what were previously separate Inspection, Intervention, and WorkOrder entities. A recordType field (INSPECTION or INTERVENTION) distinguishes the type.

{
  "id": 1,
  "recordType": "INSPECTION",
  "reportNumber": "INS-2026-0001",
  "title": "Monthly Turbine Inspection",
  "status": "OPEN",
  "priority": "MEDIUM",
  "maintenanceType": "PREVENTIVE",
  "plannedDate": "2026-03-01",
  "startDate": null,
  "scheduleDate": "2026-02-25",
  "creationDate": "2026-02-20T10:00:00Z",

  "costAllocation": "CAPEX",
  "actionPlan": "Follow standard turbine inspection checklist",
  "comments": null,
  "relevantInformation": "Unit has been running continuously for 6 months",
  "recommendations": null,
  "estimatedRevenueShortFall": 0,
  "isRiskComponents": false,
  "productInterruption": "NONE",
  "unitStatus": "RUNNING",
  "operatingMode": "NORMAL",
  "waterLevel": "NORMAL",
  "systemIsolationCompleted": false,

  "inspectionType": "ROUTINE",
  "inspectionNature": "VISUAL",
  "inspectionLevel": "LEVEL_1",
  "reasonForInspection": "Scheduled quarterly inspection",

  "customFields": {
    "weatherConditions": "Clear"
  },

  "units": [{"id": 100, "name": "Turbine Unit 1"}],
  "users": [{"id": 50, "name": "John Smith"}],
  "initiators": [{"id": 45, "name": "Operations Manager"}],
  "departments": [{"id": 10, "name": "Mechanical"}],
  "subAssemblies": [],
  "components": [{"id": 1000, "name": "Governor Valve"}],

  "createdAt": "2026-02-20T10:00:00Z",
  "updatedAt": "2026-02-20T10:00:00Z"
}

Shared Fields (All Record Types)

Field Type Description
id Long Unique identifier
recordType Enum INSPECTION or INTERVENTION
reportNumber String Unique report number (auto-generated)
title String Title of the maintenance record
status Enum Current status (see Status section)
priority Enum Priority level
maintenanceType String Preventive, Corrective, etc.
plannedDate Date Planned execution date
startDate Date Actual start date
scheduleDate Date Scheduled date
creationDate DateTime When the record was created
costAllocation String Cost allocation category
actionPlan Text Description of planned actions
comments Text General comments
relevantInformation Text Relevant context
recommendations Text Post-completion recommendations
estimatedRevenueShortFall Decimal Estimated revenue impact
isRiskComponents Boolean Whether risk components are involved
productInterruption String Product interruption status
unitStatus String Unit status during maintenance
operatingMode String Operating mode during maintenance
waterLevel String Water level (hydro-specific)
systemIsolationCompleted Boolean Whether system isolation is done
sevenDaysReminderSent Boolean 7-day reminder flag
threeDaysReminderSent Boolean 3-day reminder flag
sameDayReminderSent Boolean Same-day reminder flag
customFields JSONB Custom field values
deleted Boolean Soft-delete flag

Inspection-Specific Fields

These fields are only populated when recordType = INSPECTION:

Field Type Description
inspectionType String Type of inspection (ROUTINE, PERIODIC, etc.)
inspectionNature String Nature of the inspection
inspectionLevel String Inspection level
reasonForInspection String Reason for the inspection
calendarPlanning String Calendar planning info
meteringParameter1-5 String Metering parameter readings
periodicity String Inspection periodicity
periodicityHash String Hash for periodicity detection
hasardAnalysisCompleted Boolean JSA completed
hasardAnalysisJsaNumber String JSA document number
maintenanceJsa String Maintenance JSA info
maintenanceTimes String Maintenance time details
processedIndex Integer Processed index for batch processing
initialInspection Boolean Whether this is an initial inspection
woGroupInformation String Work order group info
scheduleFollowUp String Follow-up scheduling info
locationId Long FK to locations table

Intervention-Specific Fields

These fields are only populated when recordType = INTERVENTION:

Field Type Description
reasonForIntervention String Reason for the intervention
eventNature String Nature of the triggering event
eventDescriptionType String Event description type
plannedOutageDuration String Planned outage duration
isProjectRelated Boolean Whether project-related
isMultiTeamsWork Boolean Whether multiple teams involved
immediate Boolean Whether this is an emergency intervention
interventionJsa String Intervention JSA info
Relationship Link Table Description
Units maintenance_records_unit_links Units being maintained
Users maintenance_records_users_links Assigned technicians
Initiators maintenance_records_initiator_links Who requested the work
Departments maintenance_records_departments_links Involved departments
Sub-assemblies maintenance_records_sub_assembly_links Sub-assemblies involved
Components maintenance_records_components_links Components being worked on
Inspection Components inspection_components_maintenance_record_links Inspection component results

Record Types

INSPECTION

Inspections are diagnostic maintenance records. They represent scheduled or unplanned assessments of equipment condition.

Use cases: - Routine periodic inspections - Condition-based assessments - Pre/post-outage inspections - Regulatory compliance checks

INTERVENTION

Interventions are corrective maintenance records. They represent actions taken to fix, maintain, or improve equipment.

Use cases: - Corrective repairs - Preventive maintenance tasks - Emergency repairs - Equipment improvements


API Endpoints

Primary Endpoint: /api/maintenance-records

This is the primary unified endpoint for all maintenance records.

Method Endpoint Description
GET /api/maintenance-records List all maintenance records
GET /api/maintenance-records/{id} Get a specific record
POST /api/maintenance-records Create a record
PUT /api/maintenance-records/{id} Update a record
DELETE /api/maintenance-records/{id} Delete a record

Filtering

Use query parameters to filter results. The GenericSpecificationBuilder supports any field:

# Get all inspections
GET /api/maintenance-records?recordType=INSPECTION

# Get all open interventions
GET /api/maintenance-records?recordType=INTERVENTION&status=OPEN

# Get high-priority records for a specific unit
GET /api/maintenance-records?priority=HIGH&units.id=100

# Pagination
GET /api/maintenance-records?page=0&size=25&sort=createdAt,desc

Create an Inspection

curl -X POST https://api.tgm-expert.com/api/maintenance-records \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "recordType": "INSPECTION",
    "title": "Quarterly Turbine Inspection",
    "maintenanceType": "PREVENTIVE",
    "priority": "MEDIUM",
    "plannedDate": "2026-03-01",
    "inspectionType": "ROUTINE",
    "inspectionNature": "VISUAL",
    "reasonForInspection": "Scheduled quarterly inspection"
  }'

Create an Intervention

curl -X POST https://api.tgm-expert.com/api/maintenance-records \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "recordType": "INTERVENTION",
    "title": "Seal Replacement - Unit 1",
    "maintenanceType": "CORRECTIVE",
    "priority": "HIGH",
    "plannedDate": "2026-02-10",
    "reasonForIntervention": "Worn seals detected during inspection",
    "immediate": false
  }'

Response Format

{
  "data": {
    "id": 1,
    "recordType": "INSPECTION",
    "reportNumber": "INS-2026-0001",
    "title": "Quarterly Turbine Inspection",
    "status": "OPEN",
    ...
  },
  "message": "Success"
}

Paginated List Response

{
  "data": [
    {"id": 1, "recordType": "INSPECTION", ...},
    {"id": 2, "recordType": "INTERVENTION", ...}
  ],
  "total": 150,
  "page": 0,
  "size": 25
}

Backward Compatibility

Legacy API Endpoints (Deprecated)

The following endpoints are maintained for backward compatibility. They delegate to the unified MaintenanceRecordService with automatic recordType filtering.

Legacy Endpoint Maps To Auto-filter
GET /api/inspections GET /api/maintenance-records?recordType=INSPECTION recordType=INSPECTION
POST /api/inspections POST /api/maintenance-records Forces recordType=INSPECTION
GET /api/interventions GET /api/maintenance-records?recordType=INTERVENTION recordType=INTERVENTION
POST /api/interventions POST /api/maintenance-records Forces recordType=INTERVENTION

These endpoints will be removed in a future release. Migrate to /api/maintenance-records as soon as possible.

Database Views

SQL views are created for backward compatibility with raw SQL queries, reports, and external tools:

-- Returns only inspection-type records with legacy column names
SELECT * FROM inspections;

-- Returns only intervention-type records with legacy column names
SELECT * FROM interventions;

Link table views are also available: - inspections_unit_links, inspections_users_links, etc. - interventions_unit_links, interventions_users_links, etc.

These views are read-only. All writes go through maintenance_records directly.

Entity Type Normalization

For polymorphic references (Notes, SLA breach records), the backend normalizes legacy entity type strings:

Legacy Value Normalized To
Inspection MaintenanceRecord
Intervention MaintenanceRecord
WorkOrder MaintenanceRecord

The NoteService automatically converts these values when querying, so clients using old entity types will still retrieve the correct notes.

Backup Tables

The original tables are preserved as backups after the V86 migration: - inspections_backup_v86 - interventions_backup_v86 - All link tables: *_backup_v86

These will be dropped in a future release after confirming all systems have migrated.

Migration Traceability

Every migrated record in maintenance_records has: - legacy_type'inspection' or 'intervention' (the original table) - legacy_id — the original ID from the source table

Inspection records preserve their original IDs. Intervention records receive new auto-generated IDs (use legacy_id to trace back to the original interventions table).


Notes & Chat

Notes

Notes are polymorphic — they reference a maintenance record via entity_type + entity_id.

# Get notes for a maintenance record
GET /api/notes?entityType=MaintenanceRecord&entityId=1

# Get note count
GET /api/notes/count-by-entity?entityType=MaintenanceRecord&entityId=1

# Create a note
POST /api/notes
{
  "entityType": "MaintenanceRecord",
  "entityId": 1,
  "content": "Seal inspection completed. Minor wear detected.",
  "isPrivate": false
}

The author is automatically set from the authenticated user's security context.

Chat

Chat conversations can be linked to a maintenance record via the maintenance_record_id column on chat_conversations.

# Get conversation for a maintenance record
GET /api/chat/conversations/maintenance-record/{maintenanceRecordId}

# Create a conversation linked to a maintenance record
POST /api/chat/conversations
{
  "name": "Turbine Inspection Discussion",
  "type": "GROUP",
  "maintenanceRecordId": 1,
  "participantIds": [50, 55]
}

Failures

Failure Entity

{
  "id": 1,
  "title": "Governor Valve Seal Leak",
  "type": "MECHANICAL",
  "severity": "MODERATE",
  "status": "RESOLVED",
  "unit": {"id": 100, "name": "Turbine Unit 1"},
  "component": {"id": 1000, "name": "Governor Valve"},
  "occurredAt": "2026-02-05T14:30:00Z",
  "detectedAt": "2026-02-05T14:35:00Z",
  "resolvedAt": "2026-02-10T15:00:00Z",
  "downtimeHours": 120,
  "impact": "Unit tripped, unplanned outage",
  "resolution": "Replaced worn seals, unit returned to service",
  "estimatedLoss": 50000.00
}

Failure Types

Type Description
MECHANICAL Mechanical failure
ELECTRICAL Electrical failure
HYDRAULIC Hydraulic system failure
INSTRUMENTATION Sensor/control failure
STRUCTURAL Structural damage
HUMAN_ERROR Operator error
EXTERNAL External factors

Failure Severity

Severity Description
MINOR No operational impact
MODERATE Reduced performance
MAJOR Significant impact
CRITICAL Complete failure

API Endpoints

Method Endpoint Description
GET /api/failures List failures
GET /api/failures/{id} Get failure
POST /api/failures Record failure
PUT /api/failures/{id} Update failure
DELETE /api/failures/{id} Delete failure
POST /api/failures/{id}/resolve Mark resolved

Record Failure

curl -X POST https://api.tgm-expert.com/api/failures \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Governor Valve Seal Leak",
    "type": "MECHANICAL",
    "severity": "MODERATE",
    "unitId": 100,
    "componentId": 1000,
    "occurredAt": "2026-02-05T14:30:00Z",
    "impact": "Unit tripped, unplanned outage",
    "causeId": 5
  }'

Maintenance Plans

Maintenance plans define recurring preventive maintenance schedules. They can auto-generate MaintenanceRecord entries when due.

Maintenance Plan Entity

{
  "id": 1,
  "name": "Quarterly Turbine Maintenance",
  "type": "PREVENTIVE",
  "frequency": "QUARTERLY",
  "status": "ACTIVE",
  "unit": {"id": 100, "name": "Turbine Unit 1"},
  "components": [
    {"id": 1000, "name": "Governor Valve"},
    {"id": 1001, "name": "Servo Motor"}
  ],
  "tasks": [
    "Inspect seals and gaskets",
    "Check oil levels",
    "Test emergency stop",
    "Calibrate sensors"
  ],
  "estimatedDuration": 8,
  "estimatedCost": 5000.00,
  "lastExecutedAt": "2025-12-15",
  "nextDueAt": "2026-03-15",
  "leadTimeInDays": 7,
  "assignedTo": {"id": 55, "name": "Mike Johnson"}
}

Plan Frequencies

Frequency Description
DAILY Every day
WEEKLY Every week
BIWEEKLY Every 2 weeks
MONTHLY Every month
QUARTERLY Every 3 months
SEMIANNUAL Every 6 months
ANNUAL Every year
CUSTOM Custom interval

Plan-to-Record Connection

When a maintenance plan is executed (either manually or by the scheduler), it creates a MaintenanceRecord with: - recordType derived from the plan type (PREVENTIVE → INSPECTION, CORRECTIVE → INTERVENTION) - maintenancePlanId FK linking back to the originating plan

API Endpoints

Method Endpoint Description
GET /api/maintenance-plans List plans
GET /api/maintenance-plans/{id} Get plan
POST /api/maintenance-plans Create plan
PUT /api/maintenance-plans/{id} Update plan
DELETE /api/maintenance-plans/{id} Delete plan
GET /api/maintenance-plans/due Get due plans
POST /api/maintenance-plans/{id}/execute Execute plan

Create Plan

curl -X POST https://api.tgm-expert.com/api/maintenance-plans \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Monthly Oil Analysis",
    "type": "PREDICTIVE",
    "frequency": "MONTHLY",
    "unitId": 100,
    "componentIds": [1000, 1001],
    "tasks": [
      "Collect oil sample",
      "Send to lab",
      "Review results"
    ],
    "estimatedDuration": 2,
    "assignedToId": 55,
    "leadTimeInDays": 3
  }'

Root Cause Analysis

RCA Entity

{
  "id": 10,
  "title": "Governor Valve Seal Failure Analysis",
  "status": "IN_PROGRESS",
  "failure": {"id": 1, "title": "Governor Valve Seal Leak"},
  "methodology": "5_WHY",
  "team": [
    {"id": 50, "name": "John Smith", "role": "Lead"},
    {"id": 55, "name": "Mike Johnson", "role": "Member"}
  ],
  "startedAt": "2026-02-11",
  "dueDate": "2026-02-25",
  "rootCauses": [
    {
      "cause": "Seal material degradation",
      "category": "MATERIAL",
      "evidence": "Visual inspection showed hardened seal material"
    }
  ],
  "correctiveActions": [
    {
      "action": "Replace with upgraded seal material",
      "assignedTo": {"id": 55},
      "dueDate": "2026-03-01",
      "status": "IN_PROGRESS"
    }
  ],
  "preventiveActions": [
    {
      "action": "Update maintenance plan to include seal inspection",
      "assignedTo": {"id": 50},
      "dueDate": "2026-02-28",
      "status": "PENDING"
    }
  ],
  "lessons": "Seal materials should be reviewed for compatibility with operating conditions"
}

RCA Methodologies

Method Description
5_WHY 5 Whys analysis
FISHBONE Ishikawa diagram
FMEA Failure Mode and Effects
FTA Fault Tree Analysis
PARETO Pareto analysis

API Endpoints

Method Endpoint Description
GET /api/rca List RCAs
GET /api/rca/{id} Get RCA
POST /api/rca Create RCA
PUT /api/rca/{id} Update RCA
POST /api/rca/{id}/causes Add root cause
POST /api/rca/{id}/actions Add corrective action
POST /api/rca/{id}/complete Complete RCA

SLA & Reminders

Service Level Agreements

SLAs can be configured for maintenance records. The entity type for SLA breach records is MAINTENANCE_RECORD.

{
  "id": 1,
  "name": "Critical Inspection SLA",
  "entityType": "MAINTENANCE_RECORD",
  "targetResolutionHours": 24,
  "warningThresholdHours": 18,
  "priority": "CRITICAL"
}

The SlaBreachDetectionScheduler monitors all maintenance records and creates breach records when SLA thresholds are exceeded.

Automated Reminders

The MaintenanceReminderScheduler sends reminders at three intervals: - 7 days before planned date (sevenDaysReminderSent) - 3 days before planned date (threeDaysReminderSent) - Same day as planned date (sameDayReminderSent)

The OverdueMaintenanceScheduler checks for records past their planned date and creates notifications.


Database Schema

Core Table: maintenance_records

CREATE TABLE maintenance_records (
    id                          BIGSERIAL PRIMARY KEY,
    record_type                 VARCHAR(20) NOT NULL,  -- 'INSPECTION' or 'INTERVENTION'
    report_number               VARCHAR(255) UNIQUE,
    title                       VARCHAR(500),
    status                      VARCHAR(50),
    priority                    VARCHAR(50),
    maintenance_type            VARCHAR(100),
    planned_date                DATE,
    start_date                  DATE,
    schedule_date               DATE,
    creation_date               TIMESTAMP(6),

    -- Shared fields
    cost_allocation             VARCHAR(255),
    action_plan                 TEXT,
    comments                    TEXT,
    relevant_information        TEXT,
    recommendations             TEXT,
    estimated_revenue_short_fall DECIMAL,
    is_risk_components          BOOLEAN DEFAULT FALSE,
    product_interruption        VARCHAR(255),
    unit_status                 VARCHAR(100),
    operating_mode              VARCHAR(100),
    water_level                 VARCHAR(100),
    system_isolation_completed  BOOLEAN DEFAULT FALSE,
    seven_days_reminder_sent    BOOLEAN DEFAULT FALSE,
    three_days_reminder_sent    BOOLEAN DEFAULT FALSE,
    same_day_reminder_sent      BOOLEAN DEFAULT FALSE,
    custom_fields               JSONB,
    deleted                     BOOLEAN DEFAULT FALSE,

    -- Inspection-specific (NULL for interventions)
    inspection_type             VARCHAR(100),
    inspection_nature           VARCHAR(100),
    inspection_level            VARCHAR(100),
    reason_for_inspection       TEXT,
    calendar_planning           VARCHAR(255),
    metering_parameter_1        VARCHAR(255),
    metering_parameter_2        VARCHAR(255),
    metering_parameter_3        VARCHAR(255),
    metering_parameter_4        VARCHAR(255),
    metering_parameter_5        VARCHAR(255),
    periodicity                 VARCHAR(255),
    periodicity_hash            VARCHAR(255),
    hasard_analysis_completed   BOOLEAN,
    hasard_analysis_jsa_number  VARCHAR(255),
    maintenance_jsa             VARCHAR(255),
    maintenance_times           VARCHAR(255),
    processed_index             INTEGER,
    initial_inspection          BOOLEAN,
    wo_group_information        VARCHAR(500),
    schedule_follow_up          VARCHAR(255),
    location_id                 BIGINT REFERENCES locations(id),

    -- Intervention-specific (NULL for inspections)
    reason_for_intervention     TEXT,
    event_nature                VARCHAR(255),
    event_description_type      VARCHAR(255),
    planned_outage_duration     VARCHAR(255),
    is_project_related          BOOLEAN,
    is_multi_teams_work         BOOLEAN,
    immediate                   BOOLEAN,
    intervention_jsa            VARCHAR(255),

    -- Traceability
    legacy_type                 VARCHAR(50),   -- 'inspection' or 'intervention'
    legacy_id                   BIGINT,        -- original ID from source table
    maintenance_plan_id         BIGINT REFERENCES maintenance_plans(id),

    -- Audit
    created_at                  TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP,
    updated_at                  TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP,
    published_at                TIMESTAMP(6),
    created_by_id               BIGINT,
    updated_by_id               BIGINT
);
-- Units associated with a maintenance record
CREATE TABLE maintenance_records_unit_links (
    id                    BIGSERIAL PRIMARY KEY,
    maintenance_record_id BIGINT REFERENCES maintenance_records(id),
    unit_id               BIGINT REFERENCES units(id)
);

-- Same pattern for:
-- maintenance_records_users_links (user_id)
-- maintenance_records_initiator_links (user_id)
-- maintenance_records_departments_links (department_id)
-- maintenance_records_sub_assembly_links (sub_assembly_id)
-- maintenance_records_components_links (component_id)
-- inspection_components_maintenance_record_links (inspection_component_id)

Key Indexes

CREATE INDEX idx_maintenance_records_record_type ON maintenance_records(record_type);
CREATE INDEX idx_maintenance_records_status ON maintenance_records(status);
CREATE INDEX idx_maintenance_records_planned_date ON maintenance_records(planned_date);
CREATE INDEX idx_maintenance_records_report_number ON maintenance_records(report_number);
CREATE INDEX idx_maintenance_records_legacy ON maintenance_records(legacy_type, legacy_id);

Webhook Events

Event Description
MAINTENANCE_RECORD_CREATED A new record was created
MAINTENANCE_RECORD_UPDATED A record was updated
MAINTENANCE_RECORD_DELETED A record was deleted

Legacy events (INSPECTION_CREATED, INTERVENTION_CREATED, etc.) are deprecated aliases.

Corrective Actions

Corrective actions link to maintenance records (interventions) via maintenance_record_id:

ALTER TABLE corrective_actions
    ADD COLUMN maintenance_record_id BIGINT REFERENCES maintenance_records(id);

Rollback

A revert script is available at docs/revert_v86_maintenance_records.sql. This script: 1. Drops backward-compatible views 2. Restores polymorphic references (notes, SLA breach records) to legacy entity types 3. Drops unified link tables and maintenance_records table 4. Restores backup tables to original names 5. Removes V86 from Flyway history

Important: After running the revert script, all Spring Boot, Flutter SDK, Angular SDK, and Flutter Inspector code must also be reverted to use the separate Inspection/Intervention entities.