Feature Implementation Plan: Roaster Shipping API¶
📋 Todo Checklist¶
- [ ] Create
RoasterShippingRuleentity and migration - [ ] Update
RoasterandShippingRegionentities - [ ] Implement
ShipsToDTOs - [ ] Update
EntityToDtoMapperto process shipping rules - [ ] Update
RoasterDTOto includeshipsTodata - [ ] Update
RoasterRepositoryto fetch new relationships - [ ] Final Review and Testing
🔍 Analysis & Investigation¶
Codebase Structure¶
- Entities: Located in
src/Entity/. Key entities areRoaster,ShippingRegion, andCountry. A new entity,RoasterShippingRule, will be created. - Controllers: API controllers are in
src/Controller/Api/.RoasterController.phpis the relevant controller. - Repositories: Located in
src/Repository/.RoasterRepository.phpfetches roaster data. - DTOs: API data transfer objects are in
src/DTO/Api/.RoasterDTO.phpwill be modified. - Mappers: The
EntityToDtoMapperservice insrc/Service/Api/Mapper/is responsible for converting entities to DTOs.
Current Architecture¶
The API uses a standard Symfony setup with controllers, repositories, and entities. For the API layer, it uses DTOs to decouple the API schema from the database schema. An EntityToDtoMapper service handles the transformation from Doctrine entities to DTOs. Caching is used at the repository level for performance.
Dependencies & Integration Points¶
- Doctrine: For database interactions and schema management.
- Symfony Serializer: For converting DTOs to JSON.
- NelmioApiDocBundle: For API documentation.
Considerations & Challenges¶
- Missing Relationship: The core challenge is that there is no existing relationship between
RoasterandShippingRegion. This plan addresses this by creating a new join entity,RoasterShippingRule. - Exclusion Logic: The requirement to handle country exclusions within a shipping region adds complexity. The
RoasterShippingRuleentity is designed to handle this by having aManyToManyrelationship with excluded countries. - API Caching: The existing API has caching at the repository layer. Any changes to the data fetching must be compatible with the caching strategy. The cache for roasters will need to be invalidated after the changes are deployed.
📝 Implementation Plan¶
Prerequisites¶
- Ensure you have a local development environment set up with Symfony and Doctrine.
- Have the Doctrine Migrations Bundle installed and configured.
Step-by-Step Implementation¶
- Step 1: Create the
RoasterShippingRuleEntity - File to create:
src/Entity/RoasterShippingRule.php -
Changes needed:
- Create a new Doctrine entity
RoasterShippingRule. - Add the following properties:
id(UUID)roaster(ManyToOnerelationship toRoaster)shippingRegion(ManyToOnerelationship toShippingRegion)excludedCountries(ManyToManyrelationship toCountry)createdAtandupdatedAttimestamps.
- Create a new Doctrine entity
-
Step 2: Update Existing Entities
- Files to modify:
src/Entity/Roaster.php,src/Entity/ShippingRegion.php -
Changes needed:
- In
Roaster.php, add aOneToManyrelationship toRoasterShippingRule: - In
ShippingRegion.php, add aOneToManyrelationship toRoasterShippingRule:
- In
-
Step 3: Create Doctrine Migration
- Action: Run
php bin/console make:migrationto generate a new migration file. -
Verify: Inspect the generated migration in
migrations/to ensure it correctly creates theroaster_shipping_ruletable and the necessary foreign key constraints. -
Step 4: Create
ShipsToDTOs - File to create:
src/DTO/Api/ShipsToDTO.php -
Changes needed:
- Create a new readonly DTO
ShipsToDTO. - Add the following properties:
type(string, either 'region' or 'country_list')name(string, the name of the region or "Custom Country List")countries(optional array ofCountryDTOs)
- Create a new readonly DTO
-
Step 5: Update
RoasterDTO - File to modify:
src/DTO/Api/RoasterDTO.php -
Changes needed:
- Add a new property to the constructor:
- This will hold an array of
ShipsToDTOobjects.
-
Step 6: Update
EntityToDtoMapper - File to modify:
src/Service/Api/Mapper/EntityToDtoMapper.php -
Changes needed:
- In the
mapRoasterToDtomethod, add logic to process theshippingRulesof theRoasterentity. - For each
RoasterShippingRule: - If
excludedCountriesis empty, create aShipsToDTOwithtype= 'region',name= the region's name, andcountries= null. - If
excludedCountriesis not empty, create aShipsToDTOwithtype= 'country_list',name= the region's name, andcountries= an array ofCountryDTOs for the countries in the region minus the excluded countries. - Assign the resulting array of
ShipsToDTOs to theshipsToproperty of theRoasterDTO.
- In the
-
Step 7: Update
RoasterRepository - File to modify:
src/Repository/RoasterRepository.php - Changes needed:
- In
executeRoasterQueryandfindDtoById, update the Doctrine queries to join the newshippingRulesrelationship and its sub-relationships. - Example join:
- In
Testing Strategy¶
- Unit Tests:
- Create a unit test for the
EntityToDtoMapperto verify that theshippingRulesare correctly transformed into theshipsToarray in various scenarios (no exclusions, with exclusions). - Integration Tests:
- Create integration tests for the
/api/roastersand/api/roasters/{id}endpoints. - The tests should:
- Create test data with roasters, shipping regions, and shipping rules.
- Assert that the
shipsTofield is present in the JSON response and has the correct structure and data.
🎯 Success Criteria¶
- The
/api/roastersand/api/roasters/{id}API endpoints include ashipsTofield in the response for each roaster. - If a roaster ships to a region with no exclusions, the
shipsToarray contains an object withtype: 'region'and the region's name. - If a roaster ships to a region with exclusions, the
shipsToarray contains an object withtype: 'country_list', the region's name, and a list of the included countries. - The API documentation is updated to reflect the new
shipsTofield.