diff --git a/cwms-data-api/src/main/java/cwms/cda/api/BasinController.java b/cwms-data-api/src/main/java/cwms/cda/api/BasinController.java index 028da1e38..6eba3b795 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/BasinController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/BasinController.java @@ -24,22 +24,25 @@ package cwms.cda.api; +import static cwms.cda.api.Controllers.METHOD; import static cwms.cda.api.Controllers.STATUS_200; import static cwms.cda.api.Controllers.STATUS_204; import static cwms.cda.api.Controllers.STATUS_404; import static cwms.cda.api.Controllers.STATUS_501; -import static cwms.cda.api.Controllers.DELETE_MODE; import static cwms.cda.api.Controllers.GET_ALL; import static cwms.cda.api.Controllers.GET_ONE; import static cwms.cda.api.Controllers.NAME; import static cwms.cda.api.Controllers.OFFICE; import static cwms.cda.api.Controllers.UNIT; +import static cwms.cda.api.Controllers.requiredParam; +import static cwms.cda.api.Controllers.requiredParamAs; import static cwms.cda.data.dao.JooqDao.getDslContext; import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.Timer; import cwms.cda.api.enums.UnitSystem; import cwms.cda.api.errors.CdaError; +import cwms.cda.data.dao.JooqDao; import cwms.cda.data.dao.basinconnectivity.BasinDao; import cwms.cda.data.dto.CwmsId; import cwms.cda.data.dto.basinconnectivity.Basin; @@ -184,6 +187,7 @@ public void getOne(@NotNull Context ctx, @NotNull String name) { try (final Timer.Context ignored = markAndTime(GET_ONE)) { DSLContext dsl = getDslContext(ctx); + String units = ctx.queryParamAsClass(UNIT, String.class).getOrDefault(UnitSystem.EN.value()); String office = ctx.queryParam(OFFICE); @@ -206,8 +210,7 @@ public void getOne(@NotNull Context ctx, @NotNull String name) { .withOfficeId(office) .build(); cwms.cda.data.dto.basin.Basin basin = basinDao.getBasin(basinId, units); - result = Formats.format(contentType, Collections.singletonList(basin), - cwms.cda.data.dto.basin.Basin.class); + result = Formats.format(contentType, basin); ctx.result(result); ctx.status(HttpServletResponse.SC_OK); } @@ -224,6 +227,8 @@ public void getOne(@NotNull Context ctx, @NotNull String name) { @OpenApiParam(name = NAME, required = true, description = "Specifies the new name for the basin.") }, pathParams = { + @OpenApiParam(name = OFFICE, required = true, description = "Specifies the owning office of " + + "the basin to be renamed."), @OpenApiParam(name = NAME, description = "Specifies the name of " + "the basin to be renamed.") }, @@ -233,35 +238,26 @@ public void getOne(@NotNull Context ctx, @NotNull String name) { @OpenApiResponse(status = STATUS_501, description = "Requested format is not " + "implemented") }, + method = HttpMethod.PATCH, description = "Renames CWMS Basin", tags = {TAG} ) @Override public void update(@NotNull Context ctx, @NotNull String name) { DSLContext dsl = getDslContext(ctx); - String formatHeader = ctx.header(Header.ACCEPT) != null ? ctx.header(Header.ACCEPT) : - Formats.JSONV1; - ContentType contentType = Formats.parseHeader(formatHeader, Basin.class); - ctx.contentType(contentType.toString()); - - cwms.cda.data.dto.basin.Basin basin = Formats.parseContent(contentType, ctx.body(), - cwms.cda.data.dto.basin.Basin.class); - - if (contentType.getType().equals(Formats.NAMED_PGJSON)) { - ctx.status(HttpCode.NOT_IMPLEMENTED).json(CdaError.notImplemented()); - } else { - cwms.cda.data.dao.basin.BasinDao basinDao = new cwms.cda.data.dao.basin.BasinDao(dsl); - CwmsId oldLoc = new CwmsId.Builder() - .withName(name) - .withOfficeId(basin.getBasinId().getOfficeId()) - .build(); - CwmsId newLoc = new CwmsId.Builder() - .withName(ctx.queryParam(NAME)) - .withOfficeId(basin.getBasinId().getOfficeId()) - .build(); - basinDao.renameBasin(oldLoc, newLoc); - ctx.status(HttpServletResponse.SC_OK).json("Updated Location"); - } + String officeId = requiredParam(ctx, OFFICE); + String newStreamId = requiredParam(ctx, NAME); + cwms.cda.data.dao.basin.BasinDao basinDao = new cwms.cda.data.dao.basin.BasinDao(dsl); + CwmsId oldLoc = new CwmsId.Builder() + .withName(name) + .withOfficeId(officeId) + .build(); + CwmsId newLoc = new CwmsId.Builder() + .withName(newStreamId) + .withOfficeId(officeId) + .build(); + basinDao.renameBasin(oldLoc, newLoc); + ctx.status(HttpServletResponse.SC_OK).json("Updated Location"); } @OpenApi( @@ -294,7 +290,8 @@ public void create(@NotNull Context ctx) { queryParams = { @OpenApiParam(name = OFFICE, required = true, description = "Specifies the" + " owning office of the basin to be renamed."), - @OpenApiParam(name = DELETE_MODE, required = true, description = "Specifies the delete method used.") + @OpenApiParam(name = METHOD, required = true, description = "Specifies the delete method used.", + type = JooqDao.DeleteMethod.class) }, pathParams = { @OpenApiParam(name = NAME, description = "Specifies the name of " @@ -312,19 +309,13 @@ public void create(@NotNull Context ctx) { @Override public void delete(@NotNull Context ctx, @NotNull String name) { DSLContext dsl = getDslContext(ctx); - String deleteMethod = ctx.queryParam(DELETE_MODE); + JooqDao.DeleteMethod deleteMethod = requiredParamAs(ctx, METHOD, JooqDao.DeleteMethod.class); cwms.cda.data.dao.basin.BasinDao basinDao = new cwms.cda.data.dao.basin.BasinDao(dsl); CwmsId basinId = new CwmsId.Builder() .withName(name) .withOfficeId(ctx.queryParam(OFFICE)) .build(); - cwms.cda.data.dto.basin.Basin retBasin = basinDao.getBasin(basinId, "EN"); - if (retBasin == null) { - CdaError error = new CdaError("No matching basin " + name); - ctx.status(HttpServletResponse.SC_NOT_FOUND).json(error); - return; - } - basinDao.deleteBasin(basinId, deleteMethod); + basinDao.deleteBasin(basinId, deleteMethod.getRule()); ctx.status(HttpServletResponse.SC_NO_CONTENT).json(basinId.getName() + " Deleted"); } } \ No newline at end of file diff --git a/cwms-data-api/src/main/java/cwms/cda/api/Controllers.java b/cwms-data-api/src/main/java/cwms/cda/api/Controllers.java index 668732f01..588e0d8c8 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/Controllers.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/Controllers.java @@ -161,6 +161,8 @@ public final class Controllers { public static final String STATUS_400 = "400"; public static final String TEXT_MASK = "text-mask"; public static final String DELETE_MODE = "delete-mode"; + public static final String MIN_ATTRIBUTE = "min-attribute"; + public static final String MAX_ATTRIBUTE = "max-attribute"; public static final String STANDARD_TEXT_ID_MASK = "standard-text-id-mask"; public static final String STANDARD_TEXT_ID = "standard-text-id"; public static final String STREAM_ID_MASK = "stream-id-mask"; @@ -340,6 +342,18 @@ public static String requiredParam(io.javalin.http.Context ctx, String name) { return param; } + /** + * Returns the first matching query param or throws RequiredQueryParameterException. + * @param ctx Request Context + * @param name Query parameter name + * @return value of the parameter + * @throws RequiredQueryParameterException if the parameter is not found + */ + public static T requiredParamAs(io.javalin.http.Context ctx, String name, Class type) { + return ctx.queryParamAsClass(name, type) + .getOrThrow(e -> new RequiredQueryParameterException(name)); + } + @Nullable public static ZonedDateTime queryParamAsZdt(Context ctx, String param, String timezone) { ZonedDateTime beginZdt = null; diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dao/basin/BasinDao.java b/cwms-data-api/src/main/java/cwms/cda/data/dao/basin/BasinDao.java index 4d30d2c87..00bfb622c 100644 --- a/cwms-data-api/src/main/java/cwms/cda/data/dao/basin/BasinDao.java +++ b/cwms-data-api/src/main/java/cwms/cda/data/dao/basin/BasinDao.java @@ -24,6 +24,7 @@ package cwms.cda.data.dao.basin; +import cwms.cda.data.dao.DeleteRule; import cwms.cda.data.dao.JooqDao; import cwms.cda.data.dto.CwmsId; import cwms.cda.data.dto.basin.Basin; @@ -128,12 +129,13 @@ public void renameBasin(CwmsId oldBasin, CwmsId newBasin) { } - public void deleteBasin(CwmsId basinId, String deleteAction) { + public void deleteBasin(CwmsId basinId, DeleteRule deleteAction) { basinId.validate(); connection(dsl, c -> { setOffice(c, basinId.getOfficeId()); - CWMS_BASIN_PACKAGE.call_DELETE_BASIN(DSL.using(c).configuration(), basinId.getName(), deleteAction, basinId.getOfficeId()); + CWMS_BASIN_PACKAGE.call_DELETE_BASIN(DSL.using(c).configuration(), basinId.getName(), + deleteAction.getRule(), basinId.getOfficeId()); }); } diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dao/watersupply/WaterContractDao.java b/cwms-data-api/src/main/java/cwms/cda/data/dao/watersupply/WaterContractDao.java new file mode 100644 index 000000000..514dddf23 --- /dev/null +++ b/cwms-data-api/src/main/java/cwms/cda/data/dao/watersupply/WaterContractDao.java @@ -0,0 +1,203 @@ +/* + * + * MIT License + * + * Copyright (c) 2024 Hydrologic Engineering Center + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE + * SOFTWARE. + */ + +package cwms.cda.data.dao.watersupply; + +import static java.util.stream.Collectors.toList; + +import cwms.cda.api.errors.NotFoundException; +import cwms.cda.data.dao.JooqDao; +import cwms.cda.data.dao.location.kind.LocationUtil; +import cwms.cda.data.dto.CwmsId; +import cwms.cda.data.dto.LookupType; +import cwms.cda.data.dto.watersupply.PumpType; +import cwms.cda.data.dto.watersupply.WaterUser; +import cwms.cda.data.dto.watersupply.WaterUserContract; +import java.util.List; +import org.jooq.DSLContext; +import org.jooq.impl.DSL; +import usace.cwms.db.dao.util.OracleTypeMap; +import usace.cwms.db.jooq.codegen.packages.CWMS_WATER_SUPPLY_PACKAGE; +import usace.cwms.db.jooq.codegen.udt.records.LOCATION_REF_T; +import usace.cwms.db.jooq.codegen.udt.records.LOOKUP_TYPE_TAB_T; +import usace.cwms.db.jooq.codegen.udt.records.WATER_USER_CONTRACT_REF_T; +import usace.cwms.db.jooq.codegen.udt.records.WATER_USER_CONTRACT_TAB_T; +import usace.cwms.db.jooq.codegen.udt.records.WATER_USER_OBJ_T; +import usace.cwms.db.jooq.codegen.udt.records.WATER_USER_TAB_T; + + +public class WaterContractDao extends JooqDao { + public WaterContractDao(DSLContext dsl) { + super(dsl); + } + + public List getAllWaterContracts(CwmsId projectLocation, String entityName) { + return connectionResult(dsl, c -> { + setOffice(c, projectLocation.getOfficeId()); + LOCATION_REF_T projectLocationRef = LocationUtil.getLocationRef(projectLocation); + return CWMS_WATER_SUPPLY_PACKAGE.call_RETRIEVE_CONTRACTS( + DSL.using(c).configuration(), projectLocationRef, entityName) + .stream() + .map(WaterSupplyUtils::toWaterContract) + .collect(toList()); + }); + } + + public WaterUserContract getWaterContract(String contractName, CwmsId projectLocation, String entityName) { + return connectionResult(dsl, c -> { + setOffice(c, projectLocation.getOfficeId()); + LOCATION_REF_T projectLocationRef = LocationUtil.getLocationRef(projectLocation); + return CWMS_WATER_SUPPLY_PACKAGE.call_RETRIEVE_CONTRACTS( + DSL.using(c).configuration(), projectLocationRef, entityName) + .stream() + .map(WaterSupplyUtils::toWaterContract) + .filter(contract -> contract.getContractId().getName().equals(contractName)) + .findAny() + .orElseThrow(() -> new NotFoundException("Water contract not found: " + contractName)); + }); + } + + public List getAllWaterContractTypes(String officeId) { + return connectionResult(dsl, c -> { + setOffice(c, officeId); + return CWMS_WATER_SUPPLY_PACKAGE.call_GET_CONTRACT_TYPES( + DSL.using(c).configuration(), officeId) + .stream() + .map(LocationUtil::getLookupType) + .collect(toList()); + }); + } + + public List getAllWaterUsers(CwmsId projectLocation) { + return connectionResult(dsl, c -> { + setOffice(c, projectLocation.getOfficeId()); + LOCATION_REF_T projectLocationRef = LocationUtil.getLocationRef(projectLocation); + return CWMS_WATER_SUPPLY_PACKAGE.call_RETRIEVE_WATER_USERS( + DSL.using(c).configuration(), projectLocationRef) + .stream() + .map(WaterSupplyUtils::toWaterUser) + .collect(toList()); + }); + } + + public WaterUser getWaterUser(CwmsId projectLocation, String entityName) { + return connectionResult(dsl, c -> { + setOffice(c, projectLocation.getOfficeId()); + LOCATION_REF_T projectLocationRef = LocationUtil.getLocationRef(projectLocation); + return CWMS_WATER_SUPPLY_PACKAGE.call_RETRIEVE_WATER_USERS( + DSL.using(c).configuration(), projectLocationRef) + .stream() + .map(WaterSupplyUtils::toWaterUser) + .filter(waterUser -> waterUser.getEntityName().equals(entityName)) + .findAny() + .orElseThrow(() -> new NotFoundException("Water user not found: " + entityName)); + }); + } + + public void storeWaterContract(WaterUserContract waterContract, boolean failIfExists, boolean ignoreNulls) { + connection(dsl, c -> { + setOffice(c, waterContract.getOfficeId()); + String paramFailIfExists = OracleTypeMap.formatBool(failIfExists); + String paramIgnoreNulls = OracleTypeMap.formatBool(ignoreNulls); + WATER_USER_CONTRACT_TAB_T paramContracts = WaterSupplyUtils.toWaterUserContractTs(waterContract); + CWMS_WATER_SUPPLY_PACKAGE.call_STORE_CONTRACTS2(DSL.using(c).configuration(), paramContracts, + paramFailIfExists, paramIgnoreNulls); + }); + } + + public void renameWaterUser(String oldWaterUser, String newWaterUser, CwmsId projectLocation) { + connection(dsl, c -> { + setOffice(c, projectLocation.getOfficeId()); + LOCATION_REF_T projectLocationRefT = LocationUtil.getLocationRef(projectLocation); + CWMS_WATER_SUPPLY_PACKAGE.call_RENAME_WATER_USER(DSL.using(c).configuration(), projectLocationRefT, + oldWaterUser, newWaterUser); + }); + } + + public void storeWaterUser(WaterUser waterUser, boolean failIfExists) { + connection(dsl, c -> { + setOffice(c, waterUser.getProjectId().getOfficeId()); + WATER_USER_TAB_T waterUsers = WaterSupplyUtils.toWaterUserTs(waterUser); + String paramFailIfExists = OracleTypeMap.formatBool(failIfExists); + CWMS_WATER_SUPPLY_PACKAGE.call_STORE_WATER_USERS(DSL.using(c).configuration(), + waterUsers, paramFailIfExists); + }); + } + + public void renameWaterContract(WaterUser waterUser, String oldContractName, + String newContractName) { + connection(dsl, c -> { + setOffice(c, waterUser.getProjectId().getOfficeId()); + WATER_USER_OBJ_T waterUserT = WaterSupplyUtils.toWaterUser(waterUser); + WATER_USER_CONTRACT_REF_T waterUserContract = new WATER_USER_CONTRACT_REF_T(waterUserT, oldContractName); + CWMS_WATER_SUPPLY_PACKAGE.call_RENAME_CONTRACT(DSL.using(c).configuration(), waterUserContract, + oldContractName, newContractName); + }); + } + + public void deleteWaterUser(CwmsId location, String entityName, String deleteAction) { + connection(dsl, c -> { + setOffice(c, location.getOfficeId()); + LOCATION_REF_T projectLocationRef = LocationUtil.getLocationRef(location); + CWMS_WATER_SUPPLY_PACKAGE.call_DELETE_WATER_USER(DSL.using(c).configuration(), projectLocationRef, + entityName, deleteAction); + }); + } + + public void deleteWaterContract(WaterUserContract contract, String deleteAction) { + connection(dsl, c -> { + setOffice(c, contract.getOfficeId()); + WATER_USER_OBJ_T waterUserT = WaterSupplyUtils.toWaterUser(contract.getWaterUser()); + String contractName = contract.getContractId().getName(); + WATER_USER_CONTRACT_REF_T waterUserContract = new WATER_USER_CONTRACT_REF_T(waterUserT, contractName); + CWMS_WATER_SUPPLY_PACKAGE.call_DELETE_CONTRACT(DSL.using(c).configuration(), waterUserContract, + deleteAction); + }); + } + + public void storeWaterContractTypes(List lookupTypes, + boolean failIfExists) { + connection(dsl, c -> { + setOffice(c, lookupTypes.get(0).getOfficeId()); + LOOKUP_TYPE_TAB_T contractTypes = WaterSupplyUtils.toLookupTypeT(lookupTypes); + String paramFailIfExists = OracleTypeMap.formatBool(failIfExists); + CWMS_WATER_SUPPLY_PACKAGE.call_SET_CONTRACT_TYPES(DSL.using(c).configuration(), + contractTypes, paramFailIfExists); + }); + } + + public void removePumpFromContract(WaterUserContract contract, String pumpLocName, + PumpType pumpType, boolean deleteAccountingData) { + connection(dsl, c -> { + setOffice(c, contract.getOfficeId()); + WATER_USER_CONTRACT_REF_T waterUserContractRefT = WaterSupplyUtils + .toWaterUserContractRefTs(contract); + String paramDeleteAccountingData = OracleTypeMap.formatBool(deleteAccountingData); + CWMS_WATER_SUPPLY_PACKAGE.call_DISASSOCIATE_PUMP(DSL.using(c).configuration(), + waterUserContractRefT, pumpLocName, pumpType.toString(), paramDeleteAccountingData); + }); + } +} diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dao/watersupply/WaterSupplyUtils.java b/cwms-data-api/src/main/java/cwms/cda/data/dao/watersupply/WaterSupplyUtils.java new file mode 100644 index 000000000..611bfb3c0 --- /dev/null +++ b/cwms-data-api/src/main/java/cwms/cda/data/dao/watersupply/WaterSupplyUtils.java @@ -0,0 +1,162 @@ +/* + * + * MIT License + * + * Copyright (c) 2024 Hydrologic Engineering Center + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE + * SOFTWARE. + */ + +package cwms.cda.data.dao.watersupply; + +import cwms.cda.data.dao.location.kind.LocationUtil; +import cwms.cda.data.dto.CwmsId; +import cwms.cda.data.dto.LookupType; +import cwms.cda.data.dto.watersupply.PumpType; +import cwms.cda.data.dto.watersupply.WaterSupplyPump; +import cwms.cda.data.dto.watersupply.WaterUser; +import cwms.cda.data.dto.watersupply.WaterUserContract; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.List; +import usace.cwms.db.dao.util.OracleTypeMap; +import usace.cwms.db.jooq.codegen.udt.records.LOOKUP_TYPE_OBJ_T; +import usace.cwms.db.jooq.codegen.udt.records.LOOKUP_TYPE_TAB_T; +import usace.cwms.db.jooq.codegen.udt.records.WATER_USER_CONTRACT_OBJ_T; +import usace.cwms.db.jooq.codegen.udt.records.WATER_USER_CONTRACT_REF_T; +import usace.cwms.db.jooq.codegen.udt.records.WATER_USER_CONTRACT_TAB_T; +import usace.cwms.db.jooq.codegen.udt.records.WATER_USER_OBJ_T; +import usace.cwms.db.jooq.codegen.udt.records.WATER_USER_TAB_T; + + +public final class WaterSupplyUtils { + + private WaterSupplyUtils() { + throw new IllegalStateException("Utility class"); + } + + public static WaterUserContract toWaterContract(WATER_USER_CONTRACT_OBJ_T contract) { + return new WaterUserContract.Builder().withContractedStorage(contract.getCONTRACTED_STORAGE()) + .withTotalAllocPercentActivated(contract.getTOTAL_ALLOC_PERCENT_ACTIVATED()) + .withContractType(LocationUtil.getLookupType(contract.getWATER_SUPPLY_CONTRACT_TYPE())) + .withContractEffectiveDate(contract.getWS_CONTRACT_EFFECTIVE_DATE()) + .withOfficeId(contract.getWATER_SUPPLY_CONTRACT_TYPE().getOFFICE_ID()) + .withStorageUnitsId(contract.getSTORAGE_UNITS_ID()) + .withContractExpirationDate(contract.getWS_CONTRACT_EXPIRATION_DATE()) + .withWaterUser(toWaterUser(contract.getWATER_USER_CONTRACT_REF().getWATER_USER())) + .withContractId(new CwmsId.Builder().withOfficeId(contract.getWATER_SUPPLY_CONTRACT_TYPE() + .getOFFICE_ID()).withName(contract.getWATER_USER_CONTRACT_REF() + .getCONTRACT_NAME()).build()) + .withFutureUseAllocation(contract.getFUTURE_USE_ALLOCATION()) + .withFutureUsePercentActivated(contract.getFUTURE_USE_PERCENT_ACTIVATED()) + .withInitialUseAllocation(contract.getINITIAL_USE_ALLOCATION()) + .withPumpOutLocation(new WaterSupplyPump.Builder().withPumpLocation(LocationUtil + .getLocation(contract.getPUMP_OUT_LOCATION())).withPumpType(PumpType.OUT).build()) + .withPumpOutBelowLocation(new WaterSupplyPump.Builder().withPumpLocation(LocationUtil + .getLocation(contract.getPUMP_OUT_BELOW_LOCATION())).withPumpType(PumpType.BELOW).build()) + .withPumpInLocation(new WaterSupplyPump.Builder().withPumpLocation(LocationUtil + .getLocation(contract.getPUMP_IN_LOCATION())).withPumpType(PumpType.IN).build()) + .build(); + } + + public static WaterUser toWaterUser(WATER_USER_OBJ_T waterUserTabT) { + return new WaterUser.Builder().withEntityName(waterUserTabT.getENTITY_NAME()) + .withProjectId(new CwmsId.Builder().withName(waterUserTabT.getPROJECT_LOCATION_REF() + .call_GET_LOCATION_ID()).withOfficeId(waterUserTabT.getPROJECT_LOCATION_REF() + .getOFFICE_ID()).build()) + .withWaterRight(waterUserTabT.getWATER_RIGHT()).build(); + } + + public static WATER_USER_OBJ_T toWaterUser(WaterUser waterUser) { + WATER_USER_OBJ_T waterUserObjT = new WATER_USER_OBJ_T(); + waterUserObjT.setENTITY_NAME(waterUser.getEntityName()); + waterUserObjT.setPROJECT_LOCATION_REF(LocationUtil.getLocationRef(waterUser.getProjectId())); + waterUserObjT.setWATER_RIGHT(waterUser.getWaterRight()); + return waterUserObjT; + } + + public static WATER_USER_TAB_T toWaterUserTs(WaterUser waterUser) { + WATER_USER_OBJ_T waterUserObjT = new WATER_USER_OBJ_T(); + waterUserObjT.setENTITY_NAME(waterUser.getEntityName()); + waterUserObjT.setPROJECT_LOCATION_REF(LocationUtil.getLocationRef(waterUser.getProjectId())); + waterUserObjT.setWATER_RIGHT(waterUser.getWaterRight()); + List waterUserList = new ArrayList<>(); + waterUserList.add(waterUserObjT); + return new WATER_USER_TAB_T(waterUserList); + } + + public static LOOKUP_TYPE_OBJ_T toLookupTypeT(LookupType lookupType) { + LOOKUP_TYPE_OBJ_T lookupTypeObjT = new LOOKUP_TYPE_OBJ_T(); + lookupTypeObjT.setOFFICE_ID(lookupType.getOfficeId()); + lookupTypeObjT.setDISPLAY_VALUE(lookupType.getDisplayValue()); + lookupTypeObjT.setTOOLTIP(lookupType.getTooltip()); + lookupTypeObjT.setACTIVE(OracleTypeMap.formatBool(lookupType.getActive())); + return lookupTypeObjT; + } + + public static LOOKUP_TYPE_TAB_T toLookupTypeT(List lookupTypes) { + List lookupTypeList = new ArrayList<>(); + for (LookupType lookupType : lookupTypes) { + lookupTypeList.add(toLookupTypeT(lookupType)); + } + return new LOOKUP_TYPE_TAB_T(lookupTypeList); + } + + public static WATER_USER_CONTRACT_REF_T toContractRef(WaterUser waterUser, String contractName) { + WATER_USER_CONTRACT_REF_T waterUserContractRefT = new WATER_USER_CONTRACT_REF_T(); + waterUserContractRefT.setWATER_USER(toWaterUser(waterUser)); + waterUserContractRefT.setCONTRACT_NAME(contractName); + return waterUserContractRefT; + } + + public static WATER_USER_CONTRACT_REF_T toWaterUserContractRefTs(WaterUserContract waterUserContract) { + WATER_USER_CONTRACT_REF_T waterUserContractRefT = new WATER_USER_CONTRACT_REF_T(); + waterUserContractRefT.setWATER_USER(toWaterUser(waterUserContract.getWaterUser())); + waterUserContractRefT.setCONTRACT_NAME(waterUserContract.getContractId().getName()); + return waterUserContractRefT; + } + + public static WATER_USER_CONTRACT_TAB_T toWaterUserContractTs(WaterUserContract waterUserContract) { + WATER_USER_CONTRACT_OBJ_T waterUserContractObjT = new WATER_USER_CONTRACT_OBJ_T(); + waterUserContractObjT.setCONTRACTED_STORAGE(waterUserContract.getContractedStorage()); + waterUserContractObjT.setTOTAL_ALLOC_PERCENT_ACTIVATED(waterUserContract.getTotalAllocPercentActivated()); + waterUserContractObjT.setWS_CONTRACT_EFFECTIVE_DATE(new Timestamp(waterUserContract + .getContractEffectiveDate().toInstant().toEpochMilli())); + waterUserContractObjT.setSTORAGE_UNITS_ID(waterUserContract.getStorageUnitsId()); + waterUserContractObjT.setWS_CONTRACT_EXPIRATION_DATE(new Timestamp(waterUserContract + .getContractExpirationDate().toInstant().toEpochMilli())); + waterUserContractObjT.setWATER_USER_CONTRACT_REF(toContractRef(waterUserContract.getWaterUser(), + waterUserContract.getContractId().getName())); + waterUserContractObjT.setWATER_SUPPLY_CONTRACT_TYPE(toLookupTypeT(waterUserContract.getContractType())); + waterUserContractObjT.setFUTURE_USE_ALLOCATION(waterUserContract.getFutureUseAllocation()); + waterUserContractObjT.setFUTURE_USE_PERCENT_ACTIVATED(waterUserContract.getFutureUsePercentActivated()); + waterUserContractObjT.setINITIAL_USE_ALLOCATION(waterUserContract.getInitialUseAllocation()); + waterUserContractObjT.setPUMP_OUT_LOCATION(LocationUtil.getLocation(waterUserContract.getPumpOutLocation() + .getPumpLocation())); + waterUserContractObjT.setPUMP_OUT_BELOW_LOCATION(LocationUtil.getLocation(waterUserContract + .getPumpOutBelowLocation().getPumpLocation())); + waterUserContractObjT.setPUMP_IN_LOCATION(LocationUtil.getLocation(waterUserContract.getPumpInLocation() + .getPumpLocation())); + + List contractList = new ArrayList<>(); + contractList.add(waterUserContractObjT); + return new WATER_USER_CONTRACT_TAB_T(contractList); + } +} diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dto/Catalog.java b/cwms-data-api/src/main/java/cwms/cda/data/dto/Catalog.java index 504b28de1..0f2fc6ab6 100644 --- a/cwms-data-api/src/main/java/cwms/cda/data/dto/Catalog.java +++ b/cwms-data-api/src/main/java/cwms/cda/data/dto/Catalog.java @@ -18,7 +18,7 @@ @JsonRootName("catalog") @FormattableWith(contentType = Formats.XML, formatter = XMLv1.class) -@FormattableWith(contentType = Formats.JSON, formatter = JsonV1.class) +@FormattableWith(contentType = Formats.JSONV1, formatter = JsonV1.class, aliases = {Formats.DEFAULT, Formats.JSON}) @FormattableWith(contentType = Formats.JSONV2, formatter = JsonV2.class) public class Catalog extends CwmsDTOPaginated { @Schema( diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dto/CwmsId.java b/cwms-data-api/src/main/java/cwms/cda/data/dto/CwmsId.java index 865671ea4..16983b744 100644 --- a/cwms-data-api/src/main/java/cwms/cda/data/dto/CwmsId.java +++ b/cwms-data-api/src/main/java/cwms/cda/data/dto/CwmsId.java @@ -34,10 +34,8 @@ import cwms.cda.formatters.Formats; import cwms.cda.formatters.annotations.FormattableWith; import cwms.cda.formatters.json.JsonV1; -import java.util.ArrayList; -import java.util.List; -@FormattableWith(contentType = Formats.JSON, formatter = JsonV1.class) +@FormattableWith(contentType = Formats.JSONV1, formatter = JsonV1.class, aliases = {Formats.DEFAULT, Formats.JSON}) @JsonDeserialize(builder = CwmsId.Builder.class) @JsonInclude(JsonInclude.Include.NON_NULL) @JsonNaming(PropertyNamingStrategies.KebabCaseStrategy.class) diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dto/LocationCategory.java b/cwms-data-api/src/main/java/cwms/cda/data/dto/LocationCategory.java index a4c8ab6f4..1483c2bb5 100644 --- a/cwms-data-api/src/main/java/cwms/cda/data/dto/LocationCategory.java +++ b/cwms-data-api/src/main/java/cwms/cda/data/dto/LocationCategory.java @@ -33,7 +33,7 @@ @Schema(description = "A representation of a location category") @JsonRootName("location_category") -@FormattableWith(contentType = Formats.JSON, formatter = JsonV1.class) +@FormattableWith(contentType = Formats.JSONV1, formatter = JsonV1.class, aliases = {Formats.DEFAULT, Formats.JSON}) public class LocationCategory extends CwmsDTO { private final String id; diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dto/LocationGroup.java b/cwms-data-api/src/main/java/cwms/cda/data/dto/LocationGroup.java index f8affd749..dac169e19 100644 --- a/cwms-data-api/src/main/java/cwms/cda/data/dto/LocationGroup.java +++ b/cwms-data-api/src/main/java/cwms/cda/data/dto/LocationGroup.java @@ -38,7 +38,7 @@ @Schema(description = "A representation of a location group") @JsonRootName("location_group") @JsonNaming(PropertyNamingStrategies.KebabCaseStrategy.class) -@FormattableWith(contentType = Formats.JSON, formatter = JsonV1.class) +@FormattableWith(contentType = Formats.JSONV1, formatter = JsonV1.class, aliases = {Formats.DEFAULT, Formats.JSON}) @FormattableWith(contentType = Formats.CSV, formatter = CsvV1.class) public class LocationGroup extends CwmsDTO { private String id; diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dto/Property.java b/cwms-data-api/src/main/java/cwms/cda/data/dto/Property.java index d9f5a5db8..046aecb3a 100644 --- a/cwms-data-api/src/main/java/cwms/cda/data/dto/Property.java +++ b/cwms-data-api/src/main/java/cwms/cda/data/dto/Property.java @@ -37,7 +37,7 @@ import java.util.Objects; @JsonRootName("property") -@FormattableWith(contentType = Formats.JSON, formatter = JsonV1.class) +@FormattableWith(contentType = Formats.JSONV1, formatter = JsonV1.class, aliases = {Formats.DEFAULT, Formats.JSON}) @JsonDeserialize(builder = Property.Builder.class) @JsonInclude(JsonInclude.Include.NON_NULL) @JsonNaming(PropertyNamingStrategies.KebabCaseStrategy.class) diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dto/RecentValue.java b/cwms-data-api/src/main/java/cwms/cda/data/dto/RecentValue.java index f2197c479..c3f6c01c1 100644 --- a/cwms-data-api/src/main/java/cwms/cda/data/dto/RecentValue.java +++ b/cwms-data-api/src/main/java/cwms/cda/data/dto/RecentValue.java @@ -4,7 +4,7 @@ import cwms.cda.formatters.json.JsonV1; import cwms.cda.formatters.Formats; -@FormattableWith(contentType = Formats.JSON, formatter = JsonV1.class) +@FormattableWith(contentType = Formats.JSONV1, formatter = JsonV1.class, aliases = {Formats.DEFAULT, Formats.JSON}) public class RecentValue extends CwmsDTOBase { String id; diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dto/TimeSeriesCategory.java b/cwms-data-api/src/main/java/cwms/cda/data/dto/TimeSeriesCategory.java index 9b74cc982..ca5cecc82 100644 --- a/cwms-data-api/src/main/java/cwms/cda/data/dto/TimeSeriesCategory.java +++ b/cwms-data-api/src/main/java/cwms/cda/data/dto/TimeSeriesCategory.java @@ -33,7 +33,7 @@ @Schema(description = "A representation of a TimeSeries category") @JsonRootName("timeseries-category") -@FormattableWith(contentType = Formats.JSON, formatter = JsonV1.class) +@FormattableWith(contentType = Formats.JSONV1, formatter = JsonV1.class, aliases = {Formats.DEFAULT, Formats.JSON}) public class TimeSeriesCategory extends CwmsDTO { private String id; diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dto/TimeSeriesGroup.java b/cwms-data-api/src/main/java/cwms/cda/data/dto/TimeSeriesGroup.java index 1a98b5b32..d237ade47 100644 --- a/cwms-data-api/src/main/java/cwms/cda/data/dto/TimeSeriesGroup.java +++ b/cwms-data-api/src/main/java/cwms/cda/data/dto/TimeSeriesGroup.java @@ -39,7 +39,7 @@ @Schema(description = "A representation of a timeseries group") @JsonRootName("timeseries-group") @JsonNaming(PropertyNamingStrategies.KebabCaseStrategy.class) -@FormattableWith(contentType = Formats.JSON, formatter = JsonV1.class) +@FormattableWith(contentType = Formats.JSONV1, formatter = JsonV1.class, aliases = {Formats.DEFAULT, Formats.JSON}) public class TimeSeriesGroup extends CwmsDTO { private String id; private TimeSeriesCategory timeSeriesCategory; diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dto/project/LockRevokerRights.java b/cwms-data-api/src/main/java/cwms/cda/data/dto/project/LockRevokerRights.java index 6f8226290..fef1d8558 100644 --- a/cwms-data-api/src/main/java/cwms/cda/data/dto/project/LockRevokerRights.java +++ b/cwms-data-api/src/main/java/cwms/cda/data/dto/project/LockRevokerRights.java @@ -38,7 +38,7 @@ @JsonDeserialize(builder = LockRevokerRights.Builder.class) @JsonInclude(JsonInclude.Include.NON_NULL) @JsonNaming(PropertyNamingStrategies.KebabCaseStrategy.class) -@FormattableWith(contentType = Formats.JSON, formatter = JsonV1.class) +@FormattableWith(contentType = Formats.JSONV1, formatter = JsonV1.class, aliases = {Formats.DEFAULT, Formats.JSON}) public class LockRevokerRights extends CwmsDTO { private final String projectId; diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dto/project/ProjectLock.java b/cwms-data-api/src/main/java/cwms/cda/data/dto/project/ProjectLock.java index 2fa6edfc4..7ea9dc434 100644 --- a/cwms-data-api/src/main/java/cwms/cda/data/dto/project/ProjectLock.java +++ b/cwms-data-api/src/main/java/cwms/cda/data/dto/project/ProjectLock.java @@ -39,7 +39,7 @@ @JsonDeserialize(builder = ProjectLock.Builder.class) @JsonInclude(JsonInclude.Include.NON_NULL) @JsonNaming(PropertyNamingStrategies.KebabCaseStrategy.class) -@FormattableWith(contentType = Formats.JSON, formatter = JsonV2.class) +@FormattableWith(contentType = Formats.JSONV1, formatter = JsonV2.class, aliases = {Formats.DEFAULT, Formats.JSON}) public class ProjectLock extends CwmsDTO { // officeId held by CwmsDTO private final String projectId; diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dto/project/ProjectLockId.java b/cwms-data-api/src/main/java/cwms/cda/data/dto/project/ProjectLockId.java index bda935d8a..88b071393 100644 --- a/cwms-data-api/src/main/java/cwms/cda/data/dto/project/ProjectLockId.java +++ b/cwms-data-api/src/main/java/cwms/cda/data/dto/project/ProjectLockId.java @@ -35,7 +35,7 @@ @JsonInclude(JsonInclude.Include.NON_NULL) @JsonNaming(PropertyNamingStrategies.KebabCaseStrategy.class) -@FormattableWith(contentType = Formats.JSON, formatter = JsonV1.class) +@FormattableWith(contentType = Formats.JSONV1, formatter = JsonV1.class, aliases = {Formats.DEFAULT, Formats.JSON}) public class ProjectLockId extends CwmsDTOBase { private final String id; diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dto/watersupply/PumpType.java b/cwms-data-api/src/main/java/cwms/cda/data/dto/watersupply/PumpType.java new file mode 100644 index 000000000..d7c25a270 --- /dev/null +++ b/cwms-data-api/src/main/java/cwms/cda/data/dto/watersupply/PumpType.java @@ -0,0 +1,43 @@ +/* + * + * MIT License + * + * Copyright (c) 2024 Hydrologic Engineering Center + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE + * SOFTWARE. + */ + +package cwms.cda.data.dto.watersupply; + +public enum PumpType { + IN("IN"), + OUT("OUT"), + BELOW("BELOW"); + + private final String pumpName; + + PumpType(String name) { + this.pumpName = name; + } + + public String getName() { + return pumpName; + } +} diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dto/watersupply/WaterSupplyPump.java b/cwms-data-api/src/main/java/cwms/cda/data/dto/watersupply/WaterSupplyPump.java new file mode 100644 index 000000000..4f534d018 --- /dev/null +++ b/cwms-data-api/src/main/java/cwms/cda/data/dto/watersupply/WaterSupplyPump.java @@ -0,0 +1,74 @@ +/* + * + * MIT License + * + * Copyright (c) 2024 Hydrologic Engineering Center + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE + * SOFTWARE. + */ + +package cwms.cda.data.dto.watersupply; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonRootName; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import cwms.cda.data.dto.CwmsDTOBase; +import cwms.cda.data.dto.Location; + +@JsonRootName("water_supply_pump") +@JsonDeserialize(builder = WaterSupplyPump.Builder.class) +public final class WaterSupplyPump extends CwmsDTOBase { + @JsonProperty(required = true) + private final Location pumpLocation; + @JsonProperty(required = true) + private final PumpType pumpType; + + private WaterSupplyPump(Builder builder) { + this.pumpLocation = builder.pumpLocation; + this.pumpType = builder.pumpType; + } + + public Location getPumpLocation() { + return this.pumpLocation; + } + + public PumpType getPumpType() { + return this.pumpType; + } + + public static class Builder { + private Location pumpLocation; + private PumpType pumpType; + + public Builder withPumpLocation(@JsonProperty("pump-location") Location pumpLocation) { + this.pumpLocation = pumpLocation; + return this; + } + + public Builder withPumpType(@JsonProperty("pump-type") PumpType pumpType) { + this.pumpType = pumpType; + return this; + } + + public WaterSupplyPump build() { + return new WaterSupplyPump(this); + } + } +} diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dto/watersupply/WaterUser.java b/cwms-data-api/src/main/java/cwms/cda/data/dto/watersupply/WaterUser.java new file mode 100644 index 000000000..9330e4614 --- /dev/null +++ b/cwms-data-api/src/main/java/cwms/cda/data/dto/watersupply/WaterUser.java @@ -0,0 +1,96 @@ +/* + * + * MIT License + * + * Copyright (c) 2024 Hydrologic Engineering Center + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package cwms.cda.data.dto.watersupply; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import cwms.cda.data.dto.CwmsDTOBase; +import cwms.cda.data.dto.CwmsId; +import cwms.cda.formatters.Formats; +import cwms.cda.formatters.annotations.FormattableWith; +import cwms.cda.formatters.json.JsonV1; + + +@FormattableWith(contentType = Formats.JSONV1, formatter = JsonV1.class, + aliases = {Formats.DEFAULT, Formats.JSON}) +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonNaming(PropertyNamingStrategies.KebabCaseStrategy.class) +@JsonDeserialize(builder = WaterUser.Builder.class) +public final class WaterUser extends CwmsDTOBase { + @JsonProperty(required = true) + private final String entityName; + @JsonProperty(required = true) + private final CwmsId projectId; + @JsonProperty(required = true) + private final String waterRight; + + private WaterUser(Builder builder) { + this.entityName = builder.entityName; + this.projectId = builder.projectId; + this.waterRight = builder.waterRight; + } + + public CwmsId getProjectId() { + return this.projectId; + } + + public String getEntityName() { + return this.entityName; + } + + public String getWaterRight() { + return this.waterRight; + } + + public static class Builder { + private String entityName; + private CwmsId projectId; + private String waterRight; + + public Builder withEntityName(@JsonProperty("entity-name") String entityName) { + this.entityName = entityName; + return this; + } + + public Builder withProjectId(@JsonProperty("project-id") CwmsId projectId) { + this.projectId = projectId; + return this; + } + + public Builder withWaterRight(@JsonProperty("water-right") String waterRight) { + this.waterRight = waterRight; + return this; + } + + public WaterUser build() { + return new WaterUser(this); + } + } +} diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dto/watersupply/WaterUserContract.java b/cwms-data-api/src/main/java/cwms/cda/data/dto/watersupply/WaterUserContract.java new file mode 100644 index 000000000..30ef2aec2 --- /dev/null +++ b/cwms-data-api/src/main/java/cwms/cda/data/dto/watersupply/WaterUserContract.java @@ -0,0 +1,241 @@ +/* + * + * MIT License + * + * Copyright (c) 2024 Hydrologic Engineering Center + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE + * SOFTWARE. + */ + +package cwms.cda.data.dto.watersupply; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import cwms.cda.data.dto.CwmsDTO; +import cwms.cda.data.dto.CwmsId; +import cwms.cda.data.dto.LookupType; +import cwms.cda.formatters.Formats; +import cwms.cda.formatters.annotations.FormattableWith; +import cwms.cda.formatters.json.JsonV1; +import java.util.Date; + +@FormattableWith(contentType = Formats.JSONV1, formatter = JsonV1.class) +@JsonDeserialize(builder = WaterUserContract.Builder.class) +public final class WaterUserContract extends CwmsDTO { + + @JsonProperty(required = true) + private final WaterUser waterUser; + @JsonProperty(required = true) + private final CwmsId contractId; + @JsonProperty(required = true) + private final LookupType contractType; + @JsonProperty(required = true) + private final Date contractEffectiveDate; + @JsonProperty(required = true) + private final Date contractExpirationDate; + @JsonProperty(required = true) + private final Double contractedStorage; + @JsonProperty(required = true) + private final Double initialUseAllocation; + @JsonProperty(required = true) + private final Double futureUseAllocation; + @JsonProperty(required = true) + private final String storageUnitsId; + @JsonProperty(required = true) + private final Double futureUsePercentActivated; + @JsonProperty(required = true) + private final Double totalAllocPercentActivated; + private final WaterSupplyPump pumpOutLocation; + private final WaterSupplyPump pumpOutBelowLocation; + private final WaterSupplyPump pumpInLocation; + + private WaterUserContract(Builder builder) { + super(builder.officeId); + this.waterUser = builder.waterUser; + this.contractId = builder.contractId; + this.contractType = builder.contractType; + this.contractEffectiveDate = builder.contractEffectiveDate; + this.contractExpirationDate = builder.contractExpirationDate; + this.contractedStorage = builder.contractedStorage; + this.initialUseAllocation = builder.initialUseAllocation; + this.futureUseAllocation = builder.futureUseAllocation; + this.storageUnitsId = builder.storageUnitsId; + this.futureUsePercentActivated = builder.futureUsePercentActivated; + this.totalAllocPercentActivated = builder.totalAllocPercentActivated; + this.pumpOutLocation = builder.pumpOutLocation; + this.pumpOutBelowLocation = builder.pumpOutBelowLocation; + this.pumpInLocation = builder.pumpInLocation; + } + + public LookupType getContractType() { + return this.contractType; + } + + public Date getContractEffectiveDate() { + return this.contractEffectiveDate; + } + + public Date getContractExpirationDate() { + return this.contractExpirationDate; + } + + public Double getContractedStorage() { + return this.contractedStorage; + } + + public Double getInitialUseAllocation() { + return this.initialUseAllocation; + } + + public Double getFutureUseAllocation() { + return this.futureUseAllocation; + } + + public String getStorageUnitsId() { + return this.storageUnitsId; + } + + public Double getFutureUsePercentActivated() { + return this.futureUsePercentActivated; + } + + public Double getTotalAllocPercentActivated() { + return this.totalAllocPercentActivated; + } + + public WaterSupplyPump getPumpOutLocation() { + return this.pumpOutLocation; + } + + public WaterSupplyPump getPumpOutBelowLocation() { + return this.pumpOutBelowLocation; + } + + public WaterSupplyPump getPumpInLocation() { + return this.pumpInLocation; + } + + public WaterUser getWaterUser() { + return this.waterUser; + } + + public CwmsId getContractId() { + return this.contractId; + } + + public static class Builder { + private String officeId; + private WaterUser waterUser; + private CwmsId contractId; + private LookupType contractType; + private Date contractEffectiveDate; + private Date contractExpirationDate; + private Double contractedStorage; + private Double initialUseAllocation; + private Double futureUseAllocation; + private String storageUnitsId; + private Double futureUsePercentActivated; + private Double totalAllocPercentActivated; + private WaterSupplyPump pumpOutLocation; + private WaterSupplyPump pumpOutBelowLocation; + private WaterSupplyPump pumpInLocation; + + public Builder withOfficeId(String officeId) { + this.officeId = officeId; + return this; + } + + public Builder withWaterUser(WaterUser waterUser) { + this.waterUser = waterUser; + return this; + } + + public Builder withContractId(CwmsId contractId) { + this.contractId = contractId; + return this; + } + + public Builder withContractType(LookupType contractType) { + this.contractType = contractType; + return this; + } + + public Builder withContractEffectiveDate(Date contractEffectiveDate) { + this.contractEffectiveDate = contractEffectiveDate; + return this; + } + + public Builder withContractExpirationDate(Date contractExpirationDate) { + this.contractExpirationDate = contractExpirationDate; + return this; + } + + public Builder withContractedStorage(Double contractedStorage) { + this.contractedStorage = contractedStorage; + return this; + } + + public Builder withInitialUseAllocation(Double initialUseAllocation) { + this.initialUseAllocation = initialUseAllocation; + return this; + } + + public Builder withFutureUseAllocation(Double futureUseAllocation) { + this.futureUseAllocation = futureUseAllocation; + return this; + } + + public Builder withStorageUnitsId(String storageUnitsId) { + this.storageUnitsId = storageUnitsId; + return this; + } + + public Builder withFutureUsePercentActivated(Double futureUsePercentActivated) { + this.futureUsePercentActivated = futureUsePercentActivated; + return this; + } + + public Builder withTotalAllocPercentActivated(Double totalAllocPercentActivated) { + this.totalAllocPercentActivated = totalAllocPercentActivated; + return this; + } + + public Builder withPumpOutLocation(WaterSupplyPump pumpOutLocation) { + this.pumpOutLocation = pumpOutLocation; + return this; + } + + public Builder withPumpOutBelowLocation(WaterSupplyPump pumpOutBelowLocation) { + this.pumpOutBelowLocation = pumpOutBelowLocation; + return this; + } + + public Builder withPumpInLocation(WaterSupplyPump pumpInLocation) { + this.pumpInLocation = pumpInLocation; + return this; + } + + public WaterUserContract build() { + return new WaterUserContract(this); + } + } + + +} diff --git a/cwms-data-api/src/test/java/cwms/cda/api/BasinControllerIT.java b/cwms-data-api/src/test/java/cwms/cda/api/BasinControllerIT.java index f761088d6..c002f6edc 100644 --- a/cwms-data-api/src/test/java/cwms/cda/api/BasinControllerIT.java +++ b/cwms-data-api/src/test/java/cwms/cda/api/BasinControllerIT.java @@ -25,6 +25,7 @@ package cwms.cda.api; import cwms.cda.api.enums.Nation; +import cwms.cda.data.dao.DeleteRule; import cwms.cda.data.dao.LocationsDaoImpl; import cwms.cda.data.dao.basin.BasinDao; import cwms.cda.data.dto.Location; @@ -61,7 +62,6 @@ class BasinControllerIT extends DataApiTestIT private static final String OFFICE = "SWT"; private static final Basin BASIN; private static final Basin BASIN_CONNECT; - private static final String DELETE_ACTION = "DELETE ALL"; static { try { BASIN = new Basin.Builder() @@ -110,7 +110,8 @@ public static void setup() throws Exception { .withActive(true) .withNearestCity("Davis") .build(); - Location loc2 = new Location.Builder(BASIN_CONNECT.getBasinId().getOfficeId(), BASIN_CONNECT.getBasinId().getName()) + Location loc2 = new Location.Builder(BASIN_CONNECT.getBasinId().getOfficeId(), + BASIN_CONNECT.getBasinId().getName()) .withStateInitial("CO") .withNation(Nation.US) .withLocationKind("BASIN") @@ -143,7 +144,7 @@ public static void tearDown() throws Exception { LocationsDaoImpl locationsDao = new LocationsDaoImpl(ctx); BasinDao basinDao = new BasinDao(ctx); locationsDao.deleteLocation(BASIN.getBasinId().getName(), OFFICE, true); - basinDao.deleteBasin(BASIN_CONNECT.getBasinId(), DELETE_ACTION); + basinDao.deleteBasin(BASIN_CONNECT.getBasinId(), DeleteRule.DELETE_ALL); locationsDao.deleteLocation(BASIN_CONNECT.getBasinId().getName(), OFFICE, true); }, CwmsDataApiSetupCallback.getWebUser()); } @@ -262,12 +263,12 @@ void test_get_create_delete() { .log().ifValidationFails(LogDetail.ALL, true) .assertThat() .statusCode(is(HttpServletResponse.SC_OK)) - .body("basin-id[0].name", equalTo(BASIN.getBasinId().getName())) - .body("basin-id[0].office-id", equalTo(BASIN.getBasinId().getOfficeId())) - .body("[0].sort-order", equalTo(BASIN.getSortOrder().floatValue())) - .body("[0].area-unit", equalTo(BASIN.getAreaUnit())) - .body("[0].total-drainage-area", equalTo(BASIN.getTotalDrainageArea().floatValue())) - .body("[0].contributing-drainage-area", equalTo(BASIN.getContributingDrainageArea().floatValue())) + .body("basin-id.name", equalTo(BASIN.getBasinId().getName())) + .body("basin-id.office-id", equalTo(BASIN.getBasinId().getOfficeId())) + .body("sort-order", equalTo(BASIN.getSortOrder().floatValue())) + .body("area-unit", equalTo(BASIN.getAreaUnit())) + .body("total-drainage-area", equalTo(BASIN.getTotalDrainageArea().floatValue())) + .body("contributing-drainage-area", equalTo(BASIN.getContributingDrainageArea().floatValue())) ; } @@ -276,7 +277,7 @@ void test_get_create_delete() { .log().ifValidationFails(LogDetail.ALL, true) .accept(Formats.JSONV1) .queryParam(Controllers.OFFICE, OFFICE) - .queryParam(DELETE_MODE, DELETE_ACTION) + .queryParam(METHOD, DeleteRule.DELETE_ALL.getRule()) .header(AUTH_HEADER, user.toHeaderValue()) .when() .redirects().follow(true) @@ -314,6 +315,7 @@ void test_update_does_not_exist() { .accept(Formats.JSONV1) .contentType(Formats.JSONV1) .queryParam(NAME, "newFakeName") + .queryParam(Controllers.OFFICE, OFFICE) .body(json) .header(AUTH_HEADER, user.toHeaderValue()) .when() @@ -335,7 +337,7 @@ void test_delete_does_not_exist() { .log().ifValidationFails(LogDetail.ALL, true) .accept(Formats.JSONV1) .queryParam(Controllers.OFFICE, OFFICE) - .queryParam(DELETE_MODE, DELETE_ACTION) + .queryParam(METHOD, DeleteRule.DELETE_ALL.getRule()) .header(AUTH_HEADER, user.toHeaderValue()) .when() .redirects().follow(true) @@ -476,7 +478,7 @@ void test_get_all() { .log().ifValidationFails(LogDetail.ALL, true) .accept(Formats.JSONV1) .queryParam(Controllers.OFFICE, OFFICE) - .queryParam(DELETE_MODE, DELETE_ACTION) + .queryParam(METHOD, DeleteRule.DELETE_ALL.getRule()) .header(AUTH_HEADER, user.toHeaderValue()) .when() .redirects().follow(true) diff --git a/cwms-data-api/src/test/java/cwms/cda/api/ControllersTest.java b/cwms-data-api/src/test/java/cwms/cda/api/ControllersTest.java index e3c589532..2b07b7a2c 100644 --- a/cwms-data-api/src/test/java/cwms/cda/api/ControllersTest.java +++ b/cwms-data-api/src/test/java/cwms/cda/api/ControllersTest.java @@ -399,4 +399,18 @@ void testAliasedQueryParamAsType(){ // if its present it should work assertEquals(JooqDao.DeleteMethod.DELETE_KEY, Controllers.queryParamAsClass(ctx, JooqDao.DeleteMethod.class, null, "Not a key", Controllers.METHOD)); } + + @Test + void testRequiredParamAs() { + HttpServletRequest request = mock(HttpServletRequest.class); + HttpServletResponse response = mock(HttpServletResponse.class); + Map urlParams = new LinkedHashMap<>(); + urlParams.put("boring", "the_value"); + String paramStr = ControllerTest.buildParamStr(urlParams); + when(request.getQueryString()).thenReturn(paramStr); + Context ctx = new Context(request, response, new LinkedHashMap()); + assertEquals("the_value", Controllers.requiredParamAs(ctx, "boring", String.class)); + assertThrows(RequiredQueryParameterException.class, + () -> Controllers.requiredParamAs(ctx, Controllers.OFFICE, String.class)); + } } \ No newline at end of file diff --git a/cwms-data-api/src/test/java/cwms/cda/data/dao/basin/BasinDaoIT.java b/cwms-data-api/src/test/java/cwms/cda/data/dao/basin/BasinDaoIT.java index c937643ce..a13110512 100644 --- a/cwms-data-api/src/test/java/cwms/cda/data/dao/basin/BasinDaoIT.java +++ b/cwms-data-api/src/test/java/cwms/cda/data/dao/basin/BasinDaoIT.java @@ -60,7 +60,6 @@ class BasinDaoIT extends DataApiTestIT { private static final String OFFICE_ID = TestAccounts.KeyUser.SWT_NORMAL.getOperatingOffice(); private static final String UNIT_SYSTEM = "SI"; private static final String UNITS = "km2"; - final String DELETE_ACTION = "DELETE ALL"; private static final ArrayList locationsCreated = new ArrayList<>(); private static final Basin parentBasin = new Basin.Builder() .withBasinId(new CwmsId.Builder() @@ -296,7 +295,7 @@ void testDeleteBasin() throws Exception { assertNotNull(basin); BasinDao basinDao = new BasinDao(ctx); basinDao.storeBasin(basin); - basinDao.deleteBasin(basin.getBasinId(), DELETE_ACTION); + basinDao.deleteBasin(basin.getBasinId(), DeleteRule.DELETE_ALL); CwmsId basinId = basin.getBasinId(); assertThrows(NotFoundException.class, () -> basinDao.getBasin(basinId, UNIT_SYSTEM)); } catch (Exception e) { @@ -312,7 +311,7 @@ private void cleanUpRoutine(Basin basin) throws Exception { DSLContext ctx = getDslContext(c, OFFICE_ID); try { BasinDao basinDao = new BasinDao(ctx); - basinDao.deleteBasin(basin.getBasinId(), DELETE_ACTION); + basinDao.deleteBasin(basin.getBasinId(), DeleteRule.DELETE_ALL); } catch (Exception e) { throw new RuntimeException(e); } diff --git a/cwms-data-api/src/test/java/cwms/cda/data/dao/watersupply/WaterContractDaoTestIT.java b/cwms-data-api/src/test/java/cwms/cda/data/dao/watersupply/WaterContractDaoTestIT.java new file mode 100644 index 000000000..dab01f0f7 --- /dev/null +++ b/cwms-data-api/src/test/java/cwms/cda/data/dao/watersupply/WaterContractDaoTestIT.java @@ -0,0 +1,445 @@ +/* + * + * MIT License + * + * Copyright (c) 2024 Hydrologic Engineering Center + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE + * SOFTWARE. + */ + +package cwms.cda.data.dao.watersupply; + +import static cwms.cda.data.dao.JooqDao.getDslContext; +import static org.junit.jupiter.api.Assertions.*; + +import cwms.cda.api.DataApiTestIT; +import cwms.cda.api.enums.Nation; +import cwms.cda.api.errors.NotFoundException; +import cwms.cda.data.dao.DeleteRule; +import cwms.cda.data.dao.LocationsDaoImpl; +import cwms.cda.data.dao.LookupTypeDao; +import cwms.cda.data.dao.project.ProjectDao; +import cwms.cda.data.dto.CwmsId; +import cwms.cda.data.dto.Location; +import cwms.cda.data.dto.LookupType; +import cwms.cda.data.dto.project.Project; +import cwms.cda.data.dto.watersupply.PumpType; +import cwms.cda.data.dto.watersupply.WaterSupplyPump; +import cwms.cda.data.dto.watersupply.WaterUser; +import cwms.cda.data.dto.watersupply.WaterUserContract; +import cwms.cda.helpers.DTOMatch; +import fixtures.CwmsDataApiSetupCallback; +import java.io.IOException; +import java.math.BigDecimal; +import java.sql.SQLException; +import java.time.ZoneId; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import mil.army.usace.hec.test.database.CwmsDatabaseContainer; +import org.jooq.DSLContext; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + + +class WaterContractDaoTestIT extends DataApiTestIT { + private static final String OFFICE_ID = "SPK"; + private static final String DELETE_ACTION = "DELETE ALL"; + private static final Location testLocation = buildTestLocation("Test Location Name", + "Test Location Type"); + private static final Project testProject = buildTestProject(); + private static final WaterUser testUser = buildTestWaterUser("Test User"); + private final List waterUserList = new ArrayList<>(); + private final List waterUserContractList = new ArrayList<>(); + private static final Location pumpInLoc = buildTestLocation("Pump 1", "PUMP"); + private static final Location pumpOutLoc = buildTestLocation("Pump 2", "PUMP"); + private static final Location pumpOutBelowLoc = buildTestLocation("Pump 3", "PUMP"); + + @BeforeAll + static void setup() throws Exception { + CwmsDatabaseContainer db = CwmsDataApiSetupCallback.getDatabaseLink(); + db.connection(c -> { + DSLContext ctx = getDslContext(c, OFFICE_ID); + LocationsDaoImpl dao = new LocationsDaoImpl(ctx); + LookupTypeDao lookupTypeDao = new LookupTypeDao(ctx); + ProjectDao projectDao = new ProjectDao(ctx); + try { + projectDao.create(testProject); + dao.storeLocation(testLocation); + lookupTypeDao.storeLookupType("AT_WS_CONTRACT_TYPE", "WS_CONTRACT_TYPE", + buildTestWaterContract("Test", false).getContractType()); + } catch (IOException e) { + throw new RuntimeException("Failed to store location or project", e); + } + }, CwmsDataApiSetupCallback.getWebUser()); + } + + @AfterAll + static void tearDown() throws Exception { + CwmsDatabaseContainer db = CwmsDataApiSetupCallback.getDatabaseLink(); + db.connection(c -> { + DSLContext ctx = getDslContext(c, OFFICE_ID); + ProjectDao projectDao = new ProjectDao(ctx); + LookupTypeDao lookupTypeDao = new LookupTypeDao(ctx); + LocationsDaoImpl locationDao = new LocationsDaoImpl(ctx); + projectDao.delete(OFFICE_ID, testProject.getLocation().getName(), DeleteRule.DELETE_ALL); + locationDao.deleteLocation(testLocation.getName(), testLocation.getOfficeId(), false); + lookupTypeDao.deleteLookupType("AT_WS_CONTRACT_TYPE", "WS_CONTRACT_TYPE", OFFICE_ID, + buildTestWaterContract("Test", false).getContractType().getDisplayValue()); + }, CwmsDataApiSetupCallback.getWebUser()); + } + + @AfterEach + void cleanup() throws SQLException { + CwmsDatabaseContainer db = CwmsDataApiSetupCallback.getDatabaseLink(); + db.connection(c -> { + DSLContext ctx = getDslContext(c, OFFICE_ID); + WaterContractDao dao = new WaterContractDao(ctx); + LocationsDaoImpl locationDao = new LocationsDaoImpl(ctx); + for (WaterUserContract waterUserContract : waterUserContractList) { + dao.deleteWaterContract(waterUserContract, DELETE_ACTION); + locationDao.deleteLocation(waterUserContract.getPumpInLocation().getPumpLocation().getName(), + waterUserContract.getPumpInLocation().getPumpLocation().getOfficeId(), true); + locationDao.deleteLocation(waterUserContract.getPumpOutLocation().getPumpLocation().getName(), + waterUserContract.getPumpOutLocation().getPumpLocation().getOfficeId(), true); + locationDao.deleteLocation(waterUserContract.getPumpOutBelowLocation().getPumpLocation().getName(), + waterUserContract.getPumpOutBelowLocation().getPumpLocation().getOfficeId(), true); + } + waterUserContractList.clear(); + for (WaterUser waterUser : waterUserList) { + dao.deleteWaterUser(waterUser.getProjectId(), waterUser.getEntityName(), DELETE_ACTION); + } + waterUserList.clear(); + }, CwmsDataApiSetupCallback.getWebUser()); + } + + @Test + void testStoreAndRetrieveWaterUserList() throws Exception { + CwmsDatabaseContainer db = CwmsDataApiSetupCallback.getDatabaseLink(); + db.connection(c -> { + DSLContext ctx = getDslContext(c, OFFICE_ID); + WaterContractDao dao = new WaterContractDao(ctx); + WaterUser user1 = buildTestWaterUser("TEST USER 1"); + WaterUser user2 = buildTestWaterUser("TEST USER 2"); + dao.storeWaterUser(user1, false); + dao.storeWaterUser(user2, false); + waterUserList.add(user1); + waterUserList.add(user2); + List results = dao.getAllWaterUsers(new CwmsId.Builder().withOfficeId(OFFICE_ID) + .withName(testLocation.getName()).build()); + DTOMatch.assertMatch(buildTestWaterUser("TEST USER 1"), results.get(0)); + DTOMatch.assertMatch(buildTestWaterUser("TEST USER 2"), results.get(1)); + }, CwmsDataApiSetupCallback.getWebUser()); + } + + @Test + void testStoreAndRetrieveWaterUser() throws Exception { + CwmsId projectLocation = new CwmsId.Builder() + .withName("Test Location Name") + .withOfficeId(OFFICE_ID) + .build(); + String entityName = "Test Entity"; + WaterUser newUser = buildTestWaterUser(entityName); + CwmsDatabaseContainer db = CwmsDataApiSetupCallback.getDatabaseLink(); + db.connection(c -> { + DSLContext ctx = getDslContext(c, OFFICE_ID); + WaterContractDao dao = new WaterContractDao(ctx); + dao.storeWaterUser(newUser, false); + waterUserList.add(newUser); + WaterUser retrievedUser = dao.getWaterUser(projectLocation, entityName); + DTOMatch.assertMatch(newUser, retrievedUser); + }, CwmsDataApiSetupCallback.getWebUser()); + } + + @Test + void testStoreAndRetrieveWaterContractList() throws Exception { + WaterUserContract contract = buildTestWaterContract("Test retrieve", false); + WaterUserContract contract2 = buildTestWaterContract("Test retrieve 2", false); + CwmsDatabaseContainer db = CwmsDataApiSetupCallback.getDatabaseLink(); + db.connection(c -> { + DSLContext ctx = getDslContext(c, OFFICE_ID); + WaterContractDao dao = new WaterContractDao(ctx); + dao.storeWaterUser(contract.getWaterUser(), false); + dao.storeWaterContract(contract, false, true); + dao.storeWaterContract(contract2, false, true); + waterUserContractList.add(contract); + waterUserContractList.add(contract2); + waterUserList.add(contract.getWaterUser()); + waterUserList.add(contract2.getWaterUser()); + List retrievedContract = dao.getAllWaterContracts(contract.getWaterUser().getProjectId(), + contract.getWaterUser().getEntityName()); + WaterUserContract result = retrievedContract.get(0); + DTOMatch.assertMatch(contract, result); + result = retrievedContract.get(1); + DTOMatch.assertMatch(contract2, result); + }, CwmsDataApiSetupCallback.getWebUser()); + } + + @Test + void testStoreAndRetrieveWaterContract() throws Exception { + WaterUserContract contract = buildTestWaterContract("Test retrieve 1", false); + CwmsDatabaseContainer db = CwmsDataApiSetupCallback.getDatabaseLink(); + db.connection(c -> { + DSLContext ctx = getDslContext(c, OFFICE_ID); + WaterContractDao dao = new WaterContractDao(ctx); + dao.storeWaterUser(contract.getWaterUser(), false); + waterUserList.add(contract.getWaterUser()); + dao.storeWaterContract(contract, false, true); + waterUserContractList.add(contract); + WaterUserContract retrievedContract = dao.getWaterContract(contract.getContractId().getName(), + contract.getWaterUser().getProjectId(), contract.getWaterUser().getEntityName()); + DTOMatch.assertMatch(contract, retrievedContract); + }, CwmsDataApiSetupCallback.getWebUser()); + } + + @Test + void testStoreAndRetrieveWaterContractTypeList() throws Exception { + CwmsDatabaseContainer db = CwmsDataApiSetupCallback.getDatabaseLink(); + db.connection(c -> { + DSLContext ctx = getDslContext(c, OFFICE_ID); + WaterContractDao dao = new WaterContractDao(ctx); + List contractType = new ArrayList<>(); + contractType.add(new LookupType.Builder() + .withTooltip("Test Tooltip") + .withActive(true) + .withDisplayValue("Test Display Value") + .withOfficeId(OFFICE_ID).build()); + contractType.add(new LookupType.Builder() + .withTooltip("Test Tooltip 2") + .withActive(true) + .withDisplayValue("Test Display Value 2") + .withOfficeId(OFFICE_ID).build()); + dao.storeWaterContractTypes(contractType, false); + List results = dao.getAllWaterContractTypes(OFFICE_ID); + DTOMatch.assertMatch(contractType.get(0), results.get(0)); + DTOMatch.assertMatch(contractType.get(1), results.get(1)); + }, CwmsDataApiSetupCallback.getWebUser()); + } + + @Test + void testRenameWaterUser() throws Exception { + WaterUser newUser = buildTestWaterUser("TEST USER"); + WaterUser updatedUser = buildTestWaterUser("TEST USER 2"); + CwmsDatabaseContainer db = CwmsDataApiSetupCallback.getDatabaseLink(); + db.connection(c -> { + DSLContext ctx = getDslContext(c, OFFICE_ID); + WaterContractDao dao = new WaterContractDao(ctx); + dao.storeWaterUser(newUser, false); + waterUserList.add(newUser); + waterUserList.add(updatedUser); + dao.renameWaterUser(newUser.getEntityName(), updatedUser.getEntityName(), newUser.getProjectId()); + waterUserList.remove(newUser); + WaterUser retrievedUser = dao.getWaterUser(newUser.getProjectId(), updatedUser.getEntityName()); + String entityName = newUser.getEntityName(); + CwmsId projectId = newUser.getProjectId(); + assertThrows(NotFoundException.class, () -> dao.getWaterUser(projectId, entityName)); + DTOMatch.assertMatch(updatedUser, retrievedUser); + }, CwmsDataApiSetupCallback.getWebUser()); + } + + @Test + void testRenameWaterContract() throws Exception { + WaterUserContract oldContract = buildTestWaterContract("Test contract", true); + WaterUserContract renamedContract = buildTestWaterContract("Test contract 2", true); + CwmsDatabaseContainer db = CwmsDataApiSetupCallback.getDatabaseLink(); + db.connection(c -> { + DSLContext ctx = getDslContext(c, OFFICE_ID); + WaterContractDao dao = new WaterContractDao(ctx); + dao.storeWaterUser(oldContract.getWaterUser(), false); + dao.storeWaterContract(oldContract, false, true); + WaterUser user = new WaterUser.Builder().withEntityName(oldContract.getWaterUser().getEntityName()) + .withProjectId(oldContract.getWaterUser().getProjectId()) + .withWaterRight(oldContract.getContractId().getName()).build(); + waterUserList.add(user); + waterUserContractList.add(oldContract); + waterUserContractList.add(renamedContract); + dao.renameWaterContract(user, oldContract.getContractId().getName(), + renamedContract.getContractId().getName()); + waterUserContractList.remove(oldContract); + WaterUserContract retrievedContract = dao.getWaterContract(renamedContract.getContractId().getName(), + renamedContract.getWaterUser().getProjectId(), renamedContract.getWaterUser().getEntityName()); + assertNotNull(retrievedContract); + String contractName = oldContract.getContractId().getName(); + CwmsId projectId = oldContract.getWaterUser().getProjectId(); + String entityName = oldContract.getWaterUser().getEntityName(); + assertThrows(NotFoundException.class, () -> dao.getWaterContract(contractName, + projectId, entityName)); + DTOMatch.assertMatch(renamedContract, retrievedContract); + }, CwmsDataApiSetupCallback.getWebUser()); + } + + @Test + void testDeleteWaterUser() throws Exception { + WaterUser newUser = buildTestWaterUser("TEST USER"); + CwmsDatabaseContainer db = CwmsDataApiSetupCallback.getDatabaseLink(); + db.connection(c -> { + DSLContext ctx = getDslContext(c, OFFICE_ID); + WaterContractDao dao = new WaterContractDao(ctx); + dao.storeWaterUser(newUser, false); + dao.deleteWaterUser(newUser.getProjectId(), newUser.getEntityName(), DELETE_ACTION); + CwmsId projectId = newUser.getProjectId(); + String entityName = newUser.getEntityName(); + assertThrows(NotFoundException.class, () -> dao.getWaterUser(projectId, entityName)); + }, CwmsDataApiSetupCallback.getWebUser()); + } + + @Test + void testDeleteWaterContract() throws Exception { + WaterUserContract contract = buildTestWaterContract("Test contract", false); + CwmsDatabaseContainer db = CwmsDataApiSetupCallback.getDatabaseLink(); + db.connection(c -> { + DSLContext ctx = getDslContext(c, OFFICE_ID); + WaterContractDao dao = new WaterContractDao(ctx); + dao.storeWaterUser(contract.getWaterUser(), false); + dao.storeWaterContract(contract, false, true); + dao.deleteWaterContract(contract, DELETE_ACTION); + waterUserList.add(contract.getWaterUser()); + String contractName = contract.getContractId().getName(); + CwmsId projectId = contract.getWaterUser().getProjectId(); + String entityName = contract.getWaterUser().getEntityName(); + assertThrows(NotFoundException.class, () -> dao.getWaterContract(contractName, + projectId, entityName)); + }, CwmsDataApiSetupCallback.getWebUser()); + } + + @Test + void testRemovePumpFromContract() throws Exception { + WaterUserContract contract = buildTestWaterContract("Test contract", false); + CwmsDatabaseContainer db = CwmsDataApiSetupCallback.getDatabaseLink(); + db.connection(c -> { + DSLContext ctx = getDslContext(c, OFFICE_ID); + WaterContractDao dao = new WaterContractDao(ctx); + assertNotNull(contract); + dao.storeWaterUser(contract.getWaterUser(), false); + dao.storeWaterContract(contract, false, true); + waterUserContractList.add(contract); + waterUserList.add(contract.getWaterUser()); + dao.removePumpFromContract(contract, contract.getPumpInLocation().getPumpLocation().getName(), + PumpType.IN, false); + WaterUserContract retrievedContract = dao.getWaterContract(contract.getContractId().getName(), + contract.getWaterUser().getProjectId(), contract.getWaterUser().getEntityName()); + assertNotNull(retrievedContract); + assertNull(retrievedContract.getPumpInLocation().getPumpLocation()); + }, CwmsDataApiSetupCallback.getWebUser()); + } + + private static WaterUser buildTestWaterUser(String entityName) { + return new WaterUser.Builder().withEntityName(entityName).withProjectId(new CwmsId.Builder() + .withName("Test Location Name") + .withOfficeId(OFFICE_ID) + .build()) + .withWaterRight("Test Water Right").build(); + } + + private static WaterUserContract buildTestWaterContract(String contractName, boolean renameTest) { + if (!renameTest){ + return new WaterUserContract.Builder() + .withContractType(new LookupType.Builder() + .withTooltip("Test Tooltip") + .withActive(true) + .withDisplayValue("Test Display Value") + .withOfficeId(OFFICE_ID).build()) + .withStorageUnitsId("m3") + .withOfficeId(OFFICE_ID) + .withFutureUseAllocation(158900.6) + .withContractedStorage(1589005.6) + .withInitialUseAllocation(1500.2) + .withContractExpirationDate(new Date(1979252516)) + .withContractEffectiveDate(new Date(1766652851)) + .withTotalAllocPercentActivated(55.1) + .withContractId(new CwmsId.Builder() + .withName(contractName) + .withOfficeId(OFFICE_ID) + .build()) + .withFutureUsePercentActivated(35.7) + .withWaterUser(testUser) + .withPumpInLocation(new WaterSupplyPump.Builder() + .withPumpLocation(buildTestLocation("Pump 1 " + contractName, + "PUMP")).withPumpType(PumpType.IN).build()) + .withPumpOutLocation(new WaterSupplyPump.Builder() + .withPumpLocation(buildTestLocation("Pump 2 " + contractName, + "PUMP")).withPumpType(PumpType.OUT).build()) + .withPumpOutBelowLocation(new WaterSupplyPump.Builder() + .withPumpLocation(buildTestLocation("Pump 3 " + contractName, + "PUMP")).withPumpType(PumpType.BELOW).build()) + .build(); + } else { + return new WaterUserContract.Builder() + .withContractType(new LookupType.Builder() + .withTooltip("Test Tooltip") + .withActive(true) + .withDisplayValue("Test Display Value") + .withOfficeId(OFFICE_ID).build()) + .withStorageUnitsId("m3") + .withOfficeId(OFFICE_ID) + .withFutureUseAllocation(158900.6) + .withContractedStorage(1589005.6) + .withInitialUseAllocation(1500.2) + .withContractExpirationDate(new Date(1979252516)) + .withContractEffectiveDate(new Date(1766652851)) + .withTotalAllocPercentActivated(55.1) + .withContractId(new CwmsId.Builder() + .withName(contractName) + .withOfficeId(OFFICE_ID) + .build()) + .withFutureUsePercentActivated(35.7) + .withWaterUser(buildTestWaterUser("Water User Name")) + .withPumpInLocation(new WaterSupplyPump.Builder().withPumpLocation(pumpInLoc).withPumpType(PumpType.IN).build()) + .withPumpOutLocation(new WaterSupplyPump.Builder().withPumpLocation(pumpOutLoc).withPumpType(PumpType.OUT).build()) + .withPumpOutBelowLocation(new WaterSupplyPump.Builder().withPumpLocation(pumpOutBelowLoc).withPumpType(PumpType.BELOW).build()) + .build(); + } + } + + private static Location buildTestLocation(String locationName, String locationType) { + return new Location.Builder(OFFICE_ID, locationName) + .withBoundingOfficeId(OFFICE_ID) + .withMapLabel("Test Map Label") + .withElevation(150.6) + .withNation(Nation.US) + .withStateInitial("CA") + .withCountyName("Yolo") + .withTimeZoneName(ZoneId.of("UTC")) + .withElevationUnits("m") + .withVerticalDatum("NGVD29") + .withHorizontalDatum("WGS84") + .withPublicName("Test Public Name") + .withLongName("Test Long Name") + .withDescription("Test Description") + .withNearestCity("Davis") + .withLatitude(38.55) + .withLongitude(-121.73) + .withPublishedLatitude(38.55) + .withPublishedLongitude(-121.73) + .withActive(true) + .withLocationType(locationType) + .withLocationKind(locationType) + .build(); + } + + private static Project buildTestProject() { + return new Project.Builder().withLocation(buildTestLocation("Test Location Name", + "Test Location Type")) + .withFederalCost(new BigDecimal("15980654.55")) + .build(); + } +} diff --git a/cwms-data-api/src/test/java/cwms/cda/data/dto/watersupply/WaterUserContractTest.java b/cwms-data-api/src/test/java/cwms/cda/data/dto/watersupply/WaterUserContractTest.java new file mode 100644 index 000000000..a682e617d --- /dev/null +++ b/cwms-data-api/src/test/java/cwms/cda/data/dto/watersupply/WaterUserContractTest.java @@ -0,0 +1,255 @@ +/* + * + * MIT License + * + * Copyright (c) 2024 Hydrologic Engineering Center + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE + * SOFTWARE. + */ + +package cwms.cda.data.dto.watersupply; + +import cwms.cda.api.enums.Nation; +import cwms.cda.api.errors.FieldException; +import cwms.cda.data.dto.CwmsId; +import cwms.cda.data.dto.Location; +import cwms.cda.data.dto.LookupType; +import cwms.cda.formatters.Formats; +import cwms.cda.helpers.DTOMatch; +import org.apache.commons.io.IOUtils; +import org.junit.jupiter.api.Test; + +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.time.ZoneId; +import java.util.Date; + +import static org.junit.jupiter.api.Assertions.*; + +final class WaterUserContractTest { + private static final String OFFICE_ID = "MVR"; + + @Test + void testWaterUserContractSerializationRoundTrip() { + WaterUserContract waterUserContract = buildTestWaterUserContract(); + String serialized = Formats.format(Formats.parseHeader(Formats.JSONV1, WaterUserContract.class), + waterUserContract); + WaterUserContract deserialized = Formats.parseContent(Formats.parseHeader(Formats.JSONV1, + WaterUserContract.class), serialized, WaterUserContract.class); + DTOMatch.assertMatch(waterUserContract, deserialized); + } + + @Test + void testWaterUserContractSerializationRoundTripFromFile() throws Exception { + WaterUserContract waterUserContract = buildTestWaterUserContract(); + InputStream resource = this.getClass() + .getResourceAsStream("/cwms/cda/data/dto/watersupply/waterusercontract.json"); + assertNotNull(resource); + String serialized = IOUtils.toString(resource, StandardCharsets.UTF_8); + WaterUserContract deserialized = Formats.parseContent(Formats.parseHeader(Formats.JSONV1, + WaterUserContract.class), serialized, WaterUserContract.class); + DTOMatch.assertMatch(waterUserContract, deserialized); + } + + @Test + void testValidate() { + assertAll( + () -> { + WaterUserContract waterUserContract = buildTestWaterUserContract(); + assertDoesNotThrow(waterUserContract::validate, + "Expected validation to pass without errors"); + }, + () -> { + WaterUserContract waterUserContract = new WaterUserContract.Builder() + .withContractType(new LookupType.Builder() + .withOfficeId(OFFICE_ID) + .withActive(true) + .withTooltip("TEST TOOLTIP") + .withDisplayValue("Test Display Value") + .build()) + .withContractId(new CwmsId.Builder().withOfficeId(OFFICE_ID).withName("TEST_CONTRACT").build()) + .withWaterUser(new WaterUser.Builder().withEntityName("Test User").withProjectId( + new CwmsId.Builder().withName("TEST_LOCATION1").withOfficeId(OFFICE_ID).build()) + .withWaterRight("Test Water Right").build()) + .withContractEffectiveDate(new Date(158000)) + .withContractExpirationDate(new Date(167000)) + .withFutureUseAllocation(27800.5) + .withStorageUnitsId("%") + .withContractedStorage(200000.5) + .withFutureUsePercentActivated(15.6) + .withTotalAllocPercentActivated(65.2) + .build(); + assertThrows(FieldException.class, waterUserContract::validate, + "Expected validation to fail with null Initial Use Allocation"); + }, + () -> { + WaterUserContract waterUserContract = new WaterUserContract.Builder() + .withContractId(new CwmsId.Builder().withOfficeId(OFFICE_ID).withName("TEST_CONTRACT").build()) + .withWaterUser(new WaterUser.Builder().withEntityName("Test User") + .withProjectId(new CwmsId.Builder().withName("TEST_LOCATION1") + .withOfficeId(OFFICE_ID).build()) + .withWaterRight("Test Water Right").build()) + .withContractType(new LookupType.Builder() + .withOfficeId(OFFICE_ID) + .withActive(true) + .withTooltip("TEST TOOLTIP") + .withDisplayValue("Test Display Value") + .build()) + .withContractEffectiveDate(new Date(158000)) + .withContractExpirationDate(new Date(167000)) + .withFutureUseAllocation(27800.5) + .withStorageUnitsId("%") + .withContractedStorage(200000.5) + .withInitialUseAllocation(15600.0) + .withFutureUsePercentActivated(15.6) + .build(); + assertThrows(FieldException.class, waterUserContract::validate, + "Expected validation to fail with null Total Activated Allocation Percentage"); + }, + () -> { + WaterUserContract waterUserContract = new WaterUserContract.Builder() + .withContractId(new CwmsId.Builder().withOfficeId(OFFICE_ID).withName("TEST_CONTRACT").build()) + .withWaterUser(new WaterUser.Builder().withEntityName("Test User") + .withProjectId(new CwmsId.Builder().withName("TEST_LOCATION1") + .withOfficeId(OFFICE_ID).build()) + .withWaterRight("Test Water Right").build()) + .withContractType(new LookupType.Builder() + .withOfficeId(OFFICE_ID) + .withActive(true) + .withTooltip("TEST TOOLTIP") + .withDisplayValue("Test Display Value") + .build()) + .withContractEffectiveDate(new Date(158000)) + .withFutureUseAllocation(27800.5) + .withStorageUnitsId("%") + .withContractedStorage(200000.5) + .withInitialUseAllocation(15600.0) + .withFutureUsePercentActivated(15.6) + .withTotalAllocPercentActivated(65.2) + .build(); + assertThrows(FieldException.class, waterUserContract::validate, + "Expected validation to fail with null Contract Expiration date"); + }, + () -> { + WaterUserContract waterUserContract = new WaterUserContract.Builder() + .withContractId(new CwmsId.Builder().withOfficeId(OFFICE_ID).withName("TEST_CONTRACT").build()) + .withWaterUser(new WaterUser.Builder().withEntityName("Test User") + .withProjectId(new CwmsId.Builder().withName("TEST_LOCATION1") + .withOfficeId(OFFICE_ID).build()) + .withWaterRight("Test Water Right").build()) + .withContractType(new LookupType.Builder() + .withOfficeId(OFFICE_ID) + .withActive(true) + .withTooltip("TEST TOOLTIP") + .withDisplayValue("Test Display Value") + .build()) + .withContractEffectiveDate(new Date(158000)) + .withContractExpirationDate(new Date(167000)) + .withFutureUseAllocation(27800.5) + .withContractedStorage(200000.5) + .withInitialUseAllocation(15600.0) + .withFutureUsePercentActivated(15.6) + .withTotalAllocPercentActivated(65.2) + .build(); + assertThrows(FieldException.class, waterUserContract::validate, + "Expected validation to fail with null Storage Units"); + }, + () -> { + WaterUserContract waterUserContract = new WaterUserContract.Builder() + .withContractType(new LookupType.Builder() + .withOfficeId(OFFICE_ID) + .withActive(true) + .withTooltip("TEST TOOLTIP") + .withDisplayValue("Test Display Value") + .build()) + .withContractEffectiveDate(new Date(158000)) + .withContractExpirationDate(new Date(167000)) + .withFutureUseAllocation(27800.5) + .withStorageUnitsId("%") + .withContractedStorage(200000.5) + .withInitialUseAllocation(15600.0) + .withFutureUsePercentActivated(15.6) + .withTotalAllocPercentActivated(65.2) + .build(); + assertThrows(FieldException.class, waterUserContract::validate, + "Expected validation to fail with null User Contract Reference"); + } + ); + + } + + private static WaterUserContract buildTestWaterUserContract() { + return new WaterUserContract.Builder() + .withContractId(new CwmsId.Builder().withOfficeId(OFFICE_ID).withName("TEST_CONTRACT").build()) + .withWaterUser(new WaterUser.Builder().withEntityName("Test User") + .withProjectId(new CwmsId.Builder().withName("TEST_LOCATION1") + .withOfficeId(OFFICE_ID).build()) + .withWaterRight("Test Water Right").build()) + .withContractType(new LookupType.Builder() + .withActive(true) + .withDisplayValue("Test Display Value") + .withOfficeId(OFFICE_ID) + .withTooltip("Test Tooltip") + .build()) + .withOfficeId(OFFICE_ID) + .withContractEffectiveDate(new Date(158000)) + .withContractExpirationDate(new Date(167000)) + .withInitialUseAllocation(15600.0) + .withFutureUseAllocation(27800.5) + .withStorageUnitsId("m3") + .withContractedStorage(200000.5) + .withFutureUsePercentActivated(15.6) + .withTotalAllocPercentActivated(65.2) + .withPumpOutLocation(new WaterSupplyPump.Builder() + .withPumpLocation(buildTestLocation( 1)).withPumpType(PumpType.OUT).build()) + .withPumpOutBelowLocation(new WaterSupplyPump.Builder() + .withPumpLocation(buildTestLocation(2)).withPumpType(PumpType.BELOW).build()) + .withPumpInLocation(new WaterSupplyPump.Builder() + .withPumpLocation(buildTestLocation(3)).withPumpType(PumpType.IN).build()) + .build(); + } + + private static Location buildTestLocation(int num) { + return new Location.Builder(OFFICE_ID, "PUMP" + num) + .withDescription("Test Description") + .withLocationType("Test Location Type") + .withLatitude(0.0) + .withLongName("Test Long Name") + .withLongitude(0.0) + .withHorizontalDatum("WGS84") + .withLocationKind("PUMP") + .withLocationType("Test Location Type") + .withVerticalDatum("WGS84") + .withTimeZoneName(ZoneId.of("UTC")) + .withActive(true) + .withPublicName("Test Public Pump Name") + .withNation(Nation.US) + .withStateInitial("NV") + .withCountyName("Clark") + .withNearestCity("Sparks") + .withPublishedLongitude(0.0) + .withPublishedLatitude(0.0) + .withElevation(150.0) + .withElevationUnits("m") + .withMapLabel("Test Map Label") + .withBoundingOfficeId(OFFICE_ID) + .build(); + } +} \ No newline at end of file diff --git a/cwms-data-api/src/test/java/cwms/cda/helpers/DTOMatch.java b/cwms-data-api/src/test/java/cwms/cda/helpers/DTOMatch.java index 0eaf5a797..90fa7efb8 100644 --- a/cwms-data-api/src/test/java/cwms/cda/helpers/DTOMatch.java +++ b/cwms-data-api/src/test/java/cwms/cda/helpers/DTOMatch.java @@ -31,6 +31,7 @@ import static org.junit.jupiter.api.Assertions.fail; import cwms.cda.data.dto.CwmsId; +import cwms.cda.data.dto.Location; import cwms.cda.data.dto.LookupType; import cwms.cda.data.dto.location.kind.VirtualOutletRecord; import cwms.cda.data.dto.location.kind.Embankment; @@ -42,6 +43,9 @@ import cwms.cda.data.dto.stream.StreamLocation; import cwms.cda.data.dto.stream.StreamNode; import cwms.cda.data.dto.stream.StreamReach; +import cwms.cda.data.dto.watersupply.WaterSupplyPump; +import cwms.cda.data.dto.watersupply.WaterUser; +import cwms.cda.data.dto.watersupply.WaterUserContract; import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -49,6 +53,7 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.function.Executable; + @SuppressWarnings({"LongLine", "checkstyle:LineLength"}) public final class DTOMatch { @@ -221,6 +226,73 @@ public static void assertMatch(List first, List second, AssertMatchMet .mapToObj(i -> () -> matcher.assertMatch(first.get(i), second.get(i))))); } + public static void assertMatch(WaterSupplyPump firstPump, WaterSupplyPump secondPump) { + assertAll( + () -> assertMatch(firstPump.getPumpLocation(), secondPump.getPumpLocation()), + () -> assertEquals(firstPump.getPumpType(), secondPump.getPumpType()) + ); + } + + public static void assertMatch(WaterUser firstUser, WaterUser secondUser) { + assertAll( + () -> assertEquals(firstUser.getEntityName(), secondUser.getEntityName()), + () -> DTOMatch.assertMatch(firstUser.getProjectId(), secondUser.getProjectId()), + () -> assertEquals(firstUser.getWaterRight(), secondUser.getWaterRight()) + ); + } + + public static void assertMatch(Location first, Location second) { + assertAll( + () -> assertEquals(first.getName(), second.getName()), + () -> assertEquals(first.getLatitude(), second.getLatitude()), + () -> assertEquals(first.getLongitude(), second.getLongitude()), + () -> assertEquals(first.getHorizontalDatum(), second.getHorizontalDatum()), + () -> assertEquals(first.getElevation(), second.getElevation()), + () -> assertEquals(first.getElevationUnits(), second.getElevationUnits()), + () -> assertEquals(first.getVerticalDatum(), second.getVerticalDatum()), + () -> assertEquals(first.getPublicName(), second.getPublicName()), + () -> assertEquals(first.getLongName(), second.getLongName()), + () -> assertEquals(first.getDescription(), second.getDescription()), + () -> assertEquals(first.getActive(), second.getActive()), + () -> assertEquals(first.getLocationKind(), second.getLocationKind()), + () -> assertEquals(first.getMapLabel(), second.getMapLabel()), + () -> assertEquals(first.getPublishedLatitude(), second.getPublishedLatitude()), + () -> assertEquals(first.getPublishedLongitude(), second.getPublishedLongitude()), + () -> assertEquals(first.getBoundingOfficeId(), second.getBoundingOfficeId()), + () -> assertEquals(first.getNation(), second.getNation()), + () -> assertEquals(first.getNearestCity(), second.getNearestCity()), + () -> assertEquals(first.getStateInitial(), second.getStateInitial()), + () -> assertEquals(first.getCountyName(), second.getCountyName()), + () -> assertEquals(first.getTimezoneName(), second.getTimezoneName()), + () -> assertEquals(first.getOfficeId(), second.getOfficeId()), + () -> assertEquals(first.getLocationType(), second.getLocationType()) + ); + } + + public static void assertMatch(WaterUserContract firstContract, WaterUserContract secondContract) { + assertAll( + () -> assertMatch(firstContract.getWaterUser(), secondContract.getWaterUser()), + () -> DTOMatch.assertMatch(firstContract.getContractId(), secondContract.getContractId()), + () -> DTOMatch.assertMatch(firstContract.getContractType(), secondContract.getContractType()), + () -> assertEquals(firstContract.getContractEffectiveDate().toInstant().getEpochSecond(), + secondContract.getContractEffectiveDate().toInstant().getEpochSecond()), + () -> assertEquals(firstContract.getContractExpirationDate().toInstant().getEpochSecond(), + secondContract.getContractExpirationDate().toInstant().getEpochSecond()), + () -> assertEquals(firstContract.getContractedStorage(), secondContract.getContractedStorage()), + () -> assertEquals(firstContract.getInitialUseAllocation(), secondContract.getInitialUseAllocation()), + () -> assertEquals(firstContract.getFutureUseAllocation(), secondContract.getFutureUseAllocation()), + () -> assertEquals(firstContract.getStorageUnitsId(), secondContract.getStorageUnitsId()), + () -> assertEquals(firstContract.getFutureUsePercentActivated(), + secondContract.getFutureUsePercentActivated()), + () -> assertEquals(firstContract.getTotalAllocPercentActivated(), + secondContract.getTotalAllocPercentActivated()), + () -> assertMatch(firstContract.getPumpOutLocation(), secondContract.getPumpOutLocation()), + () -> assertMatch(firstContract.getPumpOutBelowLocation(), secondContract.getPumpOutBelowLocation()), + () -> assertMatch(firstContract.getPumpInLocation(), secondContract.getPumpInLocation()) + ); + } + + @FunctionalInterface public interface AssertMatchMethod{ void assertMatch(T first, T second); diff --git a/cwms-data-api/src/test/java/cwms/cda/helpers/DateUtilsTest.java b/cwms-data-api/src/test/java/cwms/cda/helpers/DateUtilsTest.java index 667d32776..01fbb5188 100644 --- a/cwms-data-api/src/test/java/cwms/cda/helpers/DateUtilsTest.java +++ b/cwms-data-api/src/test/java/cwms/cda/helpers/DateUtilsTest.java @@ -2,8 +2,10 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; +import cwms.cda.api.Controllers; import cwms.cda.data.dto.TimeSeries; import java.time.DateTimeException; import java.time.Instant; @@ -122,4 +124,23 @@ void test_PT_doesnt_care_about_zone(){ assertEquals(ptZdt.toInstant(), ptChZdt.toInstant(), "PT-24H should be the same in any zone"); } + @Test + void test_controllers_example_date(){ + ZonedDateTime zdt = DateUtils.parseUserDate(Controllers.EXAMPLE_DATE, "UTC"); + assertNotNull(zdt); + Instant expected = ZonedDateTime.of(2021,6,10,13,0,0,0, + ZoneId.of("PST8PDT")).toInstant(); + assertEquals(expected, zdt.toInstant()); + } + + @Test + void test_DateTimeFormatter_iso_zoned_example(){ + String isoExample = "2011-12-03T10:15:30+01:00[Europe/Paris]"; // Example from java.time.format.DateTimeFormatter javadoc. + ZonedDateTime zdt = DateUtils.parseUserDate(isoExample, "UTC"); + assertNotNull(zdt); + Instant expected = ZonedDateTime.of(2011,12,3,10,15,30,0, + ZoneId.of("Europe/Paris")).toInstant(); + assertEquals(expected, zdt.toInstant()); + } + } diff --git a/cwms-data-api/src/test/resources/cwms/cda/data/dto/watersupply/waterusercontract.json b/cwms-data-api/src/test/resources/cwms/cda/data/dto/watersupply/waterusercontract.json new file mode 100644 index 000000000..b26d6b9e1 --- /dev/null +++ b/cwms-data-api/src/test/resources/cwms/cda/data/dto/watersupply/waterusercontract.json @@ -0,0 +1,113 @@ +{ + "office-id": "MVR", + "water-user": { + "entity-name": "Test User", + "project-id": { + "office-id": "MVR", + "name": "TEST_LOCATION1" + }, + "water-right": "Test Water Right" + }, + "contract-id": { + "office-id": "MVR", + "name": "TEST_CONTRACT" + }, + "contract-type": { + "office-id": "MVR", + "display-value": "Test Display Value", + "tooltip": "Test Tooltip", + "active": true + }, + "contract-effective-date": 158000, + "contract-expiration-date": 167000, + "contracted-storage": 200000.5, + "initial-use-allocation": 15600, + "future-use-allocation": 27800.5, + "storage-units-id": "m3", + "future-use-percent-activated": 15.6, + "total-alloc-percent-activated": 65.2, + "pump-out-location": { + "pump-location": { + "office-id": "MVR", + "name": "PUMP1", + "latitude": 0, + "longitude": 0, + "active": true, + "public-name": "Test Public Pump Name", + "long-name": "Test Long Name", + "description": "Test Description", + "timezone-name": "UTC", + "location-type": "Test Location Type", + "location-kind": "PUMP", + "nation": "US", + "state-initial": "NV", + "county-name": "Clark", + "nearest-city": "Sparks", + "horizontal-datum": "WGS84", + "published-longitude": 0, + "published-latitude": 0, + "vertical-datum": "WGS84", + "elevation": 150, + "map-label": "Test Map Label", + "bounding-office-id": "MVR", + "elevation-units": "m" + }, + "pump-type": "OUT" + }, + "pump-out-below-location": { + "pump-location": { + "office-id": "MVR", + "name": "PUMP2", + "latitude": 0, + "longitude": 0, + "active": true, + "public-name": "Test Public Pump Name", + "long-name": "Test Long Name", + "description": "Test Description", + "timezone-name": "UTC", + "location-type": "Test Location Type", + "location-kind": "PUMP", + "nation": "US", + "state-initial": "NV", + "county-name": "Clark", + "nearest-city": "Sparks", + "horizontal-datum": "WGS84", + "published-longitude": 0, + "published-latitude": 0, + "vertical-datum": "WGS84", + "elevation": 150, + "map-label": "Test Map Label", + "bounding-office-id": "MVR", + "elevation-units": "m" + }, + "pump-type": "BELOW" + }, + "pump-in-location": { + "pump-location": { + "office-id": "MVR", + "name": "PUMP3", + "latitude": 0, + "longitude": 0, + "active": true, + "public-name": "Test Public Pump Name", + "long-name": "Test Long Name", + "description": "Test Description", + "timezone-name": "UTC", + "location-type": "Test Location Type", + "location-kind": "PUMP", + "nation": "US", + "state-initial": "NV", + "county-name": "Clark", + "nearest-city": "Sparks", + "horizontal-datum": "WGS84", + "published-longitude": 0, + "published-latitude": 0, + "vertical-datum": "WGS84", + "elevation": 150, + "map-label": "Test Map Label", + "bounding-office-id": "MVR", + "elevation-units": "m" + }, + "pump-type": "IN" + } +} \ No newline at end of file