Przejdź do treści

Filtry cen

Filtr simpbire_calculated_booking_price

Od wersji 2.0.2 Simple Bike Rental PRO udostępnia filtr simpbire_calculated_booking_price, który pozwala programistom zmienić końcową cenę rezerwacji bez modyfikowania plików wtyczki.

Filtr jest stosowany po zakończeniu wszystkich wewnętrznych obliczeń wtyczki — obejmujących stawki godzinowe i dzienne, liczbę rowerów, akcesoria oraz rabaty za wynajem wielodniowy — a przed zapisaniem łącznej kwoty w rezerwacji i użyciem jej do płatności Stripe.

Jeśli żaden kod nie korzysta z tego filtra, wtyczka działa dokładnie tak samo jak w poprzednich wersjach.

Składnia

add_filter(
    'simpbire_calculated_booking_price',
    function ( $total, $context ) {

        // Use $context to check dates, rental type, 
        // bicycle rates, quantities, and accessories.

        // Apply your custom pricing logic here.

        return $total;
    },
    10,
    2
);

Parametr $total zawiera pierwotną kwotę łączną obliczoną wewnętrznie przez wtyczkę. Parametr $context umożliwia dostęp do informacji o rezerwacji i skonfigurowanych stawek roweru, takich jak daily_rate i hourly_rate.

Komunikaty informacyjne w podsumowaniu ceny

Gdy filtr zmieni kwotę końcową, wartość widoczna w podsumowaniu może nie odpowiadać sumie poszczególnych pozycji.

Na przykład:

60.00 € — Bicycle price
Total: 45.00 € 

Aby wyjaśnić użytkownikowi, dlaczego kwota łączna się zmieniła, możesz użyć filtra simpbire_calculated_booking_price_notice.

Komunikat pojawia się w podsumowaniu ceny, bezpośrednio przed kwotą końcową.

add_filter(
    'simpbire_calculated_booking_price_notice',
    function ( $notice, $filtered_total, $original_total, $context ) {
        return 'Promotional rate applied.';
    },
    10,
    4
);

Funkcja zwrotna otrzymuje cztery parametry:

Parametry Opis
$notice Bieżący komunikat. Domyślnie jest to pusty ciąg znaków.
$filtered_total Kwota końcowa po zastosowaniu filtra ceny.
$original_total Kwota łączna obliczona wewnętrznie przez wtyczkę przed filtrowaniem.
$context Ta sama tablica informacji, której używa filtr ceny.

Komunikat:

  • jest wyświetlany tylko w dynamicznym podsumowaniu ceny na stronie;
  • nie jest zapisywany w rezerwacji;
  • nie jest wysyłany do Stripe;
  • nie jest dodawany do e-maili ani szczegółów administracyjnych;
  • nie jest wyświetlany, gdy filtr zwraca pusty ciąg znaków.

Komunikat najlepiej wyświetlać tylko wtedy, gdy cena rzeczywiście się zmieniła:

add_filter(
    'simpbire_calculated_booking_price_notice',
    function ( $notice, $filtered_total, $original_total, $context ) {

        if ( abs( $filtered_total - $original_total ) < 0.01 ) {
            return '';
        }

        return 'A custom fee has been applied.';

    },
    10,
    4
);

Parametr $context

Parametr $context zawiera najważniejsze szczegóły rezerwacji. Do najbardziej przydatnych należą:

