1 <?php
2
3 class BookingOrder extends DataObject {
4 static $db = array(
5 'StartDate' => 'Date',
6 'EndDate' => 'Date',
7 'ContactPhone' => 'Varchar',
8 'Email' => 'Varchar(100)',
9 'InTime' => 'Time',
10 'OutTime' => 'Time',
11 'Comment' => 'Text',
12 'AgreeWithRulesAndPolicy' => 'Boolean',
13 'Price' => 'Decimal(10,2)',
14 'Discount' => 'Decimal(10,2)',
15 'Status' => "Enum('Basket, New, Query, Paid, Complete, MemberCancelled, AdminCancelled')",
16
17 'FIOList' => 'Text',
18 'HashLink' => 'Varchar',
19 'SubsiteID' => 'Int',
20 );
21
22 static $has_one = array(
23 'PaymentMethod' => 'PaymentMethod',
24 );
25
26 static $has_many = array(
27 'Rooms' => 'RoomOrder',
28 'OrderServices' => 'OrderServiceOrder',
29 'OrderLog' => 'BookingOrder_StatusLog'
30 );
31
32 static $default_sort = 'ID DESC';
33
34 static $defaults = array(
35 'Status' => 'Basket',
36 );
37
38 static $summary_fields = array('StartDate', 'EndDate', 'ContactPhone', 'Email', 'StatusTitle');
39
40 static $searchable_fields = array('StartDate', 'EndDate', 'FIOList', 'ContactPhone', 'Email', 'Price', 'Status' => array('filter'=> 'ExactMatchMultiFilter'));
41
42 static $field_labels = array(
43 'StatusTitle' => 'Статус'
44 );
45
46 static $use_payments = true;
47 static $use_shipping = false;
48
49
50 static $accounted_statuses = array('Query', 'Paid', 'Complete');
51
52 static function get_current_order() {
53 $orderID = (int)Session::get('CurrentBookingOrderID');
54 if ($orderID) {
55 $order = DataObject::get_one('BookingOrder', "ID = {$orderID}");
56 return $order;
57 }
58 return false;
59 }
60
61 62 63 64 65 66 67 68 69
70 static function status_title($status) {
71 return _t('BookingOrder.Status_' . $status, $status);
72 }
73
74 function canView($member = null) {
75 return Permission::check('CMS_ACCESS_BookingOrderAdmin', 'any', $member);
76 }
77
78 function canEdit($member = null) {
79 return Permission::check('CMS_ACCESS_BookingOrderAdmin', 'any', $member);
80 }
81
82 function canDelete($member = null) {
83 return Permission::check('CMS_ACCESS_BookingOrderAdmin', 'any', $member);
84 }
85
86 function canCreate($member = null) {
87 return Permission::check('CMS_ACCESS_BookingOrderAdmin', 'any', $member);
88 }
89
90 static function LocalStatuses() {
91 $rs = array();
92 foreach(singleton('BookingOrder')->dbObject('Status')->enumValues() as $value) {
93 $rs[$value] = self::status_title($value);
94 }
95 return $rs;
96 }
97
98 function OrderingMember() {
99 return $this->Rooms()->First()->MainPerson();
100 }
101
102
103 function OrderLength() {
104 return RoomRate::period_length($this->StartDate, $this->EndDate);
105 }
106
107
108 function OrderRooms() {
109 $rs = DataObject::get('RoomOrder', "OrderID = {$this->ID}", "RoomOrder.Sort, RoomRate.PersonCount", 'JOIN RoomRate ON RoomRate.ID = RoomOrder.RateID');
110 return $rs;
111 }
112
113
114 function StatusTitle() {
115 return self::status_title($this->Status);
116 }
117
118
119 function getGrandTotal() {
120 return $this->Price - $this->Discount;
121 }
122
123
124 function canCancel() {
125
126 if (($this->Status != "New") && ($this->Status != "Query")) {
127 return false;
128 }
129
130
131 if ($this->Rooms() && $this->Rooms()->Count()) {
132 foreach($this->Rooms() as $roomOrder) {
133 if ($roomOrder->Rate()->NoReturn) {
134 return false;
135 }
136 }
137 }
138 return true;
139 }
140
141 function OrderPaymentLink() {
142 return BookingPage::find_links('payment/' . $this->HashLink);
143 }
144
145
146 function PrintVoucherLink() {
147 return BookingPage::find_links('print_voucher/' . $this->HashLink);
148 }
149
150
151 function DownloadVoucherLink() {
152 return BookingPage::find_links('download_voucher/' . $this->HashLink);
153 }
154
155
156 function CancelLink() {
157 if ($this->canCancel()) {
158 return BookingPage::find_links('cancel_order/' . $this->HashLink);
159 }
160 }
161
162 function getCMSFields() {
163 $fields = parent::getCMSFields();
164 $statuses = self::LocalStatuses();
165 array_shift($statuses);
166
167 $fields->replaceField('Status', new DropdownField('Status', $this->fieldLabel('Status'), $statuses));
168
169 $fields->replaceField('Price', $fields->dataFieldByName('Price')->performReadonlyTransformation());
170
171 $fields->insertAfter(new ReadonlyField('TotalPrice', _t('BookingOrder.TotalPrice', 'TotalPrice'), $this->GrandTotal), 'Discount');
172 $fields->removeByName('FIOList');
173 $fields->removeByName('AgreeWithRulesAndPolicy');
174 $fields->removeByName('HashLink');
175 $fields->removeByName('SubsiteID');
176
177 if ($this->isInDB()) {
178 $fields->dataFieldByName('OrderLog')->setPermissions(array('view'));
179 }
180
181 return $fields;
182 }
183
184
185 function getOrderRoomsCount($rateID) {
186 if ($roomOrders = $this->Rooms("RateID = {$rateID}")) {
187 return $roomOrders->Count();
188 }
189 return false;
190 }
191
192
193 function getAdditionalPlacesValue($rateID) {
194 if ($roomOrder = $this->Rooms()->find('RateID', $rateID)) {
195 return $roomOrder->AdditionalPlacesCount;
196 }
197 return false;
198 }
199
200 function saveOrderData($data) {
201 if (isset($data['dateArrival'])) {
202 $this->StartDate = $data['dateArrival'];
203 }
204 if (isset($data['dateDeparture'])) {
205 $this->EndDate = $data['dateDeparture'];
206 }
207
208
209 210 211 212 213
214 if (isset($data['roomsList'])) {
215 foreach($this->Rooms() as $room) {
216 $room->delete();
217 }
218 $this->Rooms()->removeAll();
219 foreach($data['roomsList'] as $index=>$room) {
220 $roomOrder = new RoomOrder();
221 $roomOrder->OrderID = $this->ID;
222 $roomOrder->RoomID = $room['room-id'];
223 $roomOrder->RateID = $room['rate-id'];
224 if (isset($room['additional-count'])) {
225 $roomOrder->AdditionalPlacesCount = (int)$room['additional-count'];
226 }
227 $roomOrder->write();
228
229 $this->Rooms()->add($roomOrder);
230
231
232
233
234
235
236 $roomOrder->Sort = $index;
237
238 $roomOrder->write();
239
240 if (isset($room['services'])) {
241 foreach($roomOrder->RoomServices() as $roomService) {
242 $roomService->delete();
243 }
244 $roomOrder->RoomServices()->removeAll();
245 foreach($room['services'] as $roomService) {
246 $roomServiceOrder = DataObject::get_one('RoomServiceOrder', "RoomServiceID = " . $roomService['service-id'] . " AND RoomOrderID = {$roomOrder->ID}");
247 if (!$roomServiceOrder) {
248 $roomServiceOrder = new RoomServiceOrder();
249 $roomServiceOrder->RoomServiceID = $roomService['service-id'];
250 $roomServiceOrder->RoomOrderID = $roomOrder->ID;
251 }
252 $roomServiceOrder->Count = $roomService['service-count'];
253 $roomServiceOrder->write();
254
255 $roomOrder->RoomServices()->add($roomServiceOrder);
256 }
257 }
258
259 $roomOrder->calcRoomOrderCost();
260 $roomOrder->write();
261 }
262 }
263 if (isset($data['servicesList'])) {
264 foreach($this->OrderServices() as $orderService) {
265 $orderService->delete();
266 }
267 $this->OrderServices()->removeAll();
268
269 foreach($data['servicesList'] as $orderServiceData) {
270 if ($orderService = DataObject::get_by_id('OrderService', (int)$orderServiceData['id'])) {
271 if ($orderService->HasAdditionalField) {
272 for($i = 0; $i < $orderServiceData['count']; $i++) {
273 $orderServiceOrder = new OrderServiceOrder();
274 $orderServiceOrder->OrderServiceID = $orderService->ID;
275 $orderServiceOrder->OrderID = $this->ID;
276 $orderServiceOrder->Count = 1;
277 if (isset($orderServiceData['add-info'])) {
278 $orderServiceOrder->AdditionalFieldData = $orderServiceData['add-info'][$i];
279 }
280 $orderServiceOrder->write();
281
282 $this->OrderServices()->add($orderServiceOrder);
283 }
284 } else {
285 $orderServiceOrder = new OrderServiceOrder();
286 $orderServiceOrder->OrderServiceID = $orderService->ID;
287 $orderServiceOrder->OrderID = $this->ID;
288 $orderServiceOrder->Count = $orderServiceData['count'];
289 $orderServiceOrder->write();
290
291 $this->OrderServices()->add($orderServiceOrder);
292 }
293
294 }
295 }
296 297 298 299 300 301
302 }
303 $subsiteID = 0;
304 if (class_exists('Subsite')) {
305 $subsiteID = Subsite::currentSubsiteID();
306 }
307 $this->SubsiteID = $subsiteID;
308 $this->write();
309 310 311 312 313
314 Session::set('CurrentBookingOrderID', $this->ID);
315 }
316
317 function calculateOrderCost() {
318 $sum = 0;
319 foreach($this->Rooms() as $roomOrder) {
320 $sum += $roomOrder->RoomOrderCost;
321 if ($roomOrder->RoomServices() && $roomOrder->RoomServices()->Count()) {
322 foreach($roomOrder->RoomServices() as $roomService) {
323 $sum += $roomService->RoomServicePrice();
324 }
325 }
326 }
327 if ($this->OrderServices() && $this->OrderServices()->Count()) {
328 foreach($this->OrderServices() as $orderService) {
329 $sum += $orderService->OrderServicePrice();
330 }
331 }
332 $this->Price = $sum;
333 return $this->Price;
334 }
335
336 function onBeforeWrite() {
337 parent::onBeforeWrite();
338 if (!$this->HashLink) {
339 $this->HashLink = md5(time() . serialize($this->data()) . rand());
340 }
341
342 foreach($this->Rooms() as $roomOrder) {
343 $roomOrder->calcRoomOrderCost();
344 $roomOrder->write();
345 }
346 $this->calculateOrderCost();
347
348 }
349
350 function onAfterWrite() {
351
352 if ($this->isChanged('ID')) {
353 $log = new BookingOrder_StatusLog();
354 $log->Status = $this->StatusTitle();
355 $log->Note = ($this->Note) ? $this->Note : _t('BookingOrder.OrderCreated', 'BookingOrder was created');
356 $log->OrderID = $this->ID;
357 $log->write();
358 }
359
360 else if ($this->isChanged('Status') && ($this->Status != 'New')) {
361 $log = new BookingOrder_StatusLog();
362 $log->Status = $this->StatusTitle();
363 $log->Note = ($this->Note) ? $this->Note : _t('BookingOrder.StatusChanged', 'BookingOrder was changed');
364 $log->OrderID = $this->ID;
365 $log->write();
366 $this->sendOrderStatus();
367 }
368
369
370 if (class_exists('Payment') && ($this->isChanged('PaymentMethodID', 2) || $this->isChanged('Discount', 2))) {
371 if ($this->Payments() && $this->Payments()->Count()) {
372 foreach($this->owner->Payments() as $payment) {
373 if (($payment->Status == 'Pending') || ($payment->Status == 'Incomplete')) {
374 $payment->delete();
375 }
376 }
377 }
378
379 if (!$this->isChanged('Status') || (($changedFields = $this->getChangedFields()) && ($changedFields['Status']['before'] != 'Basket'))) {
380 if ($this->PaymentMethodID && ($method = $this->PaymentMethod())) {
381 $p = $method->createPayment($this, 'Payment');
382 }
383 }
384 }
385 parent::onAfterWrite();
386 }
387
388 function OnBeforeDelete() {
389 foreach ($this->OrderLog() as $log) {
390 $log->delete();
391 }
392 parent::OnBeforeDelete();
393 }
394
395 function sendReceipt() {
396 if (class_exists('Subsite') && $this->SubsiteID && ($subsite = DataObject::get_by_id('Subsite', $this->SubsiteID))) {
397 i18n::set_locale($subsite->Language);
398 }
399 $email = new Email();
400 $bookingPage = DataObject::get_one('BookingPage');
401 $from = ($bookingPage && $bookingPage->AdminEmail) ? $bookingPage->AdminEmail : Email::getAdminEmail();
402 $email->setFrom($from);
403 $to = $this->Email;
404 $email->setSubject(_t('BookingOrder.ReceiptMailSubject'));
405 $email->setTemplate('BookingOrderClientReceipt');
406 $email->populateTemplate(array(
407 'Order' => $this
408 ));
409
410 if ($to) {
411 $email->setTo($to);
412 $email->send();
413 }
414 i18n::set_locale('ru_RU');
415
416 $email = new Email();
417 $email->setFrom($from);
418 $email->setTo($from);
419 $email->setSubject(_t('BookingOrder.ManagerReceiptMailSubject'));
420 $email->setTemplate('BookingOrderManagerReceipt');
421 $email->populateTemplate(array(
422 'Order' => $this
423 ));
424 $email->send();
425 }
426
427 function sendOrderStatus() {
428 $paymentLink = $this->OrderPaymentLink();
429 if (class_exists('Subsite') && $this->SubsiteID && ($subsite = DataObject::get_by_id('Subsite', $this->SubsiteID))) {
430 i18n::set_locale($subsite->Language);
431
432 $paymentLink = $subsite->domain() . $paymentLink;
433 }
434 $email = new Email();
435 $bookingPage = DataObject::get_one('BookingPage');
436 $from = ($bookingPage && $bookingPage->AdminEmail) ? $bookingPage->AdminEmail : Email::getAdminEmail();
437 $email->setFrom($from);
438 $to = $this->Email;
439 $email->setSubject(_t('BookingOrder.StatusChangeMailSubject'));
440 $email->setTemplate('BookingOrderClientChangeStatus');
441
442 $email->populateTemplate(array(
443 'Order' => $this,
444 'OrderPaymentLink' => $paymentLink,
445 ));
446
447 if ($to) {
448 $email->setTo($to);
449 $email->send();
450 }
451 i18n::set_locale('ru_RU');
452 453 454 455 456 457
458 }
459 }
460
461 462 463 464 465
466 class BookingOrder_StatusLog extends DataObject {
467
468 static $db = array(
469 'Status' => 'Varchar(255)',
470 'Note' => 'Text',
471 );
472
473 static $has_one = array(
474 'Creator' => 'Member',
475 'Order' => 'BookingOrder',
476 );
477
478 static $summary_fields = array(
479 'Created', 'Status', 'Note'
480 );
481
482 static $searchable_fields = array(
483 'OrderID' => array(
484 'field' => 'NumericField',
485 'filter' => 'ExactMatchFilter'
486 ),
487 );
488
489 static $default_sort = 'ID';
490
491 function fieldLabels($includerelations = true) {
492 $labels = parent::fieldLabels($includerelations);
493 $labels['OrderID'] = _t('BookingOrder.db_ID', 'BookingOrder ID');
494 $labels['Created'] = _t('BookingOrder_StatusLog.db_Created', 'Status time');
495 return $labels;
496 }
497
498 function getCMSFields() {
499 $fields = parent::getCMSFields();
500 $fields->replaceField('OrderID', new ReadonlyField('OrderID', $this->fieldLabel('BookingOrder'), $this->OrderID));
501 $fields->removeByName('CreatorID');
502 return $fields;
503 }
504
505 function canEdit() {
506 return false;
507 }
508
509 function canDelete() {
510 return false;
511 }
512
513 function onBeforeWrite() {
514 if (!$this->ID) {
515 $this->CreatorID = (Member::currentUserID()) ? Member::currentUserID() : 1;
516 }
517 parent::onBeforeWrite();
518 }
519 }
[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.
-