Version: current

      1 <?php
      2 /*
      3  * Страница Номер (Room)
      4  *
      5  * @author menedem
      6  */
      7 class Room extends MediawebPage {
      8     static $allowed_children = 'none';
      9     static $default_parent = 'RoomCatalog';
     10     static $can_be_root = false;
     11
     12     static $db = array(
     13         'PlaceCount' => 'Int', //кол-во мест,
     14         'AdditionalPlaceCount' => 'Int', //кол-во доп. мест,
     15         'AdditionalPlaceCost' => 'Decimal(10, 2)',
     16         'OrderingRoomsCount' => 'Int', //кол-во номеров которые можно заказать
     17         'Square' => 'Decimal(6,2)', //площадь
     18         'RoomDescription' => 'Text', //краткое описание
     19         'ServiceDescription' => 'Text', //услуги и удобств
     20         //'Panorama' => 'Text', // пАнорама!!
     21
     22     );
     23
     24     static $defaults = array(
     25         'ShownInMenus' => 0,
     26     );
     27
     28     static $casting = array(
     29         'BasePrice' => 'Decimal',
     30     );
     31
     32     static $has_one = array(
     33         'Icon' => 'Image'
     34     );
     35
     36     static $has_many = array(
     37         'Rates' => 'RoomRate',
     38         //'Services' => 'RoomServiceData',
     39     );
     40
     41     static $many_many = array(
     42         'Services' => 'RoomService',
     43     );
     44
     45     private $basePrice = false;
     46     private $pricePrefix = false;
     47
     48     /**
     49      * Возвращает номера доступные для заказа
     50      *
     51      * @return Room
     52      */
     53     static function get_available_rooms() {
     54         return DataObject::get('Room', 'OrderingRoomsCount > 0');
     55     }
     56
     57     /**
     58      * Возвращает полную стоимость доп.места с учетом количества дней
     59      *
     60      * @return Decimal
     61      */
     62     function getAdditionalPlaceFullCost() {
     63         return $this->AdditionalPlaceCost * BookingPage::getFilterDatesPeriodLength();
     64     }
     65
     66     /**
     67      * Вычисляет текущую базовую/минимальную цену и префикс цены
     68      */
     69     private function calcBasePrice() {
     70         if ($this->basePrice !== false) return;
     71
     72         if ($rate = $this->ActiveRates()->find('Base', 1)) {
     73             $this->basePrice = $rate->getOneDayRoomPrice(strtotime("now"));
     74             $this->pricePrefix = '';
     75         } else {
     76             $this->basePrice = false;
     77             foreach($this->ActiveRates() as $rate) {
     78                 if (($this->basePrice === false) || ($this->basePrice > $rate->getOneDayRoomPrice(strtotime("now")))) {
     79                     $this->basePrice = $rate->getOneDayRoomPrice(strtotime("now"));
     80                 }
     81             }
     82             $this->pricePrefix = _t('Room.PRICE_FROM');
     83         }
     84     }
     85
     86     function getBasePrice() {
     87         $this->calcBasePrice();
     88         return $this->basePrice;
     89     }
     90
     91     function getPricePrefix() {
     92         $this->calcBasePrice();
     93         return $this->pricePrefix;
     94     }
     95
     96     /**
     97      * Возвращает список активных тарифов
     98      * (в отличие от Rates)
     99      *
    100      * @return DataObjectSet
    101      */
    102     function ActiveRates() {
    103         return $this->Rates("Active=1");
    104     }
    105
    106     /**
    107      * Возвращает список актуальных периодов тарифов
    108      *
    109      * @param bool $all - включая прошедшие
    110      *
    111      * @return DataObjectSet
    112      */
    113     function ActivePeriods($all = false) {
    114         if ($all) return DataObject::get('RatePeriod');
    115
    116         $dt = DataObject::get_one('RatePeriod', "Date <= now()", true, 'Date DESC');
    117         return DataObject::get('RatePeriod', "Date >= '$dt->Date'");
    118     }
    119
    120     /**
    121      * Дополнительные услуги номера к тарифу
    122      *
    123      * @param RoomRate $rate - тариф для которого определяем список доп. услуг
    124      *
    125      * @return DataObjectSet список дополнительных услуг номера к указанном тарифу
    126      */
    127     function getRoomServices($rate) {
    128         $standartServices = $rate->StandartServices()->map();
    129         $rs = new DataObjectSet();
    130         foreach($this->Services() as $service) {
    131             if ($service->Active && !isset($standartServices[$service->ID])) {
    132                 $service->RoomServiceSelector = $this->RoomServiceSelector($service);
    133                 $rs->push($service);
    134             }
    135         }
    136         return $rs;
    137     }
    138
    139     /**
    140      *
    141      *
    142      * @param <type> $service
    143      *
    144      * @return <type>
    145      */
    146     function RoomServiceSelector($service) {
    147         $nums = array();
    148         $nums[0] = _t('Room.SelectRoomCount', 'Select Room Count');
    149         /*for($i=1; $i <= $this->PersonCount; $i++) {
    150             $nums[$i] = $i;
    151         }*/
    152         $f = new DropdownField("RoomService[$service->ID][]", '', $nums);
    153         $f->addExtraClass('RoomServiceSelector');
    154         $f->addExtraAttribute('RateID', 0);
    155         $f->addExtraAttribute('RoomID', $this->ID);
    156         $f->addExtraAttribute('ServiceID', $service->ID);
    157
    158         return $f->FieldHolder();
    159     }
    160
    161     function getCMSFields() {
    162         $fields = parent::getCMSFields();
    163         $fields->removeByName('CoverImageID');
    164
    165         $fields->addFieldToTab('Root.Content', new Tab("FullContent", $this->fieldLabel('Content')), 'PagePhotos');
    166         $fields->addFieldToTab('Root.Content.FullContent', new TextAreaField('RoomDescription', $this->fieldLabel('RoomDescription')));
    167         $fields->addFieldToTab('Root.Content.FullContent', new TextAreaField('ServiceDescription', $this->fieldLabel('ServiceDescription')));
    168         $fields->addFieldToTab('Root.Content.FullContent', $fields->dataFieldByName('Content'));
    169         //$fields->addFieldToTab('Root.Content.FullContent', new TextAreaField('Panorama', $this->fieldLabel('Panorama')));
    170
    171         $fields->addFieldToTab('Root.Content.Main', new ImageField('Icon', $this->fieldLabel('Icon')));
    172
    173         $fields->addFieldToTab('Root.Content.Main', new TextField('PlaceCount', $this->fieldLabel('PlaceCount')));
    174         $fields->addFieldToTab('Root.Content.Main', new TextField('AdditionalPlaceCount', $this->fieldLabel('AdditionalPlaceCount')));
    175         $fields->addFieldToTab('Root.Content.Main', new TextField('OrderingRoomsCount', $this->fieldLabel('OrderingRoomsCount')));
    176         $fields->addFieldToTab('Root.Content.Main', new TextField('AdditionalPlaceCost', $this->fieldLabel('AdditionalPlaceCost')));
    177         $fields->addFieldToTab('Root.Content.Main', new TextField('Square', $this->fieldLabel('Square')));
    178
    179
    180         $fields->addFieldToTab('Root.Content', new Tab("Rates", _t('Room.tabRates', 'Rates')), 'FullContent');
    181         $ctf = new ComplexTableField(
    182             $this,
    183             'Rates',
    184             'RoomRate',
    185             null,
    186             null,
    187             'RoomRate.RoomID = ' . $this->ID
    188         );
    189         $ctf->setRelationAutoSetting(true);
    190         $fields->addFieldToTab('Root.Content.Rates', $ctf);
    191
    192         $fields->addFieldToTab('Root.Content', new Tab("Services", _t('Room.tabServices', 'Services')), 'FullContent');
    193         $ctf = new ManyManyComplexTableField(
    194             $this,
    195             'Services',
    196             'RoomService',
    197             null,
    198             null,
    199             'RoomService.Active = 1'
    200         );
    201         //$ctf->setRelationAutoSetting(true);
    202         //$fields->addFieldToTab('Root.Content.Services', $ctf);
    203
    204         $opt = RoomService::get_active();
    205         if ($opt) {
    206             $fields->addFieldToTab('Root.Content.Services', new CheckboxSetField('Services', $this->fieldLabel('Services'), $opt->map()));
    207         }
    208
    209         return $fields;
    210     }
    211
    212     function getOrderFormRates($startDate=false,$endDate=false) {
    213         $activeRates = $this->ActiveRates();
    214         $ratesMap = array();
    215         $minPriceID = '';
    216         $minPrice = false;
    217         $baseID = '';
    218         foreach($activeRates as $activeRate) {
    219             if ($startDate && !$endDate) {
    220                 $price = $activeRate->getOneDayRoomPrice($startDate);
    221             } else {
    222                 $price = $activeRate->PeriodPrice($startDate, $endDate);
    223             }
    224             //$ratesMap[$activeRate->ID] = "{$activeRate->Title}, " . (($startDate && $endDate) ? sprintf(_t('Room.OrderFormExactPrice'), $price) : sprintf(_t('Room.OrderFormFromPrice'), $price));
    225             $ratesMap[$activeRate->ID] = "{$activeRate->Title} " . sprintf(_t('Room.PersonCountTitle'), $activeRate->PersonCount) . ($activeRate->AdditionalPlaceCount ? sprintf(_t('RoomRate.AdditionalPlaceCountTitle'), $activeRate->AdditionalPlaceCount) : '') ;
    226             if ($activeRate->Base) {
    227                 $baseID = $activeRate->ID;
    228             }
    229             if (($minPrice === false) || ($price < $minPrice)) {
    230                 $minPrice = $price;
    231                 $minPriceID = $activeRate->ID;
    232             }
    233         }
    234         if ($baseID) {
    235             $selected = $baseID;
    236         } else {
    237             $selected = $minPriceID;
    238         }
    239         return new DropdownField('RateID', _t('BookingOrder.Rate'), $ratesMap, $selected);
    240
    241         return array(
    242             'List' => $ratesMap,
    243             'Selected' => $selected,
    244         );
    245     }
    246 }
    247
    248 class Room_Controller extends MediawebPage_Controller {
    249
    250     /*
    251      * AJAX-функция получения поля выбора тарифа номера по заданным датам
    252      *
    253      * @return html
    254      */
    255     function get_rates_field($request) {
    256         $startDate = $request->param('ID');
    257         $endDate = $request->param('OtherID');
    258         return $this->getOrderFormRates(strtotime($startDate), strtotime($endDate))->fieldHolder();
    259
    260     }
    261
    262     /**
    263      * Форма бронирования номера
    264      *
    265      *
    266      * @return Form
    267      */
    268     function RoomOrderForm() {
    269         $fields = new FieldSet();
    270         $fields->push(new HiddenField('RoomID', 'RoomID', $this->ID));
    271         $fields->push(new TextField('FilterStartDate', _t('BookingOrder.StartDate')));
    272         $fields->push(new TextField('FilterEndDate', _t('BookingOrder.EndDate')));
    273         $ratesField = $this->getOrderFormRates();
    274         $fields->push($ratesField);
    275         $form = new Form(
    276             $this,
    277             'RoomOrderForm',
    278             $fields,
    279             new FieldSet(new FormAction('goBooking', _t('RoomOrder.goBooking', 'Забронировать')))
    280         );
    281         $form->loadDataFrom(BookingPage::getFilterDates());
    282         return $form;
    283     }
    284
    285     /**
    286      *
    287      *
    288      * @param <type> $data
    289      * @param <type> $form
    290      *
    291      * @return <type     */
    292     function goBooking($data, $form) {
    293         $availableCount = RoomOrder::available_rooms_count($this->ID, $data['FilterStartDate'], $data['FilterEndDate']);
    294         if (!$availableCount) {
    295             $form->sessionMessage(_t('RoomOrderForm.NoFreeRooms', 'нет свободных номерв на эти даты'), 'warning');
    296             return $this->redirectBack();
    297         }
    298
    299
    300         // ?? хранить ли ID текущего заказа в сессии - вдруг кто-то будет заказывать с 2-х вкладок ??
    301         $data['dateArrival'] = $data['FilterStartDate'];
    302         $data['dateDeparture'] = $data['FilterEndDate'];
    303
    304
    305         $data['roomsList'] = array();
    306
    307         $data['roomsList'][0]['room-id'] = $data['RoomID'];
    308         $data['roomsList'][0]['rate-id'] = $data['RateID'];
    309         $rate = DataObject::get_by_id('RoomRate', $data['RateID']);
    310         if ($rate && $rate->AdditionalPlaceCount) {
    311             $data['roomsList'][0]['additional-count'] = $rate->AdditionalPlaceCount;
    312         }
    313         $order = new BookingOrder();
    314         $order->Status = 'Basket';
    315         $order->write();
    316         $order->saveOrderData($data);
    317         $rateID = $data['RateID'];
    318         /*
    319
    320         unset($data['RateID']);
    321         Session::set('BookingFilter', $data);
    322         */
    323         if ($bookingLink = BookingPage::find_links('services?RateID=' . $rateID)) {
    324             $this->redirect($bookingLink);
    325             return;
    326         }
    327         $this->redirectBack();
    328         return;
    329     }
    330 }
    331

[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the Silverstripe Forums to ask development related questions. -