TGM Expert provides comprehensive grid services management for energy assets, enabling operators to manage ancillary services, grid connections, and curtailment events with full financial impact tracking.
Table of Contents¶
- Overview
- Data Model
- Ancillary Services
- Grid Connections
- Curtailment Events
- API Reference
- Ancillary Services API
- Grid Connections API
- Curtailment Events API
- Multi-Tenancy
- Examples
Overview¶
Key Features¶
- Ancillary Service Contracts - Track frequency regulation, spinning reserve, voltage support, and other grid services
- Grid Connection Management - Monitor interconnection points, voltage levels, and capacity limits
- Curtailment Tracking - Record curtailment events with financial impact analysis
- Financial Impact Dashboard - Calculate total lost revenue, compensation, and net impact
- Performance Monitoring - Track availability targets vs. actual performance
- Unit Association - Link all grid services to specific generating units
Architecture¶
AncillaryService GridConnection
├── Company ├── Company
├── Unit ├── Unit
└── (contract details) └── CurtailmentEvent[]
├── Company
└── Unit
Data Model¶
AncillaryService Entity¶
| Field | Type | Description |
|---|---|---|
id |
Long | Auto-generated primary key |
serviceName |
String | Name of the ancillary service |
description |
String | Detailed description |
serviceType |
AncillaryServiceType | Type of ancillary service |
status |
AncillaryServiceStatus | ACTIVE, EXPIRED, SUSPENDED, PENDING |
unit |
Unit | Associated generating unit |
contractNumber |
String | Grid service contract number |
gridOperator |
String | Name of the grid operator (e.g., ISO, TSO) |
startDate |
LocalDateTime | Contract start date |
endDate |
LocalDateTime | Contract end date |
committedCapacityMw |
BigDecimal | Committed capacity in MW |
availableCapacityMw |
BigDecimal | Currently available capacity in MW |
ratePerMw |
BigDecimal | Revenue rate per MW |
monthlyRevenue |
BigDecimal | Expected monthly revenue |
totalRevenue |
BigDecimal | Cumulative revenue earned |
penaltyRate |
BigDecimal | Penalty rate for non-compliance |
availabilityTarget |
BigDecimal | Required availability percentage |
actualAvailability |
BigDecimal | Actual availability percentage |
responseTimeSeconds |
Integer | Required response time in seconds |
notes |
String | Additional notes |
GridConnection Entity¶
| Field | Type | Description |
|---|---|---|
id |
Long | Auto-generated primary key |
connectionId |
String | Unique connection identifier (grid operator ID) |
connectionName |
String | Human-readable connection name |
description |
String | Detailed description |
status |
GridConnectionStatus | ACTIVE, INACTIVE, UNDER_MAINTENANCE, DISCONNECTED |
unit |
Unit | Associated generating unit |
gridOperator |
String | Grid operator name |
voltageLevelKv |
BigDecimal | Voltage level in kV |
maxExportCapacityMw |
BigDecimal | Maximum export capacity in MW |
maxImportCapacityMw |
BigDecimal | Maximum import capacity in MW |
poiName |
String | Point of interconnection name |
poiLatitude |
BigDecimal | POI latitude |
poiLongitude |
BigDecimal | POI longitude |
meterId |
String | Revenue meter ID |
meterType |
String | Type of meter installed |
connectionDate |
LocalDateTime | Date the connection was established |
lastMaintenanceDate |
LocalDateTime | Last maintenance performed |
nextMaintenanceDate |
LocalDateTime | Next scheduled maintenance |
connectionFee |
BigDecimal | Initial connection fee |
monthlyCharges |
BigDecimal | Monthly connection charges |
notes |
String | Additional notes |
CurtailmentEvent Entity¶
| Field | Type | Description |
|---|---|---|
id |
Long | Auto-generated primary key |
eventNumber |
String | Unique event identifier (auto-generated CURT-xxx) |
title |
String | Event title |
description |
String | Event description |
curtailmentType |
CurtailmentType | Type of curtailment |
status |
CurtailmentStatus | ACTIVE, COMPLETED, CANCELLED |
unit |
Unit | Affected generating unit |
gridConnection |
GridConnection | Associated grid connection |
startTime |
LocalDateTime | When curtailment started |
endTime |
LocalDateTime | When curtailment ended |
durationHours |
BigDecimal | Total duration in hours |
curtailedCapacityMw |
BigDecimal | Amount of curtailed capacity in MW |
remainingCapacityMw |
BigDecimal | Remaining operational capacity in MW |
lostRevenue |
BigDecimal | Revenue lost due to curtailment |
compensationAmount |
BigDecimal | Compensation received |
netFinancialImpact |
BigDecimal | Net financial impact (loss - compensation) |
orderedBy |
String | Entity that ordered the curtailment |
orderReference |
String | Reference number from the ordering entity |
completionNotes |
String | Notes upon completion |
notes |
String | Additional notes |
Database Tables¶
-- Migration: V56__grid_services.sql
-- Tables: ancillary_services, grid_connections, curtailment_events
Ancillary Services¶
Service Types¶
| Type | Value | Description |
|---|---|---|
| Frequency Regulation | FREQUENCY_REGULATION |
Real-time power adjustment to maintain grid frequency |
| Spinning Reserve | SPINNING_RESERVE |
Online capacity that can be dispatched within 10 minutes |
| Non-Spinning Reserve | NON_SPINNING_RESERVE |
Offline capacity that can be dispatched within 30 minutes |
| Voltage Support | VOLTAGE_SUPPORT |
Reactive power injection for voltage stability |
| Black Start | BLACK_START |
Ability to restart without external power supply |
| Reactive Power | REACTIVE_POWER |
Reactive power supply for grid stability |
Service Status¶
| Status | Value | Description |
|---|---|---|
| Active | ACTIVE |
Service contract is currently in effect |
| Expired | EXPIRED |
Contract has passed end date |
| Suspended | SUSPENDED |
Service temporarily suspended |
| Pending | PENDING |
Contract not yet active |
Grid Connections¶
Connection Status¶
| Status | Value | Description |
|---|---|---|
| Active | ACTIVE |
Connection is operational |
| Inactive | INACTIVE |
Connection exists but not in use |
| Under Maintenance | UNDER_MAINTENANCE |
Currently being maintained |
| Disconnected | DISCONNECTED |
Physically or logically disconnected |
Curtailment Events¶
Curtailment Types¶
| Type | Value | Description |
|---|---|---|
| Economic | ECONOMIC |
Curtailment due to negative or low prices |
| Reliability | RELIABILITY |
Grid operator ordered for reliability |
| Environmental | ENVIRONMENTAL |
Environmental constraint (e.g., fish passage) |
| Transmission Constraint | TRANSMISSION_CONSTRAINT |
Transmission line capacity limit |
| Voluntary | VOLUNTARY |
Operator chose to curtail |
Curtailment Lifecycle¶
┌──────────┐
Create ───> │ ACTIVE │
└────┬─────┘
│
┌─────────┼──────────┐
│ │ │
v v │
┌───────────┐ ┌──────────┐│
│ COMPLETED │ │ CANCELLED││
└───────────┘ └──────────┘│
│
| From | To | Action | Endpoint |
|---|---|---|---|
| ACTIVE | COMPLETED | Complete | POST /api/curtailments/{id}/complete |
API Reference¶
Ancillary Services API¶
Base URL¶
/api/ancillary-services
Inherited CRUD Endpoints¶
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/ancillary-services |
List all services |
GET |
/api/ancillary-services/{id} |
Get service by ID |
POST |
/api/ancillary-services |
Create new service |
PUT |
/api/ancillary-services/{id} |
Update service |
DELETE |
/api/ancillary-services/{id} |
Delete service |
GET |
/api/ancillary-services/count |
Get total count |
Custom Endpoints¶
Get Active Services¶
GET /api/ancillary-services/active?page=1&pageSize=25
Returns all ancillary services with ACTIVE status.
Get Services by Unit¶
GET /api/ancillary-services/unit/{unitId}?page=1&pageSize=25
Returns all ancillary services associated with a specific unit.
Grid Connections API¶
Base URL¶
/api/grid-connections
Inherited CRUD Endpoints¶
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/grid-connections |
List all connections |
GET |
/api/grid-connections/{id} |
Get connection by ID |
POST |
/api/grid-connections |
Create new connection |
PUT |
/api/grid-connections/{id} |
Update connection |
DELETE |
/api/grid-connections/{id} |
Delete connection |
GET |
/api/grid-connections/count |
Get total count |
Custom Endpoints¶
Get Connections by Status¶
GET /api/grid-connections/by-status?status=ACTIVE&page=1&pageSize=25
Valid status values: ACTIVE, INACTIVE, UNDER_MAINTENANCE, DISCONNECTED
Get Connections by Unit¶
GET /api/grid-connections/unit/{unitId}?page=1&pageSize=25
Curtailment Events API¶
Base URL¶
/api/curtailments
Inherited CRUD Endpoints¶
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/curtailments |
List all curtailment events |
GET |
/api/curtailments/{id} |
Get event by ID |
POST |
/api/curtailments |
Create new event |
PUT |
/api/curtailments/{id} |
Update event |
DELETE |
/api/curtailments/{id} |
Delete event |
GET |
/api/curtailments/count |
Get total count |
Custom Endpoints¶
Complete Curtailment Event¶
POST /api/curtailments/{id}/complete
Content-Type: application/json
{
"completionNotes": "Curtailment lifted. Unit ramped back to full capacity."
}
Get Active Curtailments¶
GET /api/curtailments/active?page=1&pageSize=25
Returns all curtailment events with ACTIVE status.
Get Curtailments by Unit¶
GET /api/curtailments/unit/{unitId}?page=1&pageSize=25
Get Financial Impact Summary¶
GET /api/curtailments/financial-impact
Response:
{
"data": {
"totalLostRevenue": 1250000.00,
"totalCompensation": 450000.00,
"netFinancialImpact": 800000.00
}
}
Returns aggregate financial metrics across all completed curtailment events:
- totalLostRevenue - Sum of all lost revenue
- totalCompensation - Sum of all compensation received
- netFinancialImpact - Net impact (sum of net financial impact field)
Multi-Tenancy¶
All grid service entities are scoped to a company through the company_id foreign key. Users can only access grid service data belonging to their company.
Examples¶
Create an Ancillary Service Contract¶
POST /api/ancillary-services
Content-Type: application/json
{
"serviceName": "Frequency Regulation - Unit 3",
"description": "AGC frequency regulation service for Unit 3",
"serviceType": "FREQUENCY_REGULATION",
"unitId": 42,
"contractNumber": "ISO-FR-2024-001",
"gridOperator": "ISO New England",
"startDate": "2024-01-01T00:00:00",
"endDate": "2024-12-31T23:59:59",
"committedCapacityMw": 50.000,
"availableCapacityMw": 50.000,
"ratePerMw": 15.00,
"monthlyRevenue": 22500.00,
"penaltyRate": 25.00,
"availabilityTarget": 97.00,
"responseTimeSeconds": 4
}
Create a Grid Connection¶
POST /api/grid-connections
Content-Type: application/json
{
"connectionId": "POI-NE-2024-042",
"connectionName": "Unit 3 - 345kV Interconnection",
"description": "Main grid interconnection for Unit 3",
"unitId": 42,
"gridOperator": "ISO New England",
"voltageLevelKv": 345.00,
"maxExportCapacityMw": 200.000,
"maxImportCapacityMw": 50.000,
"poiName": "Millbury Substation",
"poiLatitude": 42.1943,
"poiLongitude": -71.7728,
"meterId": "MTR-NE-042",
"meterType": "Revenue Grade",
"connectionDate": "2020-06-15T00:00:00",
"connectionFee": 250000.00,
"monthlyCharges": 5000.00
}
Create a Curtailment Event¶
POST /api/curtailments
Content-Type: application/json
{
"title": "Transmission Constraint Curtailment",
"description": "ISO ordered curtailment due to transmission line overload",
"curtailmentType": "TRANSMISSION_CONSTRAINT",
"unitId": 42,
"gridConnectionId": 1,
"startTime": "2024-01-15T14:00:00",
"curtailedCapacityMw": 75.000,
"remainingCapacityMw": 125.000,
"lostRevenue": 18750.00,
"compensationAmount": 5000.00,
"orderedBy": "ISO New England",
"orderReference": "ISONE-CURT-2024-0042"
}
Complete a Curtailment and Check Financial Impact¶
# Complete the curtailment
POST /api/curtailments/1/complete
Content-Type: application/json
{
"completionNotes": "Transmission constraint cleared. Full capacity restored at 18:00."
}
# Check overall financial impact
GET /api/curtailments/financial-impact
Permission Resource Names¶
ancillary_services - for ancillary service CRUD
grid_connections - for grid connection CRUD
curtailment_events - for curtailment event CRUD