Consolidate prediction functionality by merging /api/prediction endpoint into /api/stations response. Move prediction logic from PredictionController into StationController, returning prediction data alongside station results. Replace usePrediction composable with unified useStations that returns {stations, meta, prediction}. Remove PredictionRequest, related tests, and unused Vue components (FuelFinderTest, MapTest, RecommendationTest, StationListTest). Add PredictionFull component and UpsellBanner. Extend NationalFuelPredictionService to include weekly_summary (7-day series, yesterday/today averages, cheapest/priciest days) and oil signal from price_predictions table. Update Home.vue to consume prediction from stations response. Add Plan::resolveCadenceForUser helper and configure Cashier to use custom Subscription model.
- Delete unused Livewire Search test and fuel type select Blade component
- Move subscription webhook listener from EventServiceProvider to AppServiceProvider
- Add FUEL_TYPES global config to app layout for client-side use
- Add Billable trait to User model and include email_verified_at in fillable
- Implement monthly/annual cadence toggle with pricing display and smart CTA routing on homepage
- Update VerifyApiKeyMiddlewareTest to use e10 instead of petrol
- Refactor PollFuelPrices to auto-refresh stale stations based on last_seen_at
- Add incremental polling with cached timestamp and effective-start-timestamp param to FuelPriceService
- Normalize amenities/fuel_types from API objects to flat arrays, skip stations missing required fields
- Log response body on API failures in ApiLogger
- Default homepage sort to 'reliable' instead of 'price'
- BrentPriceFetcher owns ingestion (fetchFromEia / fetchFromFred, each throws on failure)
- BrentPricePredictor owns prediction and marks latest brent_prices row as generated
- oil:fetch command tries EIA, falls back to FRED, fails loudly if both fail
- oil:predict command prompts if latest price already has a prediction; --force bypasses
- add prediction_generated_at column to brent_prices
- delete OilPriceService (replaced by the two focused services)
OilPriceService no longer inlines per-provider fetch/transform/error logic.
EIA and FRED are now their own classes with a common shape; the service
just iterates and upserts the first successful result.
Extends NearbyStationsRequest to accept `postcode` (full or outcode) as an alternative to lat/lng. PostcodeService resolves it via postcodes.io and falls through to coordinates. Also adds SearchResource to the Filament admin panel for viewing logged search activity with fuel type filter and price/distance stats columns. Includes SQLite GREATEST/LEAST function polyfills in AppServiceProvider for test compatibility.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
User management resource with editable is_admin field, postcode support,
admin filter, and inline delete action. Includes list and edit pages.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New method uses web_search_20260209 server-side tool so Claude fetches
48h of oil/geopolitical news autonomously before predicting direction
- Prompt uses raw prices only — no pre-computed EWMA indicators
- pause_turn loop handles server-side search continuation (up to 5 iters)
- generatePrediction() now tries context method first, falls back to
generateLlmPrediction(), then EWMA
- Default model updated to claude-sonnet-4-6
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add PostcodeService to resolve UK postcodes, outcodes, and place names to coordinates via postcodes.io API with 30-day caching
- Add LocationResult value object for resolved location data
- Add per-fuel-type price validation (80p-1050p range) to FuelPriceService with warning logs for out-of-range prices
- Change price_pence column from unsignedSmallInteger to unsignedMediumInteger in station_prices tables
- Add CHECK constraints (5000-50000 range) on price_pence columns as database-level guard
- Improve error handling in PollFuelPrices command with file/line/trace output
- Add tests for PostcodeService covering full postcodes, outcodes, place names, caching, and error handling
- Add test for price validation range checks
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Also extend Pest TestCase to Unit tests and guard MySQL-only migration
DDL (composite PK + PARTITION BY) behind a driver check so in-memory
SQLite tests can run migrations cleanly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>