Klucz Opis
reservation_id ID rezerwacji. Podczas podglądu ceny rezerwacja nie jest jeszcze zapisana, a wartość wynosi 0.
calculation_source Wskazuje, która operacja wtyczki uruchomiła obliczenie ceny. Szczególnie przydatne w zaawansowanych integracjach i debugowaniu (ajax_preview, frontend_save, admin_save, admin_accessories_update).
is_preview Określa, czy obliczenie jest dynamicznym podglądem ceny (true), czy ponownym obliczeniem dla rezerwacji (false). Szczególnie przydatne w zaawansowanych integracjach i debugowaniu.
rental_type Rodzaj wynajmu.
daily_rate Standardowa stawka dzienna skonfigurowana dla wybranego roweru.
hourly_rate Standardowa stawka godzinowa skonfigurowana dla wybranego roweru.
bike_id ID roweru.
start_date Data rozpoczęcia (Y-m-d).
end_date Data zakończenia (Y-m-d).
start_time Godzina rozpoczęcia.
end_time Godzina zakończenia.
quantity Liczba zarezerwowanych rowerów.
original_total Pierwotna kwota łączna obliczona przez wtyczkę przed filtrowaniem.
bike_total_single Końcowa kwota za pojedynczy rower.
bike_total_with_quantity Łączna kwota za rowery, uwzględniająca zarezerwowaną liczbę sztuk. Nie obejmuje akcesoriów.
accessories_total Końcowa łączna kwota za akcesoria.
currency Waluta skonfigurowana we wtyczce.

Uwaga: Zwykle nie trzeba używać calculation_source ani is_preview w regułach cenowych. Filtr powinien dawać spójne wyniki zarówno podczas podglądu ceny, jak i podczas zapisywania rezerwacji.

Wartości rental_type

Wtyczka używa obecnie następujących identyfikatorów:

Wartość Znaczenie
orario Wynajem godzinowy
giornaliero Wynajem jednodniowy
multiday Wynajem wielodniowy

Te wartości pozwalają stosować różne reguły zależnie od rodzaju rezerwacji.

Przykłady

1. Zawsze ustawiaj stałą cenę

add_filter( 
    'simpbire_calculated_booking_price', 
    function ( $total, $context ) { 
        return 10.00; 
    }, 
    10, 
    2 
);

// Fixed-price message
add_filter(
    'simpbire_calculated_booking_price_notice',
    function ( $notice, $filtered_total, $original_total, $context ) {
        if ( abs( $filtered_total - $original_total ) < 0.01 ) {
            return '';
        }
        return 'Custom fixed price applied.';
    },
    10,
    4
);

2. Zastosuj zmianę tylko do wynajmu jednodniowego

add_filter(
    'simpbire_calculated_booking_price',
    function ( $total, $context ) {
        if ( 'giornaliero' !== ( $context['rental_type'] ?? '' ) ) {
            return $total;
        }
        return $total * 0.90;
    },
    10,
    2
);

// Message regarding the discount on daily rentals
add_filter(
    'simpbire_calculated_booking_price_notice',
    function ( $notice, $filtered_total, $original_total, $context ) {
        if (
            'giornaliero' === ( $context['rental_type'] ?? '' )
            && $filtered_total < $original_total
        ) {
            return '10% discount applied to the daily rental.';
        }
        return $notice;
    },
    10,
    4
);

W tym przykładzie rabat 10% jest stosowany tylko do wynajmu jednodniowego.

3. Specjalna cena na konkretną datę

add_filter(
    'simpbire_calculated_booking_price',
    function ( $total, $context ) {
        if (
            'giornaliero' === ( $context['rental_type'] ?? '' )
            && '2026-08-15' === ( $context['start_date'] ?? '' )
        ) {
            // Special fixed price.
            return 45.00;
        }
        return $total;
    },
    10,
    2
);

// Message regarding the special price for a specific date
add_filter(
    'simpbire_calculated_booking_price_notice',
    function ( $notice, $filtered_total, $original_total, $context ) {
        if (
            'giornaliero' === ( $context['rental_type'] ?? '' )
            && '2026-08-15' === ( $context['start_date'] ?? '' )
        ) {
            return 'Special rate applied for August 15th.';
        }
        return $notice;
    },
    10,
    4
);

W tym przykładzie ustawiana jest specjalna cena wynajmu jednodniowego na konkretną datę.

Aby zastosować rabat procentowy, na przykład 20%, zamiast stałej ceny, zastąp return 45.00; przez return $total * 0.80;.

4. Zastosuj rabat do wielu dat

