diff --git a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/common/AmiBillingReadyKind.java b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/common/AmiBillingReadyKind.java new file mode 100644 index 00000000..dea72809 --- /dev/null +++ b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/common/AmiBillingReadyKind.java @@ -0,0 +1,94 @@ +/* + * + * Copyright (c) 2025 Green Button Alliance, Inc. + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.greenbuttonalliance.espi.common.domain.common; + +/** + * Lifecycle states of the metering installation at a usage point with respect to + * readiness for billing via advanced metering infrastructure reads. + * Per ESPI 4.0 XSD: AmiBillingReadyKind enumeration. + */ +public enum AmiBillingReadyKind { + /** + * Usage point is equipped with an AMI capable meter that is not yet currently + * equipped with a communications module. + */ + AMI_CAPABLE("amiCapable"), + + /** + * Usage point is equipped with an AMI capable meter; however, the AMI functionality + * has been disabled or is not being used. + */ + AMI_DISABLED("amiDisabled"), + + /** + * Usage point is equipped with an operating AMI capable meter and accuracy has been + * certified for billing purposes. + */ + BILLING_APPROVED("billingApproved"), + + /** + * Usage point is equipped with an AMI capable meter having communications capability. + */ + ENABLED("enabled"), + + /** + * Usage point is equipped with a non AMI capable meter. + */ + NON_AMI("nonAmi"), + + /** + * Usage point is not currently equipped with a meter. + */ + NON_METERED("nonMetered"), + + /** + * Usage point is equipped with an AMI capable meter that is functioning and + * communicating with the AMI network. + */ + OPERABLE("operable"); + + private final String value; + + AmiBillingReadyKind(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + /** + * Converts a string value to the corresponding AmiBillingReadyKind enum constant. + * + * @param value the string value from XML/XSD + * @return the matching enum constant, or null if not found + */ + public static AmiBillingReadyKind fromValue(String value) { + if (value == null) { + return null; + } + for (AmiBillingReadyKind kind : AmiBillingReadyKind.values()) { + if (kind.value.equals(value)) { + return kind; + } + } + return null; + } +} diff --git a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/common/PhaseCodeKind.java b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/common/PhaseCodeKind.java new file mode 100644 index 00000000..670fdc98 --- /dev/null +++ b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/common/PhaseCodeKind.java @@ -0,0 +1,191 @@ +/* + * + * Copyright (c) 2025 Green Button Alliance, Inc. + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.greenbuttonalliance.espi.common.domain.common; + +/** + * Enumeration of phase identifiers. Allows designation of phases for both transmission + * and distribution equipment, circuits and loads. Residential and small commercial loads + * are often served from single-phase, or split-phase, secondary circuits. Phases 1 and 2 + * refer to hot wires that are 180 degrees out of phase, while N refers to the neutral wire. + * Through single-phase transformer connections, these secondary circuits may be served from + * one or two of the primary phases A, B, and C. For three-phase loads, use the A, B, C + * phase codes instead of s12N. + *
+ * Per ESPI 4.0 XSD: PhaseCodeKind enumeration (UInt16 values).
+ */
+public enum PhaseCodeKind {
+ /**
+ * ABC to Neutral (three-phase, four-wire).
+ */
+ ABCN(225),
+
+ /**
+ * Involving all phases (three-phase).
+ */
+ ABC(224),
+
+ /**
+ * AB to Neutral.
+ */
+ ABN(193),
+
+ /**
+ * Phases A, C and neutral.
+ */
+ ACN(41),
+
+ /**
+ * BC to neutral.
+ */
+ BCN(97),
+
+ /**
+ * Phases A to B.
+ */
+ AB(132),
+
+ /**
+ * Phases A and C.
+ */
+ AC(96),
+
+ /**
+ * Phases B to C.
+ */
+ BC(66),
+
+ /**
+ * Phases A to neutral.
+ */
+ AN(129),
+
+ /**
+ * Phases B to neutral.
+ */
+ BN(65),
+
+ /**
+ * Phases C to neutral.
+ */
+ CN(33),
+
+ /**
+ * Phase A.
+ */
+ A(128),
+
+ /**
+ * Phase B.
+ */
+ B(64),
+
+ /**
+ * Phase C.
+ */
+ C(32),
+
+ /**
+ * Neutral.
+ */
+ N(16),
+
+ /**
+ * Phase S2 to neutral.
+ */
+ S2N(272),
+
+ /**
+ * Phase S1, S2 to neutral (split-phase secondary).
+ */
+ S12N(784),
+
+ /**
+ * Phase S1 to Neutral.
+ */
+ S1N(528),
+
+ /**
+ * Phase S2.
+ */
+ S2(256),
+
+ /**
+ * Phase S1 to S2.
+ */
+ S12(768),
+
+ /**
+ * Phase S1.
+ */
+ S1(512),
+
+ /**
+ * Not applicable to any phase.
+ */
+ NONE(0),
+
+ /**
+ * Phase A current relative to Phase A voltage.
+ */
+ A_TO_AV(136),
+
+ /**
+ * Phase B current or voltage relative to Phase A voltage.
+ */
+ B_AV(72),
+
+ /**
+ * Phase C current or voltage relative to Phase A voltage.
+ */
+ C_AV(40),
+
+ /**
+ * Neutral to ground.
+ */
+ NG(17);
+
+ private final Integer value;
+
+ PhaseCodeKind(Integer value) {
+ this.value = value;
+ }
+
+ public Integer getValue() {
+ return value;
+ }
+
+ /**
+ * Converts an integer value to the corresponding PhaseCodeKind enum constant.
+ *
+ * @param value the integer value from XML/XSD
+ * @return the matching enum constant, or null if not found
+ */
+ public static PhaseCodeKind fromValue(Integer value) {
+ if (value == null) {
+ return null;
+ }
+ for (PhaseCodeKind kind : PhaseCodeKind.values()) {
+ if (kind.value.equals(value)) {
+ return kind;
+ }
+ }
+ return null;
+ }
+}
diff --git a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/common/UsagePointConnectedKind.java b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/common/UsagePointConnectedKind.java
new file mode 100644
index 00000000..d61e4f3c
--- /dev/null
+++ b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/common/UsagePointConnectedKind.java
@@ -0,0 +1,75 @@
+/*
+ *
+ * Copyright (c) 2025 Green Button Alliance, Inc.
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.greenbuttonalliance.espi.common.domain.common;
+
+/**
+ * State of the usage point with respect to connection to the network.
+ * Per ESPI 4.0 XSD: UsagePointConnectedKind enumeration.
+ */
+public enum UsagePointConnectedKind {
+ /**
+ * The usage point is connected to the network and able to receive or send
+ * the applicable commodity (electricity, gas, water, etc.).
+ */
+ CONNECTED("connected"),
+
+ /**
+ * The usage point has been disconnected through operation of a disconnect function
+ * within the meter present at the usage point. The usage point is unable to receive
+ * or send the applicable commodity (electricity, gas, water, etc.). A logical
+ * disconnect can often be achieved without utilising a field crew.
+ */
+ LOGICALLY_DISCONNECTED("logicallyDisconnected"),
+
+ /**
+ * The usage point has been disconnected from the network at a point upstream of the meter.
+ * The usage point is unable to receive or send the applicable commodity (electricity,
+ * gas, water, etc.). A physical disconnect is often achieved by utilising a field crew.
+ */
+ PHYSICALLY_DISCONNECTED("physicallyDisconnected");
+
+ private final String value;
+
+ UsagePointConnectedKind(String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ /**
+ * Converts a string value to the corresponding UsagePointConnectedKind enum constant.
+ *
+ * @param value the string value from XML/XSD
+ * @return the matching enum constant, or null if not found
+ */
+ public static UsagePointConnectedKind fromValue(String value) {
+ if (value == null) {
+ return null;
+ }
+ for (UsagePointConnectedKind kind : UsagePointConnectedKind.values()) {
+ if (kind.value.equals(value)) {
+ return kind;
+ }
+ }
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/usage/UsagePointEntity.java b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/usage/UsagePointEntity.java
index 055c0080..c3637df6 100644
--- a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/usage/UsagePointEntity.java
+++ b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/usage/UsagePointEntity.java
@@ -22,9 +22,12 @@
import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
import lombok.*;
+import org.greenbuttonalliance.espi.common.domain.common.AmiBillingReadyKind;
import org.greenbuttonalliance.espi.common.domain.common.IdentifiedObject;
+import org.greenbuttonalliance.espi.common.domain.common.PhaseCodeKind;
import org.greenbuttonalliance.espi.common.domain.common.ServiceCategory;
import org.greenbuttonalliance.espi.common.domain.common.SummaryMeasurement;
+import org.greenbuttonalliance.espi.common.domain.common.UsagePointConnectedKind;
import org.hibernate.annotations.BatchSize;
import org.hibernate.proxy.HibernateProxy;
@@ -45,8 +48,12 @@ public class UsagePointEntity extends IdentifiedObject {
private static final long serialVersionUID = 1L;
+ // ==================== XSD Sequence Order (per ESPI 4.0 espi.xsd) ====================
+ // Fields ordered to match exact XSD element sequence for UsagePoint complexType
+
/**
* Role flags for the usage point (hex binary representation).
+ * XSD Position 1: roleFlags
*/
@Column(name = "role_flags")
private byte[] roleFlags;
@@ -54,6 +61,7 @@ public class UsagePointEntity extends IdentifiedObject {
/**
* Service category for this usage point.
* Required field indicating the type of service.
+ * XSD Position 2: ServiceCategory
*/
@NotNull
@Enumerated(EnumType.STRING)
@@ -62,85 +70,61 @@ public class UsagePointEntity extends IdentifiedObject {
/**
* Status of the usage point.
+ * XSD Position 3: status
*/
@Column(name = "status")
private Short status;
- /**
- * URI for this usage point.
- * Used for external references and linking.
- */
- @Column(name = "uri")
- private String uri;
+ // XSD Position 4: serviceDeliveryPoint - See relationship section below
/**
- * Estimated load for this usage point as SummaryMeasurement.
- * Contains value, unit of measure, multiplier, and reading type reference.
+ * Tracks the lifecycle of the metering installation at a usage point with respect to
+ * readiness for billing via advanced metering infrastructure reads.
+ * Per ESPI 4.0 XSD: [extension] AmiBillingReadyKind enum.
+ * XSD Position 5: amiBillingReady
*/
- @Embedded
- @AttributeOverrides({
- @AttributeOverride(name = "powerOfTenMultiplier", column = @Column(name = "estimated_load_multiplier", columnDefinition = "SMALLINT")),
- @AttributeOverride(name = "timeStamp", column = @Column(name = "estimated_load_timestamp")),
- @AttributeOverride(name = "uom", column = @Column(name = "estimated_load_uom")),
- @AttributeOverride(name = "value", column = @Column(name = "estimated_load_value")),
- @AttributeOverride(name = "readingTypeRef", column = @Column(name = "estimated_load_reading_type_ref", length = 512))
- })
- private SummaryMeasurement estimatedLoad;
+ @Enumerated(EnumType.STRING)
+ @Column(name = "ami_billing_ready", length = 32)
+ private AmiBillingReadyKind amiBillingReady;
/**
- * Nominal service voltage for this usage point as SummaryMeasurement.
- * Contains value, unit of measure, multiplier, and reading type reference.
+ * True if as a result of an inspection or otherwise, there is a reason to suspect
+ * that a previous billing may have been performed with erroneous data.
+ * Value should be reset once this potential discrepancy has been resolved.
+ * Per ESPI 4.0 XSD: [extension] boolean field.
+ * XSD Position 6: checkBilling
*/
- @Embedded
- @AttributeOverrides({
- @AttributeOverride(name = "powerOfTenMultiplier", column = @Column(name = "nominal_voltage_multiplier")),
- @AttributeOverride(name = "timeStamp", column = @Column(name = "nominal_voltage_timestamp")),
- @AttributeOverride(name = "uom", column = @Column(name = "nominal_voltage_uom")),
- @AttributeOverride(name = "value", column = @Column(name = "nominal_voltage_value")),
- @AttributeOverride(name = "readingTypeRef", column = @Column(name = "nominal_voltage_reading_type_ref", length = 512))
- })
- private SummaryMeasurement nominalServiceVoltage;
+ @Column(name = "check_billing")
+ private Boolean checkBilling;
/**
- * Rated current for this usage point as SummaryMeasurement.
- * Contains value, unit of measure, multiplier, and reading type reference.
+ * State of the usage point with respect to connection to the network.
+ * Per ESPI 4.0 XSD: [extension] UsagePointConnectedKind enum.
+ * XSD Position 7: connectionState
*/
- @Embedded
- @AttributeOverrides({
- @AttributeOverride(name = "powerOfTenMultiplier", column = @Column(name = "rated_current_multiplier")),
- @AttributeOverride(name = "timeStamp", column = @Column(name = "rated_current_timestamp")),
- @AttributeOverride(name = "uom", column = @Column(name = "rated_current_uom")),
- @AttributeOverride(name = "value", column = @Column(name = "rated_current_value")),
- @AttributeOverride(name = "readingTypeRef", column = @Column(name = "rated_current_reading_type_ref", length = 512))
- })
- private SummaryMeasurement ratedCurrent;
+ @Enumerated(EnumType.STRING)
+ @Column(name = "connection_state", length = 32)
+ private UsagePointConnectedKind connectionState;
/**
- * Rated power for this usage point as SummaryMeasurement.
+ * Estimated load for this usage point as SummaryMeasurement.
* Contains value, unit of measure, multiplier, and reading type reference.
+ * XSD Position 8: estimatedLoad
*/
@Embedded
@AttributeOverrides({
- @AttributeOverride(name = "powerOfTenMultiplier", column = @Column(name = "rated_power_multiplier")),
- @AttributeOverride(name = "timeStamp", column = @Column(name = "rated_power_timestamp")),
- @AttributeOverride(name = "uom", column = @Column(name = "rated_power_uom")),
- @AttributeOverride(name = "value", column = @Column(name = "rated_power_value")),
- @AttributeOverride(name = "readingTypeRef", column = @Column(name = "rated_power_reading_type_ref", length = 512))
+ @AttributeOverride(name = "powerOfTenMultiplier", column = @Column(name = "estimated_load_multiplier", columnDefinition = "SMALLINT")),
+ @AttributeOverride(name = "timeStamp", column = @Column(name = "estimated_load_timestamp")),
+ @AttributeOverride(name = "uom", column = @Column(name = "estimated_load_uom")),
+ @AttributeOverride(name = "value", column = @Column(name = "estimated_load_value")),
+ @AttributeOverride(name = "readingTypeRef", column = @Column(name = "estimated_load_reading_type_ref", length = 512))
})
- private SummaryMeasurement ratedPower;
-
- /**
- * True if as a result of an inspection or otherwise, there is a reason to suspect
- * that a previous billing may have been performed with erroneous data.
- * Value should be reset once this potential discrepancy has been resolved.
- * Per ESPI 4.0 XSD: [extension] boolean field.
- */
- @Column(name = "check_billing")
- private Boolean checkBilling;
+ private SummaryMeasurement estimatedLoad;
/**
* True if grounded.
* Per ESPI 4.0 XSD: [extension] boolean field.
+ * XSD Position 9: grounded
*/
@Column(name = "grounded")
private Boolean grounded;
@@ -149,6 +133,7 @@ public class UsagePointEntity extends IdentifiedObject {
* If true, this usage point is a service delivery point, i.e., a usage point
* where the ownership of the service changes hands.
* Per ESPI 4.0 XSD: [extension] boolean field.
+ * XSD Position 10: isSdp
*/
@Column(name = "is_sdp")
private Boolean isSdp;
@@ -161,6 +146,7 @@ public class UsagePointEntity extends IdentifiedObject {
* Otherwise, the usage point is physical, i.e., there is a logical point in the network
* where a meter could be located to collect meter readings.
* Per ESPI 4.0 XSD: [extension] boolean field.
+ * XSD Position 11: isVirtual
*/
@Column(name = "is_virtual")
private Boolean isVirtual;
@@ -170,21 +156,81 @@ public class UsagePointEntity extends IdentifiedObject {
* premises vacancy, logical or physical disconnect.
* It is used for readings validation and estimation.
* Per ESPI 4.0 XSD: [extension] boolean field.
+ * XSD Position 12: minimalUsageExpected
*/
@Column(name = "minimal_usage_expected")
private Boolean minimalUsageExpected;
+ /**
+ * Nominal service voltage for this usage point as SummaryMeasurement.
+ * Contains value, unit of measure, multiplier, and reading type reference.
+ * XSD Position 13: nominalServiceVoltage
+ */
+ @Embedded
+ @AttributeOverrides({
+ @AttributeOverride(name = "powerOfTenMultiplier", column = @Column(name = "nominal_voltage_multiplier")),
+ @AttributeOverride(name = "timeStamp", column = @Column(name = "nominal_voltage_timestamp")),
+ @AttributeOverride(name = "uom", column = @Column(name = "nominal_voltage_uom")),
+ @AttributeOverride(name = "value", column = @Column(name = "nominal_voltage_value")),
+ @AttributeOverride(name = "readingTypeRef", column = @Column(name = "nominal_voltage_reading_type_ref", length = 512))
+ })
+ private SummaryMeasurement nominalServiceVoltage;
+
/**
* Outage region in which this usage point is located.
* Per ESPI 4.0 XSD: [extension] String256 field (max length 256).
+ * XSD Position 14: outageRegion
*/
@Column(name = "outage_region", length = 256)
private String outageRegion;
+ /**
+ * Phase code. Number of wires and specific nominal phases can be deduced from
+ * enumeration literal values. For example, ABCN is three-phase, four-wire,
+ * s12n (splitSecondary12N) is single-phase, three-wire, and s1n and s2n are
+ * single-phase, two-wire.
+ * Per ESPI 4.0 XSD: [extension] PhaseCodeKind enum.
+ * XSD Position 15: phaseCode
+ */
+ @Enumerated(EnumType.STRING)
+ @Column(name = "phase_code", length = 32)
+ private PhaseCodeKind phaseCode;
+
+ /**
+ * Rated current for this usage point as SummaryMeasurement.
+ * Contains value, unit of measure, multiplier, and reading type reference.
+ * XSD Position 16: ratedCurrent
+ */
+ @Embedded
+ @AttributeOverrides({
+ @AttributeOverride(name = "powerOfTenMultiplier", column = @Column(name = "rated_current_multiplier")),
+ @AttributeOverride(name = "timeStamp", column = @Column(name = "rated_current_timestamp")),
+ @AttributeOverride(name = "uom", column = @Column(name = "rated_current_uom")),
+ @AttributeOverride(name = "value", column = @Column(name = "rated_current_value")),
+ @AttributeOverride(name = "readingTypeRef", column = @Column(name = "rated_current_reading_type_ref", length = 512))
+ })
+ private SummaryMeasurement ratedCurrent;
+
+ /**
+ * Rated power for this usage point as SummaryMeasurement.
+ * Contains value, unit of measure, multiplier, and reading type reference.
+ * XSD Position 17: ratedPower
+ */
+ @Embedded
+ @AttributeOverrides({
+ @AttributeOverride(name = "powerOfTenMultiplier", column = @Column(name = "rated_power_multiplier")),
+ @AttributeOverride(name = "timeStamp", column = @Column(name = "rated_power_timestamp")),
+ @AttributeOverride(name = "uom", column = @Column(name = "rated_power_uom")),
+ @AttributeOverride(name = "value", column = @Column(name = "rated_power_value")),
+ @AttributeOverride(name = "readingTypeRef", column = @Column(name = "rated_power_reading_type_ref", length = 512))
+ })
+ private SummaryMeasurement ratedPower;
+
/**
* Cycle day on which the meter for this usage point will normally be read.
* Usually correlated with the billing cycle.
* Per ESPI 4.0 XSD: [extension] String256 field (max length 256).
+ * XSD Position 18: readCycle
*/
@Column(name = "read_cycle", length = 256)
private String readCycle;
@@ -193,6 +239,7 @@ public class UsagePointEntity extends IdentifiedObject {
* Identifier of the route to which this usage point is assigned for purposes of meter reading.
* Typically used to configure hand held meter reading systems prior to collection of reads.
* Per ESPI 4.0 XSD: [extension] String256 field (max length 256).
+ * XSD Position 19: readRoute
*/
@Column(name = "read_route", length = 256)
private String readRoute;
@@ -200,6 +247,7 @@ public class UsagePointEntity extends IdentifiedObject {
/**
* Remarks about this usage point, for example the reason for it being rated with a non-nominal priority.
* Per ESPI 4.0 XSD: [extension] String256 field (max length 256).
+ * XSD Position 20: serviceDeliveryRemark
*/
@Column(name = "service_delivery_remark", length = 256)
private String serviceDeliveryRemark;
@@ -208,10 +256,26 @@ public class UsagePointEntity extends IdentifiedObject {
* Priority of service for this usage point.
* Note that usage points at the same service location can have different priorities.
* Per ESPI 4.0 XSD: [extension] String32 field (max length 32).
+ * XSD Position 21: servicePriority
*/
@Column(name = "service_priority", length = 32)
private String servicePriority;
+ // XSD Position 22-23: pnodeRefs and aggregateNodeRefs - See relationship sections below
+
+ // ==================== Legacy Fields (NOT in ESPI 4.0 XSD) ====================
+ // TODO Phase 16c: Review if these fields should be removed or mapped to XSD elements
+
+ /**
+ * URI for this usage point.
+ * Used for external references and linking.
+ * NOTE: This field is NOT in ESPI 4.0 XSD - legacy field for review.
+ */
+ @Column(name = "uri")
+ private String uri;
+
+ // ==================== JPA Relationships ====================
+
/**
* Service delivery point associated with this usage point.
* ServiceDeliveryPoint is now a standalone ESPI resource.
diff --git a/openespi-common/src/main/resources/db/vendor/h2/V2__H2_Specific_Tables.sql b/openespi-common/src/main/resources/db/vendor/h2/V2__H2_Specific_Tables.sql
index 3b391f1c..37afc0f3 100644
--- a/openespi-common/src/main/resources/db/vendor/h2/V2__H2_Specific_Tables.sql
+++ b/openespi-common/src/main/resources/db/vendor/h2/V2__H2_Specific_Tables.sql
@@ -105,9 +105,9 @@ CREATE TABLE usage_points
service_category VARCHAR(50), -- 2. ServiceCategory
status SMALLINT, -- 3. status
-- 4. serviceDeliveryPoint (FK handled below)
- -- 5. amiBillingReady (enum - Phase 16b)
+ ami_billing_ready VARCHAR(32), -- 5. amiBillingReady (Phase 16b)
check_billing BOOLEAN, -- 6. checkBilling (Phase 16a)
- -- 7. connectionState (enum - Phase 16b)
+ connection_state VARCHAR(32), -- 7. connectionState (Phase 16b)
-- 8. estimatedLoad (embedded SummaryMeasurement)
estimated_load_multiplier VARCHAR(255),
@@ -129,7 +129,7 @@ CREATE TABLE usage_points
nominal_voltage_reading_type_ref VARCHAR(512),
outage_region VARCHAR(256), -- 14. outageRegion (Phase 16a)
- -- 15. phaseCode (enum - Phase 16b)
+ phase_code VARCHAR(32), -- 15. phaseCode (Phase 16b)
-- 16. ratedCurrent (embedded SummaryMeasurement)
rated_current_multiplier VARCHAR(255),
diff --git a/openespi-common/src/main/resources/db/vendor/mysql/V2__MySQL_Specific_Tables.sql b/openespi-common/src/main/resources/db/vendor/mysql/V2__MySQL_Specific_Tables.sql
index d2f1d3a2..dd075e5a 100644
--- a/openespi-common/src/main/resources/db/vendor/mysql/V2__MySQL_Specific_Tables.sql
+++ b/openespi-common/src/main/resources/db/vendor/mysql/V2__MySQL_Specific_Tables.sql
@@ -102,9 +102,9 @@ CREATE TABLE usage_points
service_category VARCHAR(50), -- 2. ServiceCategory
status SMALLINT, -- 3. status
-- 4. serviceDeliveryPoint (FK handled below)
- -- 5. amiBillingReady (enum - Phase 16b)
+ ami_billing_ready VARCHAR(32), -- 5. amiBillingReady (Phase 16b)
check_billing BOOLEAN, -- 6. checkBilling (Phase 16a)
- -- 7. connectionState (enum - Phase 16b)
+ connection_state VARCHAR(32), -- 7. connectionState (Phase 16b)
-- 8. estimatedLoad (embedded SummaryMeasurement)
estimated_load_multiplier VARCHAR(255),
@@ -126,7 +126,7 @@ CREATE TABLE usage_points
nominal_voltage_reading_type_ref VARCHAR(512),
outage_region VARCHAR(256), -- 14. outageRegion (Phase 16a)
- -- 15. phaseCode (enum - Phase 16b)
+ phase_code VARCHAR(32), -- 15. phaseCode (Phase 16b)
-- 16. ratedCurrent (embedded SummaryMeasurement)
rated_current_multiplier VARCHAR(255),
diff --git a/openespi-common/src/main/resources/db/vendor/postgres/V2__PostgreSQL_Specific_Tables.sql b/openespi-common/src/main/resources/db/vendor/postgres/V2__PostgreSQL_Specific_Tables.sql
index 12a84a69..40cf6729 100644
--- a/openespi-common/src/main/resources/db/vendor/postgres/V2__PostgreSQL_Specific_Tables.sql
+++ b/openespi-common/src/main/resources/db/vendor/postgres/V2__PostgreSQL_Specific_Tables.sql
@@ -103,9 +103,9 @@ CREATE TABLE usage_points
service_category VARCHAR(50), -- 2. ServiceCategory
status SMALLINT, -- 3. status
-- 4. serviceDeliveryPoint (FK handled below)
- -- 5. amiBillingReady (enum - Phase 16b)
+ ami_billing_ready VARCHAR(32), -- 5. amiBillingReady (Phase 16b)
check_billing BOOLEAN, -- 6. checkBilling (Phase 16a)
- -- 7. connectionState (enum - Phase 16b)
+ connection_state VARCHAR(32), -- 7. connectionState (Phase 16b)
-- 8. estimatedLoad (embedded SummaryMeasurement)
estimated_load_multiplier VARCHAR(255),
@@ -127,7 +127,7 @@ CREATE TABLE usage_points
nominal_voltage_reading_type_ref VARCHAR(512),
outage_region VARCHAR(256), -- 14. outageRegion (Phase 16a)
- -- 15. phaseCode (enum - Phase 16b)
+ phase_code VARCHAR(32), -- 15. phaseCode (Phase 16b)
-- 16. ratedCurrent (embedded SummaryMeasurement)
rated_current_multiplier VARCHAR(255),
diff --git a/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/repositories/usage/UsagePointRepositoryTest.java b/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/repositories/usage/UsagePointRepositoryTest.java
index 416315aa..2f7f8542 100644
--- a/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/repositories/usage/UsagePointRepositoryTest.java
+++ b/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/repositories/usage/UsagePointRepositoryTest.java
@@ -20,7 +20,10 @@
import org.greenbuttonalliance.espi.common.domain.usage.UsagePointEntity;
import org.greenbuttonalliance.espi.common.domain.usage.RetailCustomerEntity;
+import org.greenbuttonalliance.espi.common.domain.common.AmiBillingReadyKind;
import org.greenbuttonalliance.espi.common.domain.common.LinkType;
+import org.greenbuttonalliance.espi.common.domain.common.PhaseCodeKind;
+import org.greenbuttonalliance.espi.common.domain.common.UsagePointConnectedKind;
import org.greenbuttonalliance.espi.common.test.BaseRepositoryTest;
import org.greenbuttonalliance.espi.common.test.TestDataBuilders;
import org.junit.jupiter.api.DisplayName;
@@ -210,6 +213,33 @@ void shouldPersistAndRetrievePhase16aExtensionFields() {
assertThat(entity.getServiceDeliveryRemark()).isEqualTo("High priority customer");
assertThat(entity.getServicePriority()).isEqualTo("P1");
}
+
+ @Test
+ @DisplayName("Should persist and retrieve Phase 16b enum fields")
+ void shouldPersistAndRetrievePhase16bEnumFields() {
+ // Arrange - Create usage point with all Phase 16b enum fields set
+ UsagePointEntity usagePoint = TestDataBuilders.createValidUsagePoint();
+ usagePoint.setDescription("Usage Point with Phase 16b enum fields");
+
+ // Set Phase 16b enum fields
+ usagePoint.setAmiBillingReady(AmiBillingReadyKind.BILLING_APPROVED);
+ usagePoint.setConnectionState(UsagePointConnectedKind.CONNECTED);
+ usagePoint.setPhaseCode(PhaseCodeKind.ABCN);
+
+ // Act - Save and retrieve
+ UsagePointEntity saved = usagePointRepository.save(usagePoint);
+ flushAndClear();
+ Optional