QloApps Forums
    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular

    Per Day Per Person Price Calculation

    General Discussion
    3
    3
    862
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • R
      RDVAdmin last edited by

      HI,
      I am recently evaluating QloApps for a small hotel.
      The Price Model for the Hotel is Per Day Per Heat inclusive of Meals.
      If a room Capacity is 2 Adult and 1 Child , and P*P cost is Rs. 1000.00 then total cost should come Rs. 2500.00
      Per Room Cost can be defined but I want to define Per Room Per Person. for Child 50% Discount.

      Pls guide how can I achieve that.

      Thanks in advance.

      A M 2 Replies Last reply Reply Quote 0
      • A
        Archit Chandra @RDVAdmin last edited by qloadmin

        Hi @RDVAdmin ,

        Currently, we have only per-day pricing in QloApps. As of now, occupancy wise pricing is not supported but this feature is in our roadmap. Currently, we cannot give you any strict deadline for it.

        However, if you need the occupancy wise pricing on an urgent basis, we request you to create a ticket from here: https://webkul.uvdesk.com/en/customer/create-ticket/

        1 Reply Last reply Reply Quote 0
        • M
          masaro.solutions @RDVAdmin last edited by

          @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

          1. 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.

          1 Reply Last reply Reply Quote 0
          • First post
            Last post