# Postal Code Geocoding Cache ## Overview The postal code geocoding cache system stores geographic coordinates for Canadian postal codes, enabling faster representative lookups and reducing external API calls. It integrates with the multi-provider geocoding service to provide reliable centroid calculations for postal code-based geographic queries. **Key Capabilities:** - **Postal code caching**: Store lat/lng centroids for postal codes - **Geocoding integration**: Automatic geocoding via multi-provider service - **Cache hit optimization**: Reduce external API calls - **Administrative data**: City and province extraction - **Representative lookup**: Fast postal code → representative mapping **Use Cases:** - Campaign postal code lookups - Geographic representative mapping - Postal code validation - Centroid-based spatial queries ## Architecture ```mermaid graph TD A[Campaign Service] -->|Lookup Postal Code| B[Postal Code Service] B -->|Check Cache| C{Cache Hit?} C -->|Yes| D[Return Cached Centroid] C -->|No| E[Geocoding Service] E -->|Geocode| F[Multi-Provider Geocoding] F -->|Parse Result| G[Extract Centroid] G -->|Save| H[(PostalCodeCache Model)] H -->|Return| D I[Admin] -->|View Stats| J[RepresentativesPage] J -->|Display| K[Cache Statistics] style H fill:#e1f5ff style F fill:#fff4e1 ``` ## Database Models ### PostalCodeCache Model See [PostalCodeCache Model Documentation](../../database/models/postal-code-cache.md) for full schema. **Key Fields:** | Field | Type | Description | |-------|------|-------------| | `postalCode` | String | Normalized postal code (primary key) | | `latitude` | Float | Centroid latitude | | `longitude` | Float | Centroid longitude | | `city` | String? | City name | | `province` | String? | Province abbreviation | **Indexes:** - `postalCode` — Primary key, unique constraint **Related Models:** - [Representative](../../database/models/representative.md) — Uses postal codes for caching - [Location](../../database/models/location.md) — Uses postal codes for geocoding ## API Endpoints ### Admin Endpoints | Method | Endpoint | Auth | Description | |--------|----------|------|-------------| | GET | `/api/postal-codes/stats` | SUPER_ADMIN, INFLUENCE_ADMIN | Get cache statistics | | POST | `/api/postal-codes/lookup` | SUPER_ADMIN, INFLUENCE_ADMIN | Manual postal code lookup | ### Public Endpoints Postal code lookups are performed automatically via representative lookup (no direct public access). ## Configuration ### Environment Variables | Variable | Type | Default | Description | |----------|------|---------|-------------| | `GEOCODING_PROVIDER` | string | nominatim | Default geocoding provider | | `GEOCODING_FALLBACK_PROVIDERS` | string | - | Comma-separated fallback providers | ## Admin Workflow ### 1. View Cache Statistics **Steps:** 1. Navigate to **Influence > Representatives** 2. View postal code cache statistics 3. Monitor cache hit rate ## Public Workflow Postal code caching is automatic and transparent to public users. ## Code Examples ### Backend: Postal Code Caching ```typescript // api/src/modules/influence/postal-codes/postal-codes.service.ts export class PostalCodeService { async getOrCreateCache(postalCode: string): Promise { const normalized = postalCode.toUpperCase().replace(/\s/g, ''); // Check cache const cached = await prisma.postalCodeCache.findUnique({ where: { postalCode: normalized } }); if (cached) { return cached; } // Geocode postal code const result = await geocodingService.geocode({ query: postalCode, country: 'CA' }); if (!result) { throw new Error('Failed to geocode postal code'); } // Create cache entry return prisma.postalCodeCache.create({ data: { postalCode: normalized, latitude: result.latitude, longitude: result.longitude, city: result.city, province: result.province } }); } } ``` ## Related Documentation - [Representatives Module](../../backend/modules/representatives.md) - [Geocoding Service](../map/geocoding.md)