From 6d903ac7ad336edc9195d106f3476215d6101a18 Mon Sep 17 00:00:00 2001 From: "Donald F. Coffin" Date: Wed, 7 Jan 2026 17:22:55 -0500 Subject: [PATCH] refactor: Phase 2 - ReadingType ESPI 4.0 schema compliance (field order) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reordered ReadingType entity, DTO, and migration fields to match ESPI 4.0 XSD element sequence (espi.xsd:382-481). Changes: - ReadingTypeEntity: Reordered fields 13-18 to match XSD sequence: timeAttribute, tou, uom, cpp, interharmonic, measuringPeriod, argument - ReadingTypeDto: Updated @XmlType propOrder and record component order to match XSD (removed description from propOrder as it belongs to IdentifiedObject/Atom) - V1__Create_Base_Tables.sql: Reordered reading_types table columns to match XSD sequence - ReadingTypeMapper: No changes required (MapStruct maps by field name, not order) All tests passing (550 tests). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- .../domain/usage/ReadingTypeEntity.java | 48 ++++++----- .../espi/common/dto/usage/ReadingTypeDto.java | 80 +++++++++---------- .../db/migration/V1__Create_Base_Tables.sql | 10 +-- 3 files changed, 68 insertions(+), 70 deletions(-) diff --git a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/usage/ReadingTypeEntity.java b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/usage/ReadingTypeEntity.java index 4e7d702d..258871da 100644 --- a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/usage/ReadingTypeEntity.java +++ b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/usage/ReadingTypeEntity.java @@ -132,6 +132,13 @@ public class ReadingTypeEntity extends IdentifiedObject { @Column(name = "time_attribute", length = 50) private String timeAttribute; + /** + * Time-of-use indicator. + * Used for time-based pricing structures. + */ + @Column(name = "tou", length = 50) + private String tou; + /** * Unit of measure for the readings. * Values: WH (watt-hours), W (watts), V (volts), A (amperes), etc. @@ -146,6 +153,17 @@ public class ReadingTypeEntity extends IdentifiedObject { @Column(name = "cpp", length = 50) private String cpp; + /** + * Interharmonic information for power quality measurements. + * Contains details about harmonic distortion. + */ + @Embedded + @AttributeOverrides({ + @AttributeOverride(name = "numerator", column = @Column(name = "interharmonic_numerator")), + @AttributeOverride(name = "denominator", column = @Column(name = "interharmonic_denominator")) + }) + private ReadingInterharmonic interharmonic; + /** * Measuring period for the readings. * Describes the measurement timing characteristics. @@ -153,13 +171,6 @@ public class ReadingTypeEntity extends IdentifiedObject { @Column(name = "measuring_period", length = 50) private String measuringPeriod; - /** - * Time-of-use indicator. - * Used for time-based pricing structures. - */ - @Column(name = "tou", length = 50) - private String tou; - /** * Rational number argument for complex calculations. * Used for mathematical transformations of readings. @@ -171,17 +182,6 @@ public class ReadingTypeEntity extends IdentifiedObject { }) private RationalNumber argument; - /** - * Interharmonic information for power quality measurements. - * Contains details about harmonic distortion. - */ - @Embedded - @AttributeOverrides({ - @AttributeOverride(name = "numerator", column = @Column(name = "interharmonic_numerator")), - @AttributeOverride(name = "denominator", column = @Column(name = "interharmonic_denominator")) - }) - private ReadingInterharmonic interharmonic; - /** * Meter readings that use this reading type. * One-to-many relationship with eager loading for performance. @@ -253,7 +253,7 @@ public void merge(ReadingTypeEntity other) { if (other != null) { super.merge(other); - // Update all reading type characteristics + // Update all reading type characteristics (in XSD sequence order) this.accumulationBehaviour = other.accumulationBehaviour; this.commodity = other.commodity; this.consumptionTier = other.consumptionTier; @@ -266,14 +266,12 @@ public void merge(ReadingTypeEntity other) { this.phase = other.phase; this.powerOfTenMultiplier = other.powerOfTenMultiplier; this.timeAttribute = other.timeAttribute; + this.tou = other.tou; this.uom = other.uom; this.cpp = other.cpp; + this.interharmonic = other.interharmonic; this.measuringPeriod = other.measuringPeriod; - this.tou = other.tou; - - // Update embedded values this.argument = other.argument; - this.interharmonic = other.interharmonic; // Note: meterReadings collection is not merged to preserve existing relationships } @@ -437,12 +435,12 @@ public String toString() { "phase = " + getPhase() + ", " + "powerOfTenMultiplier = " + getPowerOfTenMultiplier() + ", " + "timeAttribute = " + getTimeAttribute() + ", " + + "tou = " + getTou() + ", " + "uom = " + getUom() + ", " + "cpp = " + getCpp() + ", " + + "interharmonic = " + getInterharmonic() + ", " + "measuringPeriod = " + getMeasuringPeriod() + ", " + - "tou = " + getTou() + ", " + "argument = " + getArgument() + ", " + - "interharmonic = " + getInterharmonic() + ", " + "description = " + getDescription() + ", " + "created = " + getCreated() + ", " + "updated = " + getUpdated() + ", " + diff --git a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/dto/usage/ReadingTypeDto.java b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/dto/usage/ReadingTypeDto.java index c3b0233d..7677ec4d 100644 --- a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/dto/usage/ReadingTypeDto.java +++ b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/dto/usage/ReadingTypeDto.java @@ -37,10 +37,10 @@ @XmlRootElement(name = "ReadingType", namespace = "http://naesb.org/espi") @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "ReadingType", namespace = "http://naesb.org/espi", propOrder = { - "description", "accumulationBehaviour", "commodity", "consumptionTier", "currency", - "dataQualifier", "defaultQuality", "flowDirection", "intervalLength", "kind", - "phase", "powerOfTenMultiplier", "timeAttribute", "uom", "cpp", "measuringPeriod", - "tou", "argument", "interharmonic" + "accumulationBehaviour", "commodity", "consumptionTier", "currency", "dataQualifier", + "defaultQuality", "flowDirection", "intervalLength", "kind", "phase", + "powerOfTenMultiplier", "timeAttribute", "tou", "uom", "cpp", "interharmonic", + "measuringPeriod", "argument" }) public record ReadingTypeDto( @@ -204,7 +204,7 @@ public record ReadingTypeDto( /** * Time attribute describing the time period of interest. - * + * * ESPI values: * - NONE: No specific time context * - BILLING_PERIOD: Within billing cycle @@ -217,10 +217,23 @@ public record ReadingTypeDto( */ @XmlElement(name = "timeAttribute") String timeAttribute, - + + /** + * Time-of-use indicator. + * Used for time-based pricing structures and rate schedules. + * + * Typical utility TOU periods: + * - 1: Peak hours (highest rates) + * - 2: Partial-peak hours (medium rates) + * - 3: Off-peak hours (lowest rates) + * - 0: No TOU pricing + */ + @XmlElement(name = "tou") + String tou, + /** * Unit of measure for the readings. - * + * * ESPI electrical units: * - WH: Watt-hours (energy) * - W: Watts (power) @@ -239,11 +252,11 @@ public record ReadingTypeDto( */ @XmlElement(name = "uom") String uom, - + /** * Critical peak pricing indicator. * Used for demand response programs and peak pricing events. - * + * * Values typically: * - 0: Normal pricing * - 1: Critical peak pricing active @@ -251,11 +264,24 @@ public record ReadingTypeDto( */ @XmlElement(name = "cpp") String cpp, - + + /** + * Interharmonic information for power quality measurements. + * Contains details about harmonic distortion and frequency analysis. + * + * Used for: + * - Total harmonic distortion (THD) measurements + * - Individual harmonic analysis + * - Power quality monitoring + * - Frequency domain analysis + */ + @XmlElement(name = "interharmonic") + ReadingInterharmonicDto interharmonic, + /** * Measuring period for the readings. * Describes the measurement timing characteristics and sampling. - * + * * Values describe how measurements are taken: * - CONTINUOUS: Continuous monitoring * - INTERVAL: Fixed interval sampling @@ -264,44 +290,18 @@ public record ReadingTypeDto( */ @XmlElement(name = "measuringPeriod") String measuringPeriod, - - /** - * Time-of-use indicator. - * Used for time-based pricing structures and rate schedules. - * - * Typical utility TOU periods: - * - 1: Peak hours (highest rates) - * - 2: Partial-peak hours (medium rates) - * - 3: Off-peak hours (lowest rates) - * - 0: No TOU pricing - */ - @XmlElement(name = "tou") - String tou, - + /** * Rational number argument for complex calculations. * Used for mathematical transformations and scaling of readings. - * + * * Common uses: * - CT/PT ratio transformations * - Unit conversions * - Scaling factors for display */ @XmlElement(name = "argument") - RationalNumberDto argument, - - /** - * Interharmonic information for power quality measurements. - * Contains details about harmonic distortion and frequency analysis. - * - * Used for: - * - Total harmonic distortion (THD) measurements - * - Individual harmonic analysis - * - Power quality monitoring - * - Frequency domain analysis - */ - @XmlElement(name = "interharmonic") - ReadingInterharmonicDto interharmonic + RationalNumberDto argument ) { diff --git a/openespi-common/src/main/resources/db/migration/V1__Create_Base_Tables.sql b/openespi-common/src/main/resources/db/migration/V1__Create_Base_Tables.sql index 19ba3e16..bae9ea04 100644 --- a/openespi-common/src/main/resources/db/migration/V1__Create_Base_Tables.sql +++ b/openespi-common/src/main/resources/db/migration/V1__Create_Base_Tables.sql @@ -300,7 +300,7 @@ CREATE TABLE reading_types self_link_href VARCHAR(1024), self_link_type VARCHAR(255), - -- Reading type specific fields + -- Reading type specific fields (in ESPI 4.0 XSD sequence order) accumulation_behaviour VARCHAR(50), commodity VARCHAR(50), consumption_tier VARCHAR(50), @@ -313,14 +313,14 @@ CREATE TABLE reading_types phase VARCHAR(50), power_of_ten_multiplier VARCHAR(50), time_attribute VARCHAR(50), + tou VARCHAR(50), uom VARCHAR(50), cpp VARCHAR(50), + interharmonic_numerator BIGINT, + interharmonic_denominator BIGINT, measuring_period VARCHAR(50), - tou VARCHAR(50), argument_numerator DECIMAL(38,0), - argument_denominator DECIMAL(38,0), - interharmonic_numerator BIGINT, - interharmonic_denominator BIGINT + argument_denominator DECIMAL(38,0) ); CREATE INDEX idx_reading_type_kind ON reading_types (kind);