skylence / dayrates
Fuel day rates management package for Laravel - crawl official Belgian fuel prices, exchange rates, and manage fuel product pricing
Installs: 0
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/skylence/dayrates
Requires
- php: ^8.1
- guzzlehttp/guzzle: ^7.0
- illuminate/console: ^10.0|^11.0|^12.0
- illuminate/database: ^10.0|^11.0|^12.0
- illuminate/support: ^10.0|^11.0|^12.0
- symfony/dom-crawler: ^6.0|^7.0
Requires (Dev)
- orchestra/testbench: ^8.0|^9.0|^10.0
- pestphp/pest: ^2.0|^3.0
This package is auto-updated.
Last update: 2026-01-14 01:12:44 UTC
README
A Laravel package for managing fuel day rates, including crawling official Belgian fuel prices and ECB exchange rates.
Features
- Action-driven architecture with single-purpose action classes
- Crawl official Belgian fuel prices from the government statistics API
- Import EUR/USD exchange rates from the European Central Bank
- Manage day rates for various fuel products (Benzine, Diesel, Gasoil variants)
- Convert between EUR/m³ and USD/ton using exchange rates
- Track official prices with volume-based pricing (< 2000L and >= 2000L)
- Real-time WebSocket broadcasting of price updates (Laravel Reverb compatible)
- REST API with API key authentication
Installation
composer require skylence/dayrates
Publish Configuration
php artisan vendor:publish --tag=dayrates-config
Publish Migrations
php artisan vendor:publish --tag=dayrates-migrations php artisan migrate
Configuration
The package configuration is published to config/dayrates.php. You can customize:
- API endpoints for Belgian statistics and ECB exchange rates
- Crawler retry settings (retries, delay, timeout)
- Cache settings (enabled, TTL)
- Product codes and names
- Density conversion factor
- Database table names
- Broadcasting settings
Usage
Console Commands
Crawl Belgian fuel prices:
php artisan dayrates:crawl
# Force crawl even if already crawled today
php artisan dayrates:crawl --force
Import ECB exchange rate:
php artisan dayrates:import-exchange-rate
# Force import even if already imported today
php artisan dayrates:import-exchange-rate --force
Facade
use Skylence\Dayrates\Facades\Dayrates; // Get all products with rates for a specific date $products = Dayrates::getProductsWithRates('2024-01-15'); // Get day rate for a specific product $rate = Dayrates::getDayRate('GASOIL10', '2024-01-15', 'EUR'); // Get official price $official = Dayrates::getOfficialPrice('DIESEL', '2024-01-15'); // Get exchange rate $exchange = Dayrates::getExchangeRate('2024-01-15');
Actions (Recommended)
The package uses the Action-driven pattern with single-purpose action classes:
use Skylence\Dayrates\Actions\CrawlDayratesAction; use Skylence\Dayrates\Actions\ImportExchangeRateAction; use Skylence\Dayrates\Actions\GetProductsWithRatesAction; use Skylence\Dayrates\Actions\GetDayRateAction; use Skylence\Dayrates\Actions\GetOfficialPriceAction; use Skylence\Dayrates\Actions\GetExchangeRateAction; // Crawl Belgian fuel prices $prices = app(CrawlDayratesAction::class)->execute(); // Import exchange rate $rate = app(ImportExchangeRateAction::class)->execute(); // Get products with rates $products = app(GetProductsWithRatesAction::class)->execute('2024-01-15'); // Get specific day rate $dayRate = app(GetDayRateAction::class)->execute('GASOIL10', '2024-01-15', 'EUR'); // Get official price $official = app(GetOfficialPriceAction::class)->execute('DIESEL', '2024-01-15'); // Get exchange rate $exchange = app(GetExchangeRateAction::class)->execute('2024-01-15');
Available Actions
| Action | Description |
|---|---|
CrawlDayratesAction |
Crawls Belgian govt API for fuel prices |
ImportExchangeRateAction |
Imports EUR/USD rate from ECB |
GetProductsWithRatesAction |
Gets all products with rates for a date |
GetDayRateAction |
Gets day rate for a product |
GetOfficialPriceAction |
Gets official price for a product |
GetExchangeRateAction |
Gets exchange rate for a date |
Service (Alternative)
use Skylence\Dayrates\Services\DayratesService; // The service delegates to actions internally $service = app(DayratesService::class); $products = $service->getProductsWithRates('2024-01-15');
Models
use Skylence\Dayrates\Models\DayRate; use Skylence\Dayrates\Models\ExchangeRate; use Skylence\Dayrates\Models\Product; use Skylence\Dayrates\Models\OfficialPrice; // Query day rates $rate = DayRate::where('product_code', 'GASOIL10') ->where('currency', 'EUR') ->latest('valid_from') ->first(); // Access calculated attributes echo $rate->eur_m3_rate; // EUR per m³ echo $rate->usd_ton_rate; // USD per ton // Get latest exchange rate $exchange = ExchangeRate::getLatest('EUR', 'USD'); // Get exchange rate for a specific date $exchange = ExchangeRate::forDate('2024-01-15');
REST API Endpoints
The package provides REST API endpoints for accessing dayrates data.
Endpoints
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /api/dayrates/latest |
Get latest rates (today) | - |
| GET | /api/dayrates/{date} |
Get rates for specific date | - |
| POST | /api/dayrates/crawl |
Trigger price crawl | API Key |
| POST | /api/dayrates/import-exchange-rate |
Trigger exchange rate import | API Key |
Authentication
Protected endpoints require an API key. Set DAYRATES_API_KEY in your .env and send it via:
# Header (recommended) curl -X POST https://your-app.com/api/dayrates/crawl \ -H "X-API-Key: your-api-key" # Or Bearer token curl -X POST https://your-app.com/api/dayrates/crawl \ -H "Authorization: Bearer your-api-key" # Or query parameter curl -X POST "https://your-app.com/api/dayrates/crawl?api_key=your-api-key"
Example Response
GET /api/dayrates/2024-01-15 [ { "name": "Benzine 95 Ron E10", "code": "BENZINE", "rate": { "valid_from": "2024-01-14", "product_code": "BENZINE", "rate": "1523.50", "currency": "EUR", "unit": "m3" }, "official": { "valid_from": "2024-01-15", "product_code": "BENZINE", "rate_plus_2000": "1.4532", "rate_min_2000": "1.4532" }, "exchangerate": { "exchange_rate_date": "2024-01-14", "from_currency": "EUR", "to_currency": "USD", "rate": "1.08750000" } } ]
Real-time WebSocket Updates
The package broadcasts price updates via WebSockets when prices are crawled (typically once daily). This is useful for updating your UI when new data is imported.
Note: The Belgian government updates official fuel prices once per day. The WebSocket events notify connected clients when new data has been imported into your database.
Works seamlessly with Laravel Reverb or any other Laravel broadcasting driver.
Events
| Event | Channel | Description |
|---|---|---|
dayrates.updated |
dayrates |
All prices updated (consolidated) |
exchange-rate.updated |
dayrates |
Exchange rate updated |
official-price.updated |
dayrates |
Individual official price updated |
Frontend (JavaScript/Echo)
// Using Laravel Echo with Reverb Echo.channel('dayrates') .listen('.dayrates.updated', (e) => { console.log('All rates updated:', e.rates); console.log('Date:', e.date); console.log('Updated at:', e.updated_at); }) .listen('.exchange-rate.updated', (e) => { console.log('Exchange rate:', e.rate); console.log('EUR/USD for:', e.date); }) .listen('.official-price.updated', (e) => { console.log('Product:', e.product_code); console.log('Price < 2000L:', e.rate_min_2000); console.log('Price >= 2000L:', e.rate_plus_2000); });
Configuration
# Enable/disable broadcasting (default: true) DAYRATES_BROADCASTING_ENABLED=true # Custom channel name (default: dayrates) DAYRATES_BROADCASTING_CHANNEL=dayrates
Caching
The package caches crawled data to prevent duplicate API calls and reduce database queries.
# Enable/disable caching (default: true) DAYRATES_CACHE_ENABLED=true # Cache TTL in seconds for query results (default: 3600 = 1 hour) DAYRATES_CACHE_TTL=3600
Cached items:
- Crawled prices are cached for 24 hours (prevents re-crawling same day)
- Exchange rates are cached for 24 hours (prevents re-importing same day)
- Query results from
GetProductsWithRatesActionare cached per date
Use --force flag on commands to bypass cache:
php artisan dayrates:crawl --force php artisan dayrates:import-exchange-rate --force
Livewire Integration
use Livewire\Attributes\On; use Livewire\Component; class FuelPriceDisplay extends Component { public array $rates = []; #[On('echo:dayrates,.dayrates.updated')] public function onDayratesUpdated(array $data): void { $this->rates = $data['rates']; } public function render() { return view('livewire.fuel-price-display'); } }
Scheduling
Add these commands to your scheduler for automated imports:
// app/Console/Kernel.php or routes/console.php use Illuminate\Support\Facades\Schedule; Schedule::command('dayrates:crawl')->dailyAt('08:00'); Schedule::command('dayrates:import-exchange-rate')->dailyAt('07:00');
Product Codes
| Code | Description |
|---|---|
| BENZINE | Benzine 95 Ron E10 |
| DIESEL | Diesel B7 |
| GASOIL10 | Gasolie Diesel Verwarming |
| GASOIL10IC | Gasolie Diesel Industrie & Commercieel |
| GASOIL10VW | Gasolie Diesel Verwarming VW |
| GASOIL10GENT | Gasolie Diesel Verwarming Gent |
| GASOIL10NL | Gasolie Diesel Verwarming NL |
| GASOIL50 | Gasolie verwarming 50s |
License
MIT License