add_filter(
    'simpbire_calculated_booking_price',
    function ( $total, $context ) {
        if ( 'giornaliero' !== ( $context['rental_type'] ?? '' ) ) {
            return $total;
        }
        $discount_dates = array(
            '2026-08-15',
            '2026-09-10',
            '2026-10-05',
        );
        if ( in_array( $context['start_date'] ?? '', $discount_dates, true ) ) {
            return $total * 0.80;
        }
        return $total;
    },
    10,
    2
);

// Message for the discount applied to multiple dates
add_filter(
    'simpbire_calculated_booking_price_notice',
    function ( $notice, $filtered_total, $original_total, $context ) {
        $discount_dates = array(
            '2026-08-15',
            '2026-09-10',
            '2026-10-05',
        );
        if (
            'giornaliero' === ( $context['rental_type'] ?? '' )
            && in_array( $context['start_date'] ?? '', $discount_dates, true )
            && $filtered_total < $original_total
        ) {
            return '20% promotional discount applied.';
        }
        return $notice;
    },
    10,
    4
);

W tym przykładzie rabat jest stosowany do wielu dat w przypadku wynajmu jednodniowego.

5. Różne stawki w dni powszednie i weekendy

add_filter(
    'simpbire_calculated_booking_price',
    function ( $total, $context ) {
        if ( 'giornaliero' !== ( $context['rental_type'] ?? '' ) ) {
            return $total;
        }

        $daily_rate = (float) ( $context['daily_rate'] ?? 0 );

        if ( $daily_rate <= 0 ) {
            return $total;
        }

        $date = DateTimeImmutable::createFromFormat(
            'Y-m-d',
            $context['start_date'] ?? ''
        );

        if ( ! $date ) {
            return $total;
        }

        $quantity = max(
            1,
            (int) ( $context['quantity'] ?? 1 )
        );

        $accessories_total = max(
            0.0,
            (float) ( $context['accessories_total'] ?? 0 )
        );

        $bike_total = $daily_rate * $quantity;
        $is_weekend = (int) $date->format( 'N' ) >= 6;

        return $is_weekend
            ? round( ( $bike_total * 1.10 ) + $accessories_total, 2 )
            : round( $bike_total + $accessories_total, 2 );
    },
    10,
    2
);

add_filter(
    'simpbire_calculated_booking_price_notice',
    function ( $notice, $filtered_total, $original_total, $context ) {
        if ( 'giornaliero' !== ( $context['rental_type'] ?? '' ) ) {
            return $notice;
        }

        $date = DateTimeImmutable::createFromFormat(
            'Y-m-d',
            $context['start_date'] ?? ''
        );

        if ( ! $date || (int) $date->format( 'N' ) < 6 ) {
            return $notice;
        }

        return 'A 10% weekend surcharge has been applied.';
    },
    10,
    4
);

Ten przykład wykorzystuje stawkę dzienną skonfigurowaną dla roweru i stosuje dopłatę 10% tylko w soboty i niedziele. W dni powszednie zachowana jest zwykła stawka dzienna i nie pojawia się żaden komunikat.

W weekendy wyświetlany jest komunikat „A 10% weekend surcharge has been applied.”.

6. Różne stawki na każdy dzień rezerwacji wielodniowej

To bardziej zaawansowany przykład.

Kod odtwarza cenę rezerwacji dzień po dniu, stosując inną stawkę w weekendy.

/**
 * Multi-day pricing:
 * - standard daily rate from Monday to Friday;
 * - 10% surcharge on Saturdays and Sundays.
 */
