· 9 years ago · Jan 03, 2017, 05:32 PM
1<?php
2
3/*
4 * To change this license header, choose License Headers in Project Properties.
5 * To change this template file, choose Tools | Templates
6 * and open the template in the editor.
7 */
8
9/**
10 * Description of Ex_engine
11 *
12 * @author rotichmordecai
13 */
14class Ex_engine {
15
16 var $CI;
17 var $api_functions_lang = "en";
18 var $user_id = 0;
19 var $commission_temp = 15;
20
21 function __construct() {
22 $this->CI = & get_instance();
23 $this->initialize();
24 log_message('debug', "Ex_engine Class Initialized");
25 }
26
27 function initialize() {
28 $this->CI->load->library(array('custom_log', 'forex', 'payment247'));
29 $this->CI->load->helper(array('text', 'caching_helper', 'wh_helper', 'hm_helper', 'front_helper'));
30 $this->CI->config->load('hm');
31 $this->CI->config->load('stripe', TRUE);
32 $conf = $this->CI->config->item('stripe');
33 $this->CI->load->library('stripe', $conf);
34 $this->CI->load->library('export');
35 $this->CI->load->library('ch/ch_engine');
36 $this->CI->load->library('Ex_email_engine');
37 }
38
39 function chm_log($name, $is_inbound = true, $data = null) {
40
41 $config = & get_config();
42 $CI = & get_instance();
43 $CI->load->library('custom_log');
44
45 list($usec, $sec) = explode(' ', microtime());
46 $usec = str_replace("0.", ".", $usec);
47 $date = date('Y-m-d H:i:s', $sec) . $usec;
48
49 if ($is_inbound) {
50 $log = 'Inbound API :: ' . $date . ' :: ' . getmypid();
51 } else {
52 $log = 'Outbound API :: ' . $date . ' :: ' . getmypid();
53 }
54
55
56 if ($data) {
57 $log .= " ($data)";
58 }
59
60 $log .= "\n";
61 $CI->custom_log->log("cm-wu", $log);
62 }
63
64 function district() {
65 $this->CI->load->model('extranet/district_model');
66 return $this->CI->district_model->select();
67 }
68
69 function landmark() {
70 $this->CI->load->model('extranet/landmark_model');
71 return $this->CI->landmark_model->select();
72 }
73
74 /**
75 * @param $property_id
76 * @param null $language_id
77 * @return null
78 */
79 function property($property_id, $language_id = NULL) {
80
81 $this->CI->load->model('extranet/property_model');
82 $this->CI->load->model('extranet/property_image_model');
83 $this->CI->load->model('extranet/property_has_payment_card_type_model');
84 $this->CI->load->model('extranet/property_has_language_model');
85 $this->CI->load->model('extranet/milestone_payment_model');
86 $this->CI->load->model('extranet/property_has_currency_model');
87 $this->CI->load->model('extranet/currency_exchange_model');
88
89 $this->CI->load->model('extranet/district_has_property_model');
90 $this->CI->load->model('extranet/property_has_landmark_model');
91 $this->CI->load->model('extranet/property_has_tax_model');
92 $this->CI->load->model('extranet/currency_model');
93
94 $this->CI->load->model('extranet/room_image_model');
95 $this->CI->load->model('extranet/transport_model');
96
97 $creteria = array(
98 'property.id' => $property_id
99 );
100 $property = $this->CI->property_model->select($creteria, $language_id);
101
102 $creteria = array(
103 'property_image.property_id' => $property_id
104 );
105
106 $property = isset($property[0]) ? $property[0] : NULL;
107
108 $creteria = array(
109 'property_has_payment_card_type.property_id' => $property_id
110 );
111 $pcards = array();
112 $_cards = $this->CI->property_has_payment_card_type_model->select($creteria);
113 foreach ($_cards as $cards) {
114 array_push($pcards, $cards->type);
115 }
116
117 $creteria = array(
118 'property_has_language.property_id' => $property_id
119 );
120 $planguage = array();
121 $_language = $this->CI->property_has_language_model->select($creteria);
122 foreach ($_language as $language) {
123 array_push($planguage, $language->code_lang);
124 }
125
126 $creteria = array(
127 'property_cancellation_policy.property_id' => $property_id
128 );
129 $cancel_within = array();
130 $cancel_policy = '';
131
132 if ($cancel_policy == '') {
133 $cancel_policy .= ' Deposits paid are non-refundable.';
134 }
135
136 $this->CI->load->model('extranet/property_has_currency_model');
137 $this->CI->load->model('extranet/currency_exchange_model');
138
139 $creteria = array(
140 'property_has_currency.property_id' => $property_id
141 );
142 $pcurrency = array();
143 $_currency = $this->CI->property_has_currency_model->select($creteria);
144 foreach ($_currency as $currency) {
145 array_push($pcurrency, $currency->currency_id);
146 }
147
148 $return = NULL;
149
150 $creteria = array(
151 'district_has_property.property_id' => $property_id
152 );
153 $district_has_property = $this->CI->district_has_property_model->select($creteria);
154
155 $property_district = array();
156
157 foreach ($district_has_property as $value) {
158 $district_value = array(
159 'ID' => $value->id,
160 'CITY_ID' => $value->city_id,
161 'NAME' => $value->district_name,
162 'POLYGON' => $value->polygon_coordinates,
163 'AREA' => $value->area,
164 'SLUG' => $value->slug,
165 'UM_ID' => $value->um_id,
166 'POLYGON_COORDINATES' => $value->polygon_coordinates
167 );
168 array_push($property_district, $district_value);
169 }
170
171 $creteria = array(
172 'property_has_landmark.property_id' => $property_id
173 );
174 $property_has_landmark = $this->CI->property_has_landmark_model->select($creteria);
175
176 $property_landmark = array();
177
178 foreach ($property_has_landmark as $value) {
179 $type = $value->type;
180 if ($value->landmark_name == "City Center") {
181 $type = "city_center";
182 }
183 $landmark_value = array(
184 'ID' => $value->id,
185 'LANDMARK_SOURCE_ID' => $value->landmark_source_id,
186 'GEO' => array(
187 'LATITUDE' => $value->geo_latitude,
188 'LONGITUDE' => $value->geo_longitude
189 ),
190 'NAME' => $value->landmark_name,
191 'DISTANCE' => $value->distance,
192 'TYPE' => $type,
193 'SLUG' => $value->slug
194 );
195 array_push($property_landmark, $landmark_value);
196 }
197
198 $front_images = array();
199
200 $room_images = $this->CI->room_image_model->select(array('room_image.property_id' => $property_id));
201 foreach ($room_images as $image) {
202 $_image = array();
203 $_image['thumb'] = get_dorms_path("thumbs/", $image->thumb);
204 $_image['image'] = get_dorms_path("images/", $image->image);
205 $_image['type'] = $image->type;
206 $_image['size'] = $image->size;
207 $_image['title'] = $image->title;
208 $_image['description'] = $image->description;
209 $_image = array_change_key_case($_image, CASE_UPPER);
210 //array_push($front_images, (object)$_image);
211 }
212
213 $amenity_images = $this->property_amenity_images($property_id, $language_id);
214 foreach ($amenity_images as $category => $images) {
215 foreach ($images as $image) {
216 if ($image->FRONT_IMAGE == 1)
217 array_push($front_images, $image);
218 }
219 }
220
221 if ($property != NULL) {
222
223 $currency = NULL;
224
225 if (strlen($property->currency_code) > 0) {
226 $creteria = array(
227 'currency_exchange.currency_cross' => $property->currency_code . 'USD'
228 );
229 $currency = $this->CI->currency_exchange_model->select($creteria);
230 }
231
232 $currency = isset($currency[0]) ? $currency[0] : NULL;
233
234 $criteria = array(
235 'property_has_tax.property_id' => $property_id
236 );
237 $property_tax = $this->CI->property_has_tax_model->select($criteria);
238 $taxes = array();
239 $currency_guest = $this->CI->config->item('site_currency_selected');
240 foreach ($property_tax as $tax_value) {
241 $_tax = array();
242 $_tax['AMOUNT'] = $tax_value->tax_value;
243 $_tax['AMOUNT_GUEST'] = $this->CI->forex->exchange($tax_value->tax_value, $property->currency_code, $currency_guest);
244 $_tax['CLASS'] = ucfirst(strtolower($tax_value->tax_name));
245 $_tax['TAX_TYPE'] = ucfirst(strtolower($tax_value->tax_type));
246 $_tax['INCLUDED'] = $tax_value->included;
247 $_tax['TIMELINE'] = $tax_value->timeline;
248 $_tax['GUEST_ROOM'] = $tax_value->guest_room;
249 array_push($taxes, $_tax);
250 }
251
252 if (!count($cancel_within)) {
253 array_push($cancel_within, 0);
254 }
255
256 if ($property->switch_transport_types == 'yes') {
257 $transport = $this->CI->transport_model->select_translated(array('property_id' => $property_id), $language_id);
258 } else {
259 $transport = array();
260 }
261
262 $return['PROPERTY']['ID'] = $property->id;
263 $return['PROPERTY']['NAME'] = $property->property_name;
264
265 $return['PROPERTY']['DESCRIPTION']['ABOUT'] = isset($property->about_translated) ? $property->about_translated : $property->about;
266 $return['PROPERTY']['DESCRIPTION']['OVERVIEW'] = isset($property->overview_translated) ? $property->overview_translated : $property->overview;
267 $return['PROPERTY']['DESCRIPTION']['SOCIAL_INFO'] = isset($property->social_info_translated) ? $property->social_info_translated : $property->social_info;
268 $return['PROPERTY']['DESCRIPTION']['IMPORTANT'] = isset($property->important_info_translated) ? $property->important_info_translated : $property->important_info;
269 $return['PROPERTY']['DESCRIPTION']['SOLO_TRAVELLER'] = isset($property->solo_traveller_translated) ? $property->solo_traveller_translated : $property->solo_traveller;
270
271 $all_currencies = $this->CI->currency_model->select();
272 foreach ($all_currencies as $c)
273 $return['PROPERTY']['CURRENCIES'][$c->id] = $c->currency_code;
274 $return['PROPERTY']['AMENITY'] = $this->property_amenity($property_id, $language_id);
275 $return['PROPERTY']['AMENITY_IMAGES'] = $amenity_images;
276 $return['PROPERTY']['SHORTDESCRIPTION'] = isset($property->overview_translated) ? $property->overview_translated : $property->overview;
277 $return['PROPERTY']['LONGDESCRIPTION'] = isset($property->overview_translated) ? $property->overview_translated : $property->overview;
278 $return['PROPERTY']['CARDTYPES'] = implode(", ", $pcards);
279 $return['PROPERTY']['LINK'] = site_url('/whostel/property/' . $property->id);
280 $return['PROPERTY']['ACCOMMODATIONDESCRIPTION'] = "";
281 $return['PROPERTY']['DIRECTIONS'] = $property->directions;
282 $return['PROPERTY']['IMPORTANTINFORMATION'] = $property->important_info;
283 $return['PROPERTY']['LOCATIONINFO'] = "";
284 $return['PROPERTY']['ABOUT'] = $property->about;
285 $return['PROPERTY']['CANCELLATIONINFORMATION']['CANCELLATIONPERIOD'] = min($cancel_within);
286 $return['PROPERTY']['CANCELLATIONINFORMATION']['CANCELLATIONPOLICY'] = $cancel_policy;
287
288 $return['PROPERTY']['TYPE'] = $property->property_type;
289 $return['PROPERTY']['IMAGES'] = $front_images;
290 $return['PROPERTY']['TAX'] = $taxes;
291
292 $return['PROPERTY']['MODIFIED'] = 0;
293 $return['PROPERTY']['LASTMOD'] = $property->updated;
294 $return['PROPERTY']['MAX_BEDS_PER_BOOKING'] = $property->regular_maximum_booking;
295 $return['PROPERTY']['GROUPS'] = array();
296 $return['PROPERTY']['GROUPS']['ACCEPT'] = $property->group_booking;
297 $return['PROPERTY']['GROUPS']['MIN_BEDS'] = $property->group_minimum_booking;
298 $return['PROPERTY']['GROUPS']['MAX_BEDS'] = $property->group_maximum_booking;
299 $return['PROPERTY']['CHECKINTIMES']['CHECKIN'] = ""; //$property->check_in_from_time;
300 $return['PROPERTY']['CHECKINTIMES']['CHECKOUT'] = ""; //$property->check_out_to_time;
301
302 $return['PROPERTY']['EMAIL']['PROPERTY'] = $property->email;
303 $return['PROPERTY']['EMAIL']['RESERVATION'] = $property->email_reservation;
304 $return['PROPERTY']['EMAIL']['BILLING'] = $property->billing_email;
305 $return['PROPERTY']['EMAIL']['OFFICE'] = $property->office_email;
306
307 $return['PROPERTY']['ADDRESS']['STREET1'] = $property->street_address;
308 $return['PROPERTY']['ADDRESS']['STREET2'] = NULL;
309 $return['PROPERTY']['ADDRESS']['STREET3'] = NULL;
310 $return['PROPERTY']['ADDRESS']['CITY'] = $property->city;
311 $return['PROPERTY']['ADDRESS']['STATE'] = $property->state;
312 $return['PROPERTY']['ADDRESS']['ZIP'] = $property->zip;
313 $return['PROPERTY']['ADDRESS']['COUNTRY'] = $property->country;
314 $return['PROPERTY']['ADDRESS']['CONTINENT'] = $property->continent;
315 $return['PROPERTY']['PHONE'] = array(
316 'CONTACT' => $property->phone_international,
317 'CUSTOMER' => $property->customer_phone,
318 'OFFICE' => $property->office_phone,
319 'INTERNATIONAL' => $property->phone_international,
320 );
321 $return['PROPERTY']['WEBSITE'] = $property->website;
322 $return['PROPERTY']['FAX'] = $property->fax;
323 $return['PROPERTY']['CURRENCY']['ID'] = $property->currency_id;
324 $return['PROPERTY']['CURRENCY']['NAME'] = $property->currency_description;
325 $return['PROPERTY']['CURRENCY']['EXCHRATE'] = ($currency != NULL) ? $currency->exchange_value : NULL;
326 $return['PROPERTY']['CURRENCY']['CODE'] = $property->currency_code;
327
328 $return['PROPERTY']['APPROVED'] = $property->approved;
329 $return['PROPERTY']['ENABLED'] = $property->enabled;
330 $return['PROPERTY']['EX_STATUS'] = $property->status;
331 if ($property->approved == 'no' || $property->enabled == 'no' || $property->status < 4) {
332 $return['PROPERTY']['ENABLE_BOOKING'] = 'no';
333 } else {
334 $return['PROPERTY']['ENABLE_BOOKING'] = 'yes';
335 }
336 $return['PROPERTY']['LANGUAGES'] = implode(", ", $planguage);
337 $return['PROPERTY']['GPS']['LAT'] = $property->geo_latitude;
338 $return['PROPERTY']['GPS']['LON'] = $property->geo_longitude;
339
340 $return['PROPERTY']['RATING'] = '65%';
341
342 $return['PROPERTY']['DISTRICT'] = $property_district;
343 $return['PROPERTY']['LANDMARK'] = $property_landmark;
344 $return['PROPERTY']['TRANSPORT'] = $transport;
345 $return['PROPERTY']['REVIEW'] = $this->property_review($property_id);
346
347 $return = array_change_key_case($return, CASE_UPPER);
348 }
349
350 return $return;
351 }
352
353 function property_review($property_id) {
354
355 $this->CI->load->model('extranet/review_model');
356 $this->CI->load->model('extranet/review_comment_model');
357 $this->CI->load->model('extranet/rating_model');
358
359 $review = $this->CI->review_model->select(array('review.property_id = ' => $property_id));
360 $review_comment = $this->CI->review_comment_model->select(array('review.property_id = ' => $property_id));
361 $rating = $this->CI->rating_model->select(array('rating.property_id = ' => $property_id));
362
363 $review_comment_data = array();
364 foreach ($review_comment as $_review_comment) {
365 if (!isset($review_comment_data[$_review_comment->review_id])) {
366 $review_comment_data[$_review_comment->review_id] = array();
367 }
368 $response = array();
369 $response['publisher'] = $_review_comment->first_name . ' ' . $_review_comment->last_name;
370 $response['review_comment'] = $_review_comment->review_comment;
371 $response['published'] = $_review_comment->created;
372 array_push($review_comment_data[$_review_comment->review_id], $response);
373 }
374
375 $rating_data = array();
376
377 foreach ($rating as $_rating) {
378 if (!isset($rating_data[$_rating->review_id])) {
379 $rating_data[$_rating->review_id] = array();
380 }
381 $response = array();
382 $response['rating_category'] = $_rating->name;
383 $response['rating_value'] = $_rating->rating;
384 array_push($rating_data[$_rating->review_id], $response);
385 }
386
387 $return = array();
388
389 foreach ($review as $_review) {
390 $response = array();
391 $response['guest'] = $_review->first_name . ' ' . $_review->last_name;
392 $response['review'] = $_review->review;
393 $response['published'] = $_review->approve_date;
394 $response['rating'] = isset($rating_data[$_review->review_id]) ? $rating_data[$_review->review_id] : array();
395 $response['response'] = isset($review_comment_data[$_review->review_id]) ? $review_comment_data[$_review->review_id] : array();
396 array_push($return, $response);
397 }
398 return $return;
399 }
400
401 function property_booking($property_id) {
402
403 $this->CI->load->model('extranet/booking_model');
404 $booking = $this->CI->booking_model->select(array('booking.property_id' => $property_id));
405 return $booking;
406 }
407
408 function booking_by_number($property_id, $booking_id) {
409
410 $this->CI->load->model('extranet/booking_model');
411 $booking = $this->CI->booking_model->select(array('booking.property_id' => $property_id, 'booking.id' => $booking_id));
412
413 if (isset($booking[0])) {
414 return $booking[0];
415 }
416 return NULL;
417 }
418
419 private function get_amenities_property_or_room($id, $type = 'property', $language_id = NULL) {
420
421 if ($type !== 'property' && $type !== 'room')
422 return false;
423
424 $this->CI->load->model('extranet/currency_model');
425 $this->CI->load->model('extranet/amenity_model');
426 $this->CI->load->model('extranet/amenity_category_model');
427 $this->CI->load->model('extranet/room_model');
428 $this->CI->load->model('extranet/property_has_amenity_model');
429
430 if ($type == 'property') {
431 $this->CI->load->model('extranet/amenity_image_property_model');
432 } else if ($type == 'room') {
433 $this->CI->load->model('extranet/room_has_amenity_model');
434 $this->CI->load->model('extranet/amenity_image_room_model');
435 }
436
437 $amenity = $this->CI->amenity_model->select_translated(null, null, $language_id);
438
439 if ($type == 'property') {
440 $amenity_category = $this->CI->amenity_category_model->select_translated(array('amenity_category.id !=' => 6), $language_id);
441 $amenity_list = $this->CI->property_has_amenity_model->select(array('property_has_amenity.property_id' => $id));
442 } else if ($type == 'room') {
443 $room = $this->CI->room_model->get_room($id);
444 $room_type_id = $room->room_type_id;
445 $amenity_category = $this->CI->amenity_category_model->select_translated(array('amenity_category.id' => 6), $language_id);
446 $amenity_list = $this->CI->room_has_amenity_model->select(array('room_has_amenity.room_id' => $id));
447 $property_amenity_list = $this->CI->property_has_amenity_model->select(array('property_has_amenity.property_id' => $room->property_id));
448 }
449
450 $_property_amenity = array();
451 foreach ($amenity_list as $amenity_value) {
452 $_property_amenity[$amenity_value->amenity_id] = array(
453 'value' => $amenity_value->amenity_value,
454 'comment' => $amenity_value->amenity_comment,
455 'currency' => $amenity_value->currency_id
456 );
457 }
458 if ($type == 'room') {
459 foreach ($property_amenity_list as $amenity_value) {
460 $_property_amenity[$amenity_value->amenity_id] = array(
461 'value' => $amenity_value->amenity_value,
462 'comment' => $amenity_value->amenity_comment,
463 'currency' => $amenity_value->currency_id
464 );
465 }
466 }
467
468 $amenity_image = array();
469 if ($type == 'property') {
470 $amenity_image_list = $this->CI->amenity_image_property_model->select_translated(array('property_has_amenity.property_id' => $id), $language_id);
471 } else if ($type == 'room') {
472 $amenity_image_list = $this->CI->amenity_image_room_model->select_translated(array('room_has_amenity.room_id' => $id), $language_id);
473 }
474
475 foreach ($amenity as $value) {
476 foreach ($amenity_image_list as $image) {
477 if (!isset($amenity_image[$value->id])) {
478 $amenity_image[$value->id] = array();
479 }
480 $_image = array();
481 $_image['thumb'] = get_dorms_path("thumbs/", $image->thumb);
482 $_image['image'] = get_dorms_path("images/", $image->image);
483 $_image['type'] = $image->type;
484 $_image['size'] = $image->size;
485 $_image['title'] = $image->title;
486 $_image['description'] = $image->description;
487 $_image['comment'] = ""; //$image->comment;
488 $_image = array_change_key_case($_image, CASE_UPPER);
489 if ($value->id == $image->amenity_id) {
490 array_push($amenity_image[$value->id], (object) $_image);
491 }
492 }
493 }
494
495 $amenity_parent = array();
496
497 foreach ($amenity as $result) {
498 if (empty($result->amenity_id)) {
499 $amenity_parent[$result->id] = array();
500 }
501 }
502
503 $default_room_amenities = array();
504 $currency_guest = $this->CI->config->item('site_currency_selected');
505
506 foreach ($amenity as $result) {
507 if ($type == 'room' && !is_null($result->amenity_show_in_pricing_table) && $result->amenity_show_in_pricing_table == 1) {
508 if (($room_type_id == 1 && $result->amenity_category_id == 3) || ($room_type_id == 2 && $result->amenity_category_id == 2)) {
509 if (isset($_property_amenity[$result->id]) && ($_property_amenity[$result->id]['value'] == 'Yes' || $_property_amenity[$result->id]['value'] == 'On request' || $_property_amenity[$result->id]['value'] == 'Yes in all rooms' || $_property_amenity[$result->id]['value'] == 'Yes in all dorms' || $_property_amenity[$result->id]['value'] == 'Yes on every floor')) {
510 array_push($default_room_amenities, $result->id);
511 }
512 }
513 }
514
515 if (!empty($result->amenity_id)) {
516 if (isset($_property_amenity[$result->id])) {
517
518 $amenity_comment = isset($_property_amenity[$result->id]['comment']) ? $_property_amenity[$result->id]['comment'] : '';
519
520 if (strpos($result->amenity_element, 'cost') !== false) {
521 $amenity_variable = 'cost';
522 } else if ($result->amenity_variable == 'money') {
523 $amenity_variable = 'currency';
524 } else {
525 $amenity_variable = $result->amenity_variable;
526 }
527 if ($result->amenity_on_default) {
528
529 $amenity_value = isset($_property_amenity[$result->id]['value']) ? $_property_amenity[$result->id]['value'] : $result->amenity_default;
530
531 if (strpos($result->amenity_element, 'included') === false && $amenity_value == 'No')
532 continue;
533 if (strpos($result->amenity_element, 'cost') !== false && $amenity_value == '0.00')
534 continue;
535
536 $_result = array();
537 if (!is_null($_property_amenity[$result->id]['currency'])) {
538 $currency = $this->CI->currency_model->get_currency($_property_amenity[$result->id]['currency']);
539 if (isset($currency)) {
540 $_result['amenity_currency_symbol'] = format_currency_symbol($currency->currency_code);
541 $_result['amenity_currency_code'] = $currency->currency_code;
542 }
543 }
544
545 $_result['amenity_id'] = $result->id;
546 $_result['amenity_room_parent_id'] = $result->amenity_room_parent_id;
547 $_result['amenity_output'] = $result->amenity_output;
548 $_result['amenity_element'] = $result->amenity_element;
549 $_result['amenity_default'] = $result->amenity_default;
550 $_result['amenity_order'] = $result->amenity_order;
551 $_result['amenity_value'] = $amenity_value;
552 if ($amenity_variable == 'currency' || $amenity_variable == 'cost') {
553 $_result['amenity_value_guest'] = $this->CI->forex->exchange($amenity_value, $_result['amenity_currency_code'], $currency_guest);
554 }
555 $_result['amenity_variable'] = $amenity_variable;
556 $_result['amenity_comment'] = $amenity_comment;
557 if (strpos($result->amenity_element, 'set_menu') !== false) {
558 $amenity_parent[$result->amenity_id]['amenity_set_menu'] = $amenity_value;
559 $amenity_parent[$result->amenity_id]['amenity_is_free'] = 'No';
560 $amenity_parent[$result->amenity_id]['amenity_has_cost'] = false;
561 }
562 if (strpos($result->amenity_element, 'included') !== false)
563 $amenity_parent[$result->amenity_id]['amenity_is_free'] = $amenity_value;
564 if (strpos($result->amenity_element, 'included') !== false && isset($amenity_parent[$result->amenity_id]['amenity_set_menu']) && $amenity_parent[$result->amenity_id]['amenity_set_menu'] == 'No')
565 $amenity_parent[$result->amenity_id]['amenity_is_free'] = 'No';
566 if (strpos($result->amenity_element, 'cost') !== false)
567 $amenity_parent[$result->amenity_id]['amenity_has_cost'] = strpos($result->amenity_element, 'cost');
568 if (strpos($result->amenity_element, 'cost') !== false && isset($amenity_parent[$result->amenity_id]['amenity_set_menu']) && $amenity_parent[$result->amenity_id]['amenity_set_menu'] == 'No')
569 $amenity_parent[$result->amenity_id]['amenity_has_cost'] = false;
570 if (strpos($result->amenity_element, 'charged') !== false)
571 $amenity_parent[$result->amenity_id]['amenity_charged'] = strtolower($amenity_value);
572 if (isset($amenity_parent[$result->id]) && count($amenity_parent[$result->id])) {
573 $_result['amenity_children'] = $amenity_parent[$result->id];
574 }
575 if (isset($amenity_image[$result->id]) && count($amenity_image[$result->id])) {
576 $_result['amenity_image'] = $amenity_image[$result->id];
577 }
578 $_result = array_change_key_case($_result, CASE_UPPER);
579 if (!isset($amenity_parent[$result->amenity_id]['amenity_children']))
580 $amenity_parent[$result->amenity_id]['amenity_children'] = array();
581
582 if(strpos($result->amenity_element, 'set_menu') === false)
583 array_push($amenity_parent[$result->amenity_id]['amenity_children'], (object) $_result);
584 else if($amenity_value == 'Yes')
585 array_push($amenity_parent[$result->amenity_id]['amenity_children'], (object) $_result);
586 } else {
587 $amenity_value = isset($_property_amenity[$result->id]['value']) ? $_property_amenity[$result->id]['value'] : NULL;
588
589 switch ($result->amenity_variable) {
590 case 'age-range':
591 $amenity_value = json_decode($amenity_value);
592 break;
593 case 'late-checkout':
594 $amenity_value = json_decode($amenity_value);
595 foreach ($amenity_value as $a_value) {
596 $currency = $this->CI->currency_model->get_currency($a_value->currency_id);
597 if (isset($currency)) {
598 $a_value->currency_symbol = format_currency_symbol($currency->currency_code);
599 $a_value->currency_code = $currency->currency_code;
600 }
601 if ($a_value->cost_type == 'amount') {
602 $a_value->cost_guest = $this->CI->forex->exchange($a_value->cost, $a_value->currency_code, $currency_guest);
603 }
604 }
605 break;
606 case 'time-range':
607 $amenity_value = json_decode($amenity_value);
608 break;
609 case 'limit-range':
610 $amenity_value = json_decode($amenity_value);
611 break;
612 default:
613 break;
614 }
615
616 if (strpos($result->amenity_element, 'included') === false && strpos($result->amenity_element, 'set_menu') === false && ($amenity_value == 'No' || $amenity_value == 'Yes in some dorms' || $amenity_value == 'Yes in some rooms'))
617 continue;
618 if (strpos($result->amenity_element, 'cost') !== false && $amenity_value == '0.00')
619 continue;
620
621 if ($amenity_value != NULL) {
622
623 $_result = array();
624 if (!is_null($_property_amenity[$result->id]['currency'])) {
625 $currency = $this->CI->currency_model->get_currency($_property_amenity[$result->id]['currency']);
626 if (isset($currency)) {
627 $_result['amenity_currency_symbol'] = format_currency_symbol($currency->currency_code);
628 $_result['amenity_currency_code'] = $currency->currency_code;
629 }
630 }
631
632 $_result['amenity_id'] = $result->id;
633 $_result['amenity_room_parent_id'] = $result->amenity_room_parent_id;
634 $_result['amenity_output'] = $result->amenity_output;
635 $_result['amenity_element'] = $result->amenity_element;
636 $_result['amenity_default'] = $result->amenity_default;
637 $_result['amenity_order'] = $result->amenity_order;
638 $_result['amenity_value'] = $amenity_value;
639 if ($amenity_variable == 'currency' || $amenity_variable == 'cost') {
640 $_result['amenity_value_guest'] = $this->CI->forex->exchange($amenity_value, $_result['amenity_currency_code'], $currency_guest);
641 }
642 $_result['amenity_variable'] = $amenity_variable;
643 $_result['amenity_comment'] = $amenity_comment;
644 if (strpos($result->amenity_element, 'set_menu') !== false) {
645 $amenity_parent[$result->amenity_id]['amenity_set_menu'] = $amenity_value;
646 $amenity_parent[$result->amenity_id]['amenity_is_free'] = 'No';
647 $amenity_parent[$result->amenity_id]['amenity_has_cost'] = false;
648 }
649 if (strpos($result->amenity_element, 'included') !== false)
650 $amenity_parent[$result->amenity_id]['amenity_is_free'] = $amenity_value;
651 if (strpos($result->amenity_element, 'included') !== false && isset($amenity_parent[$result->amenity_id]['amenity_set_menu']) && $amenity_parent[$result->amenity_id]['amenity_set_menu'] == 'No')
652 $amenity_parent[$result->amenity_id]['amenity_is_free'] = 'No';
653 if (strpos($result->amenity_element, 'cost') !== false)
654 $amenity_parent[$result->amenity_id]['amenity_has_cost'] = strpos($result->amenity_element, 'cost');
655 if (strpos($result->amenity_element, 'cost') !== false && isset($amenity_parent[$result->amenity_id]['amenity_set_menu']) && $amenity_parent[$result->amenity_id]['amenity_set_menu'] == 'No')
656 $amenity_parent[$result->amenity_id]['amenity_has_cost'] = false;
657 if (strpos($result->amenity_element, 'charged') !== false)
658 $amenity_parent[$result->amenity_id]['amenity_charged'] = strtolower($amenity_value);
659 if (isset($amenity_parent[$result->id]) && count($amenity_parent[$result->id])) {
660 $_result['amenity_children'] = $amenity_parent[$result->id];
661 }
662 if (isset($amenity_image[$result->id]) && count($amenity_image[$result->id])) {
663 $_result['amenity_image'] = $amenity_image[$result->id];
664 }
665 $_result = array_change_key_case($_result, CASE_UPPER);
666 if (!isset($amenity_parent[$result->amenity_id]['amenity_children']))
667 $amenity_parent[$result->amenity_id]['amenity_children'] = array();
668 if(strpos($result->amenity_element, 'set_menu') === false)
669 array_push($amenity_parent[$result->amenity_id]['amenity_children'], (object) $_result);
670 else if($amenity_value == 'Yes')
671 array_push($amenity_parent[$result->amenity_id]['amenity_children'], (object) $_result);
672 }
673 }
674 }
675 }
676 }
677
678 $amenity_response = array();
679 $amenity_duplicates = array();
680
681 foreach ($amenity_category as $category) {
682 $this->data['amenity_categories'][$category->id] = $category;
683 $amenity_response[$category->id] = array();
684 foreach ($amenity as $result) {
685 if (empty($result->amenity_id)) {
686 if ($category->id == $result->amenity_category_id) {
687 if ((isset($_property_amenity[$result->id]) && $_property_amenity[$result->id]['value'] != 'No') || ($type == 'room' && in_array($result->amenity_room_parent_id, $default_room_amenities))) {
688 if ($result->amenity_hide_front == 1)
689 continue;
690 if ($type == 'room' && isset($_property_amenity[$result->amenity_room_parent_id]['value']) && $_property_amenity[$result->amenity_room_parent_id]['value'] == 'No') {
691 continue;
692 }
693 if ($type == 'room' && in_array($result->amenity_room_parent_id, $default_room_amenities)) {
694 array_push($amenity_duplicates, $result->amenity_room_parent_id);
695 }
696
697 $amenity_comment = isset($_property_amenity[$result->id]['comment']) ? $_property_amenity[$result->id]['comment'] : '';
698
699 if (strpos($result->amenity_element, 'cost') !== false) {
700 $amenity_variable = 'cost';
701 } else if ($result->amenity_variable == 'money') {
702 $amenity_variable = 'currency';
703 } else {
704 $amenity_variable = 'varchar';
705 }
706 if ($result->amenity_on_default) {
707
708 $amenity_value = isset($_property_amenity[$result->id]['value']) ? $_property_amenity[$result->id]['value'] : $result->amenity_default;
709
710 if ($amenity_value == 'No' || $amenity_value == 'Yes in some dorms' || $amenity_value == 'Yes in some rooms')
711 continue;
712
713 $_result = array();
714 $_result['amenity_id'] = $result->id;
715 $_result['amenity_output'] = $result->amenity_output;
716 $_result['amenity_element'] = $result->amenity_element;
717 $_result['amenity_default'] = $result->amenity_default;
718 $_result['amenity_order'] = $result->amenity_order;
719 $_result['amenity_value'] = $amenity_value;
720 $_result['amenity_variable'] = $amenity_variable;
721 $_result['amenity_comment'] = $amenity_comment;
722 if ($result->amenity_default_free == 1)
723 $_result['amenity_is_free'] = 'Yes';
724 else if (isset($amenity_parent[$result->id]['amenity_is_free']))
725 $_result['amenity_is_free'] = $amenity_parent[$result->id]['amenity_is_free'];
726 $_result['amenity_has_cost'] = isset($amenity_parent[$result->id]['amenity_has_cost']);
727 if (isset($amenity_parent[$result->id]['amenity_set_menu'])) {
728 $_result['amenity_set_menu'] = $amenity_parent[$result->id]['amenity_set_menu'];
729 $_result['amenity_is_free'] = $amenity_parent[$result->id]['amenity_set_menu'] == 'No' ? 'No' : $amenity_parent[$result->id]['amenity_is_free'];
730 $_result['amenity_has_cost'] = $amenity_parent[$result->id]['amenity_set_menu'] == 'No' ? false : $amenity_parent[$result->id]['amenity_has_cost'];
731 }
732 if (isset($amenity_parent[$result->id]['amenity_charged']))
733 $_result['amenity_charged'] = $amenity_parent[$result->id]['amenity_charged'];
734 if (isset($amenity_parent[$result->id]['amenity_children']) && count($amenity_parent[$result->id]['amenity_children'])) {
735 $_result['amenity_children'] = array();
736 $children = $amenity_parent[$result->id]['amenity_children'];
737 foreach ($children as $child) {
738 if (strpos($child->AMENITY_ELEMENT, 'included') !== false)
739 continue;
740 if (strpos($child->AMENITY_ELEMENT, 'charged') !== false)
741 continue;
742 if (strpos($child->AMENITY_ELEMENT, 'timed') !== false)
743 continue;
744 if (isset($_result['amenity_is_free']) && $_result['amenity_is_free'] == 'Yes') {
745 if (strpos($child->AMENITY_ELEMENT, 'charged') !== false || strpos($child->AMENITY_ELEMENT, 'cost') !== false)
746 continue;
747 }
748 array_push($_result['amenity_children'], $child);
749 }
750 }
751 if (isset($amenity_image[$result->id]) && count($amenity_image[$result->id])) {
752 $_result['amenity_image'] = $amenity_image[$result->id];
753 }
754 $_result = array_change_key_case($_result, CASE_UPPER);
755 array_push($amenity_response[$category->id], (object) $_result);
756 } else {
757
758 $amenity_value = isset($_property_amenity[$result->id]['value']) ? $_property_amenity[$result->id]['value'] : NULL;
759
760 if($type == 'room' && in_array($result->amenity_room_parent_id, $default_room_amenities)) {
761 $amenity_value = $_property_amenity[$result->amenity_room_parent_id]['value'];
762 }
763
764 if ($amenity_value == 'No' || $amenity_value == 'Yes in some dorms' || $amenity_value == 'Yes in some rooms')
765 continue;
766
767 if ($amenity_value != NULL) {
768 $_result = array();
769 $_result['amenity_id'] = $result->id;
770 $_result['amenity_output'] = $result->amenity_output;
771 $_result['amenity_element'] = $result->amenity_element;
772 $_result['amenity_default'] = $result->amenity_default;
773 $_result['amenity_order'] = $result->amenity_order;
774 $_result['amenity_value'] = $amenity_value;
775 $_result['amenity_variable'] = $amenity_variable;
776 $_result['amenity_comment'] = $amenity_comment;
777 if ($result->amenity_default_free == 1)
778 $_result['amenity_is_free'] = 'Yes';
779 else if (isset($amenity_parent[$result->id]['amenity_is_free']))
780 $_result['amenity_is_free'] = $amenity_parent[$result->id]['amenity_is_free'];
781 $_result['amenity_has_cost'] = isset($amenity_parent[$result->id]['amenity_has_cost']);
782 if (isset($amenity_parent[$result->id]['amenity_set_menu'])) {
783 $_result['amenity_set_menu'] = $amenity_parent[$result->id]['amenity_set_menu'];
784 $_result['amenity_is_free'] = $amenity_parent[$result->id]['amenity_set_menu'] == 'No' ? 'No' : $amenity_parent[$result->id]['amenity_is_free'];
785 $_result['amenity_has_cost'] = $amenity_parent[$result->id]['amenity_set_menu'] == 'No' ? false : $amenity_parent[$result->id]['amenity_has_cost'];
786 }
787 if (isset($amenity_parent[$result->id]['amenity_charged']))
788 $_result['amenity_charged'] = $amenity_parent[$result->id]['amenity_charged'];
789 if (isset($amenity_parent[$result->id]['amenity_children']) && count($amenity_parent[$result->id]['amenity_children'])) {
790 $_result['amenity_children'] = array();
791 $children = $amenity_parent[$result->id]['amenity_children'];
792 foreach ($children as $child) {
793 if (strpos($child->AMENITY_ELEMENT, 'included') !== false)
794 continue;
795 if (strpos($child->AMENITY_ELEMENT, 'charged') !== false)
796 continue;
797 if (strpos($child->AMENITY_ELEMENT, 'timed') !== false)
798 continue;
799 if ((isset($_result['amenity_is_free']) && $_result['amenity_is_free'] == 'Yes') || (isset($_result['amenity_set_menu']) && $_result['amenity_set_menu'] == 'Yes')) {
800 if (strpos($child->AMENITY_ELEMENT, 'charged') !== false || strpos($child->AMENITY_ELEMENT, 'cost') !== false)
801 continue;
802 }
803 array_push($_result['amenity_children'], $child);
804 }
805 }
806 if (isset($amenity_image[$result->id]) && count($amenity_image[$result->id])) {
807 $_result['amenity_image'] = $amenity_image[$result->id];
808 }
809 $_result = array_change_key_case($_result, CASE_UPPER);
810 array_push($amenity_response[$category->id], (object) $_result);
811 }
812 }
813 }
814 }
815 }
816 }
817 }
818
819 foreach ($amenity_response as $key => $category) {
820 $amenity_response[$key] = order_amenity($category);
821 $amenities = array();
822 $amenities_free = array();
823 foreach ($amenity_response[$key] as $amenity) {
824 if (in_array($amenity->AMENITY_ID, $amenity_duplicates))
825 continue;
826 if (isset($amenity->AMENITY_IS_FREE) && $amenity->AMENITY_IS_FREE == 'Yes')
827 array_push($amenities_free, $amenity);
828 else
829 array_push($amenities, $amenity);
830 }
831 $amenity_response[$key] = array(
832 'amenities' => array_merge($amenities_free, $amenities),
833 'title' => $this->data['amenity_categories'][$key]->title,
834 'icon' => $this->data['amenity_categories'][$key]->icon,
835 );
836 }
837
838 return $amenity_response;
839 }
840
841 function get_amenities_images_property_or_room($id, $type = 'property', $language_id = NULL) {
842 if ($type !== 'property' && $type !== 'room')
843 return false;
844
845 $this->CI->load->model('extranet/amenity_model');
846 $this->CI->load->model('extranet/amenity_category_model');
847 if ($type == 'property') {
848 $this->CI->load->model('extranet/property_has_amenity_model');
849 $this->CI->load->model('extranet/amenity_image_property_model');
850 } else if ($type == 'room') {
851 $this->CI->load->model('extranet/room_has_amenity_model');
852 $this->CI->load->model('extranet/amenity_image_room_model');
853 }
854
855 $amenity_category = $this->CI->amenity_category_model->select(array('amenity_category.id !=' => 6));
856
857 $amenity = $this->CI->amenity_model->select();
858
859 if ($type == 'property') {
860 $amenity_list = $this->CI->property_has_amenity_model->select(array('property_has_amenity.property_id' => $id));
861 } else if ($type == 'room') {
862 $amenity_list = $this->CI->room_has_amenity_model->select(array('room_has_amenity.room_id' => $id));
863 }
864
865 $_property_amenity = array();
866 foreach ($amenity_list as $amenity_value) {
867 $_property_amenity[$amenity_value->amenity_id] = array(
868 'value' => $amenity_value->amenity_value,
869 'comment' => $amenity_value->amenity_comment
870 );
871 }
872
873 $amenity_category_images = array();
874 if ($type == 'property') {
875 $amenity_image_list = $this->CI->amenity_image_property_model->select_translated(array('property_has_amenity.property_id' => $id), $language_id);
876 } else if ($type == 'room') {
877 $amenity_image_list = $this->CI->amenity_image_room_model->select_translated(array('room_has_amenity.room_id' => $id), $language_id);
878 }
879
880 foreach ($amenity as $value) {
881 foreach ($amenity_image_list as $image) {
882 $_image = array();
883 $_image['thumb'] = get_dorms_path("thumbs/", $image->thumb);
884 $_image['image'] = get_dorms_path("images/", $image->image);
885 $_image['type'] = $image->type;
886 $_image['size'] = $image->size;
887 $_image['title'] = $image->title;
888 $_image['description'] = $image->description;
889 $_image['front_image'] = $value->amenity_show_content_on_top;
890 $_image['comment'] = ""; //$image->comment;
891 $_image = array_change_key_case($_image, CASE_UPPER);
892 if ($value->id == $image->amenity_id) {
893 if (!isset($amenity_category_images[$value->amenity_category_id]))
894 $amenity_category_images[$value->amenity_category_id] = array();
895 array_push($amenity_category_images[$value->amenity_category_id], (object) $_image);
896 }
897 }
898 }
899
900 return $amenity_category_images;
901 }
902
903 function property_amenity($property_id, $language_id = NULL) {
904 return $this->get_amenities_property_or_room($property_id, 'property', $language_id);
905 }
906
907 function property_amenity_images($property_id, $language_id = NULL) {
908 return $this->get_amenities_images_property_or_room($property_id, 'property', $language_id);
909 }
910
911 function room_amenity($room_id, $language_id = NULL) {
912 return $this->get_amenities_property_or_room($room_id, 'room', $language_id);
913 }
914
915 function rooms($property_id, $language_id = NULL) {
916
917 $this->CI->load->model('extranet/language_model');
918 $this->CI->load->model('extranet/room_model');
919 $this->CI->load->model('extranet/room_image_model');
920 $this->CI->load->model('extranet/room_has_bed_type_model');
921 $this->CI->load->model('extranet/milestone_model');
922 $this->CI->load->model('extranet/cancellation_model');
923 $this->CI->load->model('extranet/rate_plan_has_room_model');
924 $this->CI->load->model('extranet/rate_plan_rule_model');
925
926 if (!is_null($language_id)) {
927 $language = $this->CI->language_model->get_language($language_id);
928 $language_code = str_replace('-', '_', $language->code_lang);
929 } else {
930 $language_code = null;
931 }
932 $rooms = $this->CI->room_model->select(array('room.property_id' => $property_id), $language_code);
933
934 $return = array();
935
936 foreach ($rooms as $room) {
937
938 $image = $this->CI->room_image_model->select(array('room_image.room_id' => $room->id));
939 $bed_type = $this->CI->room_has_bed_type_model->select(array('room_has_bed_type.room_id' => $room->id));
940 $amenities = $this->room_amenity($room->id);
941
942 $rate_plan = $this->CI->rate_plan_has_room_model->room_rate_plan($property_id, $room->id, $room->room_type_id);
943 $rate_plans = array();
944
945 $rate_plan_rule = $this->CI->rate_plan_rule_model->select(array('rate_plan.property_id' => $property_id));
946
947 $cancellation = $this->CI->cancellation_model->select(array('rate_plan.property_id' => $property_id));
948 $milestones = $this->CI->milestone_model->select(array('rate_plan.property_id' => $property_id));
949
950 foreach ($rate_plan as $value) {
951
952 $rate_rule = array();
953
954 if ($value->status == 0) {
955 continue;
956 }
957
958 foreach ($rate_plan_rule as $plan_rule) {
959 if ($plan_rule->rate_plan_id == $value->rate_plan_id) {
960
961 $plan_sell = array();
962
963 if ($plan_rule->action_auto_stop_sell_dorm == 1 || $plan_rule->action_auto_stop_sell_room == 1) {
964 $plan_sell = array(
965 'auto_stop_sell' => TRUE,
966 'plans' => array(
967 'sell_dorm' => (bool) $plan_rule->action_auto_stop_sell_dorm,
968 'sell_room' => (bool) $plan_rule->action_auto_stop_sell_room
969 )
970 );
971 } else {
972 $plan_sell = array(
973 'auto_stop_sell' => FALSE,
974 'plans' => array()
975 );
976 }
977
978 $plan_meal = array();
979
980 if ($plan_rule->action_breakfast == '1' || $plan_rule->action_lunch == '1' || $plan_rule->action_lunch_pack == '1' || $plan_rule->action_dinner == '1') {
981 $plan_meal = array(
982 'meals' => TRUE,
983 'plans' => array(
984 'breakfast' => ($plan_rule->action_breakfast == '1' ? TRUE : FALSE),
985 'lunch' => ($plan_rule->action_lunch == '1' ? TRUE : FALSE),
986 'lunch_pack' => ($plan_rule->action_lunch_pack == '1' ? TRUE : FALSE),
987 'dinner' => ($plan_rule->action_dinner == '1' ? TRUE : FALSE)
988 )
989 );
990 } else {
991 $plan_meal = array(
992 'meals' => FALSE,
993 'plans' => array()
994 );
995 }
996
997 $plan_amenity = array();
998 if ($plan_rule->action_towel == '1' || $plan_rule->action_linen == '1' || $plan_rule->action_internet == '1' || $plan_rule->action_airport_transfer == '1') {
999 $plan_amenity = array(
1000 'amenities' => TRUE,
1001 'plans' => array(
1002 'towel' => ($plan_rule->action_towel == '1' ? TRUE : FALSE),
1003 'linen' => ($plan_rule->action_linen == '1' ? TRUE : FALSE),
1004 'internet' => ($plan_rule->action_internet == '1' ? TRUE : FALSE),
1005 'airport_transfer' => ($plan_rule->action_airport_transfer == '1' ? TRUE : FALSE)
1006 )
1007 );
1008 } else {
1009 $plan_amenity = array(
1010 'amenities' => FALSE,
1011 'plans' => array()
1012 );
1013 }
1014
1015 $variation = FALSE;
1016
1017 if ($value->rate_sync_value > 0) {
1018 $variation = TRUE;
1019 } else {
1020 $variation = FALSE;
1021 }
1022
1023 $cancel = FALSE;
1024 $cancel_rule = array();
1025 if ($plan_rule->setup_late_cancellation_fee == 1) {
1026 foreach ($cancellation as $cancel_value) {
1027 if ($cancel_value->rate_plan_rule_id == $plan_rule->rate_plan_rule_id) {
1028 $cancel = TRUE;
1029 $cancel_rule = [
1030 "interval" => $cancel_value->interval,
1031 "charge" => $cancel_value->charge,
1032 "amount" => $cancel_value->amount,
1033 ];
1034 }
1035 }
1036 }
1037
1038 $milestone = FALSE;
1039 $milestone_rule = array();
1040 if ($plan_rule->setup_milestone == 1) {
1041 foreach ($milestones as $milestone_value) {
1042 if ($milestone_value->rate_plan_rule_id == $plan_rule->rate_plan_rule_id) {
1043 $milestone = TRUE;
1044 $milestone_rule = [
1045 "percentage" => $milestone_value->percentage,
1046 "interval" => $milestone_value->interval,
1047 ];
1048 }
1049 }
1050 }
1051
1052 $price_variation = false;
1053 $price_variation_rules = array();
1054 if ($plan_rule->rate_change_value > 0) {
1055 $price_variation = true;
1056 $price_variation_rules = [
1057 "rate_change" => $plan_rule->rate_change,
1058 "rate_change_type" => $plan_rule->rate_change_type,
1059 "rate_change_value" => $plan_rule->rate_change_value
1060 ];
1061 }
1062
1063 array_push($rate_rule, array(
1064 'id' => $plan_rule->id,
1065 'deposit' => $plan_rule->deposit,
1066 'variation' => $variation,
1067 'milestone' => $milestone,
1068 'milestone_rule' => $milestone_rule,
1069 'cancellation' => $cancel,
1070 'cancellation_rule' => $cancel_rule,
1071 'meals' => $plan_meal,
1072 'amenities' => $plan_amenity,
1073 'auto_stop_sell' => $plan_sell,
1074 'price_variation' => $price_variation,
1075 'price_variation_rule' => $price_variation_rules,
1076 'status' => $plan_rule->rate_plan_rule_status
1077 ));
1078 }
1079 }
1080
1081 array_push($rate_plans, (object) array(
1082 'id' => $value->rate_plan_id,
1083 'title' => $value->title,
1084 'description' => $value->description,
1085 'plan_rule' => $rate_rule,
1086 'level' => $value->child == 'yes' ? 'Child' : 'Parent',
1087 'type' => $value->type,
1088 'rate_sync_change' => $value->rate_sync_change,
1089 'rate_sync_type' => $value->rate_sync_type,
1090 'rate_sync_value' => $value->rate_sync_value,
1091 )
1092 );
1093 }
1094
1095 array_push($return, (object) array(
1096 'room_id' => $room->id,
1097 'room_description' => ($room->grade != 'Standard Grade' ? ' ' . $room->grade : '') . ' ' . (($room->room_sub_type2 != '' && $room->number_of_guests == 2) ? $room->room_sub_type2 : ($room->number_of_guests . ' ' . _('Bed') . ' ' . $room->type)) . ' - ' . $room->gender . ' (' . $room->bathroom . ' )',
1098 'number_of_guests' => $room->number_of_guests,
1099 'number_of_rooms' => $room->number_of_rooms,
1100 'room_type_id' => $room->room_type_id,
1101 'room_gender_id' => $room->room_gender_id,
1102 'room_type' => $room->type,
1103 'room_gender' => $room->gender,
1104 'channel_manager' => $room->channel_manager,
1105 'channel_room_id' => $room->channel_room_id,
1106 'accept_groups' => $room->accept_groups,
1107 'status' => ($room->is_enabled == 'yes') ? 1 : 0,
1108 'image' => $image,
1109 'bed_type' => $bed_type,
1110 'amenities' => $amenities,
1111 'rate_plans' => $rate_plans
1112 ));
1113 }
1114 return $return;
1115 }
1116
1117 function rate_plans($property_id) {
1118
1119 $this->CI->load->model('extranet/rate_plan_model');
1120 $this->CI->load->model('extranet/rate_plan_rule_model');
1121 $this->CI->load->model('extranet/rate_plan_has_room_model');
1122
1123 $rate_plans = $this->CI->rate_plan_model->select(array('rate_plan.property_id' => $property_id));
1124
1125 $rate_plan_rules = $this->CI->rate_plan_rule_model->select(array('rate_plan.property_id' => $property_id));
1126
1127 $plan_rule = array();
1128
1129 foreach ($rate_plan_rules as $rate_plan_rule) {
1130
1131 if (!isset($plan_rule[$rate_plan_rule->rate_plan_id])) {
1132 $plan_rule[$rate_plan_rule->rate_plan_id] = array();
1133 }
1134
1135 $rule = array(
1136 'rate_plan_rule_id' => $rate_plan_rule->rate_plan_rule_id,
1137 'deposit' => $rate_plan_rule->deposit,
1138 'rate_change' => $rate_plan_rule->rate_change,
1139 'rate_change_type' => $rate_plan_rule->rate_change_type,
1140 'rate_change_value' => $rate_plan_rule->rate_change_value,
1141 'activated' => $rate_plan_rule->rate_plan_rule_status
1142 );
1143
1144 array_push($plan_rule[$rate_plan_rule->rate_plan_id], $rule);
1145 }
1146
1147 $parent = array();
1148
1149 foreach ($rate_plans as $rate_plan) {
1150 if ($rate_plan->child == 'yes') {
1151
1152 if (!isset($parent[$rate_plan->rate_plan_id])) {
1153 $parent[$rate_plan->rate_plan_id] = array();
1154 }
1155
1156 $children = array(
1157 'rate_plan_id' => $rate_plan->id,
1158 'rate_plan_title' => $rate_plan->title,
1159 'rate_sync_change' => $rate_plan->rate_sync_change,
1160 'rate_sync_type' => $rate_plan->rate_sync_type,
1161 'rate_sync_value' => $rate_plan->rate_sync_value,
1162 'rate_plan_rules' => $plan_rule[$rate_plan->id],
1163 'activated' => $rate_plan->status,
1164 );
1165 array_push($parent[$rate_plan->rate_plan_id], $children);
1166 }
1167 }
1168
1169 $return = array();
1170 foreach ($rate_plans as $rate_plan) {
1171
1172 if ($rate_plan->child == 'yes') {
1173 continue;
1174 // avoid child plans in response
1175 // they only should be as a sub-item to the parent
1176 }
1177 $rooms = '';
1178
1179 switch ($rate_plan->applicable) {
1180
1181 case 'standard':
1182 $rooms = 'BOTH';
1183 break;
1184
1185 case 'rooms':
1186 $rooms = 'ROOM';
1187 break;
1188
1189 case 'dorms':
1190 $rooms = 'DORM';
1191 break;
1192
1193 case 'selected':
1194
1195 $plan_room = $this->CI->rate_plan_has_room_model->select(array('rate_plan_has_room.rate_plan_id' => $rate_plan->id));
1196
1197 $rooms = array();
1198 foreach ($plan_room as $room) {
1199 array_push($rooms, $room->room_id);
1200 }
1201
1202 $rooms = array_unique($rooms);
1203 $rooms = array_values($rooms);
1204
1205 break;
1206
1207 default:
1208 break;
1209 }
1210
1211 array_push($return, (object) array(
1212 'rate_plan_id' => $rate_plan->id,
1213 'rate_plan_title' => $rate_plan->title,
1214 'rate_plan_parent' => $rate_plan->child == 'no' ? TRUE : FALSE,
1215 'rate_plan_rules' => $plan_rule[$rate_plan->id],
1216 'applicable' => $rooms,
1217 'activated' => $rate_plan->status,
1218 'children' => isset($parent[$rate_plan->id]) ? $parent[$rate_plan->id] : NULL
1219 ));
1220 }
1221 return $return;
1222 }
1223
1224 function get_rateplan_prices($rate_plan_id, $channel_price, $channel_currency = null, $property_currency = null) {
1225
1226 // gets 2 rate plan rules
1227 // calculates prices
1228 // returns list with price and price option
1229 $this->CI->load->model('extranet/rate_plan_rule_model');
1230 $this->CI->load->library('forex');
1231
1232 if ($channel_currency == null || $property_currency == null || $channel_currency == $property_currency) {
1233 $price_input = $channel_price;
1234 } else {
1235 $price_input = $this->CI->forex->exchange($channel_price, $channel_currency, $property_currency);
1236 }
1237
1238
1239
1240 $rate_plan_rule_0 = $this->CI->rate_plan_rule_model->select(array('rate_plan_rule.deposit !=' => "100", "rate_plan_rule.rate_plan_id" => $rate_plan_id))[0];
1241 $rate_plan_rule_100 = $this->CI->rate_plan_rule_model->select(array('rate_plan_rule.deposit' => "100", "rate_plan_rule.rate_plan_id" => $rate_plan_id))[0];
1242
1243 $price = NULL;
1244 $price_option = NULL;
1245 if ($rate_plan_rule_0->rate_plan_rule_status == "1") {
1246 $price = calculate_price_adjustment($rate_plan_rule_0->rate_change, $rate_plan_rule_0->rate_change_type, $rate_plan_rule_0->rate_change_value, $price_input);
1247 }
1248
1249 if ($rate_plan_rule_100->rate_plan_rule_status == "1") {
1250 $price_option = calculate_price_adjustment($rate_plan_rule_100->rate_change, $rate_plan_rule_100->rate_change_type, $rate_plan_rule_100->rate_change_value, $price_input);
1251 }
1252
1253 // price_input is not rounded, other fields are rounded on 2 decimals with calculate_price_adjustment
1254 return array(
1255 "price_input" => round($price_input, 2),
1256 "price" => $price,
1257 "price_option" => $price_option
1258 );
1259 }
1260
1261 function update_property_inventory($param) {
1262
1263 $return_total = 0;
1264
1265 foreach ($param['data'] as $value) {
1266
1267 $where = array(
1268 'room_id' => $value['room_id'],
1269 'rate_plan_id' => isset($value['rate_plan_id']) ? $value['rate_plan_id'] : NULL,
1270 'date' => $value['date']
1271 );
1272
1273 if (!isset($value['rate_plan_id'])) {
1274 unset($where['rate_plan_id']);
1275 }
1276
1277 $this->CI->load->model('extranet/inventory_model');
1278
1279 if ($this->CI->inventory_model->update_inventory($where, $value)) {
1280 $return_total++;
1281 }
1282 }
1283
1284 return $return_total;
1285 }
1286
1287 function availability($property_id, $start_date, $number_of_nights, $guest_currency, $number_of_guests = "", $language_id = NULL, $only_available = false) {
1288
1289 $this->CI->load->model('extranet/amenity_model');
1290 $this->CI->load->model('extranet/rate_plan_model');
1291 $this->CI->load->model('extranet/rate_plan_rule_model');
1292 $this->CI->load->model('extranet/milestone_model');
1293 $this->CI->load->model('extranet/cancellation_model');
1294
1295 $rate_plan_amenities_helper = array();
1296 $rate_plan_amenities_result = $this->CI->amenity_model->get_rate_plan_amenities($language_id);
1297
1298 foreach ($rate_plan_amenities_result as $amenity) {
1299 $rate_plan_amenities_helper[$amenity->amenity_element] = isset($amenity->amenity_output_translated) ? $amenity->amenity_output_translated : $amenity->amenity_output;
1300 }
1301
1302 $d1 = new DateTime(date('Y-m-d'));
1303 $d2 = new DateTime($start_date);
1304 $diff = $d1->diff($d2);
1305 $diff->format('%R');
1306 $interval = (int) $diff->days;
1307
1308 $payment_currency = $booking_currency = $this->CI->config->item('payment_currency');
1309 $payment_encrypt = $this->CI->config->item('payment_encrypt');
1310
1311 $this->CI->load->library('encrypt');
1312 $this->CI->load->model('extranet/inventory_model');
1313
1314 $return = array();
1315 $param = array();
1316 $param['property_id'] = $property_id;
1317 $property = $this->property($param);
1318
1319 if ($property['PROPERTY']['ID'] != NULL) {
1320
1321 $number_of_guests = (int) $number_of_guests;
1322 $rate_type = 'regular';
1323
1324 if ($number_of_guests > 0 && $number_of_guests > (int) $property['PROPERTY']['MAX_BEDS_PER_BOOKING']) {
1325 $rate_type = 'group';
1326 }
1327
1328 $property_currency = $property['PROPERTY']['CURRENCY']['CODE'];
1329 $return['RESPONSE'] = array();
1330 $return['MAX_BEDS_PER_BOOKING'] = $property['PROPERTY']['MAX_BEDS_PER_BOOKING'];
1331
1332 $end_date = date("Y-m-d", strtotime("+{$number_of_nights} day", strtotime($start_date)));
1333
1334 $rooms = $this->rooms($property_id, $language_id);
1335
1336 $property_inventory = $this->CI->inventory_model->get_property_inventory($property_id, $start_date, $end_date, null, $number_of_guests, ($rate_type == 'group') ? true : false, $only_available);
1337 $room_rates = array();
1338
1339 foreach ($property_inventory as $a => $b) {
1340 if(count($b) >= 1){
1341 foreach ($b as $c => $d) {
1342 array_push($payment_currency, $d['CURRENCY']);
1343 $room_rates[$a] = $d['RATE_PLAN_ID'];
1344 }
1345 }
1346 }
1347
1348 array_push($payment_currency, $property_currency);
1349 array_push($payment_currency, $guest_currency);
1350 $payment_currency = array_unique($payment_currency);
1351
1352 $currency_exchange = $this->CI->forex->batch_rate($payment_currency);
1353
1354 $rate_plans = $this->CI->rate_plan_model->select(array("rate_plan.property_id" => $property_id, "rate_plan.type" => $rate_type));
1355 $rate_plan_rules = $this->CI->rate_plan_rule_model->select(array("rate_plan.property_id" => $property_id));
1356 $milestones = $this->CI->milestone_model->select(array("rate_plan.property_id" => $property_id));
1357 $cancellations = $this->CI->cancellation_model->select(array("rate_plan.property_id" => $property_id));
1358
1359 foreach ($rooms as $room) {
1360
1361 $inventory = array();
1362 $beds = array();
1363
1364 foreach ($property_inventory as $room_id => $available) {
1365 if(!$available){
1366 continue;
1367 }
1368 if (($room->room_id == $room_id)) {
1369
1370 $inventory['NAME'] = $room->room_description;
1371 $inventory['ID'] = $room->room_id;
1372 $inventory['AMENITY'] = $this->room_amenity($room->room_id, $language_id);
1373 $inventory['AMENITY'] = $inventory['AMENITY'][6];
1374
1375 foreach ($available as $rate_plan_rule_id => $rate_plan_rule_value) {
1376
1377 $amenities = array();
1378
1379 $amenities['SPECIAL']['AMENITY']['airport_transfer'] = array(
1380 'title' => $rate_plan_amenities_helper['airport_transfer'],
1381 'available' => $rate_plan_rule_value['SPECIAL']['AMENITY']['airport_transfer']
1382 );
1383
1384 /*
1385 $amenities['SPECIAL']['AMENITY']['train_transfer'] = array(
1386 'title' => $rate_plan_amenities_helper['train_transfer'],
1387 'available' => $rate_plan_rule_value['SPECIAL']['AMENITY']['train_transfer']
1388 );
1389 *
1390 */
1391
1392 $amenities['SPECIAL']['AMENITY']['internet'] = array(
1393 'title' => $rate_plan_amenities_helper['internet'],
1394 'available' => $rate_plan_rule_value['SPECIAL']['AMENITY']['internet']
1395 );
1396
1397 $amenities['SPECIAL']['AMENITY']['linen'] = array(
1398 'title' => $rate_plan_amenities_helper['linen'],
1399 'available' => $rate_plan_rule_value['SPECIAL']['AMENITY']['linen']
1400 );
1401
1402 $amenities['SPECIAL']['AMENITY']['towel'] = array(
1403 'title' => $rate_plan_amenities_helper['towel'],
1404 'available' => $rate_plan_rule_value['SPECIAL']['AMENITY']['towel']
1405 );
1406
1407 $amenities['SPECIAL']['MEAL']['breakfast'] = array(
1408 'title' => $rate_plan_amenities_helper['breakfast'],
1409 'available' => $rate_plan_rule_value['SPECIAL']['MEAL']['breakfast']
1410 );
1411
1412 $amenities['SPECIAL']['MEAL']['lunch'] = array(
1413 'title' => $rate_plan_amenities_helper['lunch'],
1414 'available' => $rate_plan_rule_value['SPECIAL']['MEAL']['lunch']
1415 );
1416
1417 $amenities['SPECIAL']['MEAL']['lunch_pack'] = array(
1418 'title' => $rate_plan_amenities_helper['lunch_pack'],
1419 'available' => $rate_plan_rule_value['SPECIAL']['MEAL']['lunch_pack']
1420 );
1421
1422 $amenities['SPECIAL']['MEAL']['dinner'] = array(
1423 'title' => $rate_plan_amenities_helper['dinner'],
1424 'available' => $rate_plan_rule_value['SPECIAL']['MEAL']['dinner']
1425 );
1426
1427 $inventory[$rate_plan_rule_id]['SPECIAL'] = $amenities['SPECIAL'];
1428
1429 $_milestone = "";
1430 $_cancellation = "";
1431 $deposit = $rate_plan_rule_value['DEPOSIT'];
1432 foreach ($milestones as $milestone) {
1433 if ($milestone->rate_plan_rule_id == $rate_plan_rule_id) {
1434 // if booking is made after or within 7 days milestone timeline should be considered part of the deposit.
1435 if ($interval <= ($milestone->interval + 7)) {
1436 // add to deposit
1437 $deposit = $deposit + $milestone->percentage;
1438 }else{
1439 // add to list
1440 $_milestone = array(
1441 'ID' => $milestone->id,
1442 'RATE_PLAN_RULE_ID' => $milestone->rate_plan_rule_id,
1443 'INTERVAL' => $milestone->interval,
1444 'PERCENTAGE' => $milestone->percentage,
1445 'STATUS' => $milestone->status
1446 );
1447 }
1448 }
1449 }
1450
1451 foreach ($cancellations as $cancelation) {
1452 if ($cancelation->rate_plan_rule_id == $rate_plan_rule_id) {
1453 $_cancellation = array(
1454 'ID' => $cancelation->id,
1455 'RATE_PLAN_RULE_ID' => $cancelation->rate_plan_rule_id,
1456 'RATE_PLAN_ID' => $cancelation->rate_plan_id,
1457 'INTERVAL' => $cancelation->interval,
1458 'CHARGE' => $cancelation->charge,
1459 'AMOUNT' => $cancelation->amount,
1460 'OFFER_PAYMENT' => $cancelation->offer_prepayment,
1461 'STATUS' => $cancelation->status
1462 );
1463 }
1464 }
1465
1466 $inventory['NIGHTS'][$rate_plan_rule_id]['RATE_PLAN_ID'] = $rate_plan_rule_value['RATE_PLAN_ID'];
1467 $inventory['NIGHTS'][$rate_plan_rule_id]['DEPOSIT'] = $deposit;
1468 $inventory['NIGHTS'][$rate_plan_rule_id]['MILESTONES'] = $_milestone;
1469 $inventory['NIGHTS'][$rate_plan_rule_id]['CANCELLATIONS'] = $_cancellation;
1470 $inventory['NIGHTS'][$rate_plan_rule_id]['AVG_PRICE'] = 0;
1471
1472 foreach ($rate_plan_rule_value['OUTLAY'] as $inventory_id => $inventory_value) {
1473
1474 foreach ($booking_currency as $settle_currency) {
1475 $payment[$settle_currency] = $this->CI->forex->batch_exchange($inventory_value['AMOUNT'], $rate_plan_rule_value['CURRENCY'], $settle_currency);
1476 }
1477
1478 $inventory['NIGHTS'][$rate_plan_rule_id]['INVENTORY'][$inventory_id] = array(
1479 'CUSTOMER' => array(
1480 'CURRENCY' => $guest_currency,
1481 'MINPRICE' => $this->CI->forex->batch_exchange($inventory_value['AMOUNT'], $rate_plan_rule_value['CURRENCY'], $guest_currency)
1482 ),
1483 'PROPERTY' => array(
1484 'CURRENCY' => $property_currency,
1485 'MINPRICE' => $this->CI->forex->batch_exchange($inventory_value['AMOUNT'], $rate_plan_rule_value['CURRENCY'], $property_currency)
1486 ),
1487 'PAYMENT' => $payment,
1488 'DATE' => $inventory_value['DATE'],
1489 );
1490
1491 $inventory['NIGHTS'][$rate_plan_rule_id]['AVG_PRICE'] += $inventory_value['AMOUNT'];
1492 }
1493
1494 $inventory['NIGHTS'][$rate_plan_rule_id]['AVG_PRICE'] = ($inventory['NIGHTS'][$rate_plan_rule_id]['AVG_PRICE'] / count($rate_plan_rule_value['OUTLAY']) );
1495 }
1496
1497 // filter out double pre-payments
1498 $min_price = 0;
1499 $tmp_delete_rule = 0;
1500 $rules_to_delete = array();
1501 foreach($inventory['NIGHTS'] as $rate_plan_rule_id => $inventory_row){
1502 if($inventory_row['DEPOSIT'] == "100"){
1503 if($min_price == 0){
1504 $min_price = $inventory_row['AVG_PRICE'];
1505 $tmp_delete_rule = $rate_plan_rule_id;
1506 continue;
1507 }
1508 if($min_price != 0 && $inventory_row['AVG_PRICE'] < $min_price){
1509 // delete previous rule as it was more expencive
1510 $rules_to_delete[] = $tmp_delete_rule;
1511 // set this one as minimum
1512 $min_price = $inventory_row['AVG_PRICE'];
1513 $tmp_delete_rule = $rate_plan_rule_id;
1514 }elseif($min_price != 0 && $inventory_row['AVG_PRICE'] >= $min_price){
1515 // delete current rule as it is more expencive
1516 $rules_to_delete[] = $rate_plan_rule_id;
1517 }
1518
1519 }
1520 }
1521 // delete prices higher then the cheapest
1522 foreach($rules_to_delete as $rule_id_to_delete){
1523 unset($inventory['NIGHTS'][$rule_id_to_delete]);
1524 }
1525
1526 $plan_rules_ids = array();
1527 foreach($inventory['NIGHTS'] as $rate_plan_rule_id => $inventory_row){
1528 $plan_rules_ids[] = $rate_plan_rule_id;
1529 }
1530
1531 if( isset($plan_rules_ids[0]) && isset($plan_rules_ids[1]) ){
1532 $specials_one = $inventory[$plan_rules_ids[0]];
1533 $specials_two = $inventory[$plan_rules_ids[1]];
1534 // same amenities and same prices
1535 // one needs to be deleted
1536 if( $specials_one['SPECIAL']['AMENITY']['airport_transfer']['available'] == $specials_two['SPECIAL']['AMENITY']['airport_transfer']['available'] &&
1537 $specials_one['SPECIAL']['AMENITY']['internet']['available'] == $specials_two['SPECIAL']['AMENITY']['internet']['available'] &&
1538 $specials_one['SPECIAL']['AMENITY']['linen']['available'] == $specials_two['SPECIAL']['AMENITY']['linen']['available'] &&
1539 $specials_one['SPECIAL']['AMENITY']['towel']['available'] == $specials_two['SPECIAL']['AMENITY']['towel']['available'] &&
1540 $specials_one['SPECIAL']['MEAL']['breakfast']['available'] == $specials_two['SPECIAL']['MEAL']['breakfast']['available'] &&
1541 $specials_one['SPECIAL']['MEAL']['lunch']['available'] == $specials_two['SPECIAL']['MEAL']['lunch']['available'] &&
1542 $specials_one['SPECIAL']['MEAL']['lunch_pack']['available'] == $specials_two['SPECIAL']['MEAL']['lunch_pack']['available'] &&
1543 $specials_one['SPECIAL']['MEAL']['dinner']['available'] == $specials_two['SPECIAL']['MEAL']['dinner']['available'] &&
1544 $inventory['NIGHTS'][$plan_rules_ids[0]]['AVG_PRICE'] == $inventory['NIGHTS'][$plan_rules_ids[1]]['AVG_PRICE']
1545 ){
1546 if( $inventory['NIGHTS'][$plan_rules_ids[0]]['DEPOSIT'] == "100" ){
1547 unset($inventory['NIGHTS'][$plan_rules_ids[0]]);
1548 }else if( $inventory['NIGHTS'][$plan_rules_ids[1]]['DEPOSIT'] == "100" ){
1549 unset($inventory['NIGHTS'][$plan_rules_ids[1]]);
1550 }
1551 }
1552 }
1553
1554 if ($room->room_type_id == 1) {
1555 $inventory['ROOM_TYPE'] = 'ROOM';
1556 } else {
1557 $inventory['ROOM_TYPE'] = 'DORM';
1558 }
1559
1560 foreach ($rate_plan_rule_value['AVAILABLE'] as $inventory_key => $inventory_value) {
1561 array_push($beds, $inventory_value['AVAILABLE']);
1562 }
1563
1564 if (count($beds)) {
1565 if ($room->room_type_id == 1) {
1566 $inventory['BEDS'] = min($beds) * $room->number_of_guests;
1567 } else {
1568 $inventory['BEDS'] = min($beds);
1569 }
1570 } else {
1571 $inventory['BEDS'] = 0;
1572 }
1573
1574 $inventory['OCCUPANCY'] = $room->number_of_guests;
1575
1576 if (isset($inventory['NIGHTS'])) {
1577
1578 uasort($inventory['NIGHTS'], function($a, $b) {
1579 if( $a['DEPOSIT'] == $b['DEPOSIT'] )
1580 return 0;
1581
1582 return ($a['DEPOSIT'] > $b['DEPOSIT'])?-1:1;
1583 });
1584
1585 foreach ($inventory['NIGHTS'] as $rate_plan_rule_id => $night_value) {
1586 if (count($night_value['INVENTORY']) == $number_of_nights) {
1587
1588 } else {
1589 unset($inventory['NIGHTS'][$rate_plan_rule_id]);
1590 }
1591 }
1592 if (count($inventory['NIGHTS']) >= 1) {
1593 // add to responce if there is at least one rate available for whole stay
1594 array_push($return['RESPONSE'], $inventory);
1595 $return['PROPERTY'] = $property;
1596 }
1597 }
1598 }
1599 }
1600 }
1601 }
1602 return $return;
1603 }
1604
1605 function location_search($country_id, $city_id, $start_date, $number_of_nights, $customer_currency, $number_of_guests = NULL, $approved_properties = true) {
1606
1607 $this->CI->load->model('extranet/inventory_model');
1608 $this->CI->load->model('extranet/property_model');
1609 $this->CI->load->model('extranet/room_model');
1610 $this->CI->load->model('extranet/property_image_model');
1611 $this->CI->load->model('extranet/district_has_property_model');
1612 $this->CI->load->model('extranet/property_has_landmark_model');
1613 $this->CI->load->model('extranet/rating_model');
1614 $this->CI->load->model('extranet/property_has_payment_card_type_model');
1615 $this->CI->load->model('extranet/currency_exchange_model');
1616 $this->CI->load->model('extranet/currency_model');
1617
1618 $this->CI->load->library('forex');
1619
1620 $date = new DateTime($start_date);
1621 $today = new DateTime(date('Y-m-d'));
1622 $interval = $date->diff($today);
1623
1624 if ($interval->invert == 0 && $interval->days >= 1) {
1625 throw new Exception("Requested date is in the past");
1626 }
1627
1628 if (!is_numeric($number_of_nights) || $number_of_nights < 1) {
1629 throw new Exception("Number of nights must be number bigger than zero");
1630 }
1631
1632 $end_date = date("Y-m-d", strtotime("+{$number_of_nights} day", strtotime($start_date)));
1633 $property_inventory = $this->CI->inventory_model->get_location_inventory($country_id, $city_id, $start_date, $end_date, $number_of_guests, $approved_properties);
1634
1635 $property_response = array();
1636 $hotel_cache = $this->CI->property_model->search_cache($property_inventory['property_id']);
1637
1638 $property_searched = array();
1639
1640 foreach ($property_inventory['property_id'] as $property_id) {
1641
1642 $property = NULL;
1643
1644 foreach ($hotel_cache as $hotel) {
1645 $hotel_data = json_decode($hotel->cache_data);
1646 if ($hotel_data->property_id == $property_id) {
1647 $property = $hotel_data;
1648 }
1649 }
1650
1651 if ($property == NULL) {
1652
1653 $property_data = $this->CI->property_model->get_property_by_id($property_id);
1654 $rating = $this->CI->rating_model->get_rating_by_category($property_id);
1655
1656 $real_image = "";
1657 $amenity_images = $this->property_amenity_images($property_id);
1658 foreach ($amenity_images as $category => $images) {
1659 foreach ($images as $image) {
1660 if ($real_image == "") {
1661 // init any image
1662 $real_image = $image->IMAGE;
1663 }
1664 if ($image->FRONT_IMAGE == 1) {
1665 // if there is front image use that
1666 $real_image = $image->THUMB;
1667 break;
1668 }
1669 }
1670 }
1671
1672 $creteria = array(
1673 'district_has_property.property_id' => $property_id
1674 );
1675 $district_has_property = $this->CI->district_has_property_model->select($creteria);
1676 $property_district = array();
1677
1678 foreach ($district_has_property as $value) {
1679 $district_value = array(
1680 'ID' => $value->id,
1681 'CITY_ID' => $value->city_id,
1682 'NAME' => $value->district_name,
1683 'POLYGON' => $value->polygon_coordinates,
1684 'AREA' => $value->area,
1685 'SLUG' => $value->slug,
1686 'UM_ID' => $value->um_id,
1687 'POLYGON_COORDINATES' => $value->polygon_coordinates
1688 );
1689 array_push($property_district, $district_value);
1690 }
1691
1692 $creteria = array(
1693 'property_has_landmark.property_id' => $property_id
1694 );
1695 $property_has_landmark = $this->CI->property_has_landmark_model->select($creteria);
1696 $property_landmark = array();
1697 foreach ($property_has_landmark as $value) {
1698 $type = $value->type;
1699 if ($value->landmark_name == "City Center") {
1700 $type = "city_center";
1701 }
1702 $landmark_value = array(
1703 'ID' => $value->id,
1704 'LANDMARK_SOURCE_ID' => $value->landmark_source_id,
1705 'GEO' => array(
1706 'LATITUDE' => $value->geo_latitude,
1707 'LONGITUDE' => $value->geo_longitude
1708 ),
1709 'NAME' => $value->landmark_name,
1710 'DISTANCE' => $value->distance,
1711 'TYPE' => $type,
1712 'SLUG' => $value->slug
1713 );
1714 array_push($property_landmark, $landmark_value);
1715 }
1716
1717 $property_amenity = $this->property_amenity($property_id);
1718
1719 $listing_response = array();
1720 $listing_response['property_id'] = $property_data['id'];
1721 $listing_response['property_name'] = $property_data['property_name'];
1722 $listing_response['min_stay'] = 0;
1723 $listing_response['preferred_currency'] = $property_data['currency_code'];
1724 $listing_response['image'] = $real_image;
1725 $listing_response['overall_rating'] = isset($rating['overall']) ? $rating['overall'] * 10 : rand(1, 10);
1726 $listing_response['percent_rating'] = isset($rating['overall']) ? $rating['overall'] * 10 : rand(1, 10);
1727
1728 $listing_response['description'] = array(
1729 'overview' => $property_data['overview'],
1730 'about' => $property_data['about'],
1731 'social_info' => $property_data['social_info'],
1732 'important_info' => $property_data['important_info']
1733 );
1734 $listing_response['location'] = array(
1735 'lat' => $property_data['geo_latitude'],
1736 'lng' => $property_data['geo_longitude']
1737 );
1738 $listing_response['ADDRESS'] = array(
1739 'STATE' => $property_data['state'],
1740 'ZIP' => $property_data['zip'],
1741 'COUNTRY' => $property_data['country_name'],
1742 'CITY' => $property_data['city_name'],
1743 'STREET1' => $property_data['street_address'],
1744 'STREET2' => '',
1745 'STREET3' => ''
1746 );
1747
1748 $listing_response['phone'] = array(
1749 'phone' => $property_data['phone'],
1750 'international' => $property_data['phone_international']
1751 );
1752
1753 $listing_response['ratings'] = array(
1754 'atmosphere' => isset($rating['atmosphere']) ? $rating['atmosphere'] : rand(1, 10),
1755 'staff' => isset($rating['staff']) ? $rating['staff'] : rand(1, 10),
1756 'location' => isset($rating['location']) ? $rating['location'] : rand(1, 10),
1757 'cleanliness' => isset($rating['cleanliness']) ? $rating['cleanliness'] : rand(1, 10),
1758 'facilities' => isset($rating['facilities']) ? $rating['facilities'] : rand(1, 10),
1759 'safety' => isset($rating['safety']) ? $rating['safety'] : rand(1, 10),
1760 'value' => isset($rating['value']) ? $rating['value'] : rand(1, 10),
1761 'overall' => isset($rating['overall']) ? $rating['overall'] : rand(1, 10)
1762 );
1763
1764 $listing_response['type'] = $property_data['property_type'];
1765 $listing_response['image_thumbnail'] = $real_image;
1766 $listing_response['image_list'] = $real_image;
1767 $listing_response['districts'] = $property_district;
1768 $listing_response['landmarks'] = $property_landmark;
1769 $listing_response['amenities'] = $property_amenity;
1770
1771 $property_response[$property_id] = $listing_response;
1772
1773 $this->CI->cache_model->set_item_id($property_id);
1774 $this->CI->cache_model->set_cache_type('minimum_property');
1775 $this->CI->cache_model->set_cache_data(json_encode($listing_response));
1776 $this->CI->cache_model->set_created(date('Y-m-d H:i:s'));
1777 $this->CI->cache_model->set_status(1);
1778 $this->CI->cache_model->insert();
1779
1780 $property = json_encode($listing_response);
1781 $property = json_decode($property);
1782 }
1783 array_push($property_searched, $property);
1784 }
1785
1786
1787 $payment_currency = $this->CI->config->item('payment_currency');
1788 $payment_currency = array_merge($payment_currency, $property_inventory['currency']);
1789
1790 foreach ($property_searched as $searched) {
1791 array_push($payment_currency, $searched->preferred_currency);
1792 }
1793
1794 array_push($payment_currency, $customer_currency);
1795
1796 $payment_currency = array_unique($payment_currency);
1797 $payment_currency = array_values($payment_currency);
1798
1799 $currency_exchange = $this->CI->forex->batch_rate($payment_currency);
1800 $property_response = array();
1801
1802 foreach ($property_inventory['property'] as $property_id => $cheapest) {
1803 foreach ($property_searched as $searched) {
1804 if ($property_id == $searched->property_id) {
1805
1806 $best_rate = array();
1807
1808 foreach ($cheapest as $plan_key => $plan_data) {
1809 foreach ($plan_data as $rule_key => $rule_data) {
1810
1811 $payment = array();
1812 $payment_currency = $this->CI->config->item('payment_currency');
1813
1814 $room_type = $plan_key == 1 ? 'ROOM' : 'DORM';
1815
1816 foreach ($payment_currency as $settle_currency) {
1817 $payment[$settle_currency] = $this->CI->forex->batch_exchange($rule_data['AMOUNT'], $searched->preferred_currency, $settle_currency);
1818 }
1819
1820 $best_rate['BEST_RATE'][$room_type][$rule_data['DEPOSIT']] = array(
1821 'CUSTOMER' => array(
1822 'CURRENCY' => $customer_currency,
1823 'MINPRICE' => $this->CI->forex->batch_exchange($rule_data['AMOUNT'], $searched->preferred_currency, $customer_currency)
1824 ),
1825 'PROPERTY' => array(
1826 'CURRENCY' => $searched->preferred_currency,
1827 'MINPRICE' => $this->CI->forex->batch_exchange($rule_data['AMOUNT'], $searched->preferred_currency, $searched->preferred_currency)
1828 ),
1829 'PAYMENT' => $payment,
1830 'INCLUDE' => $rule_data['SPECIAL'],
1831 'DEPOSIT' => $rule_data['DEPOSIT'],
1832 'PRICING' => $rule_data['CATEGORY'],
1833 'OCCUPANCY' => $rule_data['OCCUPANCY'],
1834 'RATE_PLAN_RULE_ID' => $rule_data['RATE_PLAN_RULE_ID']
1835 );
1836 }
1837 }
1838
1839 $best_rate = json_encode($best_rate);
1840 $best_rate = json_decode($best_rate);
1841 $searched->BEST_RATE = $best_rate->BEST_RATE;
1842
1843 array_push($property_response, $searched);
1844 }
1845 }
1846 }
1847
1848 return $property_response;
1849 }
1850
1851 function property_search($country_id, $city_id, $start_date, $number_of_nights, $guest_currency) {
1852
1853 $this->CI->load->model('extranet/inventory_model');
1854 $this->CI->load->model('extranet/property_model');
1855 $this->CI->load->model('extranet/room_model');
1856 $this->CI->load->model('extranet/rating_model');
1857 $this->CI->load->model('extranet/property_has_payment_card_type_model');
1858
1859 $date = new DateTime($start_date);
1860 $today = new DateTime(date('Y-m-d'));
1861 $interval = $date->diff($today);
1862
1863 if ($interval->invert == 0 && $interval->days >= 1) { // date is in the past
1864 throw new Exception("Requested date is in the past");
1865 }
1866
1867 if (!is_numeric($number_of_nights) || $number_of_nights < 1) { // number nights of stay bigger than 0
1868 throw new Exception("Number of nights must be number bigger than zero");
1869 }
1870
1871 // If user come on 2014-10-20 and stays for 2 nights
1872 // Room should be available on 10-20 and 10-21
1873
1874 $end_date = date("Y-m-d", strtotime("+{$number_of_nights} day", strtotime($start_date)));
1875
1876 $properties = $this->CI->inventory_model->get_location_inventory($country_id, $city_id, $start_date, $end_date);
1877
1878 $property_list = array();
1879 $tmp = array();
1880 $single_property = false;
1881
1882 if ($property_id) {
1883 $single_property = true;
1884 }
1885
1886 foreach ($properties as $property_id => $rooms) {
1887
1888 if (count($rooms) >= 1) { // If at least one room is available
1889 $property_data = $this->CI->property_model->get_property_by_id($property_id);
1890
1891 if ($single_property == false) {
1892
1893 $tmp = array();
1894 $tmp['preferredcurrency'] = $property_data['currency_code'];
1895 $tmp['image'] = $property_data['images'][0];
1896 $tmp['includes'] = array();
1897 $rating = $this->CI->rating_model->get_rating_by_category($property_id);
1898 $tmp['percentagerating'] = (isset($rating['overall'])) ? $rating['overall'] : 0;
1899 unset($rating['overall']); // Delete overall and assign all other avg ratings
1900 $tmp['ratings'] = $rating;
1901 $tmp['marketing_weight'] = 0;
1902 $tmp['image_list'] = $property_data['images'];
1903
1904 if ($tmp['percentagerating'] > 59 && $tmp['percentagerating'] < 70) {
1905 $tmp['rating'] = "Good";
1906 } else if ($tmp['percentagerating'] > 69 && $tmp['percentagerating'] < 80) {
1907 $tmp['rating'] = "Very good";
1908 } else if ($tmp['percentagerating'] > 79 && $tmp['percentagerating'] < 90) {
1909 $tmp['rating'] = "Great";
1910 } else if ($tmp['percentagerating'] > 89) {
1911 $tmp['rating'] = "Fantastic";
1912 } else {
1913 $tmp['rating'] = "";
1914 }
1915
1916 $tmp['property_page_url'] = "";
1917 $tmp['savedToFavorites'] = "";
1918 $tmp['saveToFavorites'] = "";
1919 $tmp['propertyNumber'] = $property_id;
1920 $tmp['propertyName'] = $property_data['property_name'];
1921 $tmp['shortDescription'] = $property_data['overview'];
1922 $tmp['propertyType'] = $property_data['property_type'];
1923 $tmp['minNights'] = 0;
1924
1925 $tmp['Geo'] = array(
1926 'Latitude' => $property_data['geo_latitude'],
1927 'Longitude' => $property_data['geo_longitude']
1928 );
1929
1930 $tmp['city_name'] = $property_data['city_name'];
1931 $tmp['country_name'] = $property_data['country_name'];
1932 $tmp['zip'] = $property_data['zip'];
1933 $tmp['address1'] = $property_data['address'];
1934 $tmp['Ratings'] = $rating;
1935 $tmp['isRatingsEmpty'] = (count($rating) >= 1) ? true : false;
1936 $tmp['PropertyImages'] = $property_data['images'];
1937 $tmp['amenities'] = array();
1938 $amenities_filter = array();
1939 $extras = array();
1940
1941 foreach ($property_data['extras'] as $extra) {
1942 $tmp['amenities'][] = array(
1943 "facility_id" => "extra" . $extra['extra_id'],
1944 "description" => $extra['description'],
1945 "type" => 'extra',
1946 "to_display" => '1',
1947 "slug" => ''
1948 );
1949 $amenities_filter[] = "extra" . $extra['extra_id'];
1950 $extras[] = $extra['description'];
1951 }
1952 foreach ($property_data['features'] as $feature) {
1953 $tmp['amenities'][] = array(
1954 "facility_id" => "feature" . $feature['feature_id'],
1955 "description" => $feature['description'],
1956 "type" => 'feature',
1957 "to_display" => '1',
1958 "slug" => ''
1959 );
1960 $amenities_filter[] = "feature" . $feature['feature_id'];
1961 }
1962
1963 $tmp['amenities_filter'] = $amenities_filter;
1964 $tmp['extras']['extra'] = $extras;
1965 $tmp['has_amenities'] = ( count($tmp['amenities']) >= 1 ) ? "1" : "0";
1966 $tmp['districts'] = $this->CI->property_model->get_all_districts($property_id);
1967 $tmp['landmarks'] = array();
1968 $tmp['safety80'] = false;
1969 $tmp['overall_rating'] = $tmp['percentagerating'];
1970 $tmp['isMinNightNeeded'] = false;
1971
1972 $tmp['dual_price'] = 1;
1973 $tmp['display_price'] = 0;
1974 $tmp['display_shared_price'] = 0;
1975 $tmp['display_private_price'] = 0;
1976 $tmp['currency_code'] = 0;
1977
1978 $available_dates = array();
1979 $private_prices = array();
1980 $shared_prices = array();
1981
1982 foreach ($rooms as $room_id => $inventorys) {
1983 foreach ($inventorys as $alocation) {
1984 if ($alocation->type == "Private") {
1985 $private_prices[] = $alocation->price;
1986 } else {
1987 $shared_prices[] = $alocation->price;
1988 }
1989 $available_dates[$alocation->date] = $alocation->date; // Date as key to prevent duplicates
1990 }
1991 }
1992
1993 $tmp['display_shared_price'] = ($shared_prices) ? min($shared_prices) : "";
1994 $tmp['display_private_price'] = ($private_prices) ? min($private_prices) : "";
1995 $tmp['display_price'] = min(array_merge($shared_prices, $private_prices));
1996 $tmp['currency_code'] = "EUR"; // when allocating price is in euro
1997 $tmp['display_currency'] = "€";
1998 $tmp['display_price_formatted'] = $tmp['display_price'];
1999 $tmp['display_shared_price_formatted'] = $tmp['display_shared_price'];
2000 $tmp['display_private_formatted'] = $tmp['display_private_price'];
2001 $tmp['display_price_general_format'] = $tmp['display_price'] . $tmp['display_currency'];
2002 $tmp['display_shared_price_general_format'] = ($tmp['display_shared_price']) ? $tmp['display_shared_price'] . $tmp['display_currency'] : "";
2003 $tmp['display_private_general_format'] = ($tmp['display_private_price']) ? $tmp['display_private_price'] . $tmp['display_currency'] : "";
2004 $tmp['isGeoValid'] = ($property_data['geo_latitude'] && $property_data['geo_longitude']) ? true : false;
2005 $tmp['AvailableDates']['availableDate'] = $available_dates;
2006
2007 $property_list[] = $tmp;
2008 } else {
2009
2010 $tmp = array();
2011 $main_services = array();
2012 $breakfast_included = 0;
2013
2014 foreach ($property_data['extras'] as $extra) {
2015 $services = new stdClass();
2016 $services->service_id = $extra['extra_id'];
2017 $services->description = $extra['description'];
2018 $main_services[] = $services;
2019 if ($extra['description'] == "Breakfast") {
2020 $breakfast_included = 1;
2021 }
2022 }
2023
2024 $tmp['main_services'] = $main_services;
2025 $tmp['breakfast_included'] = $breakfast_included;
2026 $tmp['country_selected'] = $property_data['country_name'];
2027 $tmp['city_selected'] = $property_data['city_name'];
2028
2029 $all_cards = $this->CI->property_has_payment_card_type_model->get_all_property_cards($property_id);
2030 $cards = array();
2031
2032 foreach ($all_cards as $card) {
2033 $cards[] = $card->type;
2034 }
2035
2036 $tmp['property_cards'] = implode(',', $cards);
2037 $tmp['propertyName'] = $property_data['property_name'];
2038 $tmp['propertyNumber'] = $property_data['id'];
2039
2040 $new_date_time = new DateTime($start_date);
2041
2042 $tmp['dateStart'] = $new_date_time;
2043 $tmp['numNights'] = $number_of_nights;
2044 $tmp['currency'] = $property_data['currency_code'];
2045 $tmp['print'] = false;
2046 $tmp['booking_rooms'] = array();
2047
2048 foreach ($rooms as $room_id => $inventory) {
2049
2050 $room_data = $this->CI->room_model->get_room_details($room_id);
2051 $room_data = $room_data[0];
2052
2053 $room_name = "";
2054
2055 if ($room_data->offer) {
2056 $room_name .= $room_data->offer;
2057 }
2058 if ($room_data->grade) {
2059 $room_name .= " - " . $room_data->grade;
2060 }
2061
2062 $room_name .= " " . $room_data->number_of_guests . " bed " . $room_data->type;
2063 if ($room_data->gender != "mixed") {
2064 $room_name .= " - " . $room_data->gender . " only";
2065 }
2066 $room_name .= " (" . $room_data->bathroom . " bathroom";
2067 if ($room_data->views) {
2068 $room_name .= ", " . $room_data->views . ")";
2069 } else {
2070 $room_name .= ")";
2071 }
2072
2073 $room_tmp = array();
2074 $room_tmp['NAME'] = $room_name;
2075 $room_tmp['BLOCKBEDS'] = "";
2076 $room_tmp['BEDS'] = $room_data->number_of_guests;
2077 $room_tmp['ID'] = $room_id;
2078 $room_tmp['NAME_TRANSLATED'] = $room_name;
2079 $room_tmp['NIGHTS'] = array();
2080 $night_tmp = array();
2081 $night_tmp['CUSTOMER']['CURRENCY'] = $property_data['currency_code'];
2082 $night_tmp['HOSTEL']['CURRENCY'] = $property_data['currency_code'];
2083 $night_tmp['PAYMENT']['CURRENCY'] = $property_data['currency_code'];
2084 $prices = array();
2085
2086 foreach ($inventory as $night) {
2087 $prices[] = $night->price;
2088 }
2089
2090 $night_tmp['CUSTOMER']['MINPRICE'] = min($prices);
2091 $night_tmp['HOSTEL']['MINPRICE'] = min($prices);
2092 $night_tmp['PAYMENT']['MINPRICE'] = min($prices);
2093 $room_tmp['NIGHTS'][$night->id] = $night_tmp;
2094 $tmp['booking_rooms'][] = $room_tmp;
2095 }
2096 $tmp['booking_rooms']['DEPOSITPERCENTAGE'] = $property_data['billing_plans']['deposit']->percentage;
2097 $property_list = $tmp;
2098 }
2099 }
2100 }
2101 return $property_list;
2102 }
2103
2104 function checkout($param) {
2105
2106 $this->CI->load->model('extranet/inventory_model');
2107 $this->CI->load->model('extranet/room_model');
2108 $this->CI->load->model('extranet/property_model');
2109 $this->CI->load->model('extranet/currency_exchange_model');
2110 $this->CI->load->model('extranet/rate_plan_model');
2111 $this->CI->load->model('extranet/rate_plan_rule_model');
2112 $this->CI->load->model('extranet/milestone_model');
2113 $this->CI->load->model('extranet/cancellation_model');
2114 $this->CI->load->library('encrypt');
2115
2116 $payment_currency = $booking_currency = $this->CI->config->item('payment_currency');
2117 $payment_encrypt = $this->CI->config->item('payment_encrypt');
2118 $booking_expense = $this->CI->config->item('booking_expense');
2119
2120 $start_date = $param['start_date'];
2121 $number_of_nights = $param['number_of_nights'];
2122 $property_id = $param['property_id'];
2123 $guest_currency = $param['guest_currency'];
2124 $charge_expense = isset($param['charge_expense']) ? $param['charge_expense'] : FALSE;
2125 $modification_checkout = isset($param['modification_checkout']) ? $param['modification_checkout'] : FALSE;
2126 $only_available = ($modification_checkout == TRUE) ? FALSE : TRUE; // if modification checkout get non available rooms too
2127
2128 $d1 = new DateTime(date('Y-m-d'));
2129 $d2 = new DateTime($start_date);
2130 $diff = $d1->diff($d2);
2131 $diff->format('%R');
2132 $interval = (int) $diff->days;
2133
2134 $chosen_rooms = $param['chosen_rooms'];
2135 $chosen_rates = $param['chosen_rates'];
2136 $chosen_guest = $param['chosen_guest'];
2137
2138 $return_source = array();
2139 $return_source['PROPERTY_ID'] = $property_id;
2140 $return_source['START_DATE'] = $start_date;
2141 $return_source['NIGHT'] = $number_of_nights;
2142 $return_source['CUSTOMER_CURRENCY'] = $guest_currency;
2143 $return_source['CHOSEN_RATES'] = $chosen_rates;
2144 $return_source['CHOSEN_GUEST'] = $chosen_guest;
2145 $return_source['CHOSEN_ROOMS'] = $chosen_rooms;
2146
2147 $num_rooms = count($param['chosen_rooms']);
2148 $num_rates = count($param['chosen_rates']);
2149 $num_guests = count($param['chosen_guest']);
2150
2151 $return = array();
2152
2153 if (($num_rooms >= 1) && ($num_rooms == $num_rates) && ($num_rates == $num_guests)) {
2154 $total_number_of_beds = 0;
2155 foreach ($chosen_rooms as $key => $value) {
2156 $room_rates[$value] = $chosen_rates[$key];
2157 $room_guests[$value] = $chosen_guest[$key];
2158 $total_number_of_beds += $chosen_guest[$key];
2159 }
2160
2161 $datetime = DateTime::createFromFormat('Y-m-d', $start_date);
2162 $start_date = $datetime->format('Y-m-d');
2163
2164 $end_date = date("Y-m-d", strtotime("+$number_of_nights days", strtotime($start_date)));
2165
2166 $param_helper['date1'] = new DateTime($start_date);
2167 $param_helper['date2'] = new DateTime($end_date);
2168 $param_helper['chosen_rooms'] = $chosen_rooms;
2169 $param_helper['chosen_rates'] = $chosen_rates;
2170 $param_helper['chosen_guest'] = $chosen_guest;
2171
2172 $live_data = roomrate_inventory($param_helper);
2173
2174 $number_of_guests = 0;
2175 foreach ($chosen_guest as $value) {
2176 $number_of_guests += (int) $value;
2177 }
2178
2179 $param = array();
2180 $param['property_id'] = $property_id;
2181 $property = $this->property($param);
2182
2183 if ($property['PROPERTY']['ID'] != NULL) {
2184
2185 $property_currency = $property['PROPERTY']['CURRENCY']['CODE'];
2186
2187 $return['RESPONSE'] = array();
2188
2189 $this->CI->load->model("extranet/language_model");
2190 $criteria = array('language.code_lang' => str_replace('-', '_', $this->CI->site_lang));
2191 $language_result = $this->CI->language_model->select($criteria);
2192 $language_id = isset($language_result[0]) ? $language_result[0]->id : null;
2193
2194 $rooms = $this->rooms($property_id, $language_id);
2195
2196 $end_date = date("Y-m-d", strtotime("+{$number_of_nights} day", strtotime($start_date)));
2197
2198 $group_rate_type = false;
2199
2200 if ($number_of_guests > 0 && $number_of_guests > (int) $property['PROPERTY']['MAX_BEDS_PER_BOOKING']) {
2201 $group_rate_type = true;
2202 }
2203
2204 $property_inventory = $this->CI->inventory_model->get_property_inventory($property_id, $start_date, $end_date, $live_data, $total_number_of_beds ,$group_rate_type, $only_available);
2205
2206 foreach ($property_inventory as $a => $b) {
2207 foreach ($b as $c => $d) {
2208 array_push($payment_currency, $d['CURRENCY']);
2209 }
2210 }
2211
2212 array_push($payment_currency, $guest_currency);
2213 array_push($payment_currency, $property_currency);
2214 $payment_currency = array_unique($payment_currency);
2215
2216 $currency_exchange = $this->CI->forex->batch_rate($payment_currency);
2217
2218
2219 $datetime = DateTime::createFromFormat('Y-m-d', $start_date);
2220 $start_date = $datetime->format('Y-m-d');
2221
2222 $end_date = date("Y-m-d", strtotime("+$number_of_nights days", strtotime($start_date)));
2223
2224 while (strtotime($start_date) < strtotime($end_date)) {
2225
2226 $inventory_available = array();
2227
2228 foreach ($property_inventory as $room_id => $available) {
2229
2230 foreach ($available as $rate_plan_rule_id => $rate_plan_rule_value) {
2231
2232 if ($room_rates[$room_id] == $rate_plan_rule_id) {
2233
2234 foreach ($rate_plan_rule_value['OUTLAY'] as $inventory_id_1 => $inventory_value) {
2235
2236 foreach ($rate_plan_rule_value['AVAILABLE'] as $inventory_id_2 => $available_value) {
2237
2238 if ($inventory_id_1 == $inventory_id_2) {
2239 if ($start_date == $inventory_value['DATE']) {
2240
2241 foreach ($rooms as $room) {
2242
2243 if (in_array($room->room_id, $chosen_rooms)) {
2244
2245 $inventory = array();
2246
2247 if ($room->room_id == $room_id) {
2248
2249 $rate_plan = $this->CI->rate_plan_model->get_rate_plan($rate_plan_rule_value['RATE_PLAN_ID']);
2250 $rate_plan_rule = $this->CI->rate_plan_rule_model->get_rate_plan_rule($rate_plan_rule_id);
2251
2252 $rate_plan_deposit = $rate_plan_rule->deposit;
2253 $reservation_milestones = array();
2254 $milestones = $this->CI->milestone_model->select(array("rate_plan_rule.id" => $rate_plan_rule_id));
2255 $cancellations = $this->CI->cancellation_model->select(array("rate_plan_rule.id" => $rate_plan_rule_id));
2256
2257 if ($milestones) {
2258 foreach ($milestones as $milestone) {
2259 if ($interval <= $milestone->interval) {
2260 $rate_plan_deposit = $rate_plan_deposit + $milestone->percentage;
2261 } else {
2262 $reservation_milestones[] = array(
2263 'id' => $milestone->id,
2264 'interval' => $milestone->interval,
2265 'percentage' => $milestone->percentage
2266 );
2267 }
2268 }
2269 }
2270
2271 $reservation_cancellations = array();
2272 $cancellation = $this->CI->cancellation_model->select(array("cancellation.rate_plan_rule_id" => $rate_plan_rule_id));
2273 if ($cancellations) {
2274 foreach ($cancellations as $cancellation) {
2275 $reservation_cancellations[$cancellation->rate_plan_rule_id] = array(
2276 'rate_plan_id' => $cancellation->rate_plan_id,
2277 'cancellation_id' => $cancellation->id,
2278 "interval" => $cancellation->interval,
2279 "charge" => $cancellation->charge,
2280 "amount" => $cancellation->amount
2281 );
2282 }
2283 }
2284
2285 if ($room->room_type_id == 1) {
2286 $room_cost = $inventory_value['AMOUNT'] * ceil($room_guests[$room->room_id] / $room->number_of_guests);
2287 } else {
2288 $room_cost = $inventory_value['AMOUNT'] * $room_guests[$room->room_id];
2289 }
2290
2291 $payment = array();
2292
2293 foreach ($booking_currency as $current_currency) {
2294 $payment[$current_currency] = $this->CI->forex->batch_exchange($room_cost, $rate_plan_rule_value['CURRENCY'], $current_currency);
2295 }
2296
2297 $inventory['INVENTORY_ID'] = $inventory_id_1;
2298
2299 $inventory['PRICES'] = array(
2300 'CUSTOMER' => array(
2301 'CURRENCY' => $guest_currency,
2302 'MINPRICE' => $this->CI->forex->batch_exchange($room_cost, $rate_plan_rule_value['CURRENCY'], $guest_currency)
2303 ),
2304 'PROPERTY' => array(
2305 'CURRENCY' => $property_currency,
2306 'MINPRICE' => $this->CI->forex->batch_exchange($room_cost, $rate_plan_rule_value['CURRENCY'], $property_currency)
2307 ),
2308 'PAYMENT' => $payment
2309 );
2310
2311 $inventory['ROOM_ID'] = $room->room_id;
2312 $inventory['ROOM_NAME'] = $room->room_description;
2313 $inventory['NAME_TRANSLATED'] = $room->room_description;
2314
2315 if ($room->room_type_id == 1) {
2316 $inventory['ROOM_TYPE'] = 'ROOM';
2317 } else {
2318 $inventory['ROOM_TYPE'] = 'DORM';
2319 }
2320
2321 if($modification_checkout){
2322 // modification checkout should add beds that are booked to existing inventory
2323 // get key for $room->room_id
2324 // get and add guests to the availability
2325 $key = array_search($room->room_id, $chosen_rooms);
2326 if($key !== false){
2327 $available_value['AVAILABLE']+= $chosen_guest[$key];
2328 }
2329 }
2330
2331
2332 $inventory['BEDS'] = $available_value['AVAILABLE'];
2333 $inventory['GUESTS'] = $room_guests[$room->room_id];
2334 $datetime = DateTime::createFromFormat('Y-m-d', $inventory_value['DATE']);
2335 $inventory['NIGHT'] = $datetime->format('Y-m-d');
2336
2337 $inventory['PAYMENT']['DEPOSIT'] = $rate_plan_deposit;
2338 $inventory['PAYMENT']['MILESTONES'] = $reservation_milestones;
2339 $inventory['PAYMENT']['CANCELLATIONS'] = $reservation_cancellations;
2340 $inventory['OCCUPANCY'] = $room->number_of_guests;
2341 $inventory['PAYMENT']['SPECIAL'] = select_action($rate_plan_rule);
2342
2343 $available_units = $room_guests[$room->room_id];
2344 if ($room->room_type_id == 1) {
2345 // for rooms we send beds but we need to compare rooms because $available_value['AVAILABLE'] will hold room number
2346 $available_units = (int)($room_guests[$room->room_id] / $room->number_of_guests);
2347 }
2348
2349 if ($available_units <= $available_value['AVAILABLE']) {
2350 array_push($inventory_available, $inventory);
2351 }
2352 }
2353 }
2354 }
2355 }
2356 }
2357 }
2358 }
2359 }
2360 }
2361 }
2362
2363 $return['BOOKING_EXPENSE'] = array(
2364 'USD' => 0.00,
2365 'EUR' => 0.00,
2366 'GBP' => 0.00
2367 );
2368 if (count($inventory_available)) {
2369 array_push($return['RESPONSE'], $inventory_available);
2370
2371 if ($charge_expense) {
2372 $return['BOOKING_EXPENSE'] = $booking_expense;
2373 }
2374 }
2375
2376 $start_date = date("Y-m-d", strtotime("+1 day", strtotime($start_date)));
2377 }
2378 } else {
2379 $return['ERROR'] = array(
2380 'STATUS' => TRUE,
2381 'MESSAGE' => 'Wrong property'
2382 );
2383 }
2384 } else {
2385 $return['ERROR'] = array(
2386 'STATUS' => TRUE,
2387 'MESSAGE' => 'Wrong parameters'
2388 );
2389 }
2390
2391 $return['PARAM'] = $return_source;
2392 return $return;
2393 }
2394
2395 function payment($param) {
2396
2397 if( isset($param['test_mode']) && $param['test_mode'] == 1 ){
2398 // set test mode
2399 $this->CI->stripe->change_test_mode(TRUE);
2400 }
2401
2402 $this->CI->load->model('extranet/property_model');
2403 $this->CI->load->model('/csr/credit_card_model', 'ci_credit_card_model');
2404 $this->CI->load->model('extranet/guest_model');
2405 $this->CI->load->model('extranet/currency_model');
2406 $this->CI->load->model('extranet/country_model');
2407 $this->CI->load->model('extranet/currency_exchange_model');
2408 $this->CI->load->model('extranet/payment_model');
2409 $this->CI->load->model('extranet/booking_model');
2410 $this->CI->load->model('extranet/booking_has_milestone_model');
2411 $this->CI->load->model('extranet/property_has_tax_model');
2412 $this->CI->load->model('extranet/room_model');
2413 $this->CI->load->model('extranet/inventory_model');
2414 $this->CI->load->model('extranet/milestone_payment_model');
2415 $this->CI->load->model('extranet/inventory_has_booking_model');
2416 $this->CI->load->model('extranet/account_model');
2417 $this->CI->load->model('extranet/invoice_model');
2418 $this->CI->load->model('extranet/rate_plan_rule_model');
2419 $this->CI->load->model('user_model');
2420
2421 $this->CI->load->library('forex');
2422
2423 $stripe_conf = $this->CI->config->item('stripe');
2424 $stripe_fees = $stripe_conf['transaction_fee'];
2425
2426 $return = array();
2427 $return['STATUS'] = array();
2428
2429 try {
2430
2431 $request_time = microtime(true);
2432
2433 $payment_currency = $this->CI->config->item('payment_currency');
2434 $payment_encrypt = $this->CI->config->item('payment_encrypt');
2435
2436 $guest_currency = $param['guest_currency'];
2437 $billing_currency = $param['billing_currency'];
2438 $default_settle_currency = $param['default_settle_currency'];
2439
2440 $first_name = $param['first_name'];
2441 $last_name = $param['last_name'];
2442 $country_id = $param['country_id'];
2443 $count_male = $param['count_male'];
2444 $count_female = $param['count_female'];
2445 $guest_phone = $param['guest_phone'];
2446 $guest_email = $param['guest_email'];
2447 $guest_currency = $param['guest_currency'];
2448 $billing_currency = $param['billing_currency'];
2449 $deposit_amount = $param['deposit_amount'][$billing_currency];
2450 $total_amount = $param['total_amount'][$billing_currency];
2451 $property_id = $param['property_id'];
2452 $param_start_date = $param['start_date']->format('Y-m-d');
2453 $number_of_nights = $param['number_of_nights'];
2454
2455 $chosen_rooms = $param['chosen_rooms'];
2456 $chosen_guest = $param['chosen_guest'];
2457 $chosen_rates = $param['chosen_rates'];
2458
2459 $arrival_time = $param['arrival_time'];
2460 $booking_comment = $param['comment'];
2461
2462 $charge_expense = isset($param['charge_expense']) ? $param['charge_expense'] : FALSE;
2463 $booking_expense = $this->CI->config->item('booking_expense');
2464
2465 if (!$charge_expense) {
2466 $booking_expense = array(
2467 'USD' => 0.00,
2468 'EUR' => 0.00,
2469 'GBP' => 0.00
2470 );
2471 }
2472
2473 $stripe_token = $param['stripe_token'];
2474 //or a saved card
2475 $card_uuid = $param['card_uuid'];
2476 $reuse_card = $param['reuse_card'];
2477 //we build this string so its reusable for the stripe customer
2478 //we have 3 stripe customer accounts per Dorms.com user
2479 //USD | GBP | EUR so we have that as a centralized data
2480 $customer_stripe_id_country = FALSE;
2481 //Get the user id if he is logged in
2482 //this is important because if he is logged in we can reuse his Stripe customer account
2483 $logged_in_user_id = $param['logged_in_user_id'];
2484 if ($logged_in_user_id) {
2485 $user_info = $this->CI->user_model->get_user($logged_in_user_id);
2486 //stripe_customer_id_EUR || stripe_customer_id_USD || stripe_customer_id_GBP
2487 $customer_stripe_id_country = 'stripe_customer_id_' . $billing_currency;
2488 $stripe_customer_id = $user_info->$customer_stripe_id_country;
2489 } else {
2490 $stripe_customer_id = false;
2491 }
2492 if ($reuse_card == 'on' && $card_uuid) {
2493 //get the card object
2494 $saved_card_object = $this->CI->ci_credit_card_model->get_credit_card_by_uuid($card_uuid);
2495 //change stripe to saved card currency because the card is created on that account
2496 $this->CI->stripe->change_account($saved_card_object->currency_code);
2497 } else {
2498 //because its a new account switch it to the website currency
2499 $this->CI->stripe->change_account($billing_currency);
2500 }
2501
2502
2503
2504 $check_param['start_date'] = $param_start_date;
2505 $check_param['number_of_nights'] = $number_of_nights;
2506 $check_param['property_id'] = $property_id;
2507 $check_param['chosen_rooms'] = $chosen_rooms;
2508 $check_param['chosen_rates'] = $chosen_rates;
2509 $check_param['chosen_guest'] = $chosen_guest;
2510 $check_param['guest_currency'] = $guest_currency;
2511 $check_param['charge_expense'] = $charge_expense;
2512
2513 $checkout = $this->checkout($check_param);
2514
2515 $room_guests = array();
2516 $room_rates = array();
2517
2518 foreach ($chosen_rooms as $key => $value) {
2519 $room_rates[$value] = $chosen_rates[$key];
2520 $room_guests[$value] = $chosen_guest[$key];
2521 }
2522
2523 $count_female = count($chosen_guest);
2524
2525 $param = array();
2526 $param['property_id'] = $property_id;
2527 $property = $this->property($param);
2528
2529 if ($property['PROPERTY']['ID'] != NULL) {
2530
2531 $property_id = $property['PROPERTY']['ID'];
2532 $property_currency = $property['PROPERTY']['CURRENCY']['CODE'];
2533
2534 $country = $this->CI->country_model->select(array('country.id' => $country_id));
2535 $country_id = isset($country[0]->id) ? $country[0]->id : NULL;
2536
2537 $creteria = array(
2538 'currency.currency_code' => $billing_currency
2539 );
2540 $currency = $this->CI->currency_model->select($creteria);
2541
2542 if (isset($currency[0])) {
2543
2544 $currency = $currency[0];
2545
2546 $list_room = $this->rooms($property_id);
2547 $_room_name = array();
2548
2549 foreach ($list_room as $value) {
2550 if (in_array($value->room_id, $chosen_rooms)) {
2551 $_room_name[$value->room_id] = $value->room_description;
2552 }
2553 }
2554
2555 $end_date = date("Y-m-d", strtotime("+$number_of_nights days", strtotime($param_start_date)));
2556 $room_day_price = array();
2557 $room_occupancy = array();
2558 foreach ($checkout['RESPONSE'] as $date_value) {
2559 foreach ($date_value as $value) {
2560 array_push($payment_currency, $value['PRICES']['CUSTOMER']['CURRENCY']);
2561 array_push($payment_currency, $value['PRICES']['PROPERTY']['CURRENCY']);
2562 $room_day_price[$value['ROOM_ID']][$value['NIGHT']] = $value['PRICES']['PROPERTY']['MINPRICE'];
2563 if ($value['ROOM_TYPE'] == "ROOM") {
2564 $room_occupancy[$value['ROOM_ID']] = $value['OCCUPANCY'];
2565 }
2566 }
2567 }
2568
2569 $rate_plan_rule = $this->CI->rate_plan_rule_model->select(array('rate_plan.property_id' => $property_id));
2570
2571 $room_rate_inventory = array();
2572
2573 foreach ($chosen_rooms as $room_id) {
2574
2575 $date1 = new DateTime($param_start_date);
2576 $date2 = new DateTime($end_date);
2577 $interval = DateInterval::createFromDateString('1 day');
2578 $period = new DatePeriod($date1, $interval, $date2);
2579
2580 $deposit_percent = NULL;
2581 $rate_plan_id = NULL;
2582 $commission_as_deposit = NULL;
2583
2584 foreach ($rate_plan_rule as $plan_rule) {
2585 if ($plan_rule->rate_plan_rule_id == $room_rates[$room_id]) {
2586 $rate_plan_id = $plan_rule->rate_plan_id;
2587 $deposit_percent = $plan_rule->deposit;
2588 $commission_as_deposit = $plan_rule->commission_as_deposit;
2589
2590 }
2591 }
2592
2593 foreach ($period as $date) {
2594
2595 // if room is private will have room-occupancy
2596 if (isset($room_occupancy[$room_id])) {
2597 $allocation = ($room_guests[$room_id] / $room_occupancy[$room_id]);
2598 } else {
2599 $allocation = $room_guests[$room_id];
2600 }
2601
2602 array_push($room_rate_inventory, array(
2603 'room_id' => $room_id,
2604 'rate_plan_id' => $rate_plan_id,
2605 'rate_plan_rule_id' => $room_rates[$room_id],
2606 'deposit_percent' => $deposit_percent,
2607 'commission' => 15,
2608 'allocation' => $allocation,
2609 'date' => $date->format("Y-m-d"),
2610 'price' => $room_day_price[$room_id][$date->format("Y-m-d")],
2611 'commission_as_deposit' => $commission_as_deposit,
2612 ));
2613 }
2614 }
2615
2616 $start_date = $param_start_date;
2617 $end_date = date("Y-m-d", strtotime("+$number_of_nights days", strtotime($start_date)));
2618
2619 $datetime = DateTime::createFromFormat('Y-m-d', $start_date);
2620 $start_date = $datetime->format('Y-m-d');
2621
2622 $end_date = date("Y-m-d", strtotime("+$number_of_nights days", strtotime($start_date)));
2623
2624 $param_helper['date1'] = new DateTime($start_date);
2625 $param_helper['date2'] = new DateTime($end_date);
2626 $param_helper['chosen_rooms'] = $chosen_rooms;
2627 $param_helper['chosen_rates'] = $chosen_rates;
2628 $param_helper['chosen_guest'] = $chosen_guest;
2629
2630 $live_data = roomrate_inventory($param_helper);
2631
2632 $number_of_guests = 0;
2633 $group_rate_type = false;
2634
2635 foreach ($chosen_guest as $value) {
2636 $number_of_guests += (int) $value;
2637 }
2638
2639 if ($number_of_guests > 0 && $number_of_guests > (int) $property['PROPERTY']['MAX_BEDS_PER_BOOKING']) {
2640 $group_rate_type = true;
2641 }
2642
2643 $property_inventory = $this->CI->inventory_model->get_property_inventory($property_id, $start_date, $end_date, $live_data, $group_rate_type);
2644
2645 foreach ($property_inventory as $a => $b) {
2646 foreach ($b as $c => $d) {
2647 //array_push($payment_currency, $d['CURRENCY']);
2648 }
2649 }
2650
2651 array_push($payment_currency, $guest_currency);
2652 array_push($payment_currency, $currency->currency_code);
2653 array_push($payment_currency, $property_currency);
2654 // we will convert in this 3 currencies
2655 array_push($payment_currency, "EUR");
2656 array_push($payment_currency, "USD");
2657 array_push($payment_currency, "GBP");
2658
2659 $payment_currency = array_unique($payment_currency);
2660 $payment_currency = array_values($payment_currency);
2661 $currency_exchange = $this->CI->forex->batch_rate($payment_currency);
2662
2663 $calculated_total = 0;
2664 $calculated_deposit = 0;
2665 $milestone_charges = array();
2666 $cancellation_rules = array();
2667 $total_amount_list = array(
2668 "EUR" => 0,
2669 "USD" => 0,
2670 "GBP" => 0,
2671 "property" => 0
2672 );
2673
2674 $deposit_amount_list = array(
2675 "EUR" => 0,
2676 "USD" => 0,
2677 "GBP" => 0,
2678 "property" => 0
2679 );
2680
2681 foreach ($checkout['RESPONSE'] as $date_value) {
2682 foreach ($date_value as $value) {
2683
2684 $deposit = ($value['PAYMENT']['DEPOSIT'] / 100);
2685 $deposit_amount_list['EUR'] += ($value['PRICES']['PAYMENT']['EUR']) * $deposit;
2686 $deposit_amount_list['USD'] += ($value['PRICES']['PAYMENT']['USD']) * $deposit;
2687 $deposit_amount_list['GBP'] += ($value['PRICES']['PAYMENT']['GBP']) * $deposit;
2688 $deposit_amount_list['property'] += ($value['PRICES']['PROPERTY']['MINPRICE']) * $deposit;
2689
2690 $the_amt = $value['PRICES']['PAYMENT'][$billing_currency];
2691
2692 if ($value['PAYMENT']['MILESTONES']) {
2693 foreach ($value['PAYMENT']['MILESTONES'] as $milestone) {
2694 $milestone = (object) $milestone;
2695 if (!isset($milestone_charges[$milestone->id])) {
2696 $milestone_charges[$milestone->id] = array();
2697 $milestone_charges[$milestone->id]['inverval'] = $milestone->interval;
2698 $milestone_charges[$milestone->id]['amount'] = 0; // billing amount
2699 $milestone_charges[$milestone->id]['amount_currencies'] = array(
2700 "EUR" => 0,
2701 "USD" => 0,
2702 "GBP" => 0,
2703 "property" => 0,
2704 );
2705 ;
2706 }
2707 // get converted here<
2708 $deposit_part = ($milestone->percentage / 100);
2709 $milestone_charges[$milestone->id]['amount'] += ($the_amt * $deposit_part);
2710 $milestone_charges[$milestone->id]['amount_currencies']["EUR"] += $value['PRICES']['PAYMENT']['EUR'] * $deposit_part;
2711 $milestone_charges[$milestone->id]['amount_currencies']["USD"] += $value['PRICES']['PAYMENT']['USD'] * $deposit_part;
2712 $milestone_charges[$milestone->id]['amount_currencies']["GBP"] += $value['PRICES']['PAYMENT']['GBP'] * $deposit_part;
2713 $milestone_charges[$milestone->id]['amount_currencies']["property"] += $value['PRICES']['PROPERTY']['MINPRICE'] * $deposit_part;
2714 }
2715 }
2716
2717 // should have cancellations here too
2718 if ($value['PAYMENT']['CANCELLATIONS']) {
2719 foreach ($value['PAYMENT']['CANCELLATIONS'] as $plan_rule_id => $cancellation) {
2720 $cancellation = (object) $cancellation;
2721 $cancellation_rules[$plan_rule_id] = $cancellation;
2722 }
2723 }
2724
2725 $total_amount_list['property'] += $value['PRICES']['PROPERTY']['MINPRICE'];
2726 $total_amount_list['EUR'] += $value['PRICES']['PAYMENT']['EUR'];
2727 $total_amount_list['USD'] += $value['PRICES']['PAYMENT']['USD'];
2728 $total_amount_list['GBP'] += $value['PRICES']['PAYMENT']['GBP'];
2729 }
2730 }
2731
2732 // dont take from parameter, calculate again
2733 $deposit_amount = $deposit_amount_list[$billing_currency] + $booking_expense[$billing_currency];
2734 $deposit_amount_inventory = $deposit_amount_list['property']; // deposit in inventory currency only related to property (without extra expenses)
2735 // why comparing ?
2736 $calculated_deposit = number_format((float) $deposit_amount, 2, '.', '');
2737 $deposit_amount = number_format((float) $deposit_amount, 2, '.', '');
2738
2739 $charged_expense = array(
2740 'expense' => $booking_expense
2741 );
2742
2743
2744 if ($deposit_amount == $calculated_deposit) {
2745 $guest_id = 0;
2746 //if the card is reused then get the saved customer rather then creating one
2747 if ($reuse_card == 'on' && $card_uuid) {
2748 $stripe_customer = json_decode($this->CI->stripe->customer_info($saved_card_object->stripe_customer_code));
2749
2750 $sandbox = ($stripe_customer->livemode == true) ? '0' : '1';
2751
2752 $stripe_card_id = $saved_card_object->stripe_card_code;
2753 } else {
2754 //if the customer exists and the use is logged in
2755 if ($stripe_customer_id && false) { // this is causing error for logged in customers
2756 $stripe_customer = json_decode($this->CI->stripe->customer_info($stripe_customer_id));
2757
2758 $sandbox = ($stripe_customer->livemode == true) ? '0' : '1';
2759
2760 $card = json_decode($this->CI->stripe->customer_assign_card($stripe_customer_id, $stripe_token));
2761 $stripe_card_id = $card->id;
2762 } else {
2763 //update the customer for the new card to be always default
2764 $stripe_customer = json_decode($this->CI->stripe->customer_create($stripe_token, $guest_email));
2765 $sandbox = ($stripe_customer->livemode == true) ? '0' : '1';
2766
2767 $stripe_card_id = $stripe_customer->default_source;
2768 }
2769 }
2770
2771 if (isset($stripe_customer->id)) {
2772 ##get the credit card used
2773 ##for this booking
2774 $stripe_credit_card = json_decode($this->CI->stripe->card_info($stripe_customer->id, $stripe_card_id));
2775 ##Set stripe data for return
2776 ##in case the user wants to save the card for future usage
2777 $return['STRIPE_DATA'] = [
2778 'STRIPE_CUSTOMER' => $stripe_customer->id,
2779 'STRIPE_CREDIT_CARD' => $stripe_credit_card->id,
2780 ];
2781 $this->CI->guest_model->set_country_id($country_id);
2782 $this->CI->guest_model->set_first_name($first_name);
2783 $this->CI->guest_model->set_last_name($last_name);
2784 $this->CI->guest_model->set_email($guest_email);
2785 $this->CI->guest_model->set_phone_number($guest_phone);
2786 $this->CI->guest_model->set_currency($billing_currency);
2787 $this->CI->guest_model->set_stripe_customer_id($stripe_customer->id);
2788 $this->CI->guest_model->set_stripe_data(json_encode($stripe_customer));
2789 $this->CI->guest_model->set_sandbox($sandbox);
2790 $this->CI->guest_model->set_status(1);
2791 $guest_id = $this->CI->guest_model->insert();
2792
2793 $guest = $this->CI->guest_model->get_guest($guest_id);
2794 }
2795
2796 if (isset($guest)) {
2797
2798 $customer_exist = json_decode($this->CI->stripe->customer_info($guest->stripe_customer_id));
2799
2800 $allow_booking = false;
2801
2802 if (isset($guest->stripe_customer_id) && !isset($customer_exist->error)) {
2803 if ($deposit_amount != 0) {
2804 //we charge if deposit is more than 0.00
2805 //if the card is re-used then charge the card not the customer
2806 if ($reuse_card == 'on' && $card_uuid) {
2807 $charge_json = $this->CI->stripe->charge_card(
2808 round($deposit_amount * 100), //amount in cents
2809 $guest->stripe_customer_id, //customer
2810 $saved_card_object->stripe_card_code, //card
2811 $billing_currency, //currency
2812 'DORMS-' . 're-used card');
2813 } else {
2814 if ($logged_in_user_id) {
2815 ##If the user is logged in then we need to use
2816 ##his credit card
2817 $charge_json = $this->CI->stripe->charge_card(
2818 round($deposit_amount * 100), //amount in cents
2819 $guest->stripe_customer_id, //customer
2820 $stripe_card_id, //card
2821 $billing_currency, //currency
2822 'DORMS-' . 'logged user');
2823 } else {
2824 //if the customer is just created then just charge the customer rather the card
2825 $charge_json = $this->CI->stripe->charge_customer(
2826 round($deposit_amount * 100), $guest->stripe_customer_id, 'DORMS-' . 'not logged in customer', $billing_currency);
2827 }
2828 }
2829 $stripe_charge = json_decode($charge_json);
2830 if (isset($stripe_charge->id)) {
2831 $allow_booking = true;
2832 } else {
2833 $allow_booking = false;
2834 }
2835 } else { //we don't charge but the booking can be done
2836 $allow_booking = true;
2837 }
2838 } else {
2839 $stripe_charge = false;
2840 }
2841
2842 if (isset($stripe_charge->id) || $allow_booking) {
2843
2844 if (isset($stripe_charge->id)) {
2845
2846 $currency_id = get_currency_id((string) $stripe_charge->currency);
2847 $stripe_amount_charged = (double) ($stripe_charge->amount / 100);
2848 $this->CI->payment_model->set_guest_id($guest->id);
2849 $this->CI->payment_model->set_currency_id($currency_id);
2850 $this->CI->payment_model->set_stripe_datetime(date("Y-m-d H:i:s"));
2851 $this->CI->payment_model->set_stripe_carge_id($stripe_charge->id);
2852 $this->CI->payment_model->set_stripe_paid($stripe_charge->paid);
2853
2854 $stripe_amount = (double) ($stripe_charge->amount / 100);
2855 $this->CI->payment_model->set_stripe_amount($stripe_amount);
2856
2857 $this->CI->payment_model->set_stripe_currency(strtoupper($stripe_charge->currency));
2858
2859 // convert payment in EUR/USD/GBP
2860 $this->CI->payment_model->set_amount_EUR($this->CI->forex->batch_exchange($stripe_amount, strtoupper($stripe_charge->currency), 'EUR'));
2861 $this->CI->payment_model->set_amount_USD($this->CI->forex->batch_exchange($stripe_amount, strtoupper($stripe_charge->currency), 'USD'));
2862 $this->CI->payment_model->set_amount_GBP($this->CI->forex->batch_exchange($stripe_amount, strtoupper($stripe_charge->currency), 'GBP'));
2863
2864 $this->CI->payment_model->set_card_fee_percent((double) $stripe_fees['percent']);
2865 $this->CI->payment_model->set_card_fee_amount((double) $stripe_fees['flat']);
2866
2867 $this->CI->payment_model->set_stripe_data(json_encode($stripe_charge));
2868 $this->CI->payment_model->set_sandbox($sandbox);
2869 $this->CI->payment_model->set_created(date("Y-m-d H:i:s"));
2870 $this->CI->payment_model->set_status(1);
2871 $payment_id = $this->CI->payment_model->insert();
2872 } else {
2873 $payment_id = NULL;
2874 $stripe_amount_charged = 0;
2875 }
2876
2877 if ($payment_id > 0 || $payment_id === NULL) {
2878
2879 // Calculates the commission and rounds it to to decimal
2880 $commission_percent = $this->CI->config->item('commission');
2881 $commission_calculated = round(($commission_percent / 100) * $total_amount_list[$billing_currency], 2);
2882
2883 $this->CI->booking_model->set_property_id($property_id);
2884 $this->CI->booking_model->set_payment_id($payment_id);
2885 $this->CI->booking_model->set_guest_id($guest->id);
2886 $this->CI->booking_model->set_arrival($start_date);
2887 $this->CI->booking_model->set_departure($end_date);
2888 $this->CI->booking_model->set_client_ip_address($this->CI->input->ip_address());
2889 $this->CI->booking_model->set_count_male($count_female);
2890 $this->CI->booking_model->set_count_female($count_female);
2891 $this->CI->booking_model->set_inventory(json_encode($room_rate_inventory));
2892 $this->CI->booking_model->set_cancellation(json_encode($cancellation_rules));
2893
2894 $this->CI->booking_model->set_amount_charged($stripe_amount_charged);
2895 $this->CI->booking_model->set_amount_charged_inventory($deposit_amount_inventory);
2896
2897 $this->CI->booking_model->set_amount_total($total_amount_list[$billing_currency]);
2898 $this->CI->booking_model->set_amount_total_EUR($total_amount_list['EUR']);
2899 $this->CI->booking_model->set_amount_total_USD($total_amount_list['USD']);
2900 $this->CI->booking_model->set_amount_total_GBP($total_amount_list['GBP']);
2901 $this->CI->booking_model->set_amount_total_inventory($total_amount_list['property']);
2902
2903 $this->CI->booking_model->set_commission($commission_calculated);
2904 $this->CI->booking_model->set_commission_EUR(round(($commission_percent / 100) * $total_amount_list['EUR'], 2));
2905 $this->CI->booking_model->set_commission_USD(round(($commission_percent / 100) * $total_amount_list['USD'], 2));
2906 $this->CI->booking_model->set_commission_GBP(round(($commission_percent / 100) * $total_amount_list['GBP'], 2));
2907 $this->CI->booking_model->set_commission_inventory(round(($commission_percent / 100) * $total_amount_list['property'], 2));
2908
2909 $this->CI->booking_model->set_expense($booking_expense[$billing_currency]);
2910 $this->CI->booking_model->set_expense_EUR($this->CI->forex->batch_exchange($booking_expense[$billing_currency], $billing_currency, "EUR"));
2911 $this->CI->booking_model->set_expense_USD($this->CI->forex->batch_exchange($booking_expense[$billing_currency], $billing_currency, "USD"));
2912 $this->CI->booking_model->set_expense_GBP($this->CI->forex->batch_exchange($booking_expense[$billing_currency], $billing_currency, "GBP"));
2913
2914 $this->CI->booking_model->set_arrival_time($arrival_time);
2915 $this->CI->booking_model->set_comment($booking_comment);
2916 $this->CI->booking_model->set_sandbox($sandbox);
2917 $this->CI->booking_model->set_created(date("Y-m-d H:i:s"));
2918 $this->CI->booking_model->set_status(1);
2919 $booking_id = $this->CI->booking_model->insert();
2920
2921 if ($booking_id > 0) {
2922
2923 $this->CI->ch_engine->reservation_notification($property, $booking_id);
2924
2925 $this->tranfer_booking_to_property_account($this->CI->booking_model->get_booking($booking_id));
2926
2927 // Insert milestones if any
2928 if (count($milestone_charges) >= 1) {
2929 foreach ($milestone_charges as $milestone_id => $milestone_data) {
2930 $this->CI->booking_has_milestone_model->set_booking_id($booking_id);
2931 $this->CI->booking_has_milestone_model->set_milestone_id($milestone_id);
2932 $this->CI->booking_has_milestone_model->set_payment_id(null); // to be inserted after charge
2933 $this->CI->booking_has_milestone_model->set_amount_charged($milestone_data['amount']);
2934 $this->CI->booking_has_milestone_model->set_charge_currency($billing_currency);
2935 // add all 3 currencies
2936 $this->CI->booking_has_milestone_model->set_amount_EUR($milestone_data['amount_currencies']['EUR']);
2937 $this->CI->booking_has_milestone_model->set_amount_USD($milestone_data['amount_currencies']['USD']);
2938 $this->CI->booking_has_milestone_model->set_amount_GBP($milestone_data['amount_currencies']['GBP']);
2939 $this->CI->booking_has_milestone_model->set_amount_inventory($milestone_data['amount_currencies']['property']);
2940 // settle date is interval days before arrival date
2941 $settle_date = date("Y-m-d", strtotime("-{$milestone_data['inverval']} days", strtotime($start_date)));
2942 $this->CI->booking_has_milestone_model->set_settle_date($settle_date);
2943 $this->CI->booking_has_milestone_model->set_sandbox($sandbox);
2944 $this->CI->booking_has_milestone_model->set_created(date("Y-m-d H:i:s"));
2945 $this->CI->booking_has_milestone_model->set_status('0'); // 0 = to be charged; 1 = charged; 2=failed
2946 $id = $this->CI->booking_has_milestone_model->insert();
2947 }
2948 }
2949
2950 $return['BOOKING_ID'] = booking_reference($booking_id);
2951 $return['BOOKING_RAW_ID'] = $booking_id;
2952
2953 if(isset($stripe_charge) && isset($stripe_charge->id)){
2954 ##update the charge ID so it shows in the credit card description of the charge
2955 $this->CI->stripe->update_charge($stripe_charge->id, ['description' => $return['BOOKING_ID']]);
2956 }
2957
2958 $return['CURRENCY'] = array(
2959 'CUSTOMER' => $guest_currency,
2960 'BILLING' => $billing_currency
2961 );
2962
2963 $milestone_amount = 0.00;
2964 $already_charged = 0.00;
2965 $payable_on_arrival = 0.00;
2966 $rooms_booked = array();
2967
2968 foreach ($checkout['RESPONSE'] as $date_value) {
2969 foreach ($date_value as $value) {
2970
2971 $datetime = DateTime::createFromFormat('Y-m-d', $value['NIGHT']);
2972
2973 $_room['ROOM_ID'] = $value['ROOM_ID'];
2974 $_room['NAME'] = $_room_name[$value['ROOM_ID']];
2975 $_room['BEDS'] = $room_guests[$value['ROOM_ID']];
2976
2977 $_room['PRICE_PROPERTY'] = array(
2978 'CURRENCY' => $value['PRICES']['PROPERTY']['CURRENCY'],
2979 'AMOUNT' => number_format($value['PRICES']['PROPERTY']['MINPRICE'], 2, '.', '')
2980 );
2981 $_room['PRICE_CUSTOMER'] = array(
2982 'CURRENCY' => $value['PRICES']['CUSTOMER']['CURRENCY'],
2983 'AMOUNT' => number_format($value['PRICES']['CUSTOMER']['MINPRICE'], 2, '.', '')
2984 );
2985 $_room['PRICE_BILLING'] = array(
2986 'CURRENCY' => $billing_currency,
2987 'AMOUNT' => number_format($value['PRICES']['PAYMENT'][$billing_currency], 2, '.', '')
2988 );
2989 $_room['DATE'] = $datetime->format('Y-m-d');
2990
2991 array_push($rooms_booked, $_room);
2992
2993 $total_amount = $total_amount + $value['PRICES']['PAYMENT'][$billing_currency];
2994 // calculate $already_charged amount
2995 $already_charged_percent = ($value['PAYMENT']['DEPOSIT']/100);
2996 $already_charged += ($already_charged_percent * $value['PRICES']['PAYMENT'][$billing_currency]);
2997 // calculate $payable_on_arrival amount
2998 $payable_on_arrival_percent = ( (100 - $value['PAYMENT']['DEPOSIT']) /100 );
2999 $payable_on_arrival += ($payable_on_arrival_percent * $value['PRICES']['PAYMENT'][$billing_currency]);
3000
3001
3002
3003 if($value['PAYMENT']['MILESTONES']){
3004 foreach($value['PAYMENT']['MILESTONES'] as $milestone){
3005 $milestone_amount = $milestone_amount + ($value['PRICES']['PAYMENT'][$billing_currency] * ($milestone['percentage'] / 100));
3006 // milestone should be deducted from the $payable_on_arrival
3007 $payable_on_arrival -= ($value['PRICES']['PAYMENT'][$billing_currency] * ($milestone['percentage'] / 100));
3008 }
3009 }
3010
3011 // update inventory for all properties
3012 // properties related to a channel will have inventory update by the channel after booking notification
3013 $inventory_units = $room_guests[$value['ROOM_ID']];
3014 if ($value['ROOM_TYPE'] == 'ROOM') {
3015 // for rooms we send beds but we need to compare rooms because $available_value['AVAILABLE'] will hold room number
3016 $inventory_units = (int)($room_guests[$value['ROOM_ID']] / $value['OCCUPANCY']);
3017 }
3018 $this->CI->inventory_model->available_inventory(array('inventory.date' => $value['NIGHT'], 'inventory.room_id' => $value['ROOM_ID']), $inventory_units);
3019
3020 $this->CI->inventory_has_booking_model->set_inventory_id($value['INVENTORY_ID']);
3021 $this->CI->inventory_has_booking_model->set_booking_id($booking_id);
3022 $this->CI->inventory_has_booking_model->insert();
3023 }
3024 }
3025
3026 if (isset($already_charged) && isset($payable_on_arrival)) {
3027
3028 $return['PAYMENT']['CURRENCY']['CUSTOMER']['AMOUNT_TAKEN'] = $this->CI->forex->batch_exchange($already_charged, $billing_currency, $guest_currency);
3029 $return['PAYMENT']['CURRENCY']['CUSTOMER']['MILESTONE_AMOUNT'] = $this->CI->forex->batch_exchange($milestone_amount, $billing_currency, $guest_currency);
3030 $return['PAYMENT']['CURRENCY']['CUSTOMER']['PAYABLE_ON_ARRIVAL'] = $this->CI->forex->batch_exchange($payable_on_arrival, $billing_currency, $guest_currency);
3031 $return['PAYMENT']['CURRENCY']['CUSTOMER']['CURRENCY'] = $guest_currency;
3032
3033 $return['PAYMENT']['CURRENCY']['PROPERTY']['AMOUNT_TAKEN'] = $this->CI->forex->batch_exchange($already_charged, $billing_currency, $property_currency);
3034 $return['PAYMENT']['CURRENCY']['PROPERTY']['MILESTONE_AMOUNT'] = $this->CI->forex->batch_exchange($milestone_amount, $billing_currency, $property_currency);
3035 $return['PAYMENT']['CURRENCY']['PROPERTY']['PAYABLE_ON_ARRIVAL'] = $this->CI->forex->batch_exchange($payable_on_arrival, $billing_currency, $property_currency);
3036 $return['PAYMENT']['CURRENCY']['PROPERTY']['CURRENCY'] = $property_currency;
3037
3038 $return['PAYMENT']['CURRENCY'][strtoupper($guest_currency)]['AMOUNT_TAKEN'] = $this->CI->forex->batch_exchange($already_charged, $billing_currency, $guest_currency);
3039 $return['PAYMENT']['CURRENCY'][strtoupper($guest_currency)]['MILESTONE_AMOUNT'] = $this->CI->forex->batch_exchange($milestone_amount, $billing_currency, $guest_currency);
3040 $return['PAYMENT']['CURRENCY'][strtoupper($guest_currency)]['PAYABLE_ON_ARRIVAL'] = $this->CI->forex->batch_exchange($payable_on_arrival, $billing_currency, $guest_currency);
3041
3042 $return['PAYMENT']['CURRENCY'][strtoupper($billing_currency)]['AMOUNT_TAKEN'] = $this->CI->forex->batch_exchange($already_charged, $billing_currency, $billing_currency);
3043 $return['PAYMENT']['CURRENCY'][strtoupper($billing_currency)]['MILESTONE_AMOUNT'] = $this->CI->forex->batch_exchange($milestone_amount, $billing_currency, $billing_currency);
3044 $return['PAYMENT']['CURRENCY'][strtoupper($billing_currency)]['PAYABLE_ON_ARRIVAL'] = $this->CI->forex->batch_exchange($payable_on_arrival, $billing_currency, $billing_currency);
3045
3046 $return['PAYMENT']['PAYMENT_CURRENCY'] = $billing_currency;
3047
3048 $return['PROPERTY']['ID'] = $property['PROPERTY']['ID'];
3049 $return['PROPERTY']['NAME'] = $property['PROPERTY']['NAME'];
3050 $return['PROPERTY']['IMAGES'] = $property['PROPERTY']['IMAGES'];
3051 $return['PROPERTY']['ADDRESS']['STREET1'] = $property['PROPERTY']['ADDRESS']['STREET1'];
3052 $return['PROPERTY']['ADDRESS']['STREET2'] = $property['PROPERTY']['ADDRESS']['STREET2'];
3053 $return['PROPERTY']['ADDRESS']['STREET3'] = $property['PROPERTY']['ADDRESS']['STREET3'];
3054 $return['PROPERTY']['ADDRESS']['CITY'] = $property['PROPERTY']['ADDRESS']['CITY'];
3055 $return['PROPERTY']['ADDRESS']['STATE'] = $property['PROPERTY']['ADDRESS']['STATE'];
3056 $return['PROPERTY']['ADDRESS']['ZIP'] = $property['PROPERTY']['ADDRESS']['ZIP'];
3057 $return['PROPERTY']['ADDRESS']['COUNTRY'] = $property['PROPERTY']['ADDRESS']['COUNTRY'];
3058 $return['PROPERTY']['ADDRESS']['CONTACT'] = $property['PROPERTY']['PHONE']['CONTACT'];
3059 $return['PROPERTY']['ADDRESS']['FAX'] = $property['PROPERTY']['FAX'];
3060 $return['PROPERTY']['ADDRESS']['WEBSITE'] = $property['PROPERTY']['WEBSITE'];
3061 $return['PROPERTY']['ADDRESS']['EMAIL'] = $property['PROPERTY']['EMAIL']['PROPERTY'];
3062 $return['PROPERTY']['IMPORTANT_INFORMATION']['CHECK_IN_TIME'] = '';
3063 $return['PROPERTY']['IMPORTANT_INFORMATION']['CHECK_OUT_TIME'] = '';
3064 $return['PROPERTY']['IMPORTANT_INFORMATION']['CANCELLATION_POLICY'] = '';
3065 $return['PROPERTY']['IMPORTANT_INFORMATION']['TAXES'] = $property['PROPERTY']['TAX'];
3066 $return['PROPERTY']['IMPORTANT_INFORMATION']['EXTRA_INFORMATION'] = '';
3067 $return['PROPERTY']['ROOMS_BOOKED']['ROOM'] = $rooms_booked;
3068 $return['CHECKOUT'] = $checkout;
3069 } else {
3070 if (!isset($return['STATUS']['ERRORS'])) {
3071 $return['STATUS']['ERRORS'] = array();
3072 }
3073 array_push($return['STATUS']['ERRORS'], 'Sorry, error on booking. Please try again. Code:110');
3074 }
3075 } else {
3076 if (!isset($return['STATUS']['ERRORS'])) {
3077 $return['STATUS']['ERRORS'] = array();
3078 }
3079 array_push($return['STATUS']['ERRORS'], 'Sorry, error on booking. Please try again. Code:111');
3080 }
3081 }
3082 } else {
3083 $return = array();
3084 $return['STATUS']['ERRORS'] = array();
3085 if (isset($stripe_charge->error)) {
3086 array_push($return['STATUS']['ERRORS'], $stripe_charge->error->message);
3087 } else {
3088 array_push($return['STATUS']['ERRORS'], '');
3089 }
3090 }
3091 } else {
3092 if (!isset($return['STATUS']['ERRORS'])) {
3093 $return['STATUS']['ERRORS'] = array();
3094 }
3095 array_push($return['STATUS']['ERRORS'], 'Sorry, error on booking. Please try again. Code:112');
3096 }
3097
3098 $response_time = microtime(true);
3099 $total_time = ($response_time - $request_time) * 1000;
3100 $total_time = floor($total_time);
3101 $total_time = $total_time . " ms ";
3102 $this->CI->custom_log->log("audit", 'DORMS API checkout [sandbox] ' . $total_time);
3103
3104 if ($return !== false) {
3105 if (isset($return['BOOKING_ID'])) {
3106 $this->CI->custom_log->log("booking", 'DORMS-' . $return['BOOKING_ID'] . ' booking ' . $billing_currency . ' ' . $this->CI->forex->batch_exchange($deposit_amount, $billing_currency, $billing_currency));
3107 }
3108 }
3109 } else {
3110 if (!isset($return['STATUS']['ERRORS'])) {
3111 $return['STATUS']['ERRORS'] = array();
3112 }
3113 array_push($return['STATUS']['ERRORS'], 'Sorry, error on booking. Please try again. Code:113');
3114 }
3115 } else {
3116 if (!isset($return['STATUS']['ERRORS'])) {
3117 $return['STATUS']['ERRORS'] = array();
3118 }
3119 array_push($return['STATUS']['ERRORS'], 'Sorry, error on booking. Please try again. Code:114');
3120 }
3121
3122 if (!isset($return['STATUS']['ERRORS'])) {
3123 $return['STATUS']['ERRORS'] = array();
3124 }
3125
3126 if (!count($return['STATUS']['ERRORS'])) {
3127 $return['STATUS']['SUCCESS'] = 'TRUE';
3128 unset($return['STATUS']['ERRORS']);
3129 } else {
3130 $return['STATUS']['SUCCESS'] = 'FALSE';
3131 }
3132
3133 $return = array_to_object($return);
3134 return $return;
3135 } else {
3136 if (!isset($return['STATUS']['ERRORS'])) {
3137 $return['STATUS']['ERRORS'] = array();
3138 }
3139 array_push($return['STATUS']['ERRORS'], 'Sorry, error on booking. Please try again. Code:115');
3140 $return = array_to_object($return);
3141 return $return;
3142 }
3143 } catch (Exception $exc) {
3144 if (!isset($return['STATUS']['ERRORS'])) {
3145 $return['STATUS']['ERRORS'] = array();
3146 }
3147 array_push($return['STATUS']['ERRORS'], 'Sorry, error on booking. Please try again. Code:116');
3148 $this->CI->custom_log->log("Dorms-error-booking", $exc->getTraceAsString());
3149 $return = array_to_object($return);
3150 return $return;
3151 }
3152
3153 return false;
3154 }
3155
3156 function save_review($params) {
3157
3158 try {
3159 $this->CI->load->model('extranet/review_model');
3160 $this->CI->load->model('extranet/rating_model');
3161 $this->CI->load->model('extranet/review_has_review_group_model', "review_group");
3162 $this->CI->review_model->set_booking_id($params['booking_id']);
3163 $this->CI->review_model->set_approve(0);
3164 $this->CI->review_model->set_created(date("Y-m-d H:i:s"));
3165 $this->CI->review_model->set_summary($params['summary']);
3166 $this->CI->review_model->set_review($params['review']);
3167 $this->CI->review_model->set_recommend($params['recommend']);
3168 $review_id = $this->CI->review_model->insert();
3169
3170 foreach ($params['ratings'] as $id => $rating) {
3171 $this->CI->rating_model->set_property_id($params['booking_data']->property_id);
3172 $this->CI->rating_model->set_rating_category_id($id);
3173 $this->CI->rating_model->set_review_id($review_id);
3174 $this->CI->rating_model->set_rating($rating);
3175 $this->CI->rating_model->insert();
3176 }
3177
3178 if ($params['recommend'] == 1) {
3179 foreach ($params['recommend_group'] as $id => $recommend) {
3180 if ($recommend == 1) {
3181 $this->CI->review_group->set_property_review_id($review_id);
3182 $this->CI->review_group->set_review_group_id($id);
3183 $this->CI->review_group->insert();
3184 }
3185 }
3186 }
3187
3188 return $review_id;
3189 } catch (Exception $exc) {
3190 print $exc->getTraceAsString();
3191 log_message('error', __FUNCTION__ . ' : ' . $exc->getTraceAsString());
3192 }
3193
3194 return false;
3195 }
3196
3197 /**
3198 * Sets property general data into data array
3199 * @param array $data
3200 */
3201 public function set_property_page_general_data(&$data) {
3202
3203 $hostel = $data['hostel'];
3204 $hostel_address = $hostel['ADDRESS'];
3205
3206 $data['hostel_comments'] = NULL; //@remove
3207 $data['api_error'] = false; //@remove
3208 $data['api_error_msg'] = ''; //@remove
3209 $data['city_landmarks'] = array();
3210 $data['country_system_name'] = ''; //@remove
3211 $data['availability_check'] = true; //@remove
3212 $data['google_map_enable'] = true;
3213 $data['google_map_address'] = $hostel_address["STREET1"] . ", " . $hostel_address["CITY"] . ", " . $hostel_address["COUNTRY"] . ", " . $hostel_address["ZIP"];
3214
3215 if (( floatval($hostel["GPS"]["LAT"]) != 0) && ( floatval($hostel["GPS"]["LON"]) != 0)) {
3216 $data['google_map_geo_latlng'] = str_replace(",", ".", $hostel["GPS"]["LAT"]) . ", " . str_replace(",", ".", $hostel["GPS"]["LON"]);
3217 }
3218
3219 $data['hostel_rating'] = null; //@remove
3220 $data['hostel_db_data'] = new stdClass(); //@remove
3221 $data['property_ratings'] = !empty($hostel['ratings']) ? $hostel['ratings'] : array();
3222
3223 $data['continent_selected'] = ''; //related to search box, shouldn't be here
3224 $data['country_selected'] = ''; //related to search box, shouldn't be here
3225 $data['city_selected'] = ''; //related to search box, shouldn't be here
3226
3227 $data['bc_continent'] = ''; //@remove
3228 $data['bc_country'] = $hostel_address['COUNTRY'];
3229 $data['bc_city'] = $hostel_address['CITY'];
3230
3231 $data['r_country'] = $hostel_address['COUNTRY'];
3232 $data['r_city'] = $hostel_address['CITY'];
3233
3234 $data['currency'] = $this->CI->site_currency;
3235 $data['main_services'] = array();
3236
3237 $this->CI->load->helper('property_name');
3238 $data['title'] = get_site_title($hostel['NAME'], $hostel['TYPE'], $hostel['ADDRESS']['COUNTRY']);
3239 $data['load_js_livevalidation'] = true; //unused
3240 }
3241
3242 /**
3243 * Returns property reviews
3244 * @param int $property_id
3245 * @param int $max_review_count
3246 * @return int
3247 */
3248 function property_reviews($property_id, $max_review_count = 0) {
3249
3250 $this->CI->load->model('Db_property_review');
3251
3252 $data["user_reviews"] = array();
3253 $data["reviews_translation_available"] = false;
3254 $index = 0;
3255
3256 $our_reviews = $this->CI->Db_property_review->get_property_reviews($property_id, 'hm');
3257
3258 if (!empty($our_reviews)) {
3259 foreach ($our_reviews as $our_review) {
3260 $data["user_reviews"][$index] = $our_review;
3261 $index++;
3262
3263 if (($max_review_count > 0) && ($index >= $max_review_count)) {
3264 //$data["reviews_translation_available"] = $this->CI->Hb_api_translate->translate_reviews($data["user_reviews"]);
3265 $data["review_count"] = $index;
3266 return $data;
3267 }
3268 }
3269 }
3270
3271 $data["review_count"] = $index;
3272
3273 return $data;
3274 }
3275
3276 /**
3277 * Transfering a booking to property account means:
3278 *
3279 *
3280 * 1. Credit account with total amount paied (for 100% deposit and milestones)
3281 * 2. Debit account with commission
3282 * 3. Debit account with credit-card fees (for 100% deposit and milestones)
3283 *
3284 * Amounts in account table are always in EUR
3285 *
3286 * @param type $booking
3287 */
3288 private function tranfer_booking_to_property_account($booking) {
3289
3290 // if charge is greater or equal to amount_total then there is 100% deposit
3291 // and we should credit the property account
3292 // else -> there is 0% deposit and no credit shoudl happen
3293 $this->CI->load->model('extranet/account_model');
3294 $this->CI->load->model('extranet/currency_model');
3295 $this->CI->load->library('forex');
3296 // is there expense ? Save the expense with no property ID (this is Dorms.com only)
3297 if ($booking->booking_expense && $booking->booking_expense > 0) {
3298 // --- add booking_fee accouting withut property_id (only for dorms.com accounting)
3299 // there was booking fee charged, add it to accounts without property_id
3300 $this->CI->account_model->set_property_id(NULL);
3301 $this->CI->account_model->set_account_charge_id(2); // we credit dorms.com account only
3302
3303 $this->CI->account_model->set_account_entry_category_id("booking_fee"); // string will convert to ID in function
3304 $this->CI->account_model->set_currency_id($booking->currency_id);
3305 $this->CI->account_model->set_payment_id($booking->payment_id);
3306 $this->CI->account_model->set_booking_id($booking->booking_id);
3307 $this->CI->account_model->set_description("Booking fees collected by Dorms.com. Booking number #" . booking_reference($booking->booking_id));
3308 $this->CI->account_model->set_amount($booking->booking_expense); // this is invoice currency
3309 $this->CI->account_model->set_amount_EUR($booking->booking_expense_EUR);
3310 $this->CI->account_model->set_amount_USD($booking->booking_expense_USD);
3311 $this->CI->account_model->set_amount_GBP($booking->booking_expense_GBP);
3312 // $this->CI->account_model->set_amount_inventory( ); // this is only for property entries
3313 $this->CI->account_model->set_date_time(date("Y-m-d H:i:s"));
3314 $this->CI->account_model->set_status(1);
3315 $insert = $this->CI->account_model->insert();
3316 // we paied the booking fees for this transaction too
3317 }
3318
3319 // get the conversion rates for batch processing
3320 $inv_currency_data = $this->CI->currency_model->get_currency($booking->inventory_currency_id);
3321 $inventory_currency = $inv_currency_data->currency_code;
3322 $payment_currency = array();
3323 array_push($payment_currency, $booking->stripe_currency);
3324 array_push($payment_currency, "EUR");
3325 array_push($payment_currency, "USD");
3326 array_push($payment_currency, "GBP");
3327 array_push($payment_currency, $inventory_currency);
3328
3329 $payment_currency = array_unique($payment_currency);
3330 $payment_currency = array_values($payment_currency);
3331 $this->CI->forex->batch_rate($payment_currency);
3332
3333
3334 // booking_amount_charged_inventory
3335 if( $booking->booking_amount_charged_inventory > 0){
3336
3337 // reservation type for charged amount
3338 // use $booking->booking_amount_charged_inventory
3339 // converty values to all currencies
3340 $this->CI->account_model->set_property_id($booking->property_id);
3341 $this->CI->account_model->set_account_charge_id(2); // we credit the account for charged amount
3342 $this->CI->account_model->set_account_entry_category_id("reservation"); // string will convert to ID in function
3343 $this->CI->account_model->set_currency_id($booking->currency_id);
3344 $this->CI->account_model->set_payment_id($booking->payment_id);
3345 $this->CI->account_model->set_booking_id($booking->booking_id);
3346 $this->CI->account_model->set_description("Booking amount collected by Dorms.com on behalf of the property. Booking number #" . booking_reference($booking->booking_id));
3347 $this->CI->account_model->set_amount($booking->stripe_amount - $booking->booking_expense); // this is charged currency
3348 // add eur/usd/gbp
3349 $this->CI->account_model->set_amount_EUR($booking->amount_EUR - $booking->booking_expense_EUR);
3350 $this->CI->account_model->set_amount_USD($booking->amount_USD - $booking->booking_expense_USD);
3351 $this->CI->account_model->set_amount_GBP($booking->amount_GBP - $booking->booking_expense_GBP);
3352 // inventory currency amount
3353 $this->CI->account_model->set_amount_inventory($booking->booking_amount_charged_inventory);
3354 $this->CI->account_model->set_date_time(date("Y-m-d H:i:s"));
3355 $this->CI->account_model->set_status(1);
3356 $this->CI->account_model->insert();
3357
3358 // stripe charges can be different we need to fetch from transaction balance
3359 $stripe_data = json_decode($booking->stripe_data);
3360 $retrive_balance = $this->CI->stripe->retrive_balance($stripe_data->balance_transaction);
3361 $retrive_balance = json_decode($retrive_balance);
3362
3363 $commission_as_deposit = 1;
3364 $inventory_details = json_decode($booking->inventory);
3365 foreach($inventory_details as $row){
3366 if($row->commission_as_deposit == 0){
3367 // if some rate has no commission-as-deposit we charge the fees
3368 $commission_as_deposit = 0;
3369 }
3370 }
3371
3372 foreach($retrive_balance->fee_details as $fee){
3373
3374 // Check if property should not be charged processing fee
3375 if($fee->type == "stripe_fee" && $commission_as_deposit == 0){
3376 // only processing fee is vissible to the property
3377 // others are covered by Dorms.com we are just logging them
3378 $this->CI->account_model->set_property_id($booking->property_id);
3379 }else{
3380 $this->CI->account_model->set_property_id(NULL);
3381 }
3382
3383 $this->CI->account_model->set_account_charge_id(1); // we debit the account for credit card fees
3384 $this->CI->account_model->set_account_entry_category_id("collection_fee"); // string will convert to ID in function
3385 $this->CI->account_model->set_currency_id($booking->currency_id);
3386 $this->CI->account_model->set_payment_id($booking->payment_id);
3387 $this->CI->account_model->set_booking_id($booking->booking_id);
3388 $this->CI->account_model->set_description("Credit card fees (".$fee->description.") for booking #" . booking_reference($booking->booking_id));
3389 // fees are percentage + flat rate and should be based on charge currency/amount
3390
3391 $cc_fee_amount = ($fee->amount / 100);
3392 $this->CI->account_model->set_amount($cc_fee_amount);
3393 // save all 3 currencies too
3394 $this->CI->account_model->set_amount_EUR($this->CI->forex->batch_exchange($cc_fee_amount, strtoupper($fee->currency), "EUR"));
3395 $this->CI->account_model->set_amount_USD($this->CI->forex->batch_exchange($cc_fee_amount, strtoupper($fee->currency), "USD"));
3396 $this->CI->account_model->set_amount_GBP($this->CI->forex->batch_exchange($cc_fee_amount, strtoupper($fee->currency), "GBP"));
3397 // calculate the fees percent + flat rate in inventory currency
3398
3399 $fees_amount_inventory = $this->CI->forex->batch_exchange($cc_fee_amount, strtoupper($fee->currency), $inventory_currency);
3400 $this->CI->account_model->set_amount_inventory($fees_amount_inventory);
3401 // add eur/usd/gbp
3402 $this->CI->account_model->set_date_time(date("Y-m-d H:i:s"));
3403 $this->CI->account_model->set_status(1);
3404 $this->CI->account_model->insert();
3405 }
3406
3407
3408 // add type commission
3409 // calculate commission based on $booking->booking_amount_charged_inventory
3410 // converty to all cirrencies
3411 // debit the account with commission amount
3412 $commission_percent = $this->CI->config->item('commission');
3413
3414 $this->CI->account_model->set_property_id($booking->property_id);
3415 $this->CI->account_model->set_account_charge_id(1); // we debit the account for commission
3416 $this->CI->account_model->set_account_entry_category_id("commission"); // string will convert to ID in function
3417 $this->CI->account_model->set_currency_id($booking->currency_id);
3418 $this->CI->account_model->set_payment_id($booking->payment_id);
3419 $this->CI->account_model->set_booking_id($booking->booking_id);
3420 $this->CI->account_model->set_description("Commission of ".$commission_percent."% for booking #" . booking_reference($booking->booking_id));
3421
3422 // commission should be percent of what is charges today
3423 $commission_amount = round(($commission_percent / 100) * ($booking->stripe_amount - $booking->booking_expense), 2);
3424 $this->CI->account_model->set_amount( $commission_amount );
3425 // add eur/usd/gbp
3426 $commission_amount_EUR = round(($commission_percent / 100) * ($booking->amount_EUR - $booking->booking_expense_EUR), 2);
3427 $commission_amount_USD = round(($commission_percent / 100) * ($booking->amount_USD - $booking->booking_expense_USD), 2);
3428 $commission_amount_GBP = round(($commission_percent / 100) * ($booking->amount_GBP - $booking->booking_expense_GBP), 2);
3429 $this->CI->account_model->set_amount_EUR( $commission_amount_EUR );
3430 $this->CI->account_model->set_amount_USD( $commission_amount_USD );
3431 $this->CI->account_model->set_amount_GBP( $commission_amount_GBP );
3432
3433 $commission_inventory = round(($commission_percent / 100) * $booking->booking_amount_charged_inventory, 2);
3434 $this->CI->account_model->set_amount_inventory( $commission_inventory );
3435 $this->CI->account_model->set_date_time(date("Y-m-d H:i:s"));
3436 $this->CI->account_model->set_status(1);
3437 $this->CI->account_model->insert();
3438 }
3439
3440
3441 return true;
3442 }
3443
3444 function cancel_booking_brakedown($booking_id, $no_show_request = 0) {
3445
3446 $result = array();
3447 $this->CI->load->model('extranet/booking_model');
3448 $this->CI->load->model('extranet/currency_model');
3449 $this->CI->load->model('extranet/cancellation_model');
3450
3451 $booking = $this->CI->booking_model->get_booking($booking_id);
3452
3453 if ($booking->booking_processed == 1) {
3454 $result['status'] = "false";
3455 $result['message'] = "You can cancel this booking so another backpacker can enjoy this hostel, but pre-payments made are non-refundable.";
3456 return $result;
3457 }
3458
3459 if ($booking->booking_amount_total <= $booking->booking_amount) {
3460 $result['status'] = "false";
3461 $result['message'] = "You can cancel this booking so another backpacker can enjoy this hostel, but pre-payments made are non-refundable..";
3462 return $result;
3463 }
3464
3465 if ($no_show_request == 0) {
3466 $arrival_date = date_create(date("Y-m-d", strtotime("+1 day", strtotime($booking->arrival_date))));
3467 } else {
3468 $arrival_date = date_create(date("Y-m-d", strtotime("+3 days", strtotime($booking->arrival_date))));
3469 }
3470
3471 $today = date_create(date('Y-m-d'));
3472 $difference = date_diff($today, $arrival_date);
3473 $difference = $difference->format("%d");
3474
3475 if ($difference <= 0) {
3476 $result['status'] = "false";
3477 $result['message'] = "You cannot cancel bookings with arrival date in the past.";
3478 return $result;
3479 }
3480 /**
3481 * ToDo
3482 * We do the same check again because we want to do the actuall day caluclation
3483 */
3484 $arrival_date = date_create(date("Y-m-d", strtotime("+0 days", strtotime($booking->arrival_date))));
3485 $difference = date_diff($today, $arrival_date);
3486 $difference = $difference->format("%d");
3487
3488 $booking_fee = 0;
3489
3490 $inventory = json_decode($booking->inventory);
3491 $cancellation_rules = json_decode($booking->booking_cancellation, true);
3492
3493 $inventory_structure = array();
3494 foreach ($inventory as $inventory) {
3495 if (!isset($inventory_structure[$inventory->room_id])) {
3496 $inventory_structure[$inventory->room_id]['total_deposit'] = 0;
3497 $inventory_structure[$inventory->room_id]['nights'] = array();
3498 $inventory_structure[$inventory->room_id]['cancellation'] = "";
3499 if (isset($cancellation_rules[$inventory->rate_plan_rule_id])) {
3500 $inventory_structure[$inventory->room_id]['cancellation'] = (object) $cancellation_rules[$inventory->rate_plan_rule_id];
3501 }
3502 }
3503 $inventory_structure[$inventory->room_id]['nights'][] = $inventory;
3504 $deposit_taken = ($inventory->price * ($inventory->deposit_percent / 100));
3505 $inventory_structure[$inventory->room_id]['total_deposit'] += $deposit_taken;
3506 }
3507
3508 $result = array();
3509 $result['status'] = "true";
3510
3511 $inventory_currency = $this->CI->currency_model->get_currency($booking->inventory_currency_id);
3512 foreach ($inventory_structure as $room_id => $data) {
3513
3514 $result['rooms'][$room_id]['currency'] = $inventory_currency->currency_code; // this is saved in property inventory currency
3515
3516 if (isset($data['cancellation']->interval) && $data['cancellation']->interval >= $difference) {
3517 $result['rooms'][$room_id]['cancellation_fee'] = calculate_cancellation_fee($data['cancellation']->charge, $data['cancellation']->amount, $data['nights']);
3518 $result['rooms'][$room_id]['deposit'] = $data['total_deposit'];
3519 $total_to_pay = $result['rooms'][$room_id]['cancellation_fee'] - $data['total_deposit'];
3520 if($total_to_pay > 0){
3521 $result['rooms'][$room_id]['fee'] = $total_to_pay;
3522 }else{
3523 $result['rooms'][$room_id]['fee'] = 0;
3524 }
3525 } else {
3526 $result['rooms'][$room_id]['fee'] = '0';
3527 $result['rooms'][$room_id]['deposit'] = '0';
3528 }
3529 }
3530
3531 $cancel_code = strong_password(15, false, "lud");
3532 $this->CI->booking_model->set_cancel_booking_code($cancel_code);
3533 $this->CI->booking_model->set_id($booking_id);
3534 $this->CI->booking_model->update();
3535
3536 $result['cancellation_code'] = $cancel_code;
3537
3538 return $result;
3539 }
3540
3541 function cancel_booking($booking_id, $cancel_code, $no_show_request = 0) {
3542
3543 $result = array();
3544 $this->CI->load->model('extranet/currency_model');
3545 $this->CI->load->model('extranet/booking_model');
3546 $this->CI->load->model('extranet/cancellation_model');
3547 $this->CI->load->model('extranet/payment_model');
3548 $this->CI->load->model('extranet/payment_has_cancellation_model');
3549 $this->CI->load->model('extranet/account_model');
3550 $this->CI->load->model('extranet/inventory_has_booking_model');
3551 $stripe_conf = $this->CI->config->item('stripe');
3552 $stripe_fees = $stripe_conf['transaction_fee'];
3553
3554 $booking = $this->CI->booking_model->get_booking($booking_id);
3555
3556 if (!$cancel_code || !isset($booking->booking_id)) {
3557 $result['status'] = "false";
3558 $result['message'] = "Invalid booking ID or invalid cancellation code";
3559 return $result;
3560 }
3561
3562 if ($booking->cancel_booking_code !== $cancel_code) {
3563 // REF 111
3564 $result['status'] = "false";
3565 $result['message'] = "An error occurred, please contact administrator. Code: 111";
3566 return $result;
3567 }
3568
3569 if ($booking->booking_processed == 1) {
3570 // REF 112
3571 $result['status'] = "false";
3572 $result['message'] = "An error occurred, please contact administrator. Code 112";
3573 return $result;
3574 }
3575
3576 if ($booking->booking_amount_total <= $booking->booking_amount) {
3577 $result['status'] = "false";
3578 $result['message'] = "This booking was fully paid at time of booking. Deposits and pre-payments are non-refundable and non-transferable.";
3579 return $result;
3580 }
3581
3582 if ($no_show_request == 0) {
3583 $arrival_date = date_create(date("Y-m-d", strtotime("+1 day", strtotime($booking->arrival_date))));
3584 } else {
3585 $arrival_date = date_create(date("Y-m-d", strtotime("+3 days", strtotime($booking->arrival_date))));
3586 }
3587
3588 $today = date_create(date('Y-m-d'));
3589 $difference = date_diff($today, $arrival_date);
3590 $difference = $difference->format("%R%a");
3591 if ($difference <= 0 ) {
3592 $result['status'] = "false";
3593 $result['message'] = "You cannot cancel bookings with arrival date in the past.";
3594 return $result;
3595 }
3596 /**
3597 * ToDo
3598 * We do the same check again because we want to do the actuall day caluclation
3599 */
3600
3601 $arrival_date = date_create(date("Y-m-d", strtotime("+0 days", strtotime($booking->arrival_date))));
3602 $difference = date_diff($today, $arrival_date);
3603 $difference = $difference->format("%d");
3604
3605 $booking_fee = 0;
3606
3607 $inventory = json_decode($booking->inventory);
3608 $cancellation_rules = json_decode($booking->booking_cancellation, true);
3609
3610 $inventory_structure = array();
3611 foreach ($inventory as $inventory) {
3612 if (!isset($inventory_structure[$inventory->room_id])) {
3613 $inventory_structure[$inventory->room_id]['total_deposit'] = 0;
3614 $inventory_structure[$inventory->room_id]['nights'] = array();
3615 $inventory_structure[$inventory->room_id]['cancellation'] = "";
3616 if (isset($cancellation_rules[$inventory->rate_plan_rule_id])) {
3617 $inventory_structure[$inventory->room_id]['cancellation'] = (object) $cancellation_rules[$inventory->rate_plan_rule_id];
3618 }
3619 }
3620 $inventory_structure[$inventory->room_id]['nights'][] = $inventory;
3621 $deposit_taken = ($inventory->price * ($inventory->deposit_percent / 100));
3622 $inventory_structure[$inventory->room_id]['total_deposit'] += $deposit_taken;
3623 }
3624
3625 $total_to_charge = 0;
3626
3627 foreach ($inventory_structure as $room_id => $data) {
3628 if (isset($data['cancellation']->interval) && $data['cancellation']->interval >= $difference) {
3629 $total_for_room = calculate_cancellation_fee($data['cancellation']->charge, $data['cancellation']->amount, $data['nights']);
3630 $total_for_room -= $data['total_deposit'];
3631 if($total_for_room > 0){
3632 $total_to_charge += $total_for_room;
3633 }
3634 }
3635 }
3636
3637 $inventory_currency = $this->CI->currency_model->get_currency($booking->inventory_currency_id);
3638
3639
3640 $exchange_currencies = array("EUR", "GBP", "USD", $inventory_currency->currency_code);
3641 $this->CI->forex->batch_rate($exchange_currencies);
3642
3643 if ($total_to_charge > 0) {
3644
3645 $booking->currency_id = ($booking->currency_id)?$booking->currency_id:$booking->guest_currency_id; // if no stripe currency use guest currency
3646 $billing_currency = ($booking->stripe_currency)?$booking->stripe_currency:$booking->guest_currency; // if no stripe currency use guest currency
3647
3648 $billing_amount = $this->CI->forex->batch_exchange($total_to_charge, $inventory_currency->currency_code, $billing_currency);
3649 $this->CI->stripe->change_account($billing_currency);
3650
3651 $charge_amount = round($billing_amount * 100);
3652 $charge_json = $this->CI->stripe->charge_customer($charge_amount, $booking->stripe_customer_id, 'dorm-test-cancellation', $billing_currency);
3653 $stripe_charge = json_decode($charge_json);
3654
3655 if (isset($stripe_charge->id)) {
3656
3657 $this->CI->payment_model->set_currency_id($booking->currency_id);
3658 $this->CI->payment_model->set_guest_id($booking->guest_id);
3659 $this->CI->payment_model->set_stripe_datetime(date("Y-m-d H:i:s"));
3660 $this->CI->payment_model->set_stripe_carge_id($stripe_charge->id);
3661 $this->CI->payment_model->set_stripe_paid($stripe_charge->paid);
3662 $this->CI->payment_model->set_stripe_amount((double) ($stripe_charge->amount / 100));
3663 $this->CI->payment_model->set_stripe_currency(strtoupper($stripe_charge->currency));
3664 $stripe_amount = (double) ($stripe_charge->amount / 100);
3665 // convert to all 3 currencies at collection time
3666 $amount_EUR = $this->CI->forex->batch_exchange($total_to_charge, $inventory_currency->currency_code, 'EUR');
3667 $amount_USD = $this->CI->forex->batch_exchange($total_to_charge, $inventory_currency->currency_code, 'USD');
3668 $amount_GBP = $this->CI->forex->batch_exchange($total_to_charge, $inventory_currency->currency_code, 'GBP');
3669
3670 $this->CI->payment_model->set_amount_EUR($amount_EUR);
3671 $this->CI->payment_model->set_amount_USD($amount_USD);
3672 $this->CI->payment_model->set_amount_GBP($amount_GBP);
3673
3674 $this->CI->payment_model->set_card_fee_percent($stripe_fees['percent']);
3675 $this->CI->payment_model->set_card_fee_amount($stripe_fees['flat']);
3676
3677 $this->CI->payment_model->set_stripe_data(json_encode($stripe_charge));
3678 $this->CI->payment_model->set_sandbox(($stripe_charge->livemode == true) ? 1 : 0 );
3679 $this->CI->payment_model->set_created(date("Y-m-d H:i:s"));
3680 $this->CI->payment_model->set_status(1);
3681 $payment_id = $this->CI->payment_model->insert();
3682
3683 $this->CI->account_model->set_property_id($booking->property_id);
3684 $this->CI->account_model->set_account_charge_id(2); // credit amount for cancellation fee
3685 $this->CI->account_model->set_account_entry_category_id("cancellation"); // string will convert to ID in function
3686 $this->CI->account_model->set_currency_id($booking->currency_id);
3687 $this->CI->account_model->set_payment_id($payment_id);
3688 $this->CI->account_model->set_booking_id($booking->booking_id);
3689 $this->CI->account_model->set_description("Cancellation fee for booking #" . booking_reference($booking->booking_id));
3690
3691 $this->CI->account_model->set_amount($stripe_amount); // whatever was charged
3692 $this->CI->account_model->set_amount_inventory($total_to_charge); // whatever was charged
3693 // set all 3 currencies
3694 $this->CI->account_model->set_amount_EUR($amount_EUR);
3695 $this->CI->account_model->set_amount_USD($amount_USD);
3696 $this->CI->account_model->set_amount_GBP($amount_GBP);
3697 $this->CI->account_model->set_date_time(date("Y-m-d H:i:s"));
3698 $this->CI->account_model->set_status(1);
3699 $this->CI->account_model->insert();
3700
3701 // ADD credit card fees for this too
3702 // stripe charges can be different we need to fetch from transaction balance
3703 $retrive_balance = $this->CI->stripe->retrive_balance($stripe_charge->balance_transaction);
3704 $retrive_balance = json_decode($retrive_balance);
3705
3706 foreach($retrive_balance->fee_details as $fee){
3707 // TODO: Check if property should not be charged processing fee
3708 if($fee->type == "stripe_fee"){
3709 // only processing fee is vissible to the property
3710 // others are covered by Dorms.com we are just logging them
3711 $this->CI->account_model->set_property_id($booking->property_id);
3712 }else{
3713 $this->CI->account_model->set_property_id(NULL);
3714 }
3715
3716 $this->CI->account_model->set_account_charge_id(1); // we debit the account for credit card fees
3717 $this->CI->account_model->set_currency_id($booking->currency_id);
3718 $this->CI->account_model->set_account_entry_category_id("collection_fee"); // string will convert to ID in function
3719 $this->CI->account_model->set_payment_id($payment_id);
3720 $this->CI->account_model->set_booking_id($booking->booking_id);
3721
3722 $this->CI->account_model->set_description("Credit card fees (".$fee->description.") for booking #" . booking_reference($booking->booking_id));
3723 // fees are percentage + flat rate and should be based on charge currency/amount
3724 $cc_fee_amount = ($fee->amount / 100);
3725 $this->CI->account_model->set_amount($cc_fee_amount);
3726 // save all 3 currencies too
3727 $this->CI->account_model->set_amount_EUR($this->CI->forex->batch_exchange($cc_fee_amount, strtoupper($fee->currency), "EUR"));
3728 $this->CI->account_model->set_amount_USD($this->CI->forex->batch_exchange($cc_fee_amount, strtoupper($fee->currency), "USD"));
3729 $this->CI->account_model->set_amount_GBP($this->CI->forex->batch_exchange($cc_fee_amount, strtoupper($fee->currency), "GBP"));
3730 // calculate the fees percent + flat rate in inventory currency
3731 $fees_amount_inventory = $this->CI->forex->batch_exchange($cc_fee_amount, strtoupper($fee->currency), $inventory_currency->currency_code);
3732 $this->CI->account_model->set_amount_inventory($fees_amount_inventory);
3733
3734 $this->CI->account_model->set_date_time(date("Y-m-d H:i:s"));
3735 $this->CI->account_model->set_status(1);
3736 $this->CI->account_model->insert();
3737 }
3738
3739 // calculate commission here
3740 // add type commission
3741 // calculate commission based on $milestone->amount_inventory
3742 // converty to all cirrencies
3743 // debit the account with commission amount
3744 $commission_percent = $this->CI->config->item('commission');
3745 $this->CI->account_model->set_property_id($booking->property_id);
3746 $this->CI->account_model->set_account_charge_id(1); // we debit the account for commission
3747 $this->CI->account_model->set_currency_id($booking->currency_id);
3748 $this->CI->account_model->set_account_entry_category_id("commission"); // string will convert to ID in function
3749 $this->CI->account_model->set_payment_id($payment_id);
3750 $this->CI->account_model->set_booking_id($booking->booking_id);
3751 $this->CI->account_model->set_description("Commission of ".$commission_percent."% for cancellation for booking #" . booking_reference($booking->booking_id));
3752 // commission should be percent of what is charges today
3753 $commission_amount = round(($commission_percent / 100) * ($stripe_amount), 2);
3754 $this->CI->account_model->set_amount( $commission_amount );
3755 //eur/gbp/usd
3756 $commission_amount_EUR = $this->CI->forex->batch_exchange($commission_amount, strtoupper($stripe_charge->currency), "EUR");
3757 $commission_amount_USD = $this->CI->forex->batch_exchange($commission_amount, strtoupper($stripe_charge->currency), "USD");
3758 $commission_amount_GBP = $this->CI->forex->batch_exchange($commission_amount, strtoupper($stripe_charge->currency), "GBP");
3759 $this->CI->account_model->set_amount_EUR( $commission_amount_EUR );
3760 $this->CI->account_model->set_amount_USD( $commission_amount_USD );
3761 $this->CI->account_model->set_amount_GBP( $commission_amount_GBP );
3762 // inventory currency
3763 $commission_inventory = round(($commission_percent / 100) * $total_to_charge, 2);
3764 $this->CI->account_model->set_amount_inventory( $commission_inventory );
3765 $this->CI->account_model->set_date_time(date("Y-m-d H:i:s"));
3766 $this->CI->account_model->set_status(1);
3767 $this->CI->account_model->insert();
3768
3769 // to confirm structure here
3770 foreach ($cancellation_rules as $room_id => $cancellation) {
3771 $this->CI->payment_has_cancellation_model->set_payment_id($payment_id);
3772 $this->CI->payment_has_cancellation_model->set_cancellation_id($cancellation['cancellation_id']);
3773 $this->CI->payment_has_cancellation_model->set_booking_id($booking_id);
3774 $this->CI->payment_has_cancellation_model->set_created(date("Y-m-d H:i:s"));
3775 $this->CI->payment_has_cancellation_model->set_status(1);
3776 $this->CI->payment_has_cancellation_model->insert();
3777 break;
3778 }
3779
3780 // ToDo send email to traveler to notify him
3781 $result['status'] = "true";
3782 $result['message'] = "Booking was cancelled and booking fee was charged successfully";
3783 } else {
3784 // ***** NO SHOW && CANCEL *****
3785 // set pending status to booking row
3786 // create cron job to check all bookings with pending status try to charge again
3787 // if charge failed again then set to failed payment and move on with your life
3788 // try again tomorrow maybe ?
3789 // this is triggered by user so maybe shot the message is better
3790 // 1 -> pending charge
3791 // 2 -> failed OR staj go vo success
3792 $charge_time = date("Y-m-d H:i:s");
3793 if($no_show_request == 1){
3794 $type = 'no_show';
3795 } else if($no_show_request == 0) {
3796 $type = 'cancel';
3797 }
3798 // if its pending that means that
3799 // its the second attempt to do the charge
3800 // please check the statuses for one booking
3801 // in the booking model
3802 if($booking->booking_status == 9){
3803 $charge_attempt = 2;
3804 } else {
3805 $charge_attempt = 1;
3806 }
3807 $this->CI->ex_email_engine->notify_error_traveler_card_charge($booking,$type,$charge_time,$charge_amount,$charge_attempt);
3808
3809 $result['status'] = "false";
3810 $result['message'] = sprintf(gettext("Unable to charge booking fees of %s"), format_currency($this->CI->wordpress, $billing_amount, $billing_currency));
3811 return $result;
3812 }
3813 }
3814
3815 if (!isset($result['status'])) {
3816 $result['status'] = "true";
3817 $result['message'] = "Booking was cancelled no extra fees were charged";
3818 }
3819
3820 // notify channels for cancellation
3821 $this->CI->load->library('ch/ch_engine');
3822 $this->CI->ch_engine->cancellation_notification($booking->property_id, $booking_id);
3823
3824 // cancel the booking
3825 // change flags
3826 $this->CI->booking_model->set_id($booking_id);
3827 $this->CI->booking_model->set_cancel_booking_code("");
3828 $this->CI->booking_model->set_status("0");
3829 $this->CI->booking_model->update();
3830
3831 // return inventory
3832 $this->CI->inventory_has_booking_model->delete(array("booking_id" => $booking_id));
3833
3834 return $result;
3835 }
3836
3837 /**
3838 * Cancels the booking
3839 * Request by : property only
3840 * Refunds the traveler and charges the property with a credit
3841 *
3842 * @param $booking_id
3843 */
3844 function property_cancel($booking_id,$refund_commissions){
3845 $result = array();
3846 $this->CI->load->model('extranet/currency_model');
3847 $this->CI->load->model('extranet/property_model');
3848 $this->CI->load->model('extranet/booking_model');
3849 $this->CI->load->model('extranet/guest_model');
3850 $this->CI->load->model('extranet/cancellation_model');
3851 $this->CI->load->model('extranet/payment_model');
3852 $this->CI->load->model('extranet/payment_has_cancellation_model');
3853 $this->CI->load->model('extranet/account_model');
3854 $this->CI->load->model('extranet/inventory_has_booking_model');
3855 $this->CI->load->model("transactions_hostelworld");
3856 $this->CI->load->model('Db_domains');
3857 $stripe_conf = $this->CI->config->item('stripe');
3858 $stripe_fees = $stripe_conf['transaction_fee'];
3859
3860 $booking = $this->CI->booking_model->get_booking($booking_id);
3861 $commissions= $this->CI->account_model->select_booking_commissions($booking_id);
3862 $charges = $this->CI->account_model->select_booking_charge_made($booking_id);
3863
3864 if (!isset($booking->id)) {
3865 $result['status'] = "false";
3866 $result['message'] = "Invalid booking ID or invalid cancellation code";
3867 return $result;
3868 }
3869
3870 if($booking->booking_status != 3){
3871 $result['status'] = "false";
3872 $result['message'] = "The cancel request was not made by a property owner.";
3873 return $result;
3874 }
3875
3876 $arrival_date = date_create(date("Y-m-d", strtotime("+1 day", strtotime($booking->arrival_date))));
3877 $today = date_create(date('Y-m-d'));
3878 $difference = date_diff($today, $arrival_date);
3879 $difference = $difference->format("%R%a");
3880 if ($difference <= 0 ) {
3881 $result['status'] = "false";
3882 $result['message'] = "You cannot cancel if arrival date is in the past";
3883 return $result;
3884 }
3885 //Loop the commissions
3886 //and if the commission is selected as refund OK
3887 //then don't credit the property for that commission
3888 if(!empty($commissions)){
3889 foreach ($commissions as $commission){
3890 if(in_array($commission->id,$refund_commissions)){
3891 // $this->CI->account_model->set_id($commission->id); // insert NEW row not update
3892 $this->CI->account_model->set_property_id($commission->property_id);
3893 $this->CI->account_model->set_account_charge_id(2); // we credit the account for refund commission
3894 $this->CI->account_model->set_account_entry_category_id($commission->account_entry_category_id);
3895 $this->CI->account_model->set_currency_id($commission->currency_id);
3896 $this->CI->account_model->set_payment_id($commission->payment_id);
3897 $this->CI->account_model->set_booking_id($booking_id);
3898 $this->CI->account_model->set_description("Transaction rollback for #" . 'TR-' . sprintf('%08d', $commission->id));
3899 $this->CI->account_model->set_amount_inventory($commission->amount_inventory);
3900
3901 $this->CI->account_model->set_amount($commission->amount);
3902 // add eur/usd/gbp
3903 $this->CI->account_model->set_amount_EUR($commission->amount_EUR);
3904 $this->CI->account_model->set_amount_USD($commission->amount_USD);
3905 $this->CI->account_model->set_amount_GBP($commission->amount_GBP);
3906 $this->CI->account_model->set_date_time(date("Y-m-d H:i:s"));
3907 $this->CI->account_model->set_status(1);
3908 $this->CI->account_model->insert();
3909 }
3910 }
3911 }
3912 //Refund the customer
3913 //Get the guest
3914 $guest = $this->CI->guest_model->get_guest($booking->guest_id);
3915 $total_charge = 0;
3916 if(!empty($charges)){
3917 foreach ($charges as $charge){
3918 //add to the total_chrage
3919 $total_charge += $charge->amount;
3920 $payment = $this->CI->payment_model->get_payment($charge->payment_id);
3921 $this->CI->stripe->change_account($payment->stripe_currency);
3922 $charge_refund = json_decode($this->CI->stripe->charge_refund($payment->stripe_carge_id));
3923 if(isset($charge_refund->id)){
3924 //set the payment rows
3925 $this->CI->payment_model->set_id($charge->payment_id);
3926 $this->CI->payment_model->set_refund_data(json_encode($charge_refund));
3927 $this->CI->payment_model->set_refund(1); //success
3928 $this->CI->payment_model->update();
3929
3930 //insert charge in the account so we can credit the property
3931 // $this->CI->account_model->set_id($charge->id); // dont set ID insert new row
3932 $this->CI->account_model->set_property_id($charge->property_id);
3933 $this->CI->account_model->set_account_charge_id(1); // we debit the account for refund
3934 $this->CI->account_model->set_account_entry_category_id($charge->account_entry_category_id);
3935 $this->CI->account_model->set_currency_id($charge->currency_id);
3936 $this->CI->account_model->set_payment_id($payment->id);
3937 $this->CI->account_model->set_booking_id($booking->id);
3938 $this->CI->account_model->set_description("Transaction rollback for #" . 'TR-' . sprintf('%08d', $commission->id));
3939 $this->CI->account_model->set_amount_inventory($charge->amount_inventory);
3940 $this->CI->account_model->set_amount($charge->amount);
3941 // add eur/usd/gbp
3942 $this->CI->account_model->set_amount_EUR($charge->amount_EUR);
3943 $this->CI->account_model->set_amount_USD($charge->amount_USD);
3944 $this->CI->account_model->set_amount_GBP($charge->amount_GBP);
3945 $this->CI->account_model->set_date_time(date("Y-m-d H:i:s"));
3946 $this->CI->account_model->set_status(1);
3947 $this->CI->account_model->insert();
3948 } else {
3949 //set the payment for fail refund
3950 $this->CI->payment_model->set_id($charge->payment_id);
3951 $this->CI->payment_model->set_refund_data(json_encode($charge_refund));
3952 $this->CI->payment_model->set_refund(0); //fail
3953 $this->CI->payment_model->update();
3954 }
3955 }
3956 } else {
3957 $result['status'] = "true";
3958 $result['message'] = "Booking was cancelled and charges were refunded";
3959 }
3960
3961 $result['status'] = "true";
3962 $result['message'] = "Booking was cancelled and charges were refunded";
3963
3964 // delete the fees because we already refunded them
3965 $delete_criteria = [
3966 'booking_id' => $booking_id,
3967 'account_entry_category_id' => Account_model::ENTRY_CATEGORY_FEE_RESERVATION
3968 ];
3969 $this->CI->account_model->delete($delete_criteria);
3970
3971 // notify channels for cancellation
3972 $this->CI->load->library('ch/ch_engine');
3973 $this->CI->ch_engine->cancellation_notification($booking->property_id, $booking_id);
3974
3975 // return inventory
3976 $this->CI->inventory_has_booking_model->delete(array("booking_id" => $booking_id));
3977 $this->CI->ex_email_engine->notify_traveler_booking_canceled($booking_id,$total_charge);
3978
3979 return $result;
3980 }
3981
3982
3983 function modify_brakedown($param){
3984
3985 $this->CI->load->model('extranet/property_model');
3986 $this->CI->load->model('extranet/currency_model');
3987 $this->CI->load->model('extranet/booking_model');
3988 $this->CI->load->library('forex');
3989 $stripe_conf = $this->CI->config->item('stripe');
3990 $stripe_fees = $stripe_conf['transaction_fee'];
3991
3992 $return = array();
3993 $return['STATUS'] = array();
3994
3995 $booking_id = $param['booking_id'];
3996 $booking = $this->CI->booking_model->get_booking($booking_id);
3997
3998 $chosen_rooms = $param['chosen_rooms'];
3999 $chosen_guest = $param['chosen_guest'];
4000 $chosen_rates = $param['chosen_rates'];
4001 $cancel_rooms = $param['cancel_rooms'];
4002
4003 $booked_inventory = json_decode($booking->inventory);
4004 $cancellation_rules = json_decode($booking->booking_cancellation, true);
4005 // check cancellation brakedown for selected rooms
4006 // show summary
4007 $inventory_structure = array();
4008 $existing_inventory = array();
4009
4010 foreach ($booked_inventory as $inventory) {
4011
4012 if( !in_array($inventory->room_id, $cancel_rooms) ){
4013
4014 // this room will stay we need to get inventory to add/sub in the new summary
4015 $existing_inventory[$inventory->room_id] = $inventory->allocation;
4016
4017 }else if (!isset($inventory_structure[$inventory->room_id])) {
4018 $inventory_structure[$inventory->room_id]['nights'] = array();
4019 $inventory_structure[$inventory->room_id]['cancellation'] = "";
4020 if (isset($cancellation_rules[$inventory->rate_plan_rule_id])) {
4021 $inventory_structure[$inventory->room_id]['cancellation'] = (object) $cancellation_rules[$inventory->rate_plan_rule_id];
4022 }
4023 $inventory_structure[$inventory->room_id]['nights'][] = $inventory;
4024 }else{
4025 $inventory_structure[$inventory->room_id]['nights'][] = $inventory;
4026 }
4027 }
4028
4029
4030 $today = date_create(date('Y-m-d'));
4031 $arrival_date = date_create(date("Y-m-d", strtotime("+0 days", strtotime($booking->arrival_date))));
4032 $difference = date_diff($today, $arrival_date);
4033 $difference = $difference->format("%d");
4034
4035 $cancel_summary = array();
4036 $inventory_currency = $this->CI->currency_model->get_currency($booking->inventory_currency_id);
4037 foreach ($inventory_structure as $room_id => $data) {
4038
4039 $cancel_summary[$room_id]['currency'] = $inventory_currency->currency_code; // this is saved in property inventory currency
4040 $cancel_summary[$room_id]['room_name'] = create_room_name($room_id);
4041
4042 if (isset($data['cancellation']->interval) && $data['cancellation']->interval >= $difference) {
4043 $cancel_summary[$room_id]['fee'] = calculate_cancellation_fee($data['cancellation']->charge, $data['cancellation']->amount, $data['nights']);
4044 } else {
4045 $cancel_summary[$room_id]['fee'] = '0';
4046 }
4047 }
4048 // cancellation is ok
4049
4050
4051 // check if room is already booked
4052 // if is booked we need to calculate the new beds only, as the old are already paied for
4053 //
4054 // checkout with new rooms selected
4055 // show summary
4056 $arrival_date = date_create(date("Y-m-d", strtotime($booking->arrival_date)));
4057 $departure_date = date_create(date("Y-m-d", strtotime($booking->departure_date)));
4058 $difference = date_diff($arrival_date, $departure_date);
4059 $num_nights = $difference->format("%d");
4060
4061 $check_param['start_date'] = $booking->arrival_date;
4062 $check_param['number_of_nights'] = $num_nights;
4063 $check_param['property_id'] = $booking->property_id;
4064 $check_param['chosen_rooms'] = $chosen_rooms;
4065 $check_param['chosen_rates'] = $chosen_rates;
4066 $check_param['chosen_guest'] = $chosen_guest;
4067 $check_param['guest_currency'] = $booking->guest_currency;
4068 $check_param['charge_expense'] = true;
4069 $check_param['modification_checkout'] = true;
4070 // before checkout
4071 // if eixsting room has more beds added we should checkout the new beds only
4072 $booking = $this->checkout($check_param);
4073
4074 $total_amount = array();
4075 $total_amount['EUR'] = 0;
4076 $total_amount['USD'] = 0;
4077 $total_amount['GBP'] = 0;
4078 $total_amount['property'] = 0;
4079 $total_amount['user'] = 0;
4080
4081 $deposit_amount = array();
4082 $deposit_amount['EUR'] = 0;
4083 $deposit_amount['USD'] = 0;
4084 $deposit_amount['GBP'] = 0;
4085 $deposit_amount['property'] = 0;
4086 $deposit_amount['user'] = 0;
4087
4088 $upon_arrival = array();
4089 $upon_arrival['EUR'] = 0;
4090 $upon_arrival['USD'] = 0;
4091 $upon_arrival['GBP'] = 0;
4092 $upon_arrival['property'] = 0;
4093 $upon_arrival['user'] = 0;
4094
4095 $data['milestone_payments'] = FALSE;
4096 $data['cancellations'] = FALSE;
4097 $total_milestone_property = array();
4098 $total_milestone_property['EUR'] = 0;
4099 $total_milestone_property['USD'] = 0;
4100 $total_milestone_property['GBP'] = 0;
4101 $total_milestone_property['property'] = 0;
4102 $room_print_info = array();
4103
4104 if( isset($booking['RESPONSE']) ){
4105 foreach ($booking['RESPONSE'] as $date_key => $date_value) {
4106 foreach ($date_value as $value) {
4107 $guests = $value['GUESTS'];
4108 $room_type = $value['ROOM_TYPE'];
4109 $deposit = $value['PAYMENT']['DEPOSIT'] / 100;
4110
4111 $total_amount['EUR'] += $value['PRICES']['PAYMENT']['EUR'];
4112 $total_amount['USD'] += $value['PRICES']['PAYMENT']['USD'];
4113 $total_amount['GBP'] += $value['PRICES']['PAYMENT']['GBP'];
4114 $total_amount['property'] += $value['PRICES']['PROPERTY']['MINPRICE'];
4115 $total_amount['user'] += $value['PRICES']['CUSTOMER']['MINPRICE'];
4116
4117 $existing_guests = 0;
4118 if( isset($existing_inventory[$value['ROOM_ID']]) ){
4119 $existing_guests = ($room_type == "DORM")? $existing_inventory[$value['ROOM_ID']] : $existing_inventory[$value['ROOM_ID']] * $value['OCCUPANCY'];
4120 }
4121
4122 $deposit_amount['EUR'] += ((($value['PRICES']['PAYMENT']['EUR']) * $deposit) / $guests) * ($guests - $existing_guests);
4123 $deposit_amount['USD'] += ((($value['PRICES']['PAYMENT']['USD']) * $deposit) / $guests) * ($guests - $existing_guests);
4124 $deposit_amount['GBP'] += ((($value['PRICES']['PAYMENT']['GBP']) * $deposit) / $guests) * ($guests - $existing_guests);
4125 $deposit_amount['property'] += ((($value['PRICES']['PROPERTY']['MINPRICE']) * $deposit) / $guests) * ($guests - $existing_guests);
4126 $deposit_amount['user'] += ((($value['PRICES']['CUSTOMER']['MINPRICE']) * $deposit) / $guests) * ($guests - $existing_guests);
4127
4128 if (!isset($room_print_info[$value['ROOM_ID']])) {
4129
4130 $room_print_info[$value['ROOM_ID']] = array(
4131 "room_name" => $value['ROOM_NAME'],
4132 "type" => $room_type,
4133 "deposit" => $value['PAYMENT']['DEPOSIT'],
4134 "nights" => array(0 => array(
4135 "price" => ($room_type == "Dorm")?$value['PRICES']['PROPERTY']['MINPRICE'] : number_format($value['PRICES']['PROPERTY']['MINPRICE'] / $guests, 2),
4136 "price_EUR" => ($room_type == "Dorm")?$value['PRICES']['PAYMENT']['EUR'] : number_format($value['PRICES']['PAYMENT']['EUR'] / $guests, 2),
4137 "price_USD" => ($room_type == "Dorm")?$value['PRICES']['PAYMENT']['USD'] : number_format($value['PRICES']['PAYMENT']['USD'] / $guests, 2),
4138 "price_GBP" => ($room_type == "Dorm")?$value['PRICES']['PAYMENT']['GBP'] : number_format($value['PRICES']['PAYMENT']['GBP'] / $guests, 2),
4139 "persons" => $guests,
4140 "existing_guests" => $existing_guests,
4141 "night" => $value['NIGHT'],
4142 "room_total" => ($room_type != "Dorm")?$value['PRICES']['PROPERTY']['MINPRICE'] : number_format($value['PRICES']['PROPERTY']['MINPRICE'] * $guests, 2)
4143 )),
4144 "milestones" => array(),
4145 "cancellations" => array(),
4146 "total_for_room" => ($room_type != "Dorm")?$value['PRICES']['PROPERTY']['MINPRICE'] : number_format($value['PRICES']['PROPERTY']['MINPRICE'] * $guests, 2),
4147 "room_amenity" => $value['PAYMENT']['SPECIAL'],
4148 "occupancy" => $value['OCCUPANCY'],
4149 "beds" => $value['BEDS'],
4150
4151 );
4152 } else {
4153 $room_print_info[$value['ROOM_ID']]["total_for_room"] += ($room_type != "Dorm")?$value['PRICES']['PROPERTY']['MINPRICE'] : number_format($value['PRICES']['PROPERTY']['MINPRICE'] * $guests, 2);
4154
4155 $room_print_info[$value['ROOM_ID']]['nights'][] = array(
4156
4157 "price" => ($room_type == "Dorm")?$value['PRICES']['PROPERTY']['MINPRICE'] : number_format($value['PRICES']['PROPERTY']['MINPRICE'] / $guests, 2),
4158 "price_EUR" => ($room_type == "Dorm")?$value['PRICES']['PAYMENT']['EUR'] : number_format($value['PRICES']['PAYMENT']['EUR'] / $guests, 2),
4159 "price_USD" => ($room_type == "Dorm")?$value['PRICES']['PAYMENT']['USD'] : number_format($value['PRICES']['PAYMENT']['USD'] / $guests, 2),
4160 "price_GBP" => ($room_type == "Dorm")?$value['PRICES']['PAYMENT']['GBP'] : number_format($value['PRICES']['PAYMENT']['GBP'] / $guests, 2),
4161 "persons" => $guests,
4162 "existing_guests" => $existing_guests,
4163 "night" => $value['NIGHT'],
4164 "room_total" => ($room_type != "Dorm")?$value['PRICES']['PROPERTY']['MINPRICE'] : number_format($value['PRICES']['PROPERTY']['MINPRICE'] * $guests, 2),
4165 );
4166 }
4167
4168 // calculate milestone payments if any
4169 if ($value['PAYMENT']['MILESTONES']) {
4170 $data['milestone_payments'] = TRUE;
4171 foreach ($value['PAYMENT']['MILESTONES'] as $milestone) {
4172
4173 if (!isset($room_print_info[$value['ROOM_ID']]['milestones'])) {
4174 $room_print_info[$value['ROOM_ID']]['milestones'] = array();
4175 }
4176 $room_price = $value['PRICES']['PROPERTY']['MINPRICE'];
4177 $room_print_info[$value['ROOM_ID']]['milestones'][$milestone['id']] = $milestone;
4178
4179 $total_milestone_property['EUR'] += ($value['PRICES']['PAYMENT']['EUR'] * ($milestone['percentage'] / 100));
4180 $total_milestone_property['USD'] += ($value['PRICES']['PAYMENT']['USD'] * ($milestone['percentage'] / 100));
4181 $total_milestone_property['GBP'] += ($value['PRICES']['PAYMENT']['GBP'] * ($milestone['percentage'] / 100));
4182 $total_milestone_property['property'] += ($room_price * ($milestone['percentage'] / 100));
4183 }
4184 }
4185
4186 if ($value['PAYMENT']['CANCELLATIONS']) {
4187 foreach ($value['PAYMENT']['CANCELLATIONS'] as $rate_rule_id => $cancellation) {
4188 $room_print_info[$value['ROOM_ID']]['cancellations'][$rate_rule_id] = $cancellation;
4189 }
4190 }
4191 }
4192 }
4193 }
4194 // sort by type, dorms are always first
4195 uasort($room_print_info, function($a, $b) {
4196 return ($a['type'] == 'DORM')?-1:1;
4197 });
4198
4199
4200 $charge_expense = isset($param['charge_expense']) ? $param['charge_expense'] : FALSE;
4201 $booking_expense = $this->CI->config->item('booking_expense');
4202
4203 if (!$charge_expense) {
4204 $booking_expense = array(
4205 'USD' => 0.00,
4206 'EUR' => 0.00,
4207 'GBP' => 0.00
4208 );
4209 }
4210
4211 $result = array();
4212 $result['booking'] = array();
4213 $result['booking']['customer_currency'] = $booking['PARAM']['CUSTOMER_CURRENCY'];
4214 $result['booking']['rooms'] = $room_print_info;
4215 $result['booking']['total'] = $total_amount;
4216 $result['booking']['deposit'] = $deposit_amount;
4217 $result['booking']['future_prepayments'] = $total_milestone_property;
4218 $result['booking']['upon_arrival'] = $upon_arrival;
4219 $result['cancellation'] = $cancel_summary;
4220 $result['expense'] = $booking_expense;
4221
4222 $total_pay = 0;
4223 $already_paid = 0;
4224 $cancellation_fee = 0;
4225 $to_be_paid = 0;
4226 // calculate what the user has paid alraedy
4227 foreach($result['booking']['rooms'] as $room) {
4228 foreach ($room['nights'] as $night) {
4229 if($night['existing_guests'] > 0){
4230 $already_paid += ($night['price_'.$booking['PARAM']['CUSTOMER_CURRENCY']] * $night['existing_guests']);
4231 }
4232 $to_be_paid += ($night['price_'.$booking['PARAM']['CUSTOMER_CURRENCY']] * ($night['persons'] - (int)$night['existing_guests']));
4233 }
4234 }
4235 $result['already_paid'] = $already_paid;
4236 $result['to_be_paid'] = $to_be_paid;
4237
4238 // calculate the cancelation fee total
4239 foreach ($result['cancellation'] as $key => $room){
4240 $fee_amount = $this->CI->forex->exchange($room['fee'], $room['currency'], $booking['PARAM']['CUSTOMER_CURRENCY']);
4241 $cancellation_fee += $fee_amount;
4242 // update fields with billing currency
4243 $result['cancellation'][$key]['currency'] = $booking['PARAM']['CUSTOMER_CURRENCY'];
4244 $result['cancellation'][$key]['fee'] = $fee_amount;
4245
4246 }
4247 $result['cancellation_fee'] = $cancellation_fee;
4248
4249 // total pay
4250 $total_pay = $cancellation_fee + $deposit_amount[$booking['PARAM']['CUSTOMER_CURRENCY']];
4251 $result['total_pay'] = $total_pay;
4252
4253 // print_r($result);exit;
4254 // overall we add cancellation price to total of new rooms
4255 // show in separate sections what we will cancel and what will be booked
4256 return $result;
4257
4258 }
4259
4260 function modify($param){
4261
4262 if( isset($param['test_mode']) && $param['test_mode'] == 1 ){
4263 // set test mode
4264 $this->CI->stripe->change_test_mode(TRUE);
4265 }
4266
4267 $this->CI->load->model('extranet/property_model');
4268 $this->CI->load->model('extranet/currency_model');
4269 $this->CI->load->model('extranet/booking_model');
4270 $this->CI->load->model('extranet/payment_model');
4271 $this->CI->load->model('extranet/account_model');
4272 $this->CI->load->model('extranet/booking_has_milestone_model');
4273 $this->CI->load->library('forex');
4274 $stripe_conf = $this->CI->config->item('stripe');
4275 $stripe_fees = $stripe_conf['transaction_fee'];
4276
4277
4278 $chosen_rooms = $param['chosen_rooms'];
4279 $chosen_guest = $param['chosen_guest'];
4280 $chosen_rates = $param['chosen_rates'];
4281 $cancel_rooms = $param['cancel_rooms'];
4282
4283 $booking_id = $param['booking_id'];
4284 $booking = $this->CI->booking_model->get_booking($booking_id);
4285 $property_data = $this->CI->property_model->get_property_by_id($booking->property_id);
4286
4287 $property_param = array();
4288 $property_param['property_id'] = $booking->property_id;
4289 $property = $this->property($property_param);
4290
4291 $brakedown = $this->modify_brakedown($param);
4292
4293 $milestone_charges = array();
4294 $total_deposit = array();
4295 $total_deposit['property'] = 0;
4296 $total_deposit['EUR'] = 0;
4297 $total_deposit['USD'] = 0;
4298 $total_deposit['GBP'] = 0;
4299 $total_deposit_full = array();
4300 $total_deposit_full['property'] = 0;
4301 $total_deposit_full['EUR'] = 0;
4302 $total_deposit_full['USD'] = 0;
4303 $total_deposit_full['GBP'] = 0;
4304
4305 $total_amount_list = array();
4306 $total_amount_list['property'] = 0;
4307 $total_amount_list['EUR'] = 0;
4308 $total_amount_list['USD'] = 0;
4309 $total_amount_list['GBP'] = 0;
4310
4311 $room_occupancy = array();
4312 $room_day_price = array();
4313 $cancellation_rules = array();
4314
4315 foreach($brakedown['booking']['rooms'] as $room_id => $room){
4316 $room_total = array();
4317 $room_total['property'] = 0;
4318 $room_total['EUR'] = 0;
4319 $room_total['USD'] = 0;
4320 $room_total['GBP'] = 0;
4321
4322 foreach($room['nights'] as $night){
4323
4324 $deposit = ($room['deposit'] / 100);
4325 $allocation = $night['persons'] - $night['existing_guests'];
4326
4327 // deposit to be charged today
4328 $total_deposit['property'] += ($night['price'] * $allocation * $deposit);
4329 $total_deposit['EUR'] += ($night['price_EUR'] * $allocation * $deposit);
4330 $total_deposit['USD'] += ($night['price_USD'] * $allocation * $deposit);
4331 $total_deposit['GBP'] += ($night['price_GBP'] * $allocation * $deposit);
4332 // we need deposit difference, we need to save full deposit for new booking
4333 $total_deposit_full['property'] += ($night['price'] * $night['persons'] * $deposit);
4334 $total_deposit_full['EUR'] += ($night['price_EUR'] * $night['persons'] * $deposit);
4335 $total_deposit_full['USD'] += ($night['price_USD'] * $night['persons'] * $deposit);
4336 $total_deposit_full['GBP'] += ($night['price_GBP'] * $night['persons'] * $deposit);
4337
4338 //
4339 $total_amount_list['property'] += ($night['price'] * $night['persons']);
4340 $total_amount_list['EUR'] += ($night['price_EUR'] * $night['persons']);
4341 $total_amount_list['USD'] += ($night['price_USD'] * $night['persons']);
4342 $total_amount_list['GBP'] += ($night['price_GBP'] * $night['persons']);
4343
4344 $room_total['property'] += ($night['price'] * $allocation);
4345 $room_total['EUR'] += ($night['price_EUR'] * $allocation);
4346 $room_total['USD'] += ($night['price_USD'] * $allocation);
4347 $room_total['GBP'] += ($night['price_GBP'] * $allocation);
4348
4349 if ($room['type'] == "ROOM") {
4350 $room_occupancy[$room_id] = $room['occupancy'];
4351 }
4352
4353 $room_day_price[$room_id][$night['night']] = $night['room_total'];
4354 }
4355
4356 if( !empty($room['cancellations']) ){
4357 foreach($room['cancellations'] as $rate_plan_rule_id => $cancellation){
4358 $cancellation = (object) $cancellation;
4359 // rate_plan_rule_id
4360 $cancellation_rules[$rate_plan_rule_id] = $cancellation;
4361 }
4362 }
4363
4364 if ($room['milestones']) {
4365 foreach ($room['milestones'] as $milestone) {
4366 $milestone = (object) $milestone;
4367 if (!isset($milestone_charges[$milestone->id])) {
4368 $milestone_charges[$milestone->id] = array();
4369 $milestone_charges[$milestone->id]['inverval'] = $milestone->interval;
4370 $milestone_charges[$milestone->id]['amount'] = 0; // billing amount
4371 $milestone_charges[$milestone->id]['amount_currencies'] = array(
4372 "EUR" => 0,
4373 "USD" => 0,
4374 "GBP" => 0,
4375 "property" => 0,
4376 );
4377 ;
4378 }
4379 // get converted here<
4380 $deposit_part = ($milestone->percentage / 100);
4381 $milestone_charges[$milestone->id]['amount'] += ($room_total[$booking->guest_currency] * $deposit_part);
4382 $milestone_charges[$milestone->id]['amount_currencies']["EUR"] += $room_total['EUR'] * $deposit_part;
4383 $milestone_charges[$milestone->id]['amount_currencies']["USD"] += $room_total['USD'] * $deposit_part;
4384 $milestone_charges[$milestone->id]['amount_currencies']["GBP"] += $room_total['GBP'] * $deposit_part;
4385 $milestone_charges[$milestone->id]['amount_currencies']["property"] += $room_total['property'] * $deposit_part;
4386 }
4387 }
4388
4389 // reset room total
4390 $room_total['property'] = 0;
4391 $room_total['EUR'] = 0;
4392 $room_total['USD'] = 0;
4393 $room_total['GBP'] = 0;
4394 }
4395
4396 $cancellation_total = array();
4397 $cancellation_total["property"] = 0;
4398 $cancellation_total["EUR"] = 0;
4399 $cancellation_total["USD"] = 0;
4400 $cancellation_total["GBP"] = 0;
4401
4402 $currencies = ["EUR","USD","GBP", $property_data['currency_code']];
4403 $this->CI->forex->batch_rate($currencies);
4404
4405 foreach($brakedown['cancellation'] as $room_id => $fee){
4406
4407 $cancellation_total["property"] += $fee['fee'];
4408 $cancellation_total["EUR"] += $this->CI->forex->batch_exchange($fee['fee'], $fee['currency'], "EUR");
4409 $cancellation_total["USD"] += $this->CI->forex->batch_exchange($fee['fee'], $fee['currency'], "USD");
4410 $cancellation_total["GBP"] += $this->CI->forex->batch_exchange($fee['fee'], $fee['currency'], "GBP");
4411 }
4412
4413 $room_guests = array();
4414 $room_rates = array();
4415 foreach ($chosen_rooms as $key => $value) {
4416 $room_rates[$value] = $chosen_rates[$key];
4417 $room_guests[$value] = $chosen_guest[$key];
4418 }
4419
4420 $rate_plan_rule = $this->CI->rate_plan_rule_model->select(array('rate_plan.property_id' => $booking->property_id));
4421 $room_rate_inventory = array();
4422
4423
4424 foreach ($chosen_rooms as $room_id) {
4425
4426 $date1 = new DateTime($booking->arrival_date);
4427 $date2 = new DateTime($booking->departure_date);
4428 $interval = DateInterval::createFromDateString('1 day');
4429 $period = new DatePeriod($date1, $interval, $date2);
4430
4431 $deposit_percent = NULL;
4432 $rate_plan_id = NULL;
4433
4434 foreach ($rate_plan_rule as $plan_rule) {
4435 if ($plan_rule->rate_plan_rule_id == $room_rates[$room_id]) {
4436 $rate_plan_id = $plan_rule->rate_plan_id;
4437 $deposit_percent = $plan_rule->deposit;
4438 }
4439 }
4440
4441 foreach ($period as $date) {
4442
4443 // if room is private will have room-occupancy
4444 if (isset($room_occupancy[$room_id])) {
4445 $allocation = ($room_guests[$room_id] / $room_occupancy[$room_id]);
4446 } else {
4447 $allocation = $room_guests[$room_id];
4448 }
4449
4450 array_push($room_rate_inventory, array(
4451 'room_id' => $room_id,
4452 'rate_plan_id' => $rate_plan_id,
4453 'rate_plan_rule_id' => $room_rates[$room_id],
4454 'deposit_percent' => $deposit_percent,
4455 'commission' => 15,
4456 'allocation' => $allocation,
4457 'date' => $date->format("Y-m-d"),
4458 'price' => $room_day_price[$room_id][$date->format("Y-m-d")],
4459 ));
4460 }
4461 }
4462
4463 $booking_expense = $brakedown['expense'];
4464 $billing_currency = $booking->guest_currency;
4465 $deposit_amount = $total_deposit[$billing_currency] + $cancellation_total[$billing_currency];
4466
4467 if($deposit_amount > 0){
4468 $this->CI->stripe->change_account($billing_currency);
4469 $charge_json = $this->CI->stripe->charge_customer( round($deposit_amount * 100), $booking->stripe_customer_id, 'Modification of booking #'.booking_number($booking->booking_id), $billing_currency);
4470 $stripe_charge = json_decode($charge_json);
4471 }else{
4472 $payment_id = NULL;
4473 $stripe_amount_charged = 0;
4474 }
4475
4476
4477 $inventory_currency = $this->CI->currency_model->get_currency($booking->inventory_currency_id);
4478
4479 if (isset($stripe_charge->id)) {
4480
4481 $sandbox = ($stripe_charge->livemode == true) ? '0' : '1';
4482
4483 $currency_id = get_currency_id((string) $stripe_charge->currency);
4484 $stripe_amount_charged = (double) ($stripe_charge->amount / 100);
4485 $this->CI->payment_model->set_guest_id($booking->guest_id);
4486 $this->CI->payment_model->set_currency_id($booking->guest_currency_id);
4487 $this->CI->payment_model->set_stripe_datetime(date("Y-m-d H:i:s"));
4488 $this->CI->payment_model->set_stripe_carge_id($stripe_charge->id);
4489 $this->CI->payment_model->set_stripe_paid($stripe_charge->paid);
4490 $stripe_amount = (double) ($stripe_charge->amount / 100);
4491 $this->CI->payment_model->set_stripe_amount($stripe_amount);
4492 $this->CI->payment_model->set_stripe_currency(strtoupper($stripe_charge->currency));
4493 // convert payment in EUR/USD/GBP
4494 $this->CI->payment_model->set_amount_EUR($this->CI->forex->batch_exchange($stripe_amount, strtoupper($stripe_charge->currency), 'EUR'));
4495 $this->CI->payment_model->set_amount_USD($this->CI->forex->batch_exchange($stripe_amount, strtoupper($stripe_charge->currency), 'USD'));
4496 $this->CI->payment_model->set_amount_GBP($this->CI->forex->batch_exchange($stripe_amount, strtoupper($stripe_charge->currency), 'GBP'));
4497 $this->CI->payment_model->set_card_fee_percent((double) $stripe_fees['percent']);
4498 $this->CI->payment_model->set_card_fee_amount((double) $stripe_fees['flat']);
4499 $this->CI->payment_model->set_stripe_data(json_encode($stripe_charge));
4500 $this->CI->payment_model->set_sandbox($sandbox);
4501 $this->CI->payment_model->set_created(date("Y-m-d H:i:s"));
4502 $this->CI->payment_model->set_status(1);
4503 $payment_id = $this->CI->payment_model->insert();
4504 }
4505
4506 if ($payment_id > 0 || $payment_id === NULL) {
4507
4508 // Calculates the commission and rounds it to to decimal
4509 $commission_percent = $this->CI->config->item('commission');
4510 $commission_calculated = round(($commission_percent / 100) * $total_amount_list[$billing_currency], 2);
4511
4512 $this->CI->booking_model->set_property_id($booking->property_id);
4513 $this->CI->booking_model->set_payment_id($payment_id);
4514 $this->CI->booking_model->set_guest_id($booking->guest_id);
4515 $this->CI->booking_model->set_arrival($booking->arrival_date);
4516 $this->CI->booking_model->set_departure($booking->departure_date);
4517 $this->CI->booking_model->set_client_ip_address($this->CI->input->ip_address());
4518 $this->CI->booking_model->set_count_male(0);
4519 $this->CI->booking_model->set_count_female(0);
4520 $this->CI->booking_model->set_inventory(json_encode($room_rate_inventory));
4521 $this->CI->booking_model->set_cancellation(json_encode($cancellation_rules));
4522
4523 $this->CI->booking_model->set_amount_charged($total_deposit_full[$billing_currency]);
4524 $this->CI->booking_model->set_amount_charged_inventory($total_deposit_full['property']);
4525
4526 $this->CI->booking_model->set_amount_total($total_amount_list[$billing_currency]);
4527 $this->CI->booking_model->set_amount_total_EUR($total_amount_list['EUR']);
4528 $this->CI->booking_model->set_amount_total_USD($total_amount_list['USD']);
4529 $this->CI->booking_model->set_amount_total_GBP($total_amount_list['GBP']);
4530 $this->CI->booking_model->set_amount_total_inventory($total_amount_list['property']);
4531
4532 $this->CI->booking_model->set_commission($commission_calculated);
4533 $this->CI->booking_model->set_commission_EUR(round(($commission_percent / 100) * $total_amount_list['EUR'], 2));
4534 $this->CI->booking_model->set_commission_USD(round(($commission_percent / 100) * $total_amount_list['USD'], 2));
4535 $this->CI->booking_model->set_commission_GBP(round(($commission_percent / 100) * $total_amount_list['GBP'], 2));
4536 $this->CI->booking_model->set_commission_inventory(round(($commission_percent / 100) * $total_amount_list['property'], 2));
4537
4538 $this->CI->booking_model->set_expense($booking_expense[$billing_currency]);
4539 $this->CI->booking_model->set_expense_EUR($this->CI->forex->batch_exchange($booking_expense[$billing_currency], $billing_currency, "EUR"));
4540 $this->CI->booking_model->set_expense_USD($this->CI->forex->batch_exchange($booking_expense[$billing_currency], $billing_currency, "USD"));
4541 $this->CI->booking_model->set_expense_GBP($this->CI->forex->batch_exchange($booking_expense[$billing_currency], $billing_currency, "GBP"));
4542
4543 $this->CI->booking_model->set_arrival_time($booking->arrival_time);
4544 $this->CI->booking_model->set_comment($booking->booking_comment);
4545 $this->CI->booking_model->set_sandbox($sandbox);
4546 $this->CI->booking_model->set_created(date("Y-m-d H:i:s"));
4547 $this->CI->booking_model->set_status(1);
4548 $this->CI->booking_model->set_modified_booking_id($booking->booking_id); // new booking is modification for this one
4549 $new_booking_id = $this->CI->booking_model->insert();
4550
4551 if($new_booking_id){
4552
4553 $this->CI->booking_model->update_status($booking->booking_id, 11); // mark old booking as cancelled-modified
4554
4555 $this->CI->ch_engine->modify_notification($booking->property_id, $new_booking_id, $booking->booking_id);
4556
4557 // Insert milestones if any
4558 if (count($milestone_charges) >= 1) {
4559 foreach ($milestone_charges as $milestone_id => $milestone_data) {
4560 $this->CI->booking_has_milestone_model->set_booking_id($new_booking_id);
4561 $this->CI->booking_has_milestone_model->set_milestone_id($milestone_id);
4562 $this->CI->booking_has_milestone_model->set_payment_id(null); // to be inserted after charge
4563 $this->CI->booking_has_milestone_model->set_amount_charged($milestone_data['amount']);
4564 $this->CI->booking_has_milestone_model->set_charge_currency($billing_currency);
4565 // add all 3 currencies
4566 $this->CI->booking_has_milestone_model->set_amount_EUR($milestone_data['amount_currencies']['EUR']);
4567 $this->CI->booking_has_milestone_model->set_amount_USD($milestone_data['amount_currencies']['USD']);
4568 $this->CI->booking_has_milestone_model->set_amount_GBP($milestone_data['amount_currencies']['GBP']);
4569 $this->CI->booking_has_milestone_model->set_amount_inventory($milestone_data['amount_currencies']['property']);
4570 // settle date is interval days before arrival date
4571 $settle_date = date("Y-m-d", strtotime("-{$milestone_data['inverval']} days", strtotime($booking->arrival_date)));
4572 $this->CI->booking_has_milestone_model->set_settle_date($settle_date);
4573 $this->CI->booking_has_milestone_model->set_sandbox($sandbox);
4574 $this->CI->booking_has_milestone_model->set_created(date("Y-m-d H:i:s"));
4575 $this->CI->booking_has_milestone_model->set_status('0'); // 0 = to be charged; 1 = charged; 2=failed
4576
4577 // TODO:
4578 // Check if this exists for the original booking, if its charged then mark as charged here too
4579 $id = $this->CI->booking_has_milestone_model->insert();
4580 }
4581 }
4582
4583
4584
4585 // we need to transfer cancellations
4586 // we need to transfer deposit for new roomw only
4587 // Not sure if we should refund the previous booking
4588 //
4589 // $this->tranfer_booking_to_property_account($this->CI->booking_model->get_booking($booking_id));
4590 if( $cancellation_total['EUR'] > 0 ){
4591 // transfer cancellation fees (from summary)
4592 $this->CI->account_model->set_property_id($booking->property_id);
4593 $this->CI->account_model->set_account_charge_id(2); // we credit the account for charged amount
4594 $this->CI->account_model->set_account_entry_category_id("cancellation"); // string will convert to ID in function
4595 $this->CI->account_model->set_currency_id($booking->guest_currency_id);
4596 $this->CI->account_model->set_payment_id($payment_id);
4597 $this->CI->account_model->set_booking_id($booking->booking_id);
4598 $this->CI->account_model->set_description("Partial cancellation with fee for booking number #" . booking_reference($booking->booking_id));
4599 $this->CI->account_model->set_amount($cancellation_total[$billing_currency]); // this is charged currency
4600 // add eur/usd/gbp
4601 $this->CI->account_model->set_amount_EUR($cancellation_total['EUR']);
4602 $this->CI->account_model->set_amount_USD($cancellation_total['USD']);
4603 $this->CI->account_model->set_amount_GBP($cancellation_total['GBP']);
4604 // inventory currency amount
4605 $this->CI->account_model->set_amount_inventory( $cancellation_total['property'] );
4606 $this->CI->account_model->set_date_time(date("Y-m-d H:i:s"));
4607 $this->CI->account_model->set_status(1);
4608 $this->CI->account_model->insert();
4609 // add fees here
4610 // add commission ?
4611 }
4612
4613 // check if something mroe is charged
4614
4615 if( $total_deposit['EUR'] > 0 ){
4616 // transfer extra booking amount
4617 $this->CI->account_model->set_property_id($booking->property_id);
4618 $this->CI->account_model->set_account_charge_id(2); // we credit the account for charged amount
4619 $this->CI->account_model->set_account_entry_category_id("reservation"); // string will convert to ID in function
4620 $this->CI->account_model->set_currency_id($booking->guest_currency_id);
4621 $this->CI->account_model->set_payment_id($payment_id);
4622 $this->CI->account_model->set_booking_id($booking->booking_id);
4623 $this->CI->account_model->set_description("Deposit on modification for booking number #" . booking_reference($booking->booking_id));
4624 $this->CI->account_model->set_amount( $total_deposit[$billing_currency] ); // this is charged currency
4625 // add eur/usd/gbp
4626 $this->CI->account_model->set_amount_EUR( $total_deposit['EUR'] );
4627 $this->CI->account_model->set_amount_USD( $total_deposit['USD'] );
4628 $this->CI->account_model->set_amount_GBP( $total_deposit['GBP'] );
4629 // inventory currency amount
4630 $this->CI->account_model->set_amount_inventory( $total_deposit['property'] );
4631 $this->CI->account_model->set_date_time(date("Y-m-d H:i:s"));
4632 $this->CI->account_model->set_status(1);
4633 $this->CI->account_model->insert();
4634
4635 // add fees here
4636 // add commission ?
4637 }
4638
4639 if( ($cancellation_total['EUR'] + $total_deposit['EUR']) > 0 ){
4640 // if something is charged we need to take fees and deposit
4641 // one row only because of the fixed part
4642
4643 // stripe charges can be different we need to fetch from transaction balance
4644 $retrive_balance = $this->CI->stripe->retrive_balance($stripe_charge->balance_transaction);
4645 $retrive_balance = json_decode($retrive_balance);
4646
4647 foreach($retrive_balance->fee_details as $fee){
4648 // TODO: Check if property should not be charged processing fee
4649 if($fee->type == "stripe_fee"){
4650 // only processing fee is vissible to the property
4651 // others are covered by Dorms.com we are just logging them
4652 $this->CI->account_model->set_property_id($booking->property_id);
4653 }else{
4654 $this->CI->account_model->set_property_id(NULL);
4655 }
4656
4657 $this->CI->account_model->set_account_charge_id(1); // we debit the account for credit card fees
4658 $this->CI->account_model->set_account_entry_category_id("collection_fee"); // string will convert to ID in function
4659 $this->CI->account_model->set_currency_id($booking->guest_currency_id);
4660 $this->CI->account_model->set_payment_id($payment_id);
4661 $this->CI->account_model->set_booking_id($booking->booking_id);
4662
4663 $this->CI->account_model->set_description("Credit card fees (".$fee->description.") for booking #" . booking_reference($booking->booking_id));
4664 // fees are percentage + flat rate and should be based on charge currency/amount
4665 $cc_fee_amount = ($fee->amount / 100);
4666 $this->CI->account_model->set_amount($cc_fee_amount);
4667 // save all 3 currencies too
4668 $this->CI->account_model->set_amount_EUR($this->CI->forex->batch_exchange($cc_fee_amount, strtoupper($fee->currency), "EUR"));
4669 $this->CI->account_model->set_amount_USD($this->CI->forex->batch_exchange($cc_fee_amount, strtoupper($fee->currency), "USD"));
4670 $this->CI->account_model->set_amount_GBP($this->CI->forex->batch_exchange($cc_fee_amount, strtoupper($fee->currency), "GBP"));
4671 // calculate the fees percent + flat rate in inventory currency
4672 $fees_amount_inventory = $this->CI->forex->batch_exchange($cc_fee_amount, strtoupper($fee->currency), $inventory_currency->currency_code);
4673 $this->CI->account_model->set_amount_inventory($fees_amount_inventory);
4674 // add eur/usd/gbp
4675 $this->CI->account_model->set_date_time(date("Y-m-d H:i:s"));
4676 $this->CI->account_model->set_status(1);
4677 $this->CI->account_model->insert();
4678 }
4679
4680 // add type commission
4681 // calculate commission based on $booking->booking_amount_charged_inventory
4682 // converty to all cirrencies
4683 // debit the account with commission amount
4684 $commission_percent = $this->CI->config->item('commission');
4685
4686 $this->CI->account_model->set_property_id($booking->property_id);
4687 $this->CI->account_model->set_account_charge_id(1); // we debit the account for commission
4688 $this->CI->account_model->set_account_entry_category_id("commission"); // string will convert to ID in function
4689 $this->CI->account_model->set_currency_id($booking->guest_currency_id);
4690 $this->CI->account_model->set_payment_id($booking->payment_id);
4691 $this->CI->account_model->set_booking_id($booking->booking_id);
4692 $this->CI->account_model->set_description("Commission of ".$commission_percent."% for modification of booking #" . booking_reference($booking->booking_id));
4693
4694 // commission should be percent of what is charges today
4695 $commission_amount = round(($commission_percent / 100) * ($cancellation_total[$billing_currency] + $total_deposit[$billing_currency]), 2);
4696 $this->CI->account_model->set_amount( $commission_amount );
4697 // add eur/usd/gbp
4698 $commission_amount_EUR = round(($commission_percent / 100) * ($cancellation_total["EUR"] + $total_deposit["EUR"]), 2);
4699 $commission_amount_USD = round(($commission_percent / 100) * ($cancellation_total["USD"] + $total_deposit["USD"]), 2);
4700 $commission_amount_GBP = round(($commission_percent / 100) * ($cancellation_total["GBP"] + $total_deposit["GBP"]), 2);
4701 $this->CI->account_model->set_amount_EUR( $commission_amount_EUR );
4702 $this->CI->account_model->set_amount_USD( $commission_amount_USD );
4703 $this->CI->account_model->set_amount_GBP( $commission_amount_GBP );
4704
4705 $commission_inventory = round(($commission_percent / 100) * ($cancellation_total["property"] + $total_deposit["property"]), 2);
4706 $this->CI->account_model->set_amount_inventory( $commission_inventory );
4707 $this->CI->account_model->set_date_time(date("Y-m-d H:i:s"));
4708 $this->CI->account_model->set_status(1);
4709 $this->CI->account_model->insert();
4710 }
4711
4712
4713 // notif modification here
4714 //ToDo send email for success
4715
4716 $return['STRIPE_DATA'] = [
4717 'STRIPE_CUSTOMER' => $booking->stripe_customer_id,
4718 'STRIPE_CREDIT_CARD' => "",
4719 ];
4720
4721 $return['BOOKING_ID'] = booking_reference($booking_id);
4722 $return['BOOKING_RAW_ID'] = $booking_id;
4723 $return['MODIFIED_BOOKING_ID'] = $new_booking_id;
4724
4725 $return['CURRENCY'] = array(
4726 'CUSTOMER' => $booking->guest_currency,
4727 'BILLING' => $booking->guest_currency
4728 );
4729
4730 $milestone_amount = 0.00;
4731 $already_charged = 0.00;
4732 $payable_on_arrival = 0.00;
4733 $rooms_booked = array();
4734
4735 $billing_currency = $booking->guest_currency;
4736 $guest_currency = $booking->guest_currency;
4737 $total_amount = 0;
4738 foreach($brakedown['booking']['rooms'] as $room_id => $room){
4739 foreach($room['nights'] as $night){
4740
4741 $_room['ROOM_ID'] = $room_id;
4742 $_room['NAME'] = $room["room_name"];
4743 $_room['BEDS'] = $night["persons"];
4744
4745 $_room['PRICE_PROPERTY'] = array(
4746 'CURRENCY' => $inventory_currency->currency_code,
4747 'AMOUNT' => $night['price']
4748 );
4749 $_room['PRICE_CUSTOMER'] = array(
4750 'CURRENCY' => $billing_currency,
4751 'AMOUNT' => $night['price_' . $billing_currency]
4752 );
4753 $_room['PRICE_BILLING'] = array(
4754 'CURRENCY' => $billing_currency,
4755 'AMOUNT' => $night['price_' . $billing_currency]
4756 );
4757 $_room['DATE'] = $night['night'];
4758
4759 array_push($rooms_booked, $_room);
4760
4761 // THIS IS IMPORTANT NOW
4762 $room_price = ($night['price_' . $billing_currency] * $night["persons"]);
4763 $total_amount = $total_amount + $room_price;
4764 // calculate $already_charged amount
4765 $already_charged_percent = ($room['deposit']/100);
4766 $already_charged += ($already_charged_percent * $room_price);
4767 // calculate $payable_on_arrival amount
4768 $payable_on_arrival_percent = ( (100 - $room['deposit']) /100 );
4769 $payable_on_arrival += ($payable_on_arrival_percent * $room_price);
4770
4771
4772 if($room['milestones']){
4773 foreach($room['milestones'] as $milestone){
4774 $milestone_amount = $milestone_amount + ($room_price * ($milestone['percentage'] / 100));
4775 // milestone should be deducted from the $payable_on_arrival
4776 $payable_on_arrival -= ($room_price * ($milestone['percentage'] / 100));
4777 }
4778 }
4779
4780 // update inventory for all properties
4781 // properties related to a channel will have inventory update by the channel after booking notification
4782 $inventory_units = (int)$night['persons'] - (int)$night['existing_guests'];
4783 if ($room['type'] == 'ROOM') {
4784 // for rooms we send beds but we need to compare rooms because $available_value['AVAILABLE'] will hold room number
4785 $inventory_units = ceil($inventory_units / $room['occupancy']);
4786 }
4787 $this->CI->inventory_model->available_inventory(array('inventory.date' => $night['night'], 'inventory.room_id' => $room_id), $inventory_units);
4788 }
4789 }
4790
4791
4792 $return['PAYMENT']['CURRENCY']['CUSTOMER']['AMOUNT_TAKEN'] = $already_charged;
4793 $return['PAYMENT']['CURRENCY']['CUSTOMER']['MILESTONE_AMOUNT'] = $milestone_amount;
4794 $return['PAYMENT']['CURRENCY']['CUSTOMER']['PAYABLE_ON_ARRIVAL'] = $payable_on_arrival;
4795 $return['PAYMENT']['CURRENCY']['CUSTOMER']['CURRENCY'] = $guest_currency;
4796
4797 $return['PAYMENT']['CURRENCY']['PROPERTY']['AMOUNT_TAKEN'] = $this->CI->forex->batch_exchange($already_charged, $billing_currency, $property_data['currency_code']);
4798 $return['PAYMENT']['CURRENCY']['PROPERTY']['MILESTONE_AMOUNT'] = $this->CI->forex->batch_exchange($milestone_amount, $billing_currency, $property_data['currency_code']);
4799 $return['PAYMENT']['CURRENCY']['PROPERTY']['PAYABLE_ON_ARRIVAL'] = $this->CI->forex->batch_exchange($payable_on_arrival, $billing_currency, $property_data['currency_code']);
4800 $return['PAYMENT']['CURRENCY']['PROPERTY']['CURRENCY'] = $property_data['currency_code'];
4801
4802 $return['PAYMENT']['CURRENCY'][$guest_currency]['AMOUNT_TAKEN'] = $already_charged;
4803 $return['PAYMENT']['CURRENCY'][$guest_currency]['MILESTONE_AMOUNT'] = $milestone_amount;
4804 $return['PAYMENT']['CURRENCY'][$guest_currency]['PAYABLE_ON_ARRIVAL'] = $payable_on_arrival;
4805
4806 $return['PAYMENT']['CURRENCY'][$billing_currency]['AMOUNT_TAKEN'] = $already_charged;
4807 $return['PAYMENT']['CURRENCY'][$billing_currency]['MILESTONE_AMOUNT'] = $milestone_amount;
4808 $return['PAYMENT']['CURRENCY'][$billing_currency]['PAYABLE_ON_ARRIVAL'] = $payable_on_arrival;
4809
4810 $return['PAYMENT']['PAYMENT_CURRENCY'] = $billing_currency;
4811
4812 $return['PROPERTY']['ID'] = $property['PROPERTY']['ID'];
4813 $return['PROPERTY']['NAME'] = $property['PROPERTY']['NAME'];
4814 $return['PROPERTY']['IMAGES'] = $property['PROPERTY']['IMAGES'];
4815 $return['PROPERTY']['ADDRESS']['STREET1'] = $property['PROPERTY']['ADDRESS']['STREET1'];
4816 $return['PROPERTY']['ADDRESS']['STREET2'] = $property['PROPERTY']['ADDRESS']['STREET2'];
4817 $return['PROPERTY']['ADDRESS']['STREET3'] = $property['PROPERTY']['ADDRESS']['STREET3'];
4818 $return['PROPERTY']['ADDRESS']['CITY'] = $property['PROPERTY']['ADDRESS']['CITY'];
4819 $return['PROPERTY']['ADDRESS']['STATE'] = $property['PROPERTY']['ADDRESS']['STATE'];
4820 $return['PROPERTY']['ADDRESS']['ZIP'] = $property['PROPERTY']['ADDRESS']['ZIP'];
4821 $return['PROPERTY']['ADDRESS']['COUNTRY'] = $property['PROPERTY']['ADDRESS']['COUNTRY'];
4822 $return['PROPERTY']['ADDRESS']['CONTACT'] = $property['PROPERTY']['PHONE']['CONTACT'];
4823 $return['PROPERTY']['ADDRESS']['FAX'] = $property['PROPERTY']['FAX'];
4824 $return['PROPERTY']['ADDRESS']['WEBSITE'] = $property['PROPERTY']['WEBSITE'];
4825 $return['PROPERTY']['ADDRESS']['EMAIL'] = $property['PROPERTY']['EMAIL']['PROPERTY'];
4826 $return['PROPERTY']['IMPORTANT_INFORMATION']['CHECK_IN_TIME'] = '';
4827 $return['PROPERTY']['IMPORTANT_INFORMATION']['CHECK_OUT_TIME'] = '';
4828 $return['PROPERTY']['IMPORTANT_INFORMATION']['CANCELLATION_POLICY'] = '';
4829 $return['PROPERTY']['IMPORTANT_INFORMATION']['TAXES'] = $property['PROPERTY']['TAX'];
4830 $return['PROPERTY']['IMPORTANT_INFORMATION']['EXTRA_INFORMATION'] = '';
4831 $return['PROPERTY']['ROOMS_BOOKED']['ROOM'] = $rooms_booked;
4832 $checkout = array();
4833 $night_key = 0;
4834 foreach($brakedown['booking']['rooms'] as $room_id => $room){
4835 foreach($room['nights'] as $key => $night){
4836
4837 $_room['PRICE_PROPERTY'] = array(
4838 'CURRENCY' => $property_data['currency_code'],
4839 'AMOUNT' => $night['price'] * $night["persons"]
4840 );
4841 $_room['PRICE_CUSTOMER'] =
4842 $_room['PRICE_BILLING'] = array(
4843 'CURRENCY' => $billing_currency,
4844 'AMOUNT' => $night['price_' . $billing_currency] * $night["persons"]
4845 );
4846
4847 $tmp = array();
4848 $tmp['INVENTORY_ID'] = "";
4849 $tmp['PRICES'] = array(
4850 "CUSTOMER" => array(
4851 'CURRENCY' => $billing_currency,
4852 'MINPRICE' => $night['price_' . $billing_currency] * $night["persons"]
4853 ),
4854 "PROPERTY" => array(
4855 'CURRENCY' => $billing_currency,
4856 'MINPRICE' => $night['price_' . $billing_currency] * $night["persons"]
4857 ),
4858 "PAYMENT" => array(
4859 'EUR' => $night['price_EUR'],
4860 'USD' => $night['price_USD'],
4861 'GBP' => $night['price_GBP']
4862 )
4863 );
4864 $tmp['ROOM_ID'] = $room_id;
4865 $tmp['ROOM_NAME'] = $room["room_name"];
4866 $tmp['NAME_TRANSLATED'] = $room["room_name"];
4867 $tmp['ROOM_TYPE'] = $room['type'];
4868 $tmp['BEDS'] = $room['beds'];
4869 $tmp['GUESTS'] = $night["persons"];
4870 $tmp['NIGHT'] = $night['night'];
4871 $tmp['PAYMENT'] = array(
4872 "DEPOSIT" => $room['deposit'],
4873 "MILESTONES" => $room['milestones'],
4874 "CANCELLATIONS" => $room['cancellations'],
4875 "SPECIAL" => array(),
4876 );
4877 $tmp['OCCUPANCY'] = $room['occupancy'];
4878
4879 $checkout[$key][$night_key] = $tmp;
4880 }
4881 $night_key++;
4882 }
4883 $return['CHECKOUT']['RESPONSE'] = $checkout; // cannot have the same format
4884
4885 $arrival_date = date_create(date("Y-m-d", strtotime($booking->arrival_date)));
4886 $departure_date = date_create(date("Y-m-d", strtotime($booking->departure_date)));
4887 $difference = date_diff($arrival_date, $departure_date);
4888 $num_nights = $difference->format("%d");
4889
4890 $return['CHECKOUT']['PARAM'] = array(
4891 "PROPERTY_ID" => $property['PROPERTY']['ID'],
4892 "START_DATE" => $booking->arrival_date,
4893 "NIGHT" => $num_nights,
4894 "CUSTOMER_CURRENCY" => $billing_currency,
4895 "CHOSEN_RATES" => (object)$chosen_rates,
4896 "CHOSEN_GUEST" => (object)$chosen_guest,
4897 "CHOSEN_ROOMS" => (object)$chosen_rooms
4898 ); // cannot have the same format
4899
4900 }else{
4901 if (!isset($return['STATUS']['ERRORS'])) {
4902 $return['STATUS']['ERRORS'] = array();
4903 }
4904 array_push($return['STATUS']['ERRORS'], 'Sorry, error on booking. Please try again. Code:120');
4905 } // if new-booking-id
4906 }else{
4907 if (!isset($return['STATUS']['ERRORS'])) {
4908 $return['STATUS']['ERRORS'] = array();
4909 }
4910 array_push($return['STATUS']['ERRORS'], 'Sorry, error on booking. Please try again. Code:121');
4911 } // if payment ID
4912
4913 return $return;
4914 }
4915
4916}