New back-office page "Hotel Reservation System > Belegungsplan": - rooms grouped by room type as rows, 14-62 days as columns, weekends and today highlighted, sticky room column, daily occupancy footer - bookings as bars (booked / checked in / checked out / no-show) with guest name, guests, tooltip with dates, order reference and price; click opens the order; stays outside the view are cut - booking source badge from orders.id_source (W website, T phone, B Booking.com, E Expedia ...; portals highlighted), so channel-manager bookings show up with their source - blocked periods (htl_room_disable_dates) hatched with reason - CASPOS badge: nights already posted by casposbridge, "!" on failures - reserve: click a free cell (first night) and a later one (last night) in the same row -> action bar -> "Book Now" opens with dates, hotel and room type prefilled; keyboard: Enter/Space, Escape - docker/test-occupancyplan.php: 15 checks with throw-away bookings, optional HTML preview Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
67 lines
1.9 KiB
PHP
67 lines
1.9 KiB
PHP
<?php
|
||
/**
|
||
* Belegungsplan: back-office tape chart (rooms × days) under "Hotel Reservation System".
|
||
*/
|
||
|
||
if (!defined('_PS_VERSION_')) {
|
||
exit;
|
||
}
|
||
|
||
|
||
class Occupancyplan extends Module
|
||
{
|
||
public function __construct()
|
||
{
|
||
$this->name = 'occupancyplan';
|
||
$this->tab = 'administration';
|
||
$this->version = '1.0.0';
|
||
$this->author = 'Zum alten Wasserrad';
|
||
$this->need_instance = 0;
|
||
$this->bootstrap = true;
|
||
parent::__construct();
|
||
|
||
$this->displayName = $this->l('Belegungsplan');
|
||
$this->description = $this->l('Zimmer × Tage mit allen Buchungen, Status und Sperrzeiten auf einen Blick.');
|
||
$this->ps_versions_compliancy = array('min' => '1.6', 'max' => '1.6.99.99');
|
||
}
|
||
|
||
public function install()
|
||
{
|
||
return parent::install() && $this->installTab();
|
||
}
|
||
|
||
public function uninstall()
|
||
{
|
||
$idTab = (int)Tab::getIdFromClassName('AdminOccupancyPlan');
|
||
if ($idTab) {
|
||
$tab = new Tab($idTab);
|
||
$tab->delete();
|
||
}
|
||
return parent::uninstall();
|
||
}
|
||
|
||
protected function installTab()
|
||
{
|
||
if (Tab::getIdFromClassName('AdminOccupancyPlan')) {
|
||
return true;
|
||
}
|
||
$tab = new Tab();
|
||
$tab->class_name = 'AdminOccupancyPlan';
|
||
$tab->module = $this->name;
|
||
$parent = (int)Tab::getIdFromClassName('AdminHotelReservationSystemManagement');
|
||
$tab->id_parent = $parent ?: 0;
|
||
foreach (Language::getLanguages(false) as $lang) {
|
||
$tab->name[$lang['id_lang']] = 'Belegungsplan';
|
||
}
|
||
// Tab::add() returns initAccess(), which is false without a logged-in employee (CLI);
|
||
// the tab itself is created either way.
|
||
$tab->add();
|
||
return (bool)$tab->id;
|
||
}
|
||
|
||
public function getContent()
|
||
{
|
||
Tools::redirectAdmin($this->context->link->getAdminLink('AdminOccupancyPlan'));
|
||
}
|
||
}
|