From c3da4fa402c67f529b281b49b56e5a65c1840002 Mon Sep 17 00:00:00 2001 From: ZeterTheDuck Date: Fri, 22 May 2026 11:46:13 -0600 Subject: [PATCH 01/13] fix: update getCivicChild endpoint to match expected schema --- core/src/main/resources/schema.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/resources/schema.yml b/core/src/main/resources/schema.yml index 69fb5c9..f7474d3 100644 --- a/core/src/main/resources/schema.yml +++ b/core/src/main/resources/schema.yml @@ -84,7 +84,7 @@ paths: type: array items: $ref: "#/components/schemas/CountryContext" - /api/v1/locations/{parentId}/{locale}: + /api/v1/locations/chidren/{parentId}/{locale}: get: description: Get the children of a parent location, in a certain locale operationId: getCivicChild From 541b98a72dd2de998a4e5382581d4edea3ae50a2 Mon Sep 17 00:00:00 2001 From: ZeterTheDuck Date: Fri, 22 May 2026 11:53:10 -0600 Subject: [PATCH 02/13] feat: add /api/v1/locations/{language}/countries endpoint to schema --- core/src/main/resources/schema.yml | 31 ++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/core/src/main/resources/schema.yml b/core/src/main/resources/schema.yml index f7474d3..5929d3a 100644 --- a/core/src/main/resources/schema.yml +++ b/core/src/main/resources/schema.yml @@ -84,6 +84,37 @@ paths: type: array items: $ref: "#/components/schemas/CountryContext" + /api/v1/locations/{language}/countries: + get: + description: Get a list of all countries, in a certain language + operationId: getCountries + tags: + [ Location ] + parameters: + - name: language + in: path + required: true + schema: + type: string + responses: + '200': + description: OK + content: + text/plain: + schema: + type: array + items: + type: string + applications/json: + schema: + type: array + items: + type: string + text/json: + schema: + type: array + items: + type: string /api/v1/locations/chidren/{parentId}/{locale}: get: description: Get the children of a parent location, in a certain locale From 1184537a870ab5e556adf7a2037cb231911e0652 Mon Sep 17 00:00:00 2001 From: ZeterTheDuck Date: Fri, 22 May 2026 12:04:43 -0600 Subject: [PATCH 03/13] test: add test for getCountries method --- .../test/groovy/org/justserve/LocationSpec.groovy | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/core/src/test/groovy/org/justserve/LocationSpec.groovy b/core/src/test/groovy/org/justserve/LocationSpec.groovy index d322c9f..6c8c01e 100644 --- a/core/src/test/groovy/org/justserve/LocationSpec.groovy +++ b/core/src/test/groovy/org/justserve/LocationSpec.groovy @@ -38,4 +38,16 @@ class LocationSpec extends JustServeSpec { [[client, userType], lang] << [[[noAuthLocationClient, "no auth"], [locationClient, "standard"]], threeCharLocales].combinations() } + @SuppressWarnings("GroovyAssignabilityCheck") + @Unroll("Can query LocationClient.getCountries(#lang) with no error as #userType") + def "can query countries with by a given language"(LocationClient client, String userType, String lang){ + when: + client.getCountries(lang).block() + + then: + noExceptionThrown() + + where: + [[client, userType], lang] << [[[noAuthLocationClient, "no auth"], [locationClient, "standard"]], threeCharLocales].combinations() + } } From a4e753962033518f6b72580bbb0b5a8f23b4f23a Mon Sep 17 00:00:00 2001 From: ZeterTheDuck Date: Fri, 22 May 2026 13:48:06 -0600 Subject: [PATCH 04/13] feat: add support for /api/v1/location/{language}/address/{address} endpoint --- core/src/main/resources/schema.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/core/src/main/resources/schema.yml b/core/src/main/resources/schema.yml index 5929d3a..37a1349 100644 --- a/core/src/main/resources/schema.yml +++ b/core/src/main/resources/schema.yml @@ -84,6 +84,36 @@ paths: type: array items: $ref: "#/components/schemas/CountryContext" + /api/v1/locations/{language}/address/{address}: + get: + description: Get a location by an address + operationId: getLocationByAddress + tags: + [ Location ] + parameters: + - name: language + in: path + required: true + schema: + type: string + - name: address + in: path + required: true + schema: + type: string + responses: + '200': + description: OK + content: + text/plain: + schema: + $ref: "#/components/schemas/Location" + application/json: + schema: + $ref: "#/components/schemas/Location" + text/json: + schema: + $ref: "#/components/schemas/Location" /api/v1/locations/{language}/countries: get: description: Get a list of all countries, in a certain language From 88075ab625c829b2cc9c42556d6d5e3deed2acf2 Mon Sep 17 00:00:00 2001 From: ZeterTheDuck Date: Fri, 22 May 2026 13:58:17 -0600 Subject: [PATCH 05/13] fix: add missing properties for Location and LocationWithRadius in schema file --- core/src/main/resources/schema.yml | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/core/src/main/resources/schema.yml b/core/src/main/resources/schema.yml index 37a1349..ffa1b4d 100644 --- a/core/src/main/resources/schema.yml +++ b/core/src/main/resources/schema.yml @@ -1189,8 +1189,32 @@ components: additionalProperties: false Location: type: object - properties: { latitude: { type: number, format: double }, - longitude: { type: number, format: double } } + properties: + mapId: { type: string, nullable: true } + fullDisplayAddress: { type: string, nullable: true } + address: { type: string, nullable: true } + suite: { type: string, nullable: true } + city: { type: string, nullable: true } + civicCityId: { type: string, format: uuid, nullable: true } + neighborhood: { type: string, nullable: true } + county: { type: string, nullable: true } + state: { type: string, nullable: true } + postal: { type: string, nullable: true } + country: { type: string, nullable: true } + countryCode: { type: string, nullable: true } + locationVisibilityId: { type: integer, format: int32 } + missionId: { type: string, nullable: true } + ccId: { type: string, nullable: true } + stakeId: { type: string, nullable: true } + areaId: { type: string, nullable: true } + latitude: { type: number, format: double } + longitude: { type: number, format: double } + maxLatitude: { type: number, format: double } + minLatitude: { type: number, format: double } + maxLongitude: { type: number, format: double } + minLongitude: { type: number, format: double } + geoCodeOverride: { type: boolean } + timezone: { type: string, nullable: true } additionalProperties: false LocationWithRadius: type: object, @@ -1207,6 +1231,7 @@ components: postal: { type: string, nullable: true } country: { type: string, nullable: true } countryCode: { type: string, nullable: true } + locationVisibilityId: { type: integer, format: int32 } missionId: { type: string, nullable: true } ccId: { type: string, nullable: true } stakeId: { type: string, nullable: true } From bf06d4420275fd2828e56f21439a18d5c63d854f Mon Sep 17 00:00:00 2001 From: ZeterTheDuck Date: Fri, 22 May 2026 14:32:12 -0600 Subject: [PATCH 06/13] test: add test for getLocationByAddress method --- .../test/groovy/org/justserve/LocationSpec.groovy | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/core/src/test/groovy/org/justserve/LocationSpec.groovy b/core/src/test/groovy/org/justserve/LocationSpec.groovy index 6c8c01e..4234158 100644 --- a/core/src/test/groovy/org/justserve/LocationSpec.groovy +++ b/core/src/test/groovy/org/justserve/LocationSpec.groovy @@ -50,4 +50,18 @@ class LocationSpec extends JustServeSpec { where: [[client, userType], lang] << [[[noAuthLocationClient, "no auth"], [locationClient, "standard"]], threeCharLocales].combinations() } + + @SuppressWarnings("GroovyAssignabilityCheck, GroovyUnusedAssignment") + @Unroll("Can query LocationClient.getLocationByAddress(#lang, #address) with no error as #userType") + def "can query location by address for a given language"(LocationClient client, String userType, String lang, String address){ + when: + client.getLocationByAddress(lang, address).block() + + then: + noExceptionThrown() + + where: + [[client, userType], lang] << [[[noAuthLocationClient, "no auth"], [locationClient, "standard"]], threeCharLocales].combinations() + address = knownWorkingLocation + } } From 74c4b41b65f20160fa9e0c9c90987f82bd19f10d Mon Sep 17 00:00:00 2001 From: ZeterTheDuck Date: Wed, 27 May 2026 09:39:37 -0600 Subject: [PATCH 07/13] fix: change type of LocationWithRadius to object --- core/src/main/resources/schema.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/resources/schema.yml b/core/src/main/resources/schema.yml index ffa1b4d..82bbe41 100644 --- a/core/src/main/resources/schema.yml +++ b/core/src/main/resources/schema.yml @@ -1217,7 +1217,7 @@ components: timezone: { type: string, nullable: true } additionalProperties: false LocationWithRadius: - type: object, + type: object properties: mapId: { type: string, nullable: true } fullDisplayAddress: { type: string, nullable: true } From 9daf055b0753aa8d8d74e752acd791705090c0eb Mon Sep 17 00:00:00 2001 From: ZeterTheDuck Date: Wed, 27 May 2026 09:43:43 -0600 Subject: [PATCH 08/13] refactor: use known working location directly in getLocationByAddress method, rather than as a data input --- core/src/test/groovy/org/justserve/LocationSpec.groovy | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/core/src/test/groovy/org/justserve/LocationSpec.groovy b/core/src/test/groovy/org/justserve/LocationSpec.groovy index 4234158..24a74a9 100644 --- a/core/src/test/groovy/org/justserve/LocationSpec.groovy +++ b/core/src/test/groovy/org/justserve/LocationSpec.groovy @@ -51,17 +51,16 @@ class LocationSpec extends JustServeSpec { [[client, userType], lang] << [[[noAuthLocationClient, "no auth"], [locationClient, "standard"]], threeCharLocales].combinations() } - @SuppressWarnings("GroovyAssignabilityCheck, GroovyUnusedAssignment") - @Unroll("Can query LocationClient.getLocationByAddress(#lang, #address) with no error as #userType") - def "can query location by address for a given language"(LocationClient client, String userType, String lang, String address){ + @SuppressWarnings("GroovyAssignabilityCheck") + @Unroll("Can query LocationClient.getLocationByAddress(#lang, address) for a known working location with no error as #userType") + def "can query location by address for a given language"(LocationClient client, String userType, String lang){ when: - client.getLocationByAddress(lang, address).block() + client.getLocationByAddress(lang, knownWorkingLocation).block() then: noExceptionThrown() where: [[client, userType], lang] << [[[noAuthLocationClient, "no auth"], [locationClient, "standard"]], threeCharLocales].combinations() - address = knownWorkingLocation } } From 6593f1c110dacf0c416d08e5bb68d57d03ce0ad3 Mon Sep 17 00:00:00 2001 From: ZeterTheDuck Date: Thu, 28 May 2026 13:57:22 -0600 Subject: [PATCH 09/13] refactor: reduce code in schema for LocationWithRadius --- core/src/main/resources/schema.yml | 37 ++++++------------------------ 1 file changed, 7 insertions(+), 30 deletions(-) diff --git a/core/src/main/resources/schema.yml b/core/src/main/resources/schema.yml index 82bbe41..9d3b433 100644 --- a/core/src/main/resources/schema.yml +++ b/core/src/main/resources/schema.yml @@ -1217,36 +1217,13 @@ components: timezone: { type: string, nullable: true } additionalProperties: false LocationWithRadius: - type: object - properties: - mapId: { type: string, nullable: true } - fullDisplayAddress: { type: string, nullable: true } - address: { type: string, nullable: true } - suite: { type: string, nullable: true } - city: { type: string, nullable: true } - civicCityId: { type: string, format: uuid, nullable: true } - neighborhood: { type: string, nullable: true } - county: { type: string, nullable: true } - state: { type: string, nullable: true } - postal: { type: string, nullable: true } - country: { type: string, nullable: true } - countryCode: { type: string, nullable: true } - locationVisibilityId: { type: integer, format: int32 } - missionId: { type: string, nullable: true } - ccId: { type: string, nullable: true } - stakeId: { type: string, nullable: true } - areaId: { type: string, nullable: true } - latitude: { type: number, format: double } - longitude: { type: number, format: double } - maxLatitude: { type: number, format: double } - minLatitude: { type: number, format: double } - maxLongitude: { type: number, format: double } - minLongitude: { type: number, format: double } - geoCodeOverride: { type: boolean } - timezone: { type: string, nullable: true } - radiusType: { $ref: '#/components/schemas/DistanceType' } - countryCode2Char: { type: string, nullable: true } - additionalProperties: false + allOf: + - $ref: '#/components/schemas/Location' + - type: object + properties: + radiusType: { $ref: '#/components/schemas/DistanceType' } + countryCode2Char: { type: string, nullable: true } + additionalProperties: false VolunteerCenterInfo: type: object properties: From 77a0941fbc9b377db54fcd4a448a568f38383196 Mon Sep 17 00:00:00 2001 From: ZeterTheDuck Date: Thu, 28 May 2026 15:33:02 -0600 Subject: [PATCH 10/13] refactor: rename CountryInfo to CountryIdentifiers --- core/src/main/resources/schema.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/src/main/resources/schema.yml b/core/src/main/resources/schema.yml index 9d3b433..8363aec 100644 --- a/core/src/main/resources/schema.yml +++ b/core/src/main/resources/schema.yml @@ -2103,7 +2103,7 @@ components: format: uuid logo: type: string - CountryInfo: + CountryIdentifiers: type: object properties: twoCharCode: @@ -2123,7 +2123,9 @@ components: type: object properties: countryInfo: - $ref: "#/components/schemas/CountryInfo" + allOf: + - $ref: "#/components/schemas/CountryIdentifiers" + description: "Should be named countryIdentifiers to avoid confusion, but maintain JSON property 'countryInfo'" country: type: string nullable: true From d6c55c8b5e71455a4861be713018d0df781bcfb5 Mon Sep 17 00:00:00 2001 From: ZeterTheDuck Date: Thu, 28 May 2026 15:35:40 -0600 Subject: [PATCH 11/13] docs: add descriptions for CountryContext Not all countries use states and counties, so these descriptions clarify their meaning --- core/src/main/resources/schema.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/src/main/resources/schema.yml b/core/src/main/resources/schema.yml index 8363aec..5fb8293 100644 --- a/core/src/main/resources/schema.yml +++ b/core/src/main/resources/schema.yml @@ -2127,12 +2127,15 @@ components: - $ref: "#/components/schemas/CountryIdentifiers" description: "Should be named countryIdentifiers to avoid confusion, but maintain JSON property 'countryInfo'" country: + description: "Name of the country" type: string nullable: true state: + description: "A principal subdivision of a country" type: string nullable: true county: + description: "A smaller subdivision of a state" type: string nullable: true LocaleNames: From e28a8ab615d6c068dd10f276eadc3fb4a2737f0f Mon Sep 17 00:00:00 2001 From: ZeterTheDuck Date: Thu, 28 May 2026 16:16:01 -0600 Subject: [PATCH 12/13] docs: add descriptions Location and LocationRad --- core/src/main/resources/schema.yml | 111 ++++++++++++++++++++++------- 1 file changed, 85 insertions(+), 26 deletions(-) diff --git a/core/src/main/resources/schema.yml b/core/src/main/resources/schema.yml index 5fb8293..4586d59 100644 --- a/core/src/main/resources/schema.yml +++ b/core/src/main/resources/schema.yml @@ -1189,40 +1189,99 @@ components: additionalProperties: false Location: type: object + description: "Representation of a real-world location" properties: - mapId: { type: string, nullable: true } - fullDisplayAddress: { type: string, nullable: true } - address: { type: string, nullable: true } - suite: { type: string, nullable: true } - city: { type: string, nullable: true } - civicCityId: { type: string, format: uuid, nullable: true } - neighborhood: { type: string, nullable: true } - county: { type: string, nullable: true } - state: { type: string, nullable: true } - postal: { type: string, nullable: true } - country: { type: string, nullable: true } - countryCode: { type: string, nullable: true } - locationVisibilityId: { type: integer, format: int32 } - missionId: { type: string, nullable: true } - ccId: { type: string, nullable: true } - stakeId: { type: string, nullable: true } - areaId: { type: string, nullable: true } - latitude: { type: number, format: double } - longitude: { type: number, format: double } - maxLatitude: { type: number, format: double } - minLatitude: { type: number, format: double } - maxLongitude: { type: number, format: double } - minLongitude: { type: number, format: double } - geoCodeOverride: { type: boolean } - timezone: { type: string, nullable: true } + mapId: + type: string + nullable: true + fullDisplayAddress: + description: "Full representation of this location's address" + type: string + nullable: true + address: + description: "Primary street address" + type: string + nullable: true + suite: + description: "Additional address details" + type: string + nullable: true + city: + type: string + nullable: true + civicCityId: + type: string + format: uuid + nullable: true + neighborhood: + type: string + nullable: true + county: + type: string + nullable: true + state: + type: string + nullable: true + postal: + type: string + nullable: true + country: + type: string + nullable: true + countryCode: + description: "ISO 3166-1 standard three-letter country code" + type: string + nullable: true + locationVisibilityId: + type: integer + format: int32 + missionId: + type: string + nullable: true + ccId: + type: string + nullable: true + stakeId: + type: string + nullable: true + areaId: + type: string + nullable: true + latitude: + type: number + format: double + longitude: + type: number + format: double + maxLatitude: + type: number + format: double + minLatitude: + type: number + format: double + maxLongitude: + type: number + format: double + minLongitude: + type: number + format: double + geoCodeOverride: + type: boolean + timezone: + type: string + nullable: true additionalProperties: false LocationWithRadius: + description: "Representation of an area in the vicinity of a real-world location" allOf: - $ref: '#/components/schemas/Location' - type: object properties: radiusType: { $ref: '#/components/schemas/DistanceType' } - countryCode2Char: { type: string, nullable: true } + countryCode2Char: + description: "ISO 3166-1 standard two-letter country code" + type: string + nullable: true additionalProperties: false VolunteerCenterInfo: type: object From b59e5a13cae20ac35c64c39a832387f301d730da Mon Sep 17 00:00:00 2001 From: ZeterTheDuck Date: Fri, 29 May 2026 12:11:41 -0600 Subject: [PATCH 13/13] style: change CountryIdentifiers to CountryBasicIdentifiers --- core/src/main/resources/schema.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/core/src/main/resources/schema.yml b/core/src/main/resources/schema.yml index 4586d59..ab18788 100644 --- a/core/src/main/resources/schema.yml +++ b/core/src/main/resources/schema.yml @@ -2162,8 +2162,9 @@ components: format: uuid logo: type: string - CountryIdentifiers: + CountryBasicIdentifiers: type: object + description: "Basic standardized identifiers for a country." properties: twoCharCode: type: string @@ -2183,8 +2184,8 @@ components: properties: countryInfo: allOf: - - $ref: "#/components/schemas/CountryIdentifiers" - description: "Should be named countryIdentifiers to avoid confusion, but maintain JSON property 'countryInfo'" + - $ref: "#/components/schemas/CountryBasicIdentifiers" + description: "Basic standardized identifiers for a country. Should be named countryBasicIdentifiers to avoid confusion, but maintain JSON property 'countryInfo'" country: description: "Name of the country" type: string