PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.7.1
VikBooking Hotel Booking Engine & PMS v1.7.1
1.8.16 1.8.15 1.8.14 1.8.13 1.8.12 1.8.11 1.8.10 1.8.9 1.8.6 1.8.7 1.8.8 trunk 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 All 37 releases
vikbooking / admin / helpers / report / revenue.php

revenue.php in VikBooking Hotel Booking Engine & PMS 1.7.1, at admin/helpers/report/revenue.php

780 lines 22.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package VikBooking
4 * @subpackage com_vikbooking
5 * @author Alessio Gaggii - e4j - Extensionsforjoomla.com
6 * @copyright Copyright (C) 2018 e4j - Extensionsforjoomla.com. All rights reserved.
7 * @license GNU General Public License version 2 or later; see LICENSE
8 * @link https://vikwp.com
9 */
10
11 defined('ABSPATH') or die('No script kiddies please!');
12
13 /**
14 * Revenue child Class of VikBookingReport
15 */
16 class VikBookingReportRevenue extends VikBookingReport
17 {
18 /**
19 * Property 'defaultKeySort' is used by the View that renders the report.
20 */
21 public $defaultKeySort = 'day';
22
23 /**
24 * Property 'defaultKeyOrder' is used by the View that renders the report.
25 */
26 public $defaultKeyOrder = 'ASC';
27
28 /**
29 * Property 'exportAllowed' is used by the View to display the export button.
30 */
31 public $exportAllowed = 1;
32
33 /**
34 * Debug mode is activated by passing the value 'e4j_debug' > 0
35 */
36 private $debug;
37
38 /**
39 * Class constructor should define the name of the report and
40 * other vars. Call the parent constructor to define the DB object.
41 */
42 public function __construct()
43 {
44 $this->reportFile = basename(__FILE__, '.php');
45 $this->reportName = JText::translate('VBOREPORT'.strtoupper(str_replace('_', '', $this->reportFile)));
46 $this->reportFilters = array();
47
48 $this->cols = array();
49 $this->rows = array();
50 $this->footerRow = array();
51
52 $this->debug = (VikRequest::getInt('e4j_debug', 0, 'request') > 0);
53
54 $this->registerExportCSVFileName();
55
56 parent::__construct();
57 }
58
59 /**
60 * Returns the name of this report.
61 *
62 * @return string
63 */
64 public function getName()
65 {
66 return $this->reportName;
67 }
68
69 /**
70 * Returns the name of this file without .php.
71 *
72 * @return string
73 */
74 public function getFileName()
75 {
76 return $this->reportFile;
77 }
78
79 /**
80 * Returns the filters of this report.
81 *
82 * @return array
83 */
84 public function getFilters()
85 {
86 if (count($this->reportFilters)) {
87 //do not run this method twice, as it could load JS and CSS files.
88 return $this->reportFilters;
89 }
90
91 //get VBO Application Object
92 $vbo_app = VikBooking::getVboApplication();
93
94 //load the jQuery UI Datepicker
95 $this->loadDatePicker();
96
97 //From Date Filter
98 $filter_opt = array(
99 'label' => '<label for="fromdate">'.JText::translate('VBOREPORTSDATEFROM').'</label>',
100 'html' => '<input type="text" id="fromdate" name="fromdate" value="" class="vbo-report-datepicker vbo-report-datepicker-from" />',
101 'type' => 'calendar',
102 'name' => 'fromdate'
103 );
104 array_push($this->reportFilters, $filter_opt);
105
106 //To Date Filter
107 $filter_opt = array(
108 'label' => '<label for="todate">'.JText::translate('VBOREPORTSDATETO').'</label>',
109 'html' => '<input type="text" id="todate" name="todate" value="" class="vbo-report-datepicker vbo-report-datepicker-to" />',
110 'type' => 'calendar',
111 'name' => 'todate'
112 );
113 array_push($this->reportFilters, $filter_opt);
114
115 //Room ID filter
116 $pidroom = VikRequest::getInt('idroom', '', 'request');
117 $all_rooms = $this->getRooms();
118 $rooms = array();
119 foreach ($all_rooms as $room) {
120 $rooms[$room['id']] = $room['name'];
121 }
122 if (count($rooms)) {
123 $rooms_sel_html = $vbo_app->getNiceSelect($rooms, $pidroom, 'idroom', JText::translate('VBOSTATSALLROOMS'), JText::translate('VBOSTATSALLROOMS'), '', '', 'idroom');
124 $filter_opt = array(
125 'label' => '<label for="idroom">'.JText::translate('VBOREPORTSROOMFILT').'</label>',
126 'html' => $rooms_sel_html,
127 'type' => 'select',
128 'name' => 'idroom'
129 );
130 array_push($this->reportFilters, $filter_opt);
131 }
132
133 // channel filter
134 $all_channels = array();
135 $pchannel = VikRequest::getString('channel', '', 'request');
136 $q = "SELECT `channel` FROM `#__vikbooking_orders` WHERE `channel` IS NOT NULL GROUP BY `channel`;";
137 $this->dbo->setQuery($q);
138 $this->dbo->execute();
139 if ($this->dbo->getNumRows()) {
140 $ord_channels = $this->dbo->loadAssocList();
141 // push website as first option
142 $all_channels['-1'] = JText::translate('VBORDFROMSITE');
143 // push all channel names
144 foreach ($ord_channels as $o_channel) {
145 $channel_parts = explode('_', $o_channel['channel']);
146 $channel_name = count($channel_parts) > 1 ? trim($channel_parts[1]) : trim($channel_parts[0]);
147 if (isset($all_channels[$channel_name])) {
148 continue;
149 }
150 $all_channels[$channel_name] = $channel_name;
151 }
152 // push filter
153 $channels_sel_html = $vbo_app->getNiceSelect($all_channels, $pchannel, 'channel', '- - - -', '- - - -', '', '', 'channel');
154 $filter_opt = array(
155 'label' => '<label for="channel">'.JText::translate('VBCHANNELFILTER').'</label>',
156 'html' => $channels_sel_html,
157 'type' => 'select',
158 'name' => 'channel'
159 );
160 array_push($this->reportFilters, $filter_opt);
161 }
162
163 // get minimum check-in and maximum check-out for dates filters
164 $df = $this->getDateFormat();
165 $mincheckin = 0;
166 $maxcheckout = 0;
167 $q = "SELECT MIN(`checkin`) AS `mincheckin`, MAX(`checkout`) AS `maxcheckout` FROM `#__vikbooking_orders` WHERE `status`='confirmed' AND `closure`=0;";
168 $this->dbo->setQuery($q);
169 $this->dbo->execute();
170 if ($this->dbo->getNumRows()) {
171 $data = $this->dbo->loadAssoc();
172 if (!empty($data['mincheckin']) && !empty($data['maxcheckout'])) {
173 $mincheckin = $data['mincheckin'];
174 $maxcheckout = $data['maxcheckout'];
175 }
176 }
177 //
178
179 //jQuery code for the datepicker calendars and select2
180 $pfromdate = VikRequest::getString('fromdate', '', 'request');
181 $ptodate = VikRequest::getString('todate', '', 'request');
182 $js = 'jQuery(document).ready(function() {
183 jQuery(".vbo-report-datepicker:input").datepicker({
184 '.(!empty($mincheckin) ? 'minDate: "'.date($df, $mincheckin).'", ' : '').'
185 '.(!empty($maxcheckout) ? 'maxDate: "'.date($df, $maxcheckout).'", ' : '').'
186 '.(!empty($mincheckin) && !empty($maxcheckout) ? 'yearRange: "'.(date('Y', $mincheckin)).':'.date('Y', $maxcheckout).'", changeMonth: true, changeYear: true, ' : '').'
187 dateFormat: "'.$this->getDateFormat('jui').'",
188 onSelect: vboReportCheckDates
189 });
190 '.(!empty($pfromdate) ? 'jQuery(".vbo-report-datepicker-from").datepicker("setDate", "'.$pfromdate.'");' : '').'
191 '.(!empty($ptodate) ? 'jQuery(".vbo-report-datepicker-to").datepicker("setDate", "'.$ptodate.'");' : '').'
192 });
193 function vboReportCheckDates(selectedDate, inst) {
194 if (selectedDate === null || inst === null) {
195 return;
196 }
197 var cur_from_date = jQuery(this).val();
198 if (jQuery(this).hasClass("vbo-report-datepicker-from") && cur_from_date.length) {
199 var nowstart = jQuery(this).datepicker("getDate");
200 var nowstartdate = new Date(nowstart.getTime());
201 jQuery(".vbo-report-datepicker-to").datepicker("option", {minDate: nowstartdate});
202 }
203 }';
204 $this->setScript($js);
205
206 return $this->reportFilters;
207 }
208
209 /**
210 * Loads the report data from the DB.
211 * Returns true in case of success, false otherwise.
212 * Sets the columns and rows for the report to be displayed.
213 *
214 * @return boolean
215 */
216 public function getReportData()
217 {
218 if (strlen($this->getError())) {
219 //Export functions may set errors rather than exiting the process, and the View may continue the execution to attempt to render the report.
220 return false;
221 }
222 //Input fields and other vars
223 $pfromdate = VikRequest::getString('fromdate', '', 'request');
224 $ptodate = VikRequest::getString('todate', '', 'request');
225 $pidroom = VikRequest::getInt('idroom', '', 'request');
226 $pchannel = VikRequest::getString('channel', '', 'request');
227 $pkrsort = VikRequest::getString('krsort', $this->defaultKeySort, 'request');
228 $pkrsort = empty($pkrsort) ? $this->defaultKeySort : $pkrsort;
229 $pkrorder = VikRequest::getString('krorder', $this->defaultKeyOrder, 'request');
230 $pkrorder = empty($pkrorder) ? $this->defaultKeyOrder : $pkrorder;
231 $pkrorder = $pkrorder == 'DESC' ? 'DESC' : 'ASC';
232 $currency_symb = VikBooking::getCurrencySymb();
233 $df = $this->getDateFormat();
234 $datesep = VikBooking::getDateSeparator();
235 if (empty($ptodate)) {
236 $ptodate = $pfromdate;
237 }
238 //Get dates timestamps
239 $from_ts = VikBooking::getDateTimestamp($pfromdate, 0, 0);
240 $to_ts = VikBooking::getDateTimestamp($ptodate, 23, 59, 59);
241 if (empty($pfromdate) || empty($from_ts) || empty($to_ts)) {
242 $this->setError(JText::translate('VBOREPORTSERRNODATES'));
243 return false;
244 }
245
246 //Query to obtain the records
247 $records = array();
248 $q = "SELECT `o`.`id`,`o`.`ts`,`o`.`status`,`o`.`days`,`o`.`checkin`,`o`.`checkout`,`o`.`totpaid`,`o`.`roomsnum`,`o`.`total`,`o`.`idorderota`,`o`.`channel`,`o`.`country`,`o`.`tot_taxes`,".
249 "`o`.`tot_city_taxes`,`o`.`tot_fees`,`o`.`cmms`,`o`.`refund`,`o`.`canc_fee`,`or`.`idorder`,`or`.`idroom`,`or`.`optionals`,`or`.`cust_cost`,`or`.`cust_idiva`,`or`.`extracosts`,`or`.`room_cost` ".
250 "FROM `#__vikbooking_orders` AS `o` LEFT JOIN `#__vikbooking_ordersrooms` AS `or` ON `or`.`idorder`=`o`.`id` ".
251 "WHERE (`o`.`status`='confirmed' OR (`o`.`status`='cancelled' AND `o`.`canc_fee` > 0)) AND `o`.`closure`=0 AND `o`.`checkout`>=".$from_ts." AND `o`.`checkin`<=".$to_ts." ".(!empty($pidroom) ? "AND `or`.`idroom`=".(int)$pidroom." " : "").
252 (strlen($pchannel) ? "AND `o`.`channel` " . ($pchannel == '-1' ? 'IS NULL' : "LIKE " . $this->dbo->quote("%{$pchannel}%")) . ' ' : '') .
253 "ORDER BY `o`.`checkin` ASC, `o`.`id` ASC, `or`.`id` ASC;";
254 $this->dbo->setQuery($q);
255 $records = $this->dbo->loadAssocList();
256
257 if (!$records) {
258 $this->setError(JText::translate('VBOREPORTSERRNORESERV'));
259 return false;
260 }
261
262 // nest records with multiple rooms booked inside sub-array
263 $bookings = array();
264 foreach ($records as $v) {
265 if (!isset($bookings[$v['id']])) {
266 $bookings[$v['id']] = array();
267 }
268
269 // calculate the from_ts and to_ts values for later comparison
270 $in_info = getdate($v['checkin']);
271 $out_info = getdate($v['checkout']);
272 $v['from_ts'] = mktime(0, 0, 0, $in_info['mon'], $in_info['mday'], $in_info['year']);
273 $v['to_ts'] = mktime(23, 59, 59, $out_info['mon'], ($out_info['mday'] - 1), $out_info['year']);
274
275 if ($v['status'] == 'cancelled' && count($bookings[$v['id']])) {
276 // one room is sufficient for a cancelled booking with cancellation fees
277 continue;
278 }
279
280 // push nested room-booking
281 array_push($bookings[$v['id']], $v);
282 }
283
284 // define the columns of the report
285 $this->cols = array(
286 //date
287 array(
288 'key' => 'day',
289 'sortable' => 1,
290 'label' => JText::translate('VBOREPORTREVENUEDAY')
291 ),
292 //rooms sold
293 array(
294 'key' => 'rooms_sold',
295 'attr' => array(
296 'class="center"'
297 ),
298 'sortable' => 1,
299 'label' => JText::translate('VBOREPORTREVENUERSOLD')
300 ),
301 //total bookings
302 array(
303 'key' => 'tot_bookings',
304 'attr' => array(
305 'class="center"'
306 ),
307 'sortable' => 1,
308 'label' => JText::translate('VBOREPORTREVENUETOTB')
309 ),
310 //% occupancy
311 array(
312 'key' => 'occupancy',
313 'attr' => array(
314 'class="center"'
315 ),
316 'sortable' => 1,
317 'label' => JText::translate('VBOREPORTREVENUEPOCC')
318 ),
319 //IBE revenue
320 array(
321 'key' => 'ibe_revenue',
322 'attr' => array(
323 'class="center"'
324 ),
325 'sortable' => 1,
326 'label' => JText::translate('VBOREPORTREVENUEREVWEB')
327 ),
328 //OTAs revenue
329 array(
330 'key' => 'ota_revenue',
331 'attr' => array(
332 'class="center"'
333 ),
334 'sortable' => 1,
335 'label' => JText::translate('VBOREPORTREVENUEREVOTA')
336 ),
337 // Refunds
338 array(
339 'key' => 'refunds',
340 'attr' => array(
341 'class="center"'
342 ),
343 'sortable' => 1,
344 'label' => JText::translate('VBO_TOT_REFUNDS')
345 ),
346 //ADR
347 array(
348 'key' => 'adr',
349 'attr' => array(
350 'class="center"'
351 ),
352 'sortable' => 1,
353 'label' => JText::translate('VBOREPORTREVENUEADR'),
354 'tip' => JText::translate('VBOREPORTREVENUEADRHELP')
355 ),
356 //RevPAR
357 array(
358 'key' => 'revpar',
359 'attr' => array(
360 'class="center"'
361 ),
362 'sortable' => 1,
363 'label' => JText::translate('VBOREPORTREVENUEREVPAR'),
364 'tip' => JText::translate('VBOREPORTREVENUEREVPARH')
365 ),
366 //Taxes
367 array(
368 'key' => 'taxes',
369 'attr' => array(
370 'class="center"'
371 ),
372 'sortable' => 1,
373 'label' => JText::translate('VBOREPORTREVENUETAX')
374 ),
375 // Commissions
376 array(
377 'key' => 'cmms',
378 'attr' => array(
379 'class="center"'
380 ),
381 'sortable' => 1,
382 'label' => JText::translate('VBTOTALCOMMISSIONS')
383 ),
384 // Cancellation fees
385 array(
386 'key' => 'canc_fees',
387 'attr' => array(
388 'class="center"'
389 ),
390 'sortable' => 1,
391 'label' => JText::translate('VBO_CANC_FEE')
392 ),
393 //Revenue
394 array(
395 'key' => 'revenue',
396 'attr' => array(
397 'class="center"'
398 ),
399 'sortable' => 1,
400 'label' => JText::translate('VBOREPORTREVENUEREV')
401 )
402 );
403
404 $total_rooms_units = $this->countRooms($pidroom);
405
406 // loop over the dates of the report to build the rows
407 $from_info = getdate($from_ts);
408 $to_info = getdate($to_ts);
409 $canc_fee_bookings = [];
410 while ($from_info[0] <= $to_info[0]) {
411 // prepare default fields for this row
412 $day_ts = $from_info[0];
413 $curwday = $this->getWdayString($from_info['wday'], 'short');
414 $rooms_sold = 0;
415 $tot_bookings = 0;
416 $occupancy = 0;
417 $ibe_revenue = 0;
418 $ota_revenue = 0;
419 $tot_refunds = 0;
420 $adr = 0;
421 $revpar = 0;
422 $taxes = 0;
423 $cmms = 0;
424 $canc_fees = 0;
425 $revenue = 0;
426 // calculate the report details for this day
427 foreach ($bookings as $gbook) {
428 // skip already parsed cancelled bookings with cancellation fees
429 if (in_array($gbook[0]['id'], $canc_fee_bookings)) {
430 continue;
431 }
432 // check if booking affects the current day
433 if ($from_info[0] >= $gbook[0]['from_ts'] && $from_info[0] <= $gbook[0]['to_ts']) {
434 // immediately check for cancelled bookings with cancellation fees
435 if ($gbook[0]['status'] == 'cancelled') {
436 // increase value
437 $canc_fees += $gbook[0]['canc_fee'];
438 // record this booking as already counted
439 $canc_fee_bookings[] = $gbook[0]['id'];
440 continue;
441 }
442
443 // this booking affects the current day
444 if (!empty($pidroom)) {
445 $rooms_booked = 0;
446 foreach ($gbook as $sgbook) {
447 if ((int)$sgbook['idroom'] == $pidroom) {
448 $rooms_sold++;
449 }
450 }
451 } else {
452 $rooms_sold += $gbook[0]['roomsnum'];
453 }
454 $tot_bookings++;
455
456 // determine the base total amount in case of rooms filtering
457 $room_base_total = 0;
458 if ($pidroom && $rooms_sold > 0) {
459 foreach ($gbook as $room_book) {
460 if ($room_book['idroom'] != $pidroom) {
461 continue;
462 }
463 if ($room_book['cust_cost'] > 0) {
464 $room_base_total += $room_book['cust_cost'];
465 } elseif ($room_book['room_cost'] > 0) {
466 $room_base_total += $room_book['room_cost'];
467 }
468 }
469 }
470
471 // calculate net revenue and taxes
472 $tot_net = $gbook[0]['total'] - (float)$gbook[0]['tot_taxes'] - (float)$gbook[0]['tot_city_taxes'] - (float)$gbook[0]['tot_fees'] - (float)$gbook[0]['cmms'];
473
474 if ($room_base_total && (!(float)$gbook[0]['tot_taxes'] || !VikBooking::ivaInclusa())) {
475 /**
476 * Overwrite total net value in case of rooms filtering only in case of no taxes, or in
477 * case of prices before taxes, because the amount of tax per room is not available.
478 *
479 * @since 1.16.9 (J) - 1.6.9 (WP)
480 */
481 $tot_net = $room_base_total;
482 }
483
484 $tot_net = $tot_net / (int)$gbook[0]['days'];
485 $revenue += $tot_net;
486 if (!empty($gbook[0]['idorderota']) && !empty($gbook[0]['channel'])) {
487 $ota_revenue += $tot_net;
488 } else {
489 $ibe_revenue += $tot_net;
490 }
491 $taxes += ((float)$gbook[0]['tot_taxes'] + (float)$gbook[0]['tot_city_taxes'] + (float)$gbook[0]['tot_fees']) / (int)$gbook[0]['days'];
492 $cmms += (float)$gbook[0]['cmms'] / (int)$gbook[0]['days'];
493 $tot_refunds += $gbook[0]['refund'] / $gbook[0]['days'];
494 }
495 }
496 $occupancy = round(($rooms_sold * 100 / $total_rooms_units), 2);
497 $adr = $rooms_sold > 0 ? $revenue / $rooms_sold : 0;
498 $revpar = $revenue / $total_rooms_units;
499 // push fields in the rows array as a new row
500 array_push($this->rows, array(
501 array(
502 'key' => 'day',
503 'callback' => function ($val) use ($df, $datesep, $curwday) {
504 return $curwday.', '.date(str_replace("/", $datesep, $df), $val);
505 },
506 'value' => $day_ts,
507 ),
508 array(
509 'key' => 'rooms_sold',
510 'attr' => array(
511 'class="center"'
512 ),
513 'value' => $rooms_sold,
514 ),
515 array(
516 'key' => 'tot_bookings',
517 'attr' => array(
518 'class="center"'
519 ),
520 'value' => $tot_bookings,
521 ),
522 array(
523 'key' => 'occupancy',
524 'attr' => array(
525 'class="center"'
526 ),
527 'value' => $occupancy,
528 ),
529 array(
530 'key' => 'ibe_revenue',
531 'attr' => array(
532 'class="center"'
533 ),
534 'callback' => function ($val) use ($currency_symb) {
535 return $currency_symb . ' ' . VikBooking::numberFormat($val);
536 },
537 'value' => $ibe_revenue,
538 ),
539 array(
540 'key' => 'ota_revenue',
541 'attr' => array(
542 'class="center"'
543 ),
544 'callback' => function ($val) use ($currency_symb) {
545 return $currency_symb . ' ' . VikBooking::numberFormat($val);
546 },
547 'value' => $ota_revenue,
548 ),
549 array(
550 'key' => 'refunds',
551 'attr' => array(
552 'class="center"'
553 ),
554 'callback' => function ($val) use ($currency_symb) {
555 return $currency_symb . ' ' . VikBooking::numberFormat($val);
556 },
557 'value' => $tot_refunds,
558 ),
559 array(
560 'key' => 'adr',
561 'attr' => array(
562 'class="center"'
563 ),
564 'callback' => function ($val) use ($currency_symb) {
565 return $currency_symb . ' ' . VikBooking::numberFormat($val);
566 },
567 'value' => $adr,
568 ),
569 array(
570 'key' => 'revpar',
571 'attr' => array(
572 'class="center"'
573 ),
574 'callback' => function ($val) use ($currency_symb) {
575 return $currency_symb . ' ' . VikBooking::numberFormat($val);
576 },
577 'value' => $revpar,
578 ),
579 array(
580 'key' => 'taxes',
581 'attr' => array(
582 'class="center"'
583 ),
584 'callback' => function ($val) use ($currency_symb) {
585 return $currency_symb . ' ' . VikBooking::numberFormat($val);
586 },
587 'value' => $taxes,
588 ),
589 array(
590 'key' => 'cmms',
591 'attr' => array(
592 'class="center"'
593 ),
594 'callback' => function ($val) use ($currency_symb) {
595 return $currency_symb . ' ' . VikBooking::numberFormat($val);
596 },
597 'value' => $cmms,
598 ),
599 array(
600 'key' => 'canc_fees',
601 'attr' => array(
602 'class="center"'
603 ),
604 'callback' => function ($val) use ($currency_symb) {
605 return $currency_symb . ' ' . VikBooking::numberFormat($val);
606 },
607 'value' => $canc_fees,
608 ),
609 array(
610 'key' => 'revenue',
611 'attr' => array(
612 'class="center"'
613 ),
614 'callback' => function ($val) use ($currency_symb) {
615 return $currency_symb . ' ' . VikBooking::numberFormat($val);
616 },
617 'value' => ($revenue + $canc_fees),
618 )
619 ));
620
621 // next day iteration
622 $from_info = getdate(mktime(0, 0, 0, $from_info['mon'], ($from_info['mday'] + 1), $from_info['year']));
623 }
624
625 // sort rows
626 $this->sortRows($pkrsort, $pkrorder);
627
628 // loop over the rows to build the footer row with the totals
629 $foot_rooms_sold = 0;
630 $foot_tot_bookings = 0;
631 $foot_ibe_revenue = 0;
632 $foot_ota_revenue = 0;
633 $foot_tot_refunds = 0;
634 $foot_taxes = 0;
635 $foot_cmms = 0;
636 $foot_canc_fees = 0;
637 $foot_revenue = 0;
638
639 foreach ($this->rows as $row) {
640 $foot_rooms_sold += $row[1]['value'];
641 $foot_tot_bookings += $row[2]['value'];
642 $foot_ibe_revenue += $row[4]['value'];
643 $foot_ota_revenue += $row[5]['value'];
644 $foot_tot_refunds += $row[6]['value'];
645 $foot_taxes += $row[9]['value'];
646 $foot_cmms += $row[10]['value'];
647 $foot_canc_fees += $row[11]['value'];
648 $foot_revenue += $row[12]['value'];
649 }
650
651 array_push($this->footerRow, array(
652 array(
653 'attr' => array(
654 'class="vbo-report-total"'
655 ),
656 'value' => '<h3>'.JText::translate('VBOREPORTSTOTALROW').'</h3>',
657 ),
658 array(
659 'attr' => array(
660 'class="center"'
661 ),
662 'value' => $foot_rooms_sold,
663 ),
664 array(
665 'attr' => array(
666 'class="center"'
667 ),
668 'value' => $foot_tot_bookings,
669 ),
670 array(
671 'value' => '',
672 ),
673 array(
674 'attr' => array(
675 'class="center"'
676 ),
677 'callback' => function ($val) use ($currency_symb) {
678 return $currency_symb . ' ' . VikBooking::numberFormat($val);
679 },
680 'value' => $foot_ibe_revenue,
681 ),
682 array(
683 'attr' => array(
684 'class="center"'
685 ),
686 'callback' => function ($val) use ($currency_symb) {
687 return $currency_symb . ' ' . VikBooking::numberFormat($val);
688 },
689 'value' => $foot_ota_revenue,
690 ),
691 array(
692 'attr' => array(
693 'class="center"'
694 ),
695 'callback' => function ($val) use ($currency_symb) {
696 return $currency_symb . ' ' . VikBooking::numberFormat($val);
697 },
698 'value' => $foot_tot_refunds,
699 ),
700 array(
701 'value' => '',
702 ),
703 array(
704 'value' => '',
705 ),
706 array(
707 'attr' => array(
708 'class="center"'
709 ),
710 'callback' => function ($val) use ($currency_symb) {
711 return $currency_symb . ' ' . VikBooking::numberFormat($val);
712 },
713 'value' => $foot_taxes,
714 ),
715 array(
716 'attr' => array(
717 'class="center"'
718 ),
719 'callback' => function ($val) use ($currency_symb) {
720 return $currency_symb . ' ' . VikBooking::numberFormat($val);
721 },
722 'value' => $foot_cmms,
723 ),
724 array(
725 'attr' => array(
726 'class="center"'
727 ),
728 'callback' => function ($val) use ($currency_symb) {
729 return $currency_symb . ' ' . VikBooking::numberFormat($val);
730 },
731 'value' => $foot_canc_fees,
732 ),
733 array(
734 'attr' => array(
735 'class="center"'
736 ),
737 'callback' => function ($val) use ($currency_symb) {
738 return $currency_symb . ' ' . VikBooking::numberFormat($val);
739 },
740 'value' => $foot_revenue,
741 )
742 ));
743
744 // Debug
745 if ($this->debug) {
746 $this->setWarning('path to report file = '.urlencode(dirname(__FILE__)).'<br/>');
747 $this->setWarning('$total_rooms_units = '.$total_rooms_units.'<br/>');
748 $this->setWarning('$bookings:<pre>'.print_r($bookings, true).'</pre><br/>');
749 }
750
751 return true;
752 }
753
754 /**
755 * Registers the name to give to the CSV file being exported.
756 *
757 * @return void
758 *
759 * @since 1.16.1 (J) - 1.6.1 (WP)
760 */
761 private function registerExportCSVFileName()
762 {
763 $pfromdate = VikRequest::getString('fromdate', '', 'request');
764 $ptodate = VikRequest::getString('todate', '', 'request');
765
766 $report_extraname = '';
767 $pchannel = VikRequest::getString('channel', '', 'request');
768 if (strlen($pchannel)) {
769 // set channel name for exported file
770 if ($pchannel == '-1') {
771 $report_extraname = JText::translate('VBORDFROMSITE');
772 } else {
773 $report_extraname = $pchannel;
774 }
775 }
776
777 $this->setExportCSVFileName($this->reportName . (!empty($report_extraname) ? '-' . $report_extraname : '') . '-' . str_replace('/', '_', $pfromdate) . '-' . str_replace('/', '_', $ptodate) . '.csv');
778 }
779 }
780