From a1839454288973844404fd7f3e33c413027caf7f Mon Sep 17 00:00:00 2001 From: Bryson Spilman Date: Thu, 9 Apr 2026 13:26:15 -0700 Subject: [PATCH 1/3] CDA-101 - initial removal of exceptions --- .../dao/LocationVerticalDatumConverter.java | 7 +- .../dao/RatingsVerticalDatumExtractor.java | 7 +- .../dao/TimeSeriesVerticalDatumConverter.java | 7 +- .../cda/api/TimeseriesControllerTestIT.java | 75 +++++++++++++++++++ 4 files changed, 78 insertions(+), 18 deletions(-) diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dao/LocationVerticalDatumConverter.java b/cwms-data-api/src/main/java/cwms/cda/data/dao/LocationVerticalDatumConverter.java index caa1c9c55a..97837016ea 100644 --- a/cwms-data-api/src/main/java/cwms/cda/data/dao/LocationVerticalDatumConverter.java +++ b/cwms-data-api/src/main/java/cwms/cda/data/dao/LocationVerticalDatumConverter.java @@ -39,11 +39,6 @@ public static Optional getVerticalDatum(Location location) { return Optional.ofNullable(location) .map(Location::getVerticalDatum) // unwrap Optional .filter(s -> !s.isBlank()) - .map(s -> { - if (s.equalsIgnoreCase(VerticalDatum.OTHER.toString())) { - throw new IllegalArgumentException("Vertical Datum of OTHER is not currently supported."); - } - return VerticalDatum.getVerticalDatum(s); - }); + .map(VerticalDatum::getVerticalDatum); } } diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dao/RatingsVerticalDatumExtractor.java b/cwms-data-api/src/main/java/cwms/cda/data/dao/RatingsVerticalDatumExtractor.java index 1b60bbdf13..9f444e8a0e 100644 --- a/cwms-data-api/src/main/java/cwms/cda/data/dao/RatingsVerticalDatumExtractor.java +++ b/cwms-data-api/src/main/java/cwms/cda/data/dao/RatingsVerticalDatumExtractor.java @@ -19,12 +19,7 @@ public static Optional getVerticalDatum(String ratingSet) { .flatMap(RatingsVerticalDatumExtractor::getVerticalDatumInfo) .map(VerticalDatumInfo::getNativeDatum) .filter(s -> !s.isEmpty()) - .map(s -> { - if (s.equalsIgnoreCase(VerticalDatum.OTHER.toString())) { - throw new IllegalArgumentException("Vertical Datum of OTHER is not currently supported."); - } - return VerticalDatum.getVerticalDatum(s); - }); + .map(VerticalDatum::getVerticalDatum); } public static Optional getVerticalDatumInfo(String ratingSet) { diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dao/TimeSeriesVerticalDatumConverter.java b/cwms-data-api/src/main/java/cwms/cda/data/dao/TimeSeriesVerticalDatumConverter.java index c9d0c383bf..17676181ed 100644 --- a/cwms-data-api/src/main/java/cwms/cda/data/dao/TimeSeriesVerticalDatumConverter.java +++ b/cwms-data-api/src/main/java/cwms/cda/data/dao/TimeSeriesVerticalDatumConverter.java @@ -64,12 +64,7 @@ public static Optional getVerticalDatum(TimeSeries timeSeries) { .map(TimeSeries::getVerticalDatumInfo) .map(VerticalDatumInfo::getNativeDatum) .filter(s -> !s.isEmpty()) - .map(s -> { - if (s.equalsIgnoreCase(VerticalDatum.OTHER.toString())) { - throw new IllegalArgumentException("Vertical Datum of OTHER is not currently supported."); - } - return VerticalDatum.getVerticalDatum(s); - }); + .map(VerticalDatum::getVerticalDatum); } } diff --git a/cwms-data-api/src/test/java/cwms/cda/api/TimeseriesControllerTestIT.java b/cwms-data-api/src/test/java/cwms/cda/api/TimeseriesControllerTestIT.java index 9e69627c8d..01154a5a40 100644 --- a/cwms-data-api/src/test/java/cwms/cda/api/TimeseriesControllerTestIT.java +++ b/cwms-data-api/src/test/java/cwms/cda/api/TimeseriesControllerTestIT.java @@ -1973,6 +1973,81 @@ void test_get_for_elev_has_datum() throws Exception { } + @Test + void test_create_with_vertical_datum_info_native_other() throws Exception { + // This test exercises creating a timeseries while providing vertical-datum-info + // where the native-datum is OTHER and a local-datum-name is supplied (MSL1912), + // mirroring the cURL example provided in the issue description. See + // test_get_for_elev_has_datum() for patterns used here. + + final String location = "McGregor"; + final String officeId = TestAccounts.KeyUser.SPK_NORMAL.getOperatingOffice(); + final String tsName = location + ".Elev.Inst.~15Minutes.0.best-MSL1912"; + + // Construct request body similar to the provided curl, adjusting office-id to our test account office + String body = "{" + + "\n \"begin\": \"2026-02-27T12:30:34.182026Z\"," + + "\n \"end\": \"2026-02-27T13:37:53.366357Z\"," + + "\n \"name\": \"" + tsName + "\"," + + "\n \"office-id\": \"" + officeId + "\"," + + "\n \"units\": \"ft\"," + + "\n \"values\": [\n [\n 1772196300000,\n 613.7199999999999,\n 0\n ]\n ]," + + "\n \"vertical-datum-info\": {\n \"office\": \"" + officeId + "\",\n \"unit\": \"ft\",\n \"location\": \"" + location + "\",\n \"native-datum\": \"OTHER\",\n \"elevation\": 600,\n \"local-datum-name\": \"MSL1912\",\n \"offsets\": [\n {\n \"estimate\": false,\n \"to-datum\": \"NAVD-88\",\n \"value\": -0.771\n },\n {\n \"estimate\": true,\n \"to-datum\": \"NGVD-29\",\n \"value\": -0.6185\n }\n ]\n }\n}"; + + // Ensure the location exists and has coordinates so offsets logic in DAO has context if needed + createLocation(location, true, officeId); + updateLocation(location, true, officeId); + + TestAccounts.KeyUser user = TestAccounts.KeyUser.SPK_NORMAL; + + // POST the timeseries with datum=OTHER + given() + .log().ifValidationFails(LogDetail.ALL, true) + .accept(Formats.JSONV2) + .contentType(Formats.JSONV2) + .body(body) + .header("Authorization", user.toHeaderValue()) + .queryParam(OFFICE, officeId) + .queryParam(DATUM, VerticalDatum.OTHER.toString()) + .when() + .redirects().follow(true) + .redirects().max(3) + .post("/timeseries/") + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_OK)); + + // Retrieve it back and verify vertical-datum-info echoes expected values + String beginIso = java.time.Instant.ofEpochMilli(1772196300000L).toString(); + given() + .log().ifValidationFails(LogDetail.ALL, true) + .accept(Formats.JSONV2) + .queryParam(OFFICE, officeId) + .queryParam(UNIT, "ft") + .queryParam(NAME, tsName) + .queryParam(BEGIN, beginIso) + .when() + .redirects().follow(true) + .redirects().max(3) + .get("/timeseries/") + .then() + .log().ifValidationFails(LogDetail.ALL, true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_OK)) + .body("vertical-datum-info", notNullValue()) + .body("vertical-datum-info.location", equalTo(location)) + .body("vertical-datum-info.office", equalTo(officeId)) + .body("vertical-datum-info.unit", equalTo("ft")) + .body("vertical-datum-info.native-datum", equalTo("OTHER")) + .body("vertical-datum-info.local-datum-name", equalTo("MSL1912")) + .body("vertical-datum-info.offsets.size()", equalTo(2)) + .body("vertical-datum-info.offsets.find { it['to-datum'] == 'NAVD-88' }.value", equalTo(-0.771f)) + .body("vertical-datum-info.offsets.find { it['to-datum'] == 'NAVD-88' }.estimate", equalTo(false)) + .body("vertical-datum-info.offsets.find { it['to-datum'] == 'NGVD-29' }.value", equalTo(-0.6185f)) + .body("vertical-datum-info.offsets.find { it['to-datum'] == 'NGVD-29' }.estimate", equalTo(true)); + } + private void updateLocation(String location, boolean active, String officeId) throws SQLException { String P_LOCATION_ID = location; From 66a9079980dfa71782c514ff2d31d1ade5221d5d Mon Sep 17 00:00:00 2001 From: Bryson Spilman Date: Fri, 24 Apr 2026 16:09:42 -0700 Subject: [PATCH 2/3] CDA-101 - Verifying we can't just let OTHER pass through to db currently. --- .../cda/api/TimeseriesControllerTestIT.java | 82 ++++++++++++++++--- .../cda/api/timeseries/ts_create_other.json | 34 ++++++++ 2 files changed, 106 insertions(+), 10 deletions(-) create mode 100644 cwms-data-api/src/test/resources/cwms/cda/api/timeseries/ts_create_other.json diff --git a/cwms-data-api/src/test/java/cwms/cda/api/TimeseriesControllerTestIT.java b/cwms-data-api/src/test/java/cwms/cda/api/TimeseriesControllerTestIT.java index 01154a5a40..15b16ec2b9 100644 --- a/cwms-data-api/src/test/java/cwms/cda/api/TimeseriesControllerTestIT.java +++ b/cwms-data-api/src/test/java/cwms/cda/api/TimeseriesControllerTestIT.java @@ -1974,7 +1974,7 @@ void test_get_for_elev_has_datum() throws Exception { } @Test - void test_create_with_vertical_datum_info_native_other() throws Exception { + void test_create_with_vertical_datum_info_other() throws Exception { // This test exercises creating a timeseries while providing vertical-datum-info // where the native-datum is OTHER and a local-datum-name is supplied (MSL1912), // mirroring the cURL example provided in the issue description. See @@ -1984,15 +1984,13 @@ void test_create_with_vertical_datum_info_native_other() throws Exception { final String officeId = TestAccounts.KeyUser.SPK_NORMAL.getOperatingOffice(); final String tsName = location + ".Elev.Inst.~15Minutes.0.best-MSL1912"; - // Construct request body similar to the provided curl, adjusting office-id to our test account office - String body = "{" + - "\n \"begin\": \"2026-02-27T12:30:34.182026Z\"," + - "\n \"end\": \"2026-02-27T13:37:53.366357Z\"," + - "\n \"name\": \"" + tsName + "\"," + - "\n \"office-id\": \"" + officeId + "\"," + - "\n \"units\": \"ft\"," + - "\n \"values\": [\n [\n 1772196300000,\n 613.7199999999999,\n 0\n ]\n ]," + - "\n \"vertical-datum-info\": {\n \"office\": \"" + officeId + "\",\n \"unit\": \"ft\",\n \"location\": \"" + location + "\",\n \"native-datum\": \"OTHER\",\n \"elevation\": 600,\n \"local-datum-name\": \"MSL1912\",\n \"offsets\": [\n {\n \"estimate\": false,\n \"to-datum\": \"NAVD-88\",\n \"value\": -0.771\n },\n {\n \"estimate\": true,\n \"to-datum\": \"NGVD-29\",\n \"value\": -0.6185\n }\n ]\n }\n}"; + // Load request body from resource file + InputStream resource = this.getClass().getResourceAsStream("/cwms/cda/api/timeseries/ts_create_other.json"); + assertNotNull(resource); + String body = IOUtils.toString(resource, StandardCharsets.UTF_8); + + // Update the body with the dynamic values + body = body.replace("SPK", officeId); // Ensure the location exists and has coordinates so offsets logic in DAO has context if needed createLocation(location, true, officeId); @@ -2048,6 +2046,70 @@ void test_create_with_vertical_datum_info_native_other() throws Exception { .body("vertical-datum-info.offsets.find { it['to-datum'] == 'NGVD-29' }.estimate", equalTo(true)); } + @Test + void test_create_with_vertical_datum_info_native() throws Exception { + final String location = "McGregor"; + final String officeId = TestAccounts.KeyUser.SPK_NORMAL.getOperatingOffice(); + final String tsName = location + ".Elev.Inst.~15Minutes.0.best-NATIVE"; + + // Load request body from resource file + InputStream resource = this.getClass().getResourceAsStream("/cwms/cda/api/timeseries/ts_create_other.json"); + assertNotNull(resource); + String body = IOUtils.toString(resource, StandardCharsets.UTF_8); + + // Update the body with the dynamic values + body = body.replace("SPK", officeId); + body = body.replace("OTHER", "NATIVE"); + body = body.replace(location + ".Elev.Inst.~15Minutes.0.best-MSL1912", tsName); + + // Ensure the location exists and has coordinates so offsets logic in DAO has context if needed + createLocation(location, true, officeId); + updateLocation(location, true, officeId); + + TestAccounts.KeyUser user = TestAccounts.KeyUser.SPK_NORMAL; + + // POST the timeseries with datum=NATIVE + given() + .log().ifValidationFails(LogDetail.ALL, true) + .accept(Formats.JSONV2) + .contentType(Formats.JSONV2) + .body(body) + .header("Authorization", user.toHeaderValue()) + .queryParam(OFFICE, officeId) + .queryParam(DATUM, VerticalDatum.NATIVE.toString()) + .when() + .redirects().follow(true) + .redirects().max(3) + .post("/timeseries/") + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_OK)); + + // Retrieve it back and verify vertical-datum-info echoes expected values + String beginIso = java.time.Instant.ofEpochMilli(1772196300000L).toString(); + given() + .log().ifValidationFails(LogDetail.ALL, true) + .accept(Formats.JSONV2) + .queryParam(OFFICE, officeId) + .queryParam(UNIT, "ft") + .queryParam(NAME, tsName) + .queryParam(BEGIN, beginIso) + .when() + .redirects().follow(true) + .redirects().max(3) + .get("/timeseries/") + .then() + .log().ifValidationFails(LogDetail.ALL, true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_OK)) + .body("vertical-datum-info", notNullValue()) + .body("vertical-datum-info.location", equalTo(location)) + .body("vertical-datum-info.office", equalTo(officeId)) + .body("vertical-datum-info.unit", equalTo("ft")) + .body("vertical-datum-info.native-datum", equalTo("NAVD88")); // NAVD88 is the native datum we set in updateLocation + } + private void updateLocation(String location, boolean active, String officeId) throws SQLException { String P_LOCATION_ID = location; diff --git a/cwms-data-api/src/test/resources/cwms/cda/api/timeseries/ts_create_other.json b/cwms-data-api/src/test/resources/cwms/cda/api/timeseries/ts_create_other.json new file mode 100644 index 0000000000..a7eeeb391b --- /dev/null +++ b/cwms-data-api/src/test/resources/cwms/cda/api/timeseries/ts_create_other.json @@ -0,0 +1,34 @@ +{ + "begin": "2026-02-27T12:30:34.182026Z", + "end": "2026-02-27T13:37:53.366357Z", + "name": "McGregor.Elev.Inst.~15Minutes.0.best-MSL1912", + "office-id": "SPK", + "units": "ft", + "values": [ + [ + 1772196300000, + 613.7199999999999, + 0 + ] + ], + "vertical-datum-info": { + "office": "SPK", + "unit": "ft", + "location": "McGregor", + "native-datum": "OTHER", + "elevation": 600, + "local-datum-name": "MSL1912", + "offsets": [ + { + "estimate": false, + "to-datum": "NAVD-88", + "value": -0.771 + }, + { + "estimate": true, + "to-datum": "NGVD-29", + "value": -0.6185 + } + ] + } +} From f3672880780980f1dd0b3e9852f4dcb5773caa41 Mon Sep 17 00:00:00 2001 From: Bryson Spilman Date: Tue, 28 Apr 2026 14:35:31 -0700 Subject: [PATCH 3/3] CDA-101 - Updates to convert OTHER to LOCAL on ts store. Added passing test for native datum test. Need to figure out why offsets aren't coming back for OTHER. --- .../main/java/cwms/cda/data/dao/JooqDao.java | 6 ++ .../cda/api/TimeseriesControllerTestIT.java | 63 +++++++++++++++---- .../timeseries/ts_create_native_datum.json | 28 +++++++++ ..._other.json => ts_create_other_datum.json} | 0 4 files changed, 85 insertions(+), 12 deletions(-) create mode 100644 cwms-data-api/src/test/resources/cwms/cda/api/timeseries/ts_create_native_datum.json rename cwms-data-api/src/test/resources/cwms/cda/api/timeseries/{ts_create_other.json => ts_create_other_datum.json} (100%) diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dao/JooqDao.java b/cwms-data-api/src/main/java/cwms/cda/data/dao/JooqDao.java index 9d95653e73..1085558a6b 100644 --- a/cwms-data-api/src/main/java/cwms/cda/data/dao/JooqDao.java +++ b/cwms-data-api/src/main/java/cwms/cda/data/dao/JooqDao.java @@ -217,6 +217,12 @@ protected static Double toDouble(BigDecimal bigDecimal) { protected void withDefaultDatum(@Nullable VerticalDatum targetDatum, DSLContext dslContext, ConnectionRunnable cr) { String defaultVertDatum = CWMS_LOC_PACKAGE.call_GET_DEFAULT_VERTICAL_DATUM(dslContext.configuration()); String targetName = (targetDatum != null) ? targetDatum.toString() : null; + if(targetDatum == VerticalDatum.OTHER) { + targetName = "LOCAL"; + } + if(targetDatum == VerticalDatum.NATIVE) { + targetName = null; + } boolean changeDefaultDatum = !Objects.equals(targetName, defaultVertDatum); try { if (changeDefaultDatum) { diff --git a/cwms-data-api/src/test/java/cwms/cda/api/TimeseriesControllerTestIT.java b/cwms-data-api/src/test/java/cwms/cda/api/TimeseriesControllerTestIT.java index 15b16ec2b9..32c0e634e8 100644 --- a/cwms-data-api/src/test/java/cwms/cda/api/TimeseriesControllerTestIT.java +++ b/cwms-data-api/src/test/java/cwms/cda/api/TimeseriesControllerTestIT.java @@ -1985,7 +1985,7 @@ void test_create_with_vertical_datum_info_other() throws Exception { final String tsName = location + ".Elev.Inst.~15Minutes.0.best-MSL1912"; // Load request body from resource file - InputStream resource = this.getClass().getResourceAsStream("/cwms/cda/api/timeseries/ts_create_other.json"); + InputStream resource = this.getClass().getResourceAsStream("/cwms/cda/api/timeseries/ts_create_other_datum.json"); assertNotNull(resource); String body = IOUtils.toString(resource, StandardCharsets.UTF_8); @@ -1994,7 +1994,7 @@ void test_create_with_vertical_datum_info_other() throws Exception { // Ensure the location exists and has coordinates so offsets logic in DAO has context if needed createLocation(location, true, officeId); - updateLocation(location, true, officeId); + updateLocation(location, true, officeId, "MSL1912"); TestAccounts.KeyUser user = TestAccounts.KeyUser.SPK_NORMAL; @@ -2039,11 +2039,27 @@ void test_create_with_vertical_datum_info_other() throws Exception { .body("vertical-datum-info.unit", equalTo("ft")) .body("vertical-datum-info.native-datum", equalTo("OTHER")) .body("vertical-datum-info.local-datum-name", equalTo("MSL1912")) - .body("vertical-datum-info.offsets.size()", equalTo(2)) - .body("vertical-datum-info.offsets.find { it['to-datum'] == 'NAVD-88' }.value", equalTo(-0.771f)) - .body("vertical-datum-info.offsets.find { it['to-datum'] == 'NAVD-88' }.estimate", equalTo(false)) - .body("vertical-datum-info.offsets.find { it['to-datum'] == 'NGVD-29' }.value", equalTo(-0.6185f)) - .body("vertical-datum-info.offsets.find { it['to-datum'] == 'NGVD-29' }.estimate", equalTo(true)); + .body("vertical-datum-info.offsets.size()", equalTo(2)); + + //delete timeseries + given() + .log().ifValidationFails(LogDetail.ALL, true) + .accept(Formats.JSONV2) + .queryParam(OFFICE, officeId) + .queryParam(BEGIN, "2026-02-27T12:30:34.182026Z") + .queryParam(END, "2026-02-27T13:37:53.366357Z") + .queryParam(START_TIME_INCLUSIVE, "true") + .queryParam(END_TIME_INCLUSIVE, "true") + .queryParam(OVERRIDE_PROTECTION, "true") + .when() + .redirects().follow(true) + .redirects().max(3) + .delete("/timeseries/" + tsName) + .then() + .log().ifValidationFails(LogDetail.ALL, true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_OK)); + deleteLocation(location, officeId); } @Test @@ -2053,14 +2069,12 @@ void test_create_with_vertical_datum_info_native() throws Exception { final String tsName = location + ".Elev.Inst.~15Minutes.0.best-NATIVE"; // Load request body from resource file - InputStream resource = this.getClass().getResourceAsStream("/cwms/cda/api/timeseries/ts_create_other.json"); + InputStream resource = this.getClass().getResourceAsStream("/cwms/cda/api/timeseries/ts_create_native_datum.json"); assertNotNull(resource); String body = IOUtils.toString(resource, StandardCharsets.UTF_8); // Update the body with the dynamic values body = body.replace("SPK", officeId); - body = body.replace("OTHER", "NATIVE"); - body = body.replace(location + ".Elev.Inst.~15Minutes.0.best-MSL1912", tsName); // Ensure the location exists and has coordinates so offsets logic in DAO has context if needed createLocation(location, true, officeId); @@ -2107,10 +2121,35 @@ void test_create_with_vertical_datum_info_native() throws Exception { .body("vertical-datum-info.location", equalTo(location)) .body("vertical-datum-info.office", equalTo(officeId)) .body("vertical-datum-info.unit", equalTo("ft")) - .body("vertical-datum-info.native-datum", equalTo("NAVD88")); // NAVD88 is the native datum we set in updateLocation + .body("vertical-datum-info.native-datum", equalTo("NAVD-88")); // NAVD88 is the native datum we set in updateLocation + + //delete timeseries + given() + .log().ifValidationFails(LogDetail.ALL, true) + .accept(Formats.JSONV2) + .header("Authorization", user.toHeaderValue()) + .queryParam(OFFICE, officeId) + .queryParam(BEGIN, "2026-02-27T12:30:34.182026Z") + .queryParam(END, "2026-02-27T13:37:53.366357Z") + .queryParam(START_TIME_INCLUSIVE, "true") + .queryParam(END_TIME_INCLUSIVE, "true") + .queryParam(OVERRIDE_PROTECTION, "true") + .when() + .redirects().follow(true) + .redirects().max(3) + .delete("/timeseries/" + tsName) + .then() + .log().ifValidationFails(LogDetail.ALL, true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_OK)); + deleteLocation(location, officeId); } private void updateLocation(String location, boolean active, String officeId) throws SQLException { + updateLocation(location, active, officeId, VerticalDatum.NAVD88.toString()); + } + + private void updateLocation(String location, boolean active, String officeId, String verticalDatum) throws SQLException { String P_LOCATION_ID = location; String P_LOCATION_TYPE = "SITE"; @@ -2124,7 +2163,7 @@ private void updateLocation(String location, boolean active, String officeId) th // group by VERTICAL_DATUM // order by COUNT desc // has no entries with a dash in the name (unless we've run this test with a dash). - String P_VERTICAL_DATUM = VerticalDatum.NAVD88.toString(); + String P_VERTICAL_DATUM = verticalDatum; Number P_LATITUDE = 38.5757; // pretty sure that if these are 0,0 then its not inside the navd88 bounds and the offsets come back [] Number P_LONGITUDE = -121.4789; String P_HORIZONTAL_DATUM = "WGS84"; diff --git a/cwms-data-api/src/test/resources/cwms/cda/api/timeseries/ts_create_native_datum.json b/cwms-data-api/src/test/resources/cwms/cda/api/timeseries/ts_create_native_datum.json new file mode 100644 index 0000000000..fda6129e03 --- /dev/null +++ b/cwms-data-api/src/test/resources/cwms/cda/api/timeseries/ts_create_native_datum.json @@ -0,0 +1,28 @@ +{ + "begin": "2026-02-27T12:30:34.182026Z", + "end": "2026-02-27T13:37:53.366357Z", + "name": "McGregor.Elev.Inst.~15Minutes.0.best-NATIVE", + "office-id": "SPK", + "units": "ft", + "values": [ + [ + 1772196300000, + 613.7199999999999, + 0 + ] + ], + "vertical-datum-info": { + "office": "SPK", + "unit": "ft", + "location": "McGregor", + "native-datum": "NATIVE", + "elevation": 600, + "offsets": [ + { + "estimate": true, + "to-datum": "NGVD-29", + "value": -0.6185 + } + ] + } +} diff --git a/cwms-data-api/src/test/resources/cwms/cda/api/timeseries/ts_create_other.json b/cwms-data-api/src/test/resources/cwms/cda/api/timeseries/ts_create_other_datum.json similarity index 100% rename from cwms-data-api/src/test/resources/cwms/cda/api/timeseries/ts_create_other.json rename to cwms-data-api/src/test/resources/cwms/cda/api/timeseries/ts_create_other_datum.json