Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import org.greenbuttonalliance.espi.common.dto.usage.PnodeRefDto;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;

/**
* MapStruct mapper for converting between PnodeRefEntity and PnodeRefDto.
Expand Down Expand Up @@ -60,13 +59,4 @@ public interface PnodeRefMapper {
@Mapping(target = "endEffectiveDate", source = "endEffectiveDate")
PnodeRefEntity toEntity(PnodeRefDto dto);

/**
* Updates an existing PnodeRefEntity with data from a PnodeRefDto.
*
* @param dto the source DTO
* @param entity the target entity to update
*/
@Mapping(target = "id", ignore = true)
@Mapping(target = "usagePoint", ignore = true)
void updateEntity(PnodeRefDto dto, @MappingTarget PnodeRefEntity entity);
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
package org.greenbuttonalliance.espi.common.repositories.usage;

import org.greenbuttonalliance.espi.common.domain.usage.PnodeRefEntity;
import org.greenbuttonalliance.espi.common.domain.usage.UsagePointEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
Expand All @@ -34,92 +33,13 @@
* <p>
* PnodeRef extends Object (not IdentifiedObject) in ESPI 4.0 XSD,
* so it uses Long ID (not UUID).
* <p>
* Provides CRUD operations and custom queries for pricing node references.
*/
@Repository
public interface PnodeRefRepository extends JpaRepository<PnodeRefEntity, Long> {

/**
* Find all pricing node references for a specific usage point.
*
* @param usagePoint the usage point
* @return list of pricing node references
*/
List<PnodeRefEntity> findByUsagePoint(UsagePointEntity usagePoint);

/**
* Find pricing node references by usage point ID.
*
* @param usagePointId the usage point ID (UUID for UsagePoint which extends IdentifiedObject)
* @return list of pricing node references
*/
List<PnodeRefEntity> findByUsagePointId(UUID usagePointId);

/**
* Find pricing node references by type.
*
* @param apnodeType the pricing node type
* @return list of pricing node references
*/
List<PnodeRefEntity> findByApnodeType(String apnodeType);

/**
* Find pricing node references by usage point and type.
*
* @param usagePoint the usage point
* @param apnodeType the pricing node type
* @return list of pricing node references
*/
List<PnodeRefEntity> findByUsagePointAndApnodeType(UsagePointEntity usagePoint, String apnodeType);

/**
* Find pricing node references by reference identifier.
*
* @param ref the reference identifier
* @return list of pricing node references
*/
List<PnodeRefEntity> findByRef(String ref);

/**
* Find currently valid pricing node references for a usage point.
*
* @param usagePointId the usage point ID
* @param currentTime current time in epoch seconds
* @return list of valid pricing node references
*/
@Query("SELECT p FROM PnodeRefEntity p WHERE p.usagePoint.id = :usagePointId " +
"AND (p.startEffectiveDate IS NULL OR p.startEffectiveDate <= :currentTime) " +
"AND (p.endEffectiveDate IS NULL OR p.endEffectiveDate >= :currentTime)")
List<PnodeRefEntity> findValidByUsagePointId(@Param("usagePointId") UUID usagePointId,
@Param("currentTime") Long currentTime);

/**
* Find currently valid pricing node references by type.
*
* @param apnodeType the pricing node type
* @param currentTime current time in epoch seconds
* @return list of valid pricing node references
*/
@Query("SELECT p FROM PnodeRefEntity p WHERE p.apnodeType = :apnodeType " +
"AND (p.startEffectiveDate IS NULL OR p.startEffectiveDate <= :currentTime) " +
"AND (p.endEffectiveDate IS NULL OR p.endEffectiveDate >= :currentTime)")
List<PnodeRefEntity> findValidByApnodeType(@Param("apnodeType") String apnodeType,
@Param("currentTime") Long currentTime);

/**
* Delete all pricing node references for a usage point.
*
* @param usagePoint the usage point
* @return number of deleted records
*/
Long deleteByUsagePoint(UsagePointEntity usagePoint);
@Query("SELECT p.id FROM PnodeRefEntity p")
List<Long> findAllIds();

/**
* Delete pricing node references by usage point ID.
*
* @param usagePointId the usage point ID
* @return number of deleted records
*/
Long deleteByUsagePointId(UUID usagePointId);
@Query("SELECT p FROM PnodeRefEntity p WHERE p.usagePoint.id = :usagePointId")
List<PnodeRefEntity> findAllByUsagePointId(@Param("usagePointId") UUID usagePointId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -112,235 +112,52 @@ void shouldSavePricingNodeRefWithEffectiveDates() {
class CustomQueryMethodsTest {

@Test
@DisplayName("Should find pricing node refs by usage point")
void shouldFindPricingNodeRefsByUsagePoint() {
@DisplayName("Should find all IDs")
void shouldFindAllIds() {
// Arrange
UsagePointEntity usagePoint = TestDataBuilders.createValidUsagePoint();
UsagePointEntity savedUsagePoint = usagePointRepository.save(usagePoint);

PnodeRefEntity pnodeRef1 = new PnodeRefEntity("HUB", "HUB_1", savedUsagePoint);
PnodeRefEntity pnodeRef2 = new PnodeRefEntity("LOAD_ZONE", "ZONE_1", savedUsagePoint);
pnodeRefRepository.save(pnodeRef1);
pnodeRefRepository.save(pnodeRef2);

PnodeRefEntity saved1 = pnodeRefRepository.save(pnodeRef1);
PnodeRefEntity saved2 = pnodeRefRepository.save(pnodeRef2);
flushAndClear();

// Act
List<PnodeRefEntity> pnodeRefs = pnodeRefRepository.findByUsagePoint(savedUsagePoint);
List<Long> allIds = pnodeRefRepository.findAllIds();

// Assert
assertThat(pnodeRefs).hasSize(2);
assertThat(pnodeRefs).extracting(PnodeRefEntity::getRef)
.containsExactlyInAnyOrder("HUB_1", "ZONE_1");
assertThat(allIds).contains(saved1.getId(), saved2.getId());
}

@Test
@DisplayName("Should find pricing node refs by usage point ID")
void shouldFindPricingNodeRefsByUsagePointId() {
@DisplayName("Should find all pricing node refs by usage point ID")
void shouldFindAllPricingNodeRefsByUsagePointId() {
// Arrange
UsagePointEntity usagePoint1 = TestDataBuilders.createValidUsagePoint();
UsagePointEntity usagePoint2 = TestDataBuilders.createValidUsagePoint();
UsagePointEntity savedUsagePoint1 = usagePointRepository.save(usagePoint1);
UsagePointEntity savedUsagePoint2 = usagePointRepository.save(usagePoint2);

PnodeRefEntity pnodeRef1 = new PnodeRefEntity("HUB", "HUB_1", savedUsagePoint1);
PnodeRefEntity pnodeRef2 = new PnodeRefEntity("HUB", "HUB_2", savedUsagePoint1);
PnodeRefEntity pnodeRef3 = new PnodeRefEntity("HUB", "HUB_3", savedUsagePoint2);

pnodeRefRepository.save(pnodeRef1);
pnodeRefRepository.save(pnodeRef2);
pnodeRefRepository.save(pnodeRef3);
flushAndClear();

// Act
List<PnodeRefEntity> pnodeRefs = pnodeRefRepository.findByUsagePointId(savedUsagePoint1.getId());
List<PnodeRefEntity> pnodeRefs = pnodeRefRepository.findAllByUsagePointId(savedUsagePoint1.getId());

// Assert
assertThat(pnodeRefs).hasSize(2);
assertThat(pnodeRefs).extracting(PnodeRefEntity::getRef)
.containsExactlyInAnyOrder("HUB_1", "HUB_2");
}

@Test
@DisplayName("Should find pricing node refs by apnode type")
void shouldFindPricingNodeRefsByApnodeType() {
// Arrange
UsagePointEntity usagePoint = TestDataBuilders.createValidUsagePoint();
UsagePointEntity savedUsagePoint = usagePointRepository.save(usagePoint);

PnodeRefEntity pnodeRef1 = new PnodeRefEntity("HUB", "HUB_1", savedUsagePoint);
PnodeRefEntity pnodeRef2 = new PnodeRefEntity("HUB", "HUB_2", savedUsagePoint);
PnodeRefEntity pnodeRef3 = new PnodeRefEntity("LOAD_ZONE", "ZONE_1", savedUsagePoint);

pnodeRefRepository.save(pnodeRef1);
pnodeRefRepository.save(pnodeRef2);
pnodeRefRepository.save(pnodeRef3);
flushAndClear();

// Act
List<PnodeRefEntity> hubRefs = pnodeRefRepository.findByApnodeType("HUB");

// Assert
assertThat(hubRefs).hasSize(2);
assertThat(hubRefs).extracting(PnodeRefEntity::getRef)
.containsExactlyInAnyOrder("HUB_1", "HUB_2");
}

@Test
@DisplayName("Should find pricing node refs by usage point and apnode type")
void shouldFindPricingNodeRefsByUsagePointAndApnodeType() {
// Arrange
UsagePointEntity usagePoint = TestDataBuilders.createValidUsagePoint();
UsagePointEntity savedUsagePoint = usagePointRepository.save(usagePoint);

PnodeRefEntity pnodeRef1 = new PnodeRefEntity("HUB", "HUB_1", savedUsagePoint);
PnodeRefEntity pnodeRef2 = new PnodeRefEntity("LOAD_ZONE", "ZONE_1", savedUsagePoint);

pnodeRefRepository.save(pnodeRef1);
pnodeRefRepository.save(pnodeRef2);
flushAndClear();

// Act
List<PnodeRefEntity> hubRefs = pnodeRefRepository.findByUsagePointAndApnodeType(savedUsagePoint, "HUB");

// Assert
assertThat(hubRefs).hasSize(1);
assertThat(hubRefs.get(0).getRef()).isEqualTo("HUB_1");
}

@Test
@DisplayName("Should find pricing node refs by ref")
void shouldFindPricingNodeRefsByRef() {
// Arrange
UsagePointEntity usagePoint = TestDataBuilders.createValidUsagePoint();
UsagePointEntity savedUsagePoint = usagePointRepository.save(usagePoint);

PnodeRefEntity pnodeRef1 = new PnodeRefEntity("HUB", "UNIQUE_HUB", savedUsagePoint);
PnodeRefEntity pnodeRef2 = new PnodeRefEntity("LOAD_ZONE", "COMMON_REF", savedUsagePoint);

pnodeRefRepository.save(pnodeRef1);
pnodeRefRepository.save(pnodeRef2);
flushAndClear();

// Act
List<PnodeRefEntity> refs = pnodeRefRepository.findByRef("UNIQUE_HUB");

// Assert
assertThat(refs).hasSize(1);
assertThat(refs.get(0).getApnodeType()).isEqualTo("HUB");
}

@Test
@DisplayName("Should find valid pricing node refs by usage point ID")
void shouldFindValidPricingNodeRefsByUsagePointId() {
// Arrange
UsagePointEntity usagePoint = TestDataBuilders.createValidUsagePoint();
UsagePointEntity savedUsagePoint = usagePointRepository.save(usagePoint);

long currentTime = System.currentTimeMillis() / 1000;
long pastTime = currentTime - 3600; // 1 hour ago
long futureTime = currentTime + 3600; // 1 hour from now

// Valid: no dates set (always valid)
PnodeRefEntity validRef1 = new PnodeRefEntity("HUB", "ALWAYS_VALID", savedUsagePoint);

// Valid: started in past, no end date
PnodeRefEntity validRef2 = new PnodeRefEntity("HUB", "STARTED_VALID", pastTime, null, savedUsagePoint);

// Invalid: starts in future
PnodeRefEntity invalidRef = new PnodeRefEntity("HUB", "FUTURE_START", futureTime, null, savedUsagePoint);

pnodeRefRepository.save(validRef1);
pnodeRefRepository.save(validRef2);
pnodeRefRepository.save(invalidRef);
flushAndClear();

// Act
List<PnodeRefEntity> validRefs = pnodeRefRepository.findValidByUsagePointId(savedUsagePoint.getId(), currentTime);

// Assert
assertThat(validRefs).hasSize(2);
assertThat(validRefs).extracting(PnodeRefEntity::getRef)
.containsExactlyInAnyOrder("ALWAYS_VALID", "STARTED_VALID");
}

@Test
@DisplayName("Should find valid pricing node refs by apnode type")
void shouldFindValidPricingNodeRefsByApnodeType() {
// Arrange
UsagePointEntity usagePoint = TestDataBuilders.createValidUsagePoint();
UsagePointEntity savedUsagePoint = usagePointRepository.save(usagePoint);

long currentTime = System.currentTimeMillis() / 1000;
long pastTime = currentTime - 3600; // 1 hour ago
long futureTime = currentTime + 3600; // 1 hour from now

// Valid HUB
PnodeRefEntity validHub = new PnodeRefEntity("HUB", "VALID_HUB", pastTime, futureTime, savedUsagePoint);

// Invalid HUB (expired)
PnodeRefEntity expiredHub = new PnodeRefEntity("HUB", "EXPIRED_HUB", pastTime, pastTime + 1800, savedUsagePoint);

// Valid LOAD_ZONE
PnodeRefEntity validZone = new PnodeRefEntity("LOAD_ZONE", "VALID_ZONE", savedUsagePoint);

pnodeRefRepository.save(validHub);
pnodeRefRepository.save(expiredHub);
pnodeRefRepository.save(validZone);
flushAndClear();

// Act
List<PnodeRefEntity> validHubs = pnodeRefRepository.findValidByApnodeType("HUB", currentTime);

// Assert
assertThat(validHubs).hasSize(1);
assertThat(validHubs.get(0).getRef()).isEqualTo("VALID_HUB");
}

@Test
@DisplayName("Should delete pricing node refs by usage point")
void shouldDeletePricingNodeRefsByUsagePoint() {
// Arrange
UsagePointEntity usagePoint = TestDataBuilders.createValidUsagePoint();
UsagePointEntity savedUsagePoint = usagePointRepository.save(usagePoint);

PnodeRefEntity pnodeRef1 = new PnodeRefEntity("HUB", "HUB_1", savedUsagePoint);
PnodeRefEntity pnodeRef2 = new PnodeRefEntity("HUB", "HUB_2", savedUsagePoint);

pnodeRefRepository.save(pnodeRef1);
pnodeRefRepository.save(pnodeRef2);
flushAndClear();

// Act
Long deletedCount = pnodeRefRepository.deleteByUsagePoint(savedUsagePoint);
flushAndClear();

// Assert
assertThat(deletedCount).isEqualTo(2L);
List<PnodeRefEntity> remainingRefs = pnodeRefRepository.findByUsagePoint(savedUsagePoint);
assertThat(remainingRefs).isEmpty();
}

@Test
@DisplayName("Should delete pricing node refs by usage point ID")
void shouldDeletePricingNodeRefsByUsagePointId() {
// Arrange
UsagePointEntity usagePoint = TestDataBuilders.createValidUsagePoint();
UsagePointEntity savedUsagePoint = usagePointRepository.save(usagePoint);

PnodeRefEntity pnodeRef = new PnodeRefEntity("HUB", "DELETE_TEST", savedUsagePoint);
pnodeRefRepository.save(pnodeRef);
flushAndClear();

// Act
Long deletedCount = pnodeRefRepository.deleteByUsagePointId(savedUsagePoint.getId());
flushAndClear();

// Assert
assertThat(deletedCount).isEqualTo(1L);
List<PnodeRefEntity> remainingRefs = pnodeRefRepository.findByUsagePointId(savedUsagePoint.getId());
assertThat(remainingRefs).isEmpty();
}
}

@Nested
Expand Down
Loading