Skip to content

Multi-Market Implementation: Overview and Roadmap

Summary

This directory contains 8 detailed implementation plans for adding multi-market support to the Bean.Business backend system. The plans are designed to be executed sequentially, with each phase building on the previous ones.

Implementation Phases

Phase 1: Core Entities and Validation

Status: Planning Duration: 3-4 hours Dependencies: None

Creates the foundational entities:

  • Market - Consumer markets with countries and affiliate programs
  • AffiliateProgram - URL transformation templates using Twig
  • BuyingOption - Sparse manual URL overrides

Deliverables:

  • 3 new entities with full validation
  • Database migration for new tables
  • Repository classes
  • Unit tests

Phase 2: Database Migration and Data Migration

Status: Planning Duration: 2-3 hours Dependencies: Phase 1

Adds fields to existing entities and migrates data:

  • Add market and priority to RoasterCrawlConfig
  • Add available to CrawlUrl
  • Migrate CoffeeBean.availableCrawlUrl.available

Deliverables:

  • Schema migration
  • Data migration
  • Reversible migrations (up/down)
  • Transition period support

Phase 3: Services Layer

Status: Planning Duration: 4-5 hours Dependencies: Phase 1, 2

Implements core business logic:

  • AffiliateUrlService - URL transformation with Twig templates
  • BuyingOptionService - URL resolution with priority cascade
  • MarketRepository::findByCountry() - Market lookup

Deliverables:

  • 2 services with comprehensive tests
  • Twig sandbox security
  • Cache integration
  • Priority cascade logic

Phase 4: Cache Invalidation and Repository Updates

Status: Planning Duration: 3-4 hours Dependencies: Phase 1, 2, 3

Extends caching and repository layer:

  • Update CacheInvalidationSubscriber for multi-market entities
  • Add availability methods to CoffeeBeanRepository
  • Update findByRequest() for market-based filtering

Deliverables:

  • Cache tag mappings
  • Repository methods for availability checks
  • N+1 query prevention
  • Integration tests

Phase 5: API Integration

Status: Planning Duration: 3-4 hours Dependencies: Phase 1, 2, 3, 4

Integrates multi-market system into API:

  • Refactor EntityToDtoMapper to use BuyingOptionService
  • Update URL resolution logic
  • Market-based availability calculation

Deliverables:

  • Updated EntityToDtoMapper
  • API endpoints return affiliate URLs
  • Backward compatibility maintained
  • Performance tests

Phase 6: EasyAdmin Controllers

Status: Planning Duration: 4-6 hours Dependencies: Phase 1, 2, 3, 4, 5

Creates admin interfaces:

  • MarketCrudController with shipping region selector
  • AffiliateProgramCrudController with template validation
  • BuyingOptionCrudController for manual overrides
  • Update RoasterCrawlConfigCrudController with market/priority

Deliverables:

  • 4 CRUD controllers
  • Navigation menu updates
  • Form validation
  • Admin user guide

Phase 7: Bean-Centric Buying Options Matrix UI (Optional)

Status: Planning Duration: 4-6 hours Dependencies: Phase 1, 2, 3, 6

Optional enhancement for better UX:

  • Matrix view on bean detail page
  • Inline editing with AJAX
  • Visual comparison of calculated vs manual URLs

Deliverables:

  • Custom EasyAdmin field
  • AJAX endpoints
  • JavaScript for inline editing
  • Enhanced admin UX

Note: This phase is optional. Phase 6 provides all necessary functionality.

Phase 8: Remove CoffeeBean.available Field

Status: Planning Duration: 2-3 hours Dependencies: Phase 1-7 (AFTER full system transition)

Final cleanup after transition:

  • Remove CoffeeBean.available field
  • Drop database column
  • Update documentation

Deliverables:

  • Clean entity definition
  • Database migration
  • Breaking change documentation
  • Verification scripts

CRITICAL: Do not execute until ALL RoasterCrawlConfigs have markets assigned.

