Version: current

      1 <?php
      2 /*
      3  * Объект "Тариф" - тариф стоимости номера. (напр. одноместное проживание, двухместное проживание, безвозвратный)
      4  *
      5  * @author menedem
      6  */
      7 class RoomRate extends DataObject {
      8     static $db = array(
      9         'Title' => 'Varchar(150)',
     10         'PersonCount' => 'Int', //кол-во человек в тарифе
     11         'Active' => 'Boolean',
     12         'Base' => 'Boolean', // базовый тариф
     13         'NoReturn' => 'Boolean', // безвозвратный
     14         'AdditionalPlaceCount' => 'Int', //кол-во доп. мест тарифа - выбираем тариф сразу с доп.местом,
     15     );
     16
     17     static $has_one = array(
     18         'Icon' => 'Image',
     19         'Room' => 'Room',
     20     );
     21
     22     static $many_many = array(
     23         'StandartServices' => 'RoomService',
     24         'Prices' => 'RatePeriod',
     25     );
     26
     27     static $many_many_extraFields = array(
     28         'Prices' => array('Price' => 'Decimal(10, 2)'),
     29     );
     30
     31     static $default_sort = 'Active, Base desc, PersonCount, AdditionalPlaceCount';
     32
     33     static $searchable_fields = array('Title', 'PersonCount', 'Base', 'NoReturn');
     34     static $summary_fields = array('Title', 'PersonCount', 'ActiveTitle', 'BaseTitle', 'NoReturnTitle');
     35
     36     /**
     37      *
     38      *
     39      * @param <type> $startDate
     40      * @param <type> $endDate
     41      *
     42      * @return <type>
     43      */
     44     static function period_length($startDate, $endDate) {
     45         $startDate = date_create($startDate);
     46         $endDate = date_create($endDate);
     47         $interval = date_diff($startDate, $endDate);
     48         return (int)$interval->format('%a');
     49     }
     50
     51     function fieldLabels($relations = true) {
     52         // !!! вот так корректно добавляются названия виртуальных полей
     53         $labels = parent::fieldLabels($relations);
     54         $labels['ActiveTitle'] = $labels['Active'];
     55         $labels['BaseTitle'] = $labels['Base'];
     56         $labels['NoReturnTitle'] = $labels['NoReturn'];
     57         return $labels;
     58     }
     59
     60     function TitleWithPrice() {
     61         return $this->Title . " (" . $this->PeriodPrice() . " руб.)";
     62     }
     63
     64     function TitleAdditionalPlaces() {
     65         return $this->Title . " (+ {$this->AdditionalPlaceCount} чел.)";
     66     }
     67
     68     function ActiveTitle() {
     69         return ($this->Active) ? _t('Boolean.YES') : _t('Boolean.NO');
     70     }
     71
     72     function BaseTitle() {
     73         return ($this->Base) ? _t('Boolean.YES') : _t('Boolean.NO');
     74     }
     75
     76     function NoReturnTitle() {
     77         return ($this->NoReturn) ? _t('Boolean.YES') : _t('Boolean.NO');
     78     }
     79
     80     function getCMSFields() {
     81         $fields = parent::getCMSFields();
     82         $fields->removeFieldFromTab('Root.Prices','Prices');
     83         $fields->removeByName('Prices');
     84         if ($this->isInDB()) {
     85             $tab = $fields->findOrMakeTab('Root.RatePrices', _t('Room.PRICES'));
     86             if ($this->allPrices()) {
     87                 foreach ($this->allPrices() as $p) {
     88                     $tab->push(new RoomRate_PriceField('Prices', $p));
     89                 }
     90             }
     91         }
     92         $opt = $this->Room()->Services();
     93         $fields->replaceField('StandartServices', new CheckboxSetField('StandartServices', $this->fieldLabel('StandartServices'), $opt->map()));
     94
     95         return $fields;
     96     }
     97
     98     /**
     99      * Возвращает список периодов с ценами включая незаполненные (для редактирования)
    100      *
    101      * @return DataObjectSet
    102      */
    103     function allPrices() {
    104         //$all = DataObject::get('RatePeriod', "Date >= '". date('Y-m-d') ."'");
    105         $all = DataObject::get('RatePeriod');
    106         foreach ($this->Prices() as $p) {
    107             if ($rec = $all->find('ID', $p->ID)) {
    108                 $all->replace($rec, $p);
    109             }
    110         }
    111         return $all;
    112     }
    113
    114     /**
    115      * Возвращает актуальных список цен по тарифу
    116      *
    117      * @param bool $all - включая прошедшие
    118      *
    119      * @return DataObjectSet
    120      */
    121     function ActivePrices($all = false) {
    122         if ($all) $this->Prices();
    123
    124         $dt = $this->Prices("Date < now()", 'Date DESC', '', 1)->First();
    125         return $this->Prices("Date >= '$dt->Date'", 'Date ASC');
    126     }
    127
    128     function onBeforeWrite() {
    129         parent::onBeforeWrite();
    130
    131         if ($this->isChanged('Base') && ($this->Base == 1)) {
    132             foreach($this->Room()->Rates() as $rate) {
    133                 if ($rate->ID != $this->ID) {
    134                     $rate->Base = 0;
    135                     $rate->write();
    136                 }
    137             }
    138         }
    139     }
    140
    141     /*
    142      * Стоимость проживания в заданную дату
    143      *
    144      * @param integer $date - дата в unixtime
    145      *
    146      * @return Decimal $price - цена за этот день
    147      */
    148     function getOneDayRoomPrice($date=false) {
    149         if (!$date) {
    150             $date = time();
    151         }
    152         $price = 0;
    153         foreach($this->Prices() as $ratePrice) {
    154             if (strtotime($ratePrice->Date) <= $date) {
    155                 $price = $ratePrice->Price;
    156             }
    157             else break;
    158         }
    159         return (float)$price;
    160     }
    161
    162     /**
    163      * Стоимость тарифа за заданный период
    164      *
    165      * по умолчанию даты берем из фильтра BookingPage
    166      *
    167      * @param String $startDate - дата заезда в любом формате понимаемом strtotime
    168      * @param String $endDate   - дата выезда в любом формате понимаемом strtotime
    169      *
    170      * @return Decimal - стоимость номера за период
    171      */
    172     function PeriodPrice($startDate=false, $endDate=false) {
    173         $totalPrice = 0;
    174         if ((!$startDate || !$endDate) && ($filterData = BookingPage::getFilterDates())) {
    175             $startDate = strtotime($filterData['FilterStartDate']);
    176             $endDate = strtotime($filterData['FilterEndDate']);
    177         }
    178         if ($startDate && $endDate) {
    179             while($startDate <= strtotime("-1 day", $endDate)) {
    180                 $totalPrice += $this->getOneDayRoomPrice($startDate);
    181                 $startDate = strtotime("+1 day", $startDate);
    182             }
    183         }
    184         return $totalPrice;
    185     }
    186
    187     function getPrice() {
    188         return $this->PeriodPrice();
    189     }
    190
    191
    192     /**
    193      * Число доп. мест для данного тарифа
    194      *
    195      * @return Integer
    196      */
    197      /*
    198     function getAdditionalPlaceCount() {
    199         if ($this->Room()->AdditionalPlaceCount && ($this->PersonCount == $this->Room()->PlaceCount)) {
    200             return $this->Room()->AdditionalPlaceCount;
    201         }
    202         return 0;
    203     }
    204     */
    205
    206     /**
    207      * склонение кол-ва человек
    208      *
    209      * @param integer $person
    210      *
    211      * @return string
    212      */
    213     function PersonWord($person = false) {
    214         if ($person === false) $person = $this->PersonCount;
    215
    216         return Convert::number2name(
    217             $person,
    218             _t('BookingPage.Person1'),
    219             _t('BookingPage.Person4'),
    220             _t('BookingPage.Person5')
    221         );
    222     }
    223
    224     /*
    225     function RoomServiceSelector($service) {
    226         $nums = array();
    227         $nums[0] = _t('Room.SelectRoomCount', 'Select Room Count');
    228         for($i=1; $i <= $this->PersonCount; $i++) {
    229             $nums[$i] = $i;
    230         }
    231         $f = new DropdownField("RoomService[$service->ID][]", '', $nums);
    232         $f->addExtraClass('RoomServiceSelector');
    233         $f->addExtraAttribute('RateID', $this->ID);
    234         $f->addExtraAttribute('RoomID', $this->RoomID);
    235         $f->addExtraAttribute('ServiceID', $service->ID);
    236
    237         return $f->FieldHolder();
    238     }
    239     */
    240
    241     function getTotalPersonCount() {
    242         return $this->PersonCount + $this->AdditionalPlaceCount;
    243     }
    244
    245     function TotalPersonString() {
    246         return $this->PersonCount . (($this->AdditionalPlaceCount > 0) ? "+" . $this->AdditionalPlaceCount : '');
    247     }
    248
    249     /**
    250      *
    251      *
    252      *
    253      * @return <type>
    254      */
    255     function RoomCountSelector() {
    256         $nums = array();
    257         $nums[0] = _t('RoomRate.SelectRoomCount', 'select');
    258
    259         $dates = BookingPage::getFilterDates();
    260         $availableCount = RoomOrder::available_rooms_count($this->RoomID, $dates['FilterStartDate'], $dates['FilterEndDate']);
    261         if (!$availableCount) {
    262             return false;
    263         }
    264
    265         for($i = 1; $i <= $availableCount; $i++) {
    266             $nums[$i] = $i;
    267         }
    268         $count = 0;
    269         if ($order = BookingOrder::get_current_order()) {
    270             $count = $order->getOrderRoomsCount($this->ID);
    271         }
    272         $f = new DropdownField("RoomCount[$this->RoomID][$this->ID]", '', $nums, $count); // !!! Както выставить количество номеров этого тарифа в заказе !!!
    273         $f->addExtraClass('RoomCountSelector');
    274         $f->addExtraAttribute('autocomplete', 'off');
    275         $f->addExtraAttribute('data-rateid', $this->ID);
    276         $f->addExtraAttribute('data-roomid', $this->RoomID);
    277         $f->addExtraAttribute('data-personcount', $this->TotalPersonCount);
    278         return $f->FieldHolder();
    279     }
    280
    281     // селектор выбора доп.мест
    282     // если котором кол-во человек совпадает с кол-вом мест в номере и в номере есть возможность заказать доп. места, то показываем
    283     // пока условно, чтоб сформулировать
    284     /**
    285      *
    286      *
    287      *
    288      * @return <type>
    289      */
    290     function AdditionalPlacesSelector() {
    291         if ($this->AdditionalPlaceCount) {
    292             $nums = array();
    293             $nums[0] = _t('RoomRate.SelectAdditionalPlaces', 'select');
    294             for($i = 1; $i <= $this->AdditionalPlaceCount; $i++) {
    295                 $nums[$i] = $i;
    296             }
    297             $f = new DropdownField("AdditionalPlacesCount[$this->RoomID][$this->ID]", '', $nums);
    298             $f->addExtraClass('AdditionalPlacesSelector');
    299             $f->addExtraAttribute('data-rateid', $this->ID);
    300             $f->addExtraAttribute('data-roomid', $this->RoomID);
    301             $f->addExtraAttribute('data-additionalplacescost', $this->Room()->AdditionalPlaceCost * BookingPage::getFilterDatesPeriodLength());
    302             return $f;//->FieldHolder();
    303         }
    304         return false;
    305     }
    306 }
    307
    308 /**
    309  * Поле для редактирования цены тарифа за период
    310  *
    311  * @author dvp
    312  */
    313 class RoomRate_PriceField extends NumericField {
    314
    315     function __construct($name, $param) {
    316         $name .= '[' . $param->ID . ']';
    317         parent::__construct($name, $param->Title, $param->Price);
    318     }
    319
    320     function saveInto(DataObject $record) {
    321         if (!preg_match('/(\w+)\[(\d+)\]/', $this->name, $matches))
    322             user_error("RoomRate_PriceField::saveInto() $this->name has invalid format");
    323
    324         $fieldName = $matches[1];
    325         $id = $matches[2];
    326
    327         $saveDest = $record->$fieldName();
    328
    329         if (!$saveDest)
    330             user_error("RoomRate_PriceField::saveInto() Field '$fieldName' not found on $record->class.$record->ID", E_USER_ERROR);
    331
    332         if ($this->value > 0) {
    333             $saveDest->add($id, array('Price' => $this->value));
    334         }
    335         else {
    336             $saveDest->remove($id);
    337         }
    338     }
    339 }
    340

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