add_filter(
    'simpbire_calculated_booking_price',
    function ( $original_total, $context ) {

        if ( 'multiday' !== ( $context['rental_type'] ?? '' ) ) {
            return $original_total;
        }

        $daily_rate = isset( $context['daily_rate'] )
            ? (float) $context['daily_rate']
            : 0.0;

        if ( $daily_rate <= 0 ) {
            return $original_total;
        }

        $start_date = $context['start_date'] ?? '';
        $end_date   = $context['end_date'] ?? '';

        if ( ! $start_date || ! $end_date ) {
            return $original_total;
        }

        try {
            $current = new DateTimeImmutable( $start_date );
            $end     = new DateTimeImmutable( $end_date );
        } catch ( Exception $e ) {
            return $original_total;
        }

        if ( $end < $current ) {
            return $original_total;
        }

        $bike_total_single = 0.0;

        while ( $current <= $end ) {
            $day_of_week = (int) $current->format( 'N' );
            $day_rate    = $daily_rate;

            // 6 = Saturday, 7 = Sunday.
            if ( $day_of_week >= 6 ) {
                $day_rate *= 1.10;
            }

            $bike_total_single += $day_rate;
            $current = $current->modify( '+1 day' );
        }

        $quantity = max(
            1,
            (int) ( $context['quantity'] ?? 1 )
        );

        $accessories_total = max(
            0.0,
            (float) ( $context['accessories_total'] ?? 0.0 )
        );

        return round(
            ( $bike_total_single * $quantity ) + $accessories_total,
            2
        );

    },
    10,
    2
);

/**
 * Message displayed in the price summary on the frontend.
 */
add_filter(
    'simpbire_calculated_booking_price_notice',
    function ( $notice, $filtered_total, $original_total, $context ) {

        if ( 'multiday' !== ( $context['rental_type'] ?? '' ) ) {
            return $notice;
        }

        $start_date = $context['start_date'] ?? '';
        $end_date   = $context['end_date'] ?? '';

        if ( ! $start_date || ! $end_date ) {
            return $notice;
        }

        try {
            $current = new DateTimeImmutable( $start_date );
            $end     = new DateTimeImmutable( $end_date );
        } catch ( Exception $e ) {
            return $notice;
        }

        if ( $end < $current ) {
            return $notice;
        }

        while ( $current <= $end ) {
            if ( (int) $current->format( 'N' ) >= 6 ) {
                return 'A 10% surcharge applies to Saturdays and Sundays included in the booking.';
            }

            $current = $current->modify( '+1 day' );
        }

        return $notice;

    },
    10,
    4
);

To podejście pozwala wdrożyć zaawansowaną logikę cenową, na przykład różne ceny na weekendy (soboty i niedziele) w rezerwacjach wielodniowych.

Ten fragment kodu w całości odtwarza cenę wynajmu roweru, dzień po dniu. Zastępuje więc standardowe obliczenia wynajmu wielodniowego we wtyczce i nie stosuje automatycznie żadnego rabatu za wynajem wielodniowy skonfigurowanego w ustawieniach. Kwota za akcesoria pozostaje natomiast taka, jak została wcześniej obliczona przez wtyczkę.

Zalecamy nie używać tego filtra, jeśli rabat za wynajem wielodniowy jest włączony w ogólnych ustawieniach wtyczki.

Dobre praktyki

Filtr ceny

  • Zawsze zwracaj nieujemną wartość liczbową.
  • Zwracaj pierwotną kwotę łączną, gdy własna reguła nie ma zastosowania.
  • Nie modyfikuj bazy danych, nie wysyłaj e-maili ani nie zapisuj wykorzystania kuponów wewnątrz filtra.
  • Wtyczka automatycznie odrzuca wartości nieliczbowe, ujemne, NAN lub nieskończone i używa pierwotnej kwoty łącznej.
  • Pamiętaj, że filtr zmienia kwotę końcową, ale nie rozdziela automatycznie różnicy między kwoty za rower, akcesoria i rabaty widoczne w podsumowaniu.

Filtr komunikatu

  • Używaj krótkich, zrozumiałych komunikatów.
  • Nie wprowadzaj HTML: filtr przyjmuje zwykły tekst.
  • Zachowaj te same warunki co w odpowiadającym mu filtrze ceny.
  • Filtr może być stosowany wielokrotnie, gdy użytkownik zmienia daty, liczbę rowerów lub akcesoria.
  • Nie wykonuj wewnątrz filtra żadnych operacji powodujących trwałe zmiany.
  • Używaj $filtered_total i $original_total, aby sprawdzić, czy cena rzeczywiście się zmieniła.