Feature Implementation Plan: Hierarchical Location Filter (Updated)¶
📋 Todo Checklist¶
- [ ] Create a new
LocationControllerto house all location-related endpoints. - [ ] Move the existing
/api/countriesendpoint to/api/locations/countries. - [ ] Move the existing
/api/regionsendpoint to/api/locations/regions. - [ ] Add pagination and
countryIdfiltering to the/api/locations/regionsendpoint. - [ ] Implement the new
/api/locations/countries-by-continentendpoint. - [ ] Update
CoffeeBeanControllerto use the newlocationIdsfilter metadata. - [ ] Update
CoffeeBeanRepositoryto filter by continent and country fromlocationIds. - [ ] Write unit and integration tests for all changes.
- [ ] Final Review and Testing
🔍 Analysis & Investigation¶
Codebase Structure¶
- Controllers: API logic is in
src/Controller/Api/.CountryController.phpandRegionController.phpwill be refactored into a newLocationController.php. - Repositories:
CountryRepository.phpandRegionRepository.phpcontain the data access logic.CoffeeBeanRepository.phphandles the core filtering for beans. - Entities:
Country.phpandRegion.phpare the key entities. TheCountryentity already containscontinentCodeandcontinentName.
Current Architecture¶
The application uses a standard Symfony setup. The plan is to consolidate location-related endpoints into a single LocationController to improve organization. The new endpoints will follow existing patterns of using repositories for data and OpenAPI annotations for documentation.
Dependencies & Integration Points¶
- NelmioApiDocBundle: Will be used to document the new and moved endpoints.
- Doctrine: The Doctrine Query Builder will be used to implement the new repository methods and filtering logic.
- Symfony Paginator: Will be used to add pagination to the regions endpoint.
Considerations & Challenges¶
- Route Refactoring: Moving existing endpoints requires careful management of routes to avoid breaking the frontend. Redirects or clear communication with the frontend team will be necessary.
- Repository Logic: The query to fetch countries with coffee beans needs to be efficient. It will involve joins across three tables (
Country,Region,CoffeeBean) and a condition to ensure beans exist. - Pagination: Adding pagination to the
/api/locations/regionsendpoint is a new requirement for that endpoint and must be implemented correctly.
📝 Implementation Plan¶
Prerequisites¶
- No new external dependencies are required.
Step-by-Step Implementation¶
-
Create
LocationControllerand Refactor Routes- Files to create:
src/Controller/Api/LocationController.php - Files to modify:
config/routes.php(or relevant route configuration) - Files to delete:
src/Controller/Api/CountryController.php,src/Controller/Api/RegionController.php - Changes needed:
- Create a new
LocationController. - Move the logic from
CountryControllerandRegionControllerintoLocationController. - Update the
#[Route]annotations to reflect the new paths:/api/locations/countriesand/api/locations/regions. - Remove the old controller files.
- Create a new
- Files to create:
-
Update the Regions Endpoint
- Files to modify:
src/Controller/Api/LocationController.php,src/Repository/RegionRepository.php - Changes needed:
- In
LocationController, update thegetRegionsmethod to handle pagination parameters (page,limit). - In
RegionRepository, modify thefindByFiltersmethod to use Doctrine'sPaginatorto return a paginated result set. - The
countryIdfilter is already implemented, so no changes are needed there, but ensure it works with pagination.
- In
- Files to modify:
-
Implement
countries-by-continentEndpoint- Files to modify:
src/Controller/Api/LocationController.php,src/Repository/CountryRepository.php - Changes needed:
- In
CountryRepository, create a new methodfindCountriesWithCoffeeBeans(). This method will:- Join
CountrywithRegion(c.regions). - Join
RegionwithCoffeeBean(r.coffeeBeans). - Use
GROUP BY c.idandHAVING COUNT(cb.id) > 0to ensure only countries with at least one coffee bean are returned. - The method should return an array of
Countryentities.
- Join
- In
LocationController, add a new methodgetCountriesByContinentwith the route/api/locations/countries-by-continent. - This method will call
countryRepository->findCountriesWithCoffeeBeans(). - It will then process the result to build the hierarchical structure, grouping countries by
continentCode.
- In
- Files to modify:
-
Update Coffee Bean Filtering
- Files to modify:
src/Controller/Api/CoffeeBeanController.php,src/Repository/CoffeeBeanRepository.php - Changes needed:
- In
CoffeeBeanController, update the#[OA\Parameter]forlocationIds[]to change thelabelandendpointas specified. - In
CoffeeBeanRepository, update thecreateBaseFilterQueryBuildermethod. The logic forlocationIdsshould now only handle continent codes and country IDs. It should create anORcondition forc.continentCode IN (:continentCodes)andc.id IN (:countryIds).
- In
- Files to modify:
Testing Strategy¶
- Unit Tests:
- Write a unit test for the new
CountryRepository::findCountriesWithCoffeeBeans()method. - Write a unit test for the
LocationControllerto verify the response of thegetCountriesByContinentendpoint. - Update tests for the moved country and region endpoints to reflect pagination and new routes.
- Write a unit test for the new
- Integration Tests:
- Write an integration test for
/api/locations/countries-by-continent. - Update integration tests for
/api/countriesand/api/regionsto point to the new/api/locations/*routes. - Update the integration test for
/api/coffee-beansto use the updatedlocationIdsfilter and verify the results.
- Write an integration test for
🎯 Success Criteria¶
- The
/api/countriesand/api/regionsendpoints are successfully moved to/api/locations/countriesand/api/locations/regions. - The
/api/locations/regionsendpoint is paginated. - The
/api/locations/countries-by-continentendpoint returns the correct hierarchical data, filtered as required. - The
locationIdsfilter on/api/coffee-beansworks with continent codes and country IDs. - The frontend is able to consume the new and updated endpoints.
- All changes are covered by tests and there are no regressions.