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

v1.0.0 2026-01-11 22:10 UTC

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 GetProductsWithRatesAction are 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