Total Timeline

Minimum (Phases 1-6, 8): 21-27 hours With Optional UI (Phases 1-8): 25-33 hours

Prerequisites

Before starting:

  • Symfony 6.x or 7.x
  • Doctrine ORM configured
  • EasyAdmin bundle installed
  • Twig component available
  • Tag-aware cache configured
  • Test environment set up

Architecture Overview

Core Entities

Market (new)
├── countries: ManyToMany<Country>
├── affiliateProgram: ManyToOne<AffiliateProgram>
└── roasterCrawlConfigs: OneToMany<RoasterCrawlConfig>

AffiliateProgram (new)
├── provider: enum (IMPACT, AWIN, PARTNERIZE, AMAZON_ASSOCIATES, CUSTOM)
├── urlPattern: Twig template
└── parameters: JSON

BuyingOption (new) - SPARSE
├── coffeeBean: ManyToOne<CoffeeBean>
├── market: ManyToOne<Market>
└── urlOverride: string (NOT NULL)

RoasterCrawlConfig (updated)
├── market: ManyToOne<Market> (nullable during transition)
└── priority: int (default 50)

CrawlUrl (updated)
└── available: bool (default true)

URL Resolution Priority Cascade

For a visitor from country X viewing bean Y:

  1. Manual Override - Check BuyingOption for (bean Y, market serving X)
  2. RCC Priority - Find CrawlUrls where config.market serves X, sort by priority DESC
  3. Affiliate Transform - Apply market's affiliate program to URL
  4. NULL - Bean not available for this country

Key Design Decisions

  1. RCC → Market is ManyToOne - Each config serves exactly one market
  2. BuyingOption is sparse - Only created for manual overrides
  3. Priority-based selection - Higher priority wins when multiple options exist
  4. Availability per CrawlUrl - Not global per bean
  5. Twig templates for affiliates - Flexible, supports complex patterns
  6. Transition period support - Legacy mode (market = NULL) works alongside new system

Testing Strategy

Each phase includes:

  • Unit tests - Test individual components
  • Integration tests - Test component interactions
  • Manual tests - Verify admin workflows
  • Performance tests - Ensure acceptable query counts

Deployment Strategy

Development

  1. Execute phases sequentially
  2. Test each phase before proceeding
  3. Use feature branches and code reviews

Staging

  1. Deploy code without running migrations
  2. Run verification scripts
  3. Execute migrations
  4. Full smoke testing

Production

  1. Database backup
  2. Blue-green deployment recommended
  3. Run migrations
  4. Monitor closely
  5. Rollback plan ready

Common Pitfalls to Avoid

  1. ManyToMany without by_reference: false - Won't persist correctly
  2. Not checking market.isActive - Inactive markets should be filtered
  3. N+1 queries - Always use joins for related entities
  4. Skipping cache tags - Cache won't invalidate correctly
  5. Removing CoffeeBean.available too early - Wait for full transition

Success Metrics

  • ✅ All RoasterCrawlConfigs have markets assigned
  • ✅ API returns affiliate-transformed URLs
  • ✅ Manual overrides work correctly
  • ✅ Cache hit rate remains high (>90%)
  • ✅ Query count acceptable (<10 per request)
  • ✅ All tests pass
  • ✅ Admin can manage system without developer help
  • ✅ Zero production errors related to multi-market system

Post-Implementation

After all phases complete:

  • Monitor production for 1 week
  • Train admin users
  • Gather feedback
  • Plan future enhancements:
    • Additional affiliate providers
    • Enhanced analytics
    • A/B testing affiliate programs
    • More granular market segmentation

Support

For questions or issues during implementation:

  1. Check source material: multi-market-architecture-plan.md
  2. Review specific phase plan
  3. Search codebase for existing patterns
  4. Run verification scripts

Changelog

  • 2025-11-07: Initial plan structure created
  • Plans based on comprehensive architecture document
  • 8 phases with detailed implementation steps