System Diagram
The Solar Farm Maintenance Operations Hub data model, mapped — 50 models, 143 relationships
🔍 For serious exploration, open the Interactive Diagram Viewer — pan, mouse-wheel zoom, fit-to-screen, full-screen, per-module tabs, the full 143-relationship ERD, and a focus mode that draws one model and its neighbours at a chosen depth.
Person(31 links),WorkOrder(22) andAsset(15) are role/work/equipment columns that fan out to nearly everything, so the viewer hides those links by default — a toggle brings them back. The diagrams below are the readable, static summary of the principal links only.
Architecture Overview
Eight areas mirror the sidebar menu. Every arrow means "one row of the left model is referenced by many rows of the right model".
flowchart LR
subgraph ASSET["🔆 Assets & portfolio"]
Portfolio --> SolarFarm
SolarFarm --> SiteZone
SiteZone --> AssetLocation
AssetType --> Asset
SolarFarm --> Asset
end
subgraph REQ["⚠️ Requests & defects"]
AlarmEventReference --> ServiceRequest
ServiceRequest --> Defect
Defect --> OperationalImpact
Defect --> PriorityAssessment
WeatherEvent
end
subgraph WORK["🛠️ Work management"]
MaintenanceTemplate --> MaintenanceTemplateTask
WorkOrder --> WorkTask
WorkOrder --> WorkAssignment
WorkOrder --> WorkDependency
WorkOrder --> WorkStatusHistory
end
subgraph SAFE["🦺 Safety & access"]
WorkOrder --> IsolationReference
WorkOrder --> AccessRequirement
WorkOrder --> SafetyDocument
Competency --> PersonCompetency
end
subgraph FIELD["🔧 Field execution"]
Inspection --> InspectionResult
WorkOrder --> Measurement
WorkOrder --> Evidence
WorkOrder --> TestResult
WorkOrder --> ReturnToService
ReturnToService --> Verification
WorkOrder --> Closeout
end
subgraph PART["📦 Parts & warranty"]
Part --> PartStock
WorkOrder --> PartUsage
WorkOrder --> RemovedComponent
RemovedComponent --> WarrantyClaim
end
subgraph VEG["🌿 Vegetation & site"]
VegetationZone --> VegetationInspection
end
subgraph ADMIN["🏢 Administration"]
Organisation --> Person
InspectionTemplate --> InspectionTemplateItem
end
Asset --> AlarmEventReference
Defect --> WorkOrder
Defect --> WarrantyClaim
Defect --> Verification
Defect --> Closeout
WorkOrder --> Inspection
SolarFarm --> VegetationZone
(WorkOrder is the hub of execution — 22 relationships touch it — because every
field record, safety reference, part transaction and closure act hangs off the
job. Person has the most links (31) because every maintenance act records
who: requested, assessed, approved, planned, supervised, assigned, isolated,
inspected, measured, tested, returned, verified, closed.)
Assets, Portfolio and Location
The equipment being maintained. SiteZone and Asset each self-nest; an asset
lives at a location within a zone of a farm, and carries a type.
erDiagram
Organisation ||--o{ Portfolio : "owner_organisation_id"
Person ||--o{ Portfolio : "manager_person_id"
Portfolio ||--o{ SolarFarm : "portfolio_id"
Organisation ||--o{ SolarFarm : "owner_organisation_id"
SolarFarm ||--o{ SiteZone : "solar_farm_id"
SiteZone ||--o{ SiteZone : "parent_zone_id"
SolarFarm ||--o{ AssetLocation : "solar_farm_id"
SiteZone ||--o{ AssetLocation : "site_zone_id"
AssetType ||--o{ Asset : "asset_type_id"
SolarFarm ||--o{ Asset : "solar_farm_id"
AssetLocation ||--o{ Asset : "asset_location_id"
Asset ||--o{ Asset : "parent_asset_id"
Asset ||--o{ AssetRelationship : "source_asset_id"
Asset ||--o{ AssetRelationship : "target_asset_id"
Organisation ||--o{ SourceSystem : "owner_organisation_id"
Detection — Alarms, Requests and Defects
The three doors into the system converge on Defect, which carries its own
impact and priority.
erDiagram
SolarFarm ||--o{ AlarmEventReference : "solar_farm_id"
Asset ||--o{ AlarmEventReference : "asset_id"
SourceSystem ||--o{ AlarmEventReference : "source_system_id"
AlarmEventReference ||--o{ ServiceRequest : "alarm_event_reference_id"
SolarFarm ||--o{ ServiceRequest : "solar_farm_id"
ServiceRequest ||--o{ Defect : "service_request_id"
DefectCategory ||--o{ Defect : "defect_category_id"
Asset ||--o{ Defect : "asset_id"
Defect ||--o{ Defect : "parent_defect_id"
Defect ||--o{ OperationalImpact : "defect_id"
Defect ||--o{ PriorityAssessment : "defect_id"
SolarFarm ||--o{ WeatherEvent : "solar_farm_id"
Work Management
The planned response. A work order can be generated from a maintenance template, sits under a defect, and self-nests for parent/child jobs.
erDiagram
AssetType ||--o{ MaintenanceTemplate : "asset_type_id"
MaintenanceTemplate ||--o{ MaintenanceTemplateTask : "maintenance_template_id"
Defect ||--o{ WorkOrder : "defect_id"
MaintenanceTemplate ||--o{ WorkOrder : "maintenance_template_id"
WorkOrder ||--o{ WorkOrder : "parent_work_order_id"
SolarFarm ||--o{ WorkOrder : "solar_farm_id"
WorkOrder ||--o{ WorkTask : "work_order_id"
WorkOrder ||--o{ WorkAssignment : "work_order_id"
WorkOrder ||--o{ WorkDependency : "work_order_id"
WorkOrder ||--o{ WorkDependency : "related_work_order_id"
WorkOrder ||--o{ WorkStatusHistory : "work_order_id"
Safety and Access
Making the job safe before it starts. IsolationReference carries the full
proved-dead sequence; SafetyDocument joins a work order to a controlled
document.
erDiagram
WorkOrder ||--o{ IsolationReference : "work_order_id"
Asset ||--o{ IsolationReference : "asset_id"
WorkOrder ||--o{ AccessRequirement : "work_order_id"
WorkOrder ||--o{ SafetyDocument : "work_order_id"
Document ||--o{ SafetyDocument : "document_id"
Competency ||--o{ PersonCompetency : "competency_id"
Person ||--o{ PersonCompetency : "person_id"
Document ||--o{ PersonCompetency : "evidence_document_id"
Field Execution and the Three Acts of Closure
The field record, then the three deliberately separate closure steps. This is the model's core assurance argument.
erDiagram
AssetType ||--o{ InspectionTemplate : "asset_type_id"
InspectionTemplate ||--o{ InspectionTemplateItem : "inspection_template_id"
InspectionTemplate ||--o{ Inspection : "inspection_template_id"
WorkOrder ||--o{ Inspection : "work_order_id"
Asset ||--o{ Inspection : "asset_id"
Inspection ||--o{ InspectionResult : "inspection_id"
InspectionTemplateItem ||--o{ InspectionResult : "inspection_template_item_id"
WorkOrder ||--o{ Measurement : "work_order_id"
Asset ||--o{ Measurement : "asset_id"
WorkOrder ||--o{ Evidence : "work_order_id"
WorkOrder ||--o{ TechnicianNote : "work_order_id"
WorkOrder ||--o{ TestResult : "work_order_id"
Evidence ||--o{ TestResult : "evidence_id"
WorkOrder ||--o{ ReturnToService : "work_order_id"
Defect ||--o{ Verification : "defect_id"
ReturnToService ||--o{ Verification : "return_to_service_id"
Defect ||--o{ Closeout : "defect_id"
WorkOrder ||--o{ Closeout : "work_order_id"
Parts and Warranty
Lightweight materials and recovery. A required part is issued, used, and — if it failed under warranty — booked out as a removed component and claimed.
erDiagram
Part ||--o{ PartStock : "part_id"
StockLocation ||--o{ PartStock : "stock_location_id"
WorkOrder ||--o{ PartRequirement : "work_order_id"
Part ||--o{ PartRequirement : "part_id"
WorkOrder ||--o{ PartUsage : "work_order_id"
Part ||--o{ PartUsage : "part_id"
WorkOrder ||--o{ RemovedComponent : "work_order_id"
Part ||--o{ RemovedComponent : "part_id"
Defect ||--o{ WarrantyClaim : "defect_id"
RemovedComponent ||--o{ WarrantyClaim : "removed_component_id"
Organisation ||--o{ WarrantyClaim : "manufacturer_organisation_id"
Vegetation
A specialist stream with the same shape as the electrical work: a managed zone, inspected against target and intervention heights, raising defects and work like any other.
erDiagram
SolarFarm ||--o{ VegetationZone : "solar_farm_id"
SiteZone ||--o{ VegetationZone : "site_zone_id"
VegetationZone ||--o{ VegetationInspection : "vegetation_zone_id"
WorkOrder ||--o{ VegetationInspection : "work_order_id"
Defect ||--o{ VegetationInspection : "defect_id"
Application Flow — Detection to Closeout
The order in which the system is actually used, and what gates each step.
flowchart TD
A["📟 Alarm / inspection / operator request"] --> B["🧾 Service request"]
B --> C["⚠️ Defect<br/><i>impact + priority assessed</i>"]
C --> D{"Work needed?"}
D -->|yes| E["🛠️ Work order planned + assigned"]
E --> F{"Isolation required?"}
F -->|yes| G["🔌 Isolation applied → PROVED_DEAD → released"]
F -->|no| H
G --> H["🚧 Access arranged · SWMS accepted"]
H --> I["🔧 Field work<br/><i>tasks, measurements, evidence, tests</i>"]
I --> J{"Parts replaced?"}
J -->|yes| K["📦 Part used · component removed<br/>→ warranty claim if applicable"]
J -->|no| L
K --> L["♻️ Return to service<br/><i>isolation restored · alarms cleared · output confirmed</i>"]
L --> M["🔎 Verification<br/><i>independent — ACCEPTED / REJECTED / FURTHER_WORK / MONITOR</i>"]
M --> N{"Accepted?"}
N -->|no| I
N -->|yes| O["🏁 Closeout<br/><i>failure mode · root cause · capacity restored</i>"]
O --> P["Defect → CLOSED"]
Application Flow — Why "Work Finished" Is Not "Defect Closed"
The single most important distinction in the domain, drawn out.
flowchart TD
S(["Technician finishes physical work"]) --> R1["♻️ ReturnToService written<br/><i>is the EQUIPMENT safe to run?</i>"]
R1 --> R2{"Isolation restored · protection normal<br/>· alarms cleared · output confirmed?"}
R2 -->|no| R1
R2 -->|yes| V1["🔎 Verification written<br/><i>is the DEFECT actually resolved?</i>"]
V1 --> V2{"Independent check —<br/>accepted?"}
V2 -->|"REJECTED / FURTHER_WORK"| B["↩️ Back to field work"]
V2 -->|"MONITOR"| M["⏱️ Follow-up scheduled<br/><i>follow_up_due_at</i>"]
V2 -->|"ACCEPTED"| C1["🏁 Closeout written<br/><i>the DEFECT is formally closed</i>"]
C1 --> C2["Defect.defect_status → CLOSED<br/>client_accepted_by recorded"]
Reading the Diagrams
A ||--o{ Bmeans one row of A is referenced by many rows of B (the label is the foreign-key column on B).- These static diagrams show principal links only — the role columns that
appear on nearly every model (
*_person_id,work_order_id,asset_id,solar_farm_id) are omitted for readability. The interactive viewer's Full ERD shows all 143, with the person/work/asset noise toggleable. WorkOrderis the hub of execution (22 links) andPersonhas the most (31), because every maintenance act records who performed each role — the viewer's Focus mode is the fastest way to see one model's neighbourhood.- No foreign key was dropped in translation — the pack had no true reference
cycle. Four self-references are kept:
SiteZone.parent_zone_id,Asset.parent_asset_id,Defect.parent_defect_idandWorkOrder.parent_work_order_id. TheAuditRecordmodel was dropped (the framework provides audit history); everything else in the source model is present. - One pointer is deliberately not a foreign key in spirit:
AlarmEventReferenceand theexternal_*/raw_reference_urlcolumns are governed references to events and records that live in external systems (SCADA, CMMS, drone platforms), not edges into them.
Diagrams are derived from the generated schema metadata
(apps/solarfarm/generated/json/solarfarm_relationship_metadata.json). If the DSL
schema changes, regenerate the metadata (python -m codegen.cli all solarfarm),
rebuild the viewer (python apps/solarfarm/scripts/build_diagram_viewer.py) and
update this page.