@RDVAdmin ist das Problem noch aktuell? Ich stoße derzeit auf das selbe Problem. Bei mir geht es allerdings um den Preis für das Frühstück, welches in den Zimmerpreisen inbegriffen ist, sich aber bei Buchung um jede weitere Person erhöhen muss.
Ich werde mich dazu heute Abend an den Quellcode wagen und versuchen diesen für mein Problem und meine Anforderungen anzupassen.
Hat jemand aktuell noch dieses Problem? Dann könnten wir eventuell zusammenarbeiten.
**Strategie: Staffelpreise nach Personenanzahl
Datenbank-Erweiterung
Zuerst müssen wir eine neue Tabelle für die Belegungspreise erstellen**:
-- Neue Tabelle für Staffelpreise nach Personenanzahl
CREATE TABLE `ps_hotel_room_occupancy_pricing` (
`id_occupancy_pricing` int(11) NOT NULL AUTO_INCREMENT,
`id_product` int(11) NOT NULL,
`id_hotel` int(11) NOT NULL,
`occupancy` int(11) NOT NULL, -- Anzahl Personen (1, 2, 3, 4, etc.)
`price` decimal(20,6) NOT NULL,
`active` tinyint(1) NOT NULL DEFAULT 1,
`date_add` datetime NOT NULL,
`date_upd` datetime NOT NULL,
PRIMARY KEY (`id_occupancy_pricing`),
KEY `idx_product_hotel` (`id_product`, `id_hotel`),
KEY `idx_occupancy` (`occupancy`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- Beispieldaten für ein Zimmer
-- Zimmer ID 1, Hotel ID 1
INSERT INTO `ps_hotel_room_occupancy_pricing`
(`id_product`, `id_hotel`, `occupancy`, `price`, `date_add`, `date_upd`) VALUES
(1, 1, 1, 80.00, NOW(), NOW()), -- 1 Person: 80€
(1, 1, 2, 100.00, NOW(), NOW()), -- 2 Personen: 100€ (Grundpreis)
(1, 1, 3, 125.00, NOW(), NOW()), -- 3 Personen: 125€ (+25€)
(1, 1, 4, 150.00, NOW(), NOW()); -- 4 Personen: 150€ (+50€)
2. Neue Klasse für Belegungspreise
Erstelle eine neue Datei: /modules/hotelreservationsystem/classes/HotelRoomOccupancyPricing.php
<?php
/**
* Klasse für Zimmerpreise basierend auf Belegung
*/
class HotelRoomOccupancyPricing extends ObjectModel
{
public $id_occupancy_pricing;
public $id_product;
public $id_hotel;
public $occupancy;
public $price;
public $active;
public $date_add;
public $date_upd;
public static $definition = array(
'table' => 'hotel_room_occupancy_pricing',
'primary' => 'id_occupancy_pricing',
'fields' => array(
'id_product' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true),
'id_hotel' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true),
'occupancy' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'required' => true),
'price' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true),
'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'),
'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'),
'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'),
),
);
/**
* Holt den Preis für eine bestimmte Belegung
*
* @param int $idProduct Zimmer-ID
* @param int $idHotel Hotel-ID
* @param int $occupancy Anzahl Personen
* @return float|false Preis oder false
*/
public static function getPriceByOccupancy($idProduct, $idHotel, $occupancy)
{
$sql = 'SELECT `price` FROM `'._DB_PREFIX_.'hotel_room_occupancy_pricing`
WHERE `id_product` = '.(int)$idProduct.'
AND `id_hotel` = '.(int)$idHotel.'
AND `occupancy` = '.(int)$occupancy.'
AND `active` = 1';
$result = Db::getInstance()->getValue($sql);
// Falls keine spezifische Belegung gefunden wird, nimm Standardpreis (2 Personen)
if (!$result && $occupancy != 2) {
return self::getPriceByOccupancy($idProduct, $idHotel, 2);
}
return $result ? (float)$result : false;
}
/**
* Setzt Preise für alle Belegungsstufen eines Zimmers
*
* @param int $idProduct Zimmer-ID
* @param int $idHotel Hotel-ID
* @param array $prices Array mit Belegung => Preis
* @return bool
*/
public static function setOccupancyPrices($idProduct, $idHotel, $prices)
{
// Alte Preise löschen
Db::getInstance()->delete('hotel_room_occupancy_pricing',
'`id_product` = '.(int)$idProduct.' AND `id_hotel` = '.(int)$idHotel);
$success = true;
foreach ($prices as $occupancy => $price) {
$occupancyPricing = new self();
$occupancyPricing->id_product = (int)$idProduct;
$occupancyPricing->id_hotel = (int)$idHotel;
$occupancyPricing->occupancy = (int)$occupancy;
$occupancyPricing->price = (float)$price;
$occupancyPricing->active = 1;
if (!$occupancyPricing->add()) {
$success = false;
}
}
return $success;
}
/**
* Holt alle Belegungspreise für ein Zimmer
*
* @param int $idProduct Zimmer-ID
* @param int $idHotel Hotel-ID
* @return array
*/
public static function getOccupancyPrices($idProduct, $idHotel)
{
$sql = 'SELECT `occupancy`, `price` FROM `'._DB_PREFIX_.'hotel_room_occupancy_pricing`
WHERE `id_product` = '.(int)$idProduct.'
AND `id_hotel` = '.(int)$idHotel.'
AND `active` = 1
ORDER BY `occupancy` ASC';
$results = Db::getInstance()->executeS($sql);
$prices = array();
if ($results) {
foreach ($results as $row) {
$prices[$row['occupancy']] = (float)$row['price'];
}
}
return $prices;
}
}
3. Zimmerpreis-Berechnung anpassen
Du musst die bestehende Preisberechnung in der Datei anpassen, die die Zimmerpreise berechnet. Das ist wahrscheinlich in /modules/hotelreservationsystem/classes/HotelCartBookingData.php oder ähnlich:
/**
* Erweiterte Methode zur Preisberechnung mit Belegungspreisen
*/
public function getRoomPriceByOccupancy($idProduct, $idHotel, $adults, $children = 0, $dateFrom, $dateTo)
{
// Gesamtbelegung berechnen
$totalOccupancy = (int)$adults + (int)$children;
// Versuche Belegungspreis zu finden
$occupancyPrice = HotelRoomOccupancyPricing::getPriceByOccupancy($idProduct, $idHotel, $totalOccupancy);
if ($occupancyPrice !== false) {
// Belegungspreis gefunden, verwende diesen
$pricePerNight = $occupancyPrice;
} else {
// Fallback auf normalen Zimmerpreis
$pricePerNight = $this->getStandardRoomPrice($idProduct, $idHotel, $dateFrom, $dateTo);
}
// Anzahl Nächte berechnen
$dateFromObj = new DateTime($dateFrom);
$dateToObj = new DateTime($dateTo);
$nights = $dateFromObj->diff($dateToObj)->days;
return $pricePerNight * $nights;
}
/**
* Standard-Zimmerpreis (Fallback)
*/
private function getStandardRoomPrice($idProduct, $idHotel, $dateFrom, $dateTo)
{
// Hier die bestehende Preislogik verwenden
$product = new Product($idProduct);
return $product->price;
}
4. Backend-Interface für Belegungspreise
Du kannst ein neues Tab im Admin-Bereich für Zimmertypen hinzufügen:
// In der Controller-Datei für Zimmertypen
// /modules/hotelreservationsystem/controllers/admin/AdminHotelRoomTypeController.php
public function renderFormOccupancyPricing()
{
$idProduct = (int)Tools::getValue('id_product');
$idHotel = (int)Tools::getValue('id_hotel');
if ($idProduct && $idHotel) {
$occupancyPrices = HotelRoomOccupancyPricing::getOccupancyPrices($idProduct, $idHotel);
$this->context->smarty->assign(array(
'occupancy_prices' => $occupancyPrices,
'id_product' => $idProduct,
'id_hotel' => $idHotel,
'max_occupancy' => 6 // Maximale Belegung
));
return $this->context->smarty->fetch(_PS_MODULE_DIR_.'hotelreservationsystem/views/templates/admin/occupancy_pricing.tpl');
}
}
public function processOccupancyPricing()
{
$idProduct = (int)Tools::getValue('id_product');
$idHotel = (int)Tools::getValue('id_hotel');
$prices = Tools::getValue('occupancy_prices');
if ($idProduct && $idHotel && $prices) {
$cleanPrices = array();
foreach ($prices as $occupancy => $price) {
if ($price > 0) {
$cleanPrices[(int)$occupancy] = (float)$price;
}
}
if (HotelRoomOccupancyPricing::setOccupancyPrices($idProduct, $idHotel, $cleanPrices)) {
$this->confirmations[] = $this->l('Occupancy pricing saved successfully.');
} else {
$this->errors[] = $this->l('Error saving occupancy pricing.');
}
}
}
5. Frontend-Template anpassen
Im Buchungsformular musst du die Preise dynamisch anzeigen:
// JavaScript für dynamische Preisanzeige
$(document).on('change', 'select[name="adults"], select[name="children"]', function() {
updateRoomPriceByOccupancy();
});
function updateRoomPriceByOccupancy() {
var adults = parseInt($('select[name="adults"]').val()) || 1;
var children = parseInt($('select[name="children"]').val()) || 0;
var totalOccupancy = adults + children;
var roomId = $('#room_id').val();
var hotelId = $('#hotel_id').val();
// AJAX-Call zur Preisabfrage
$.ajax({
url: '/modules/hotelreservationsystem/ajax-price.php',
method: 'POST',
data: {
action: 'getRoomPriceByOccupancy',
room_id: roomId,
hotel_id: hotelId,
occupancy: totalOccupancy,
date_from: $('input[name="date_from"]').val(),
date_to: $('input[name="date_to"]').val()
},
success: function(response) {
if (response.success) {
$('.room-price').text(response.price + '€');
$('.total-price').text(response.total_price + '€');
}
}
});
}
6. AJAX-Handler erstellen
Erstelle /modules/hotelreservationsystem/ajax-price.php:
<?php
include_once('../../config/config.inc.php');
include_once('classes/HotelRoomOccupancyPricing.php');
if (Tools::getValue('action') == 'getRoomPriceByOccupancy') {
$roomId = (int)Tools::getValue('room_id');
$hotelId = (int)Tools::getValue('hotel_id');
$occupancy = (int)Tools::getValue('occupancy');
$dateFrom = Tools::getValue('date_from');
$dateTo = Tools::getValue('date_to');
$cartBooking = new HotelCartBookingData();
$totalPrice = $cartBooking->getRoomPriceByOccupancy($roomId, $hotelId, $occupancy, 0, $dateFrom, $dateTo);
$nights = (new DateTime($dateFrom))->diff(new DateTime($dateTo))->days;
$pricePerNight = $nights > 0 ? $totalPrice / $nights : $totalPrice;
header('Content-Type: application/json');
echo json_encode(array(
'success' => true,
'price' => number_format($pricePerNight, 2),
'total_price' => number_format($totalPrice, 2),
'nights' => $nights,
'occupancy' => $occupancy
));
exit;
}
Vielleicht kann ja schon mal jemand drüber gucken, ob ich irgendwo einen Fehler habe.