PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.6.9
VikBooking Hotel Booking Engine & PMS v1.6.9
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.6.9, at admin/helpers/report/revenue.php

782 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;";
254 $this->dbo->setQuery($q);
255 $this->dbo->execute();
256 if ($this->dbo->getNumRows() > 0) {
257 $records = $this->dbo->loadAssocList();
258 }
259 if (!count($records)) {
260 $this->setError(JText::translate('VBOREPORTSERRNORESERV'));
261 return false;
262 }
263
264 // nest records with multiple rooms booked inside sub-array
265 $bookings = array();
266 foreach ($records as $v) {
267 if (!isset($bookings[$v['id']])) {
268 $bookings[$v['id']] = array();
269 }
270
271 // calculate the from_ts and to_ts values for later comparison
272 $in_info = getdate($v['checkin']);
273 $out_info = getdate($v['checkout']);
274 $v['from_ts'] = mktime(0, 0, 0, $in_info['mon'], $in_info['mday'], $in_info['year']);
275 $v['to_ts'] = mktime(23, 59, 59, $out_info['mon'], ($out_info['mday'] - 1), $out_info['year']);
276
277 if ($v['status'] == 'cancelled' && count($bookings[$v['id']])) {
278 // one room is sufficient for a cancelled booking with cancellation fees
279 continue;
280 }
281
282 // push nested room-booking
283 array_push($bookings[$v['id']], $v);
284 }
285
286 // define the columns of the report
287 $this->cols = array(
288 //date
289 array(
290 'key' => 'day',
291 'sortable' => 1,
292 'label' => JText::translate('VBOREPORTREVENUEDAY')
293 ),
294 //rooms sold
295 array(
296 'key' => 'rooms_sold',
297 'attr' => array(
298 'class="center"'
299 ),
300 'sortable' => 1,
301 'label' => JText::translate('VBOREPORTREVENUERSOLD')
302 ),
303 //total bookings
304 array(
305 'key' => 'tot_bookings',
306 'attr' => array(
307 'class="center"'
308 ),
309 'sortable' => 1,
310 'label' => JText::translate('VBOREPORTREVENUETOTB')
311 ),
312 //% occupancy
313 array(
314 'key' => 'occupancy',
315 'attr' => array(
316 'class="center"'
317 ),
318 'sortable' => 1,
319 'label' => JText::translate('VBOREPORTREVENUEPOCC')
320 ),
321 //IBE revenue
322 array(
323 'key' => 'ibe_revenue',
324 'attr' => array(
325 'class="center"'
326 ),
327 'sortable' => 1,
328 'label' => JText::translate('VBOREPORTREVENUEREVWEB')
329 ),
330 //OTAs revenue
331 array(
332 'key' => 'ota_revenue',
333 'attr' => array(
334 'class="center"'
335 ),
336 'sortable' => 1,
337 'label' => JText::translate('VBOREPORTREVENUEREVOTA')
338 ),
339 // Refunds
340 array(
341 'key' => 'refunds',
342 'attr' => array(
343 'class="center"'
344 ),
345 'sortable' => 1,
346 'label' => JText::translate('VBO_TOT_REFUNDS')
347 ),
348 //ADR
349 array(
350 'key' => 'adr',
351 'attr' => array(
352 'class="center"'
353 ),
354 'sortable' => 1,
355 'label' => JText::translate('VBOREPORTREVENUEADR'),
356 'tip' => JText::translate('VBOREPORTREVENUEADRHELP')
357 ),
358 //RevPAR
359 array(
360 'key' => 'revpar',
361 'attr' => array(
362 'class="center"'
363 ),
364 'sortable' => 1,
365 'label' => JText::translate('VBOREPORTREVENUEREVPAR'),
366 'tip' => JText::translate('VBOREPORTREVENUEREVPARH')
367 ),
368 //Taxes
369 array(
370 'key' => 'taxes',
371 'attr' => array(
372 'class="center"'
373 ),
374 'sortable' => 1,
375 'label' => JText::translate('VBOREPORTREVENUETAX')
376 ),
377 // Commissions
378 array(
379 'key' => 'cmms',
380 'attr' => array(
381 'class="center"'
382 ),
383 'sortable' => 1,
384 'label' => JText::translate('VBTOTALCOMMISSIONS')
385 ),
386 // Cancellation fees
387 array(
388 'key' => 'canc_fees',
389 'attr' => array(
390 'class="center"'
391 ),
392 'sortable' => 1,
393 'label' => JText::translate('VBO_CANC_FEE')
394 ),
395 //Revenue
396 array(
397 'key' => 'revenue',
398 'attr' => array(
399 'class="center"'
400 ),
401 'sortable' => 1,
402 'label' => JText::translate('VBOREPORTREVENUEREV')
403 )
404 );
405
406 $total_rooms_units = $this->countRooms($pidroom);
407
408 // loop over the dates of the report to build the rows
409 $from_info = getdate($from_ts);
410 $to_info = getdate($to_ts);
411 $canc_fee_bookings = [];
412 while ($from_info[0] <= $to_info[0]) {
413 // prepare default fields for this row
414 $day_ts = $from_info[0];
415 $curwday = $this->getWdayString($from_info['wday'], 'short');
416 $rooms_sold = 0;
417 $tot_bookings = 0;
418 $occupancy = 0;
419 $ibe_revenue = 0;
420 $ota_revenue = 0;
421 $tot_refunds = 0;
422 $adr = 0;
423 $revpar = 0;
424 $taxes = 0;
425 $cmms = 0;
426 $canc_fees = 0;
427 $revenue = 0;
428 // calculate the report details for this day
429 foreach ($bookings as $gbook) {
430 // skip already parsed cancelled bookings with cancellation fees
431 if (in_array($gbook[0]['id'], $canc_fee_bookings)) {
432 continue;
433 }
434 // check if booking affects the current day
435 if ($from_info[0] >= $gbook[0]['from_ts'] && $from_info[0] <= $gbook[0]['to_ts']) {
436 // immediately check for cancelled bookings with cancellation fees
437 if ($gbook[0]['status'] == 'cancelled') {
438 // increase value
439 $canc_fees += $gbook[0]['canc_fee'];
440 // record this booking as already counted
441 $canc_fee_bookings[] = $gbook[0]['id'];
442 continue;
443 }
444
445 // this booking affects the current day
446 if (!empty($pidroom)) {
447 $rooms_booked = 0;
448 foreach ($gbook as $sgbook) {
449 if ((int)$sgbook['idroom'] == $pidroom) {
450 $rooms_sold++;
451 }
452 }
453 } else {
454 $rooms_sold += $gbook[0]['roomsnum'];
455 }
456 $tot_bookings++;
457
458 // determine the base total amount in case of rooms filtering
459 $room_base_total = 0;
460 if ($pidroom && $rooms_sold > 0) {
461 foreach ($gbook as $room_book) {
462 if ($room_book['idroom'] != $pidroom) {
463 continue;
464 }
465 if ($room_book['cust_cost'] > 0) {
466 $room_base_total += $room_book['cust_cost'];
467 } elseif ($room_book['room_cost'] > 0) {
468 $room_base_total += $room_book['room_cost'];
469 }
470 }
471 }
472
473 // calculate net revenue and taxes
474 $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'];
475
476 if ($room_base_total && (!(float)$gbook[0]['tot_taxes'] || !VikBooking::ivaInclusa())) {
477 /**
478 * Overwrite total net value in case of rooms filtering only in case of no taxes, or in
479 * case of prices before taxes, because the amount of tax per room is not available.
480 *
481 * @since 1.16.9 (J) - 1.6.9 (WP)
482 */
483 $tot_net = $room_base_total;
484 }
485
486 $tot_net = $tot_net / (int)$gbook[0]['days'];
487 $revenue += $tot_net;
488 if (!empty($gbook[0]['idorderota']) && !empty($gbook[0]['channel'])) {
489 $ota_revenue += $tot_net;
490 } else {
491 $ibe_revenue += $tot_net;
492 }
493 $taxes += ((float)$gbook[0]['tot_taxes'] + (float)$gbook[0]['tot_city_taxes'] + (float)$gbook[0]['tot_fees']) / (int)$gbook[0]['days'];
494 $cmms += (float)$gbook[0]['cmms'] / (int)$gbook[0]['days'];
495 $tot_refunds += $gbook[0]['refund'] / $gbook[0]['days'];
496 }
497 }
498 $occupancy = round(($rooms_sold * 100 / $total_rooms_units), 2);
499 $adr = $rooms_sold > 0 ? $revenue / $rooms_sold : 0;
500 $revpar = $revenue / $total_rooms_units;
501 // push fields in the rows array as a new row
502 array_push($this->rows, array(
503 array(
504 'key' => 'day',
505 'callback' => function ($val) use ($df, $datesep, $curwday) {
506 return $curwday.', '.date(str_replace("/", $datesep, $df), $val);
507 },
508 'value' => $day_ts,
509 ),
510 array(
511 'key' => 'rooms_sold',
512 'attr' => array(
513 'class="center"'
514 ),
515 'value' => $rooms_sold,
516 ),
517 array(
518 'key' => 'tot_bookings',
519 'attr' => array(
520 'class="center"'
521 ),
522 'value' => $tot_bookings,
523 ),
524 array(
525 'key' => 'occupancy',
526 'attr' => array(
527 'class="center"'
528 ),
529 'value' => $occupancy,
530 ),
531 array(
532 'key' => 'ibe_revenue',
533 'attr' => array(
534 'class="center"'
535 ),
536 'callback' => function ($val) use ($currency_symb) {
537 return $currency_symb . ' ' . VikBooking::numberFormat($val);
538 },
539 'value' => $ibe_revenue,
540 ),
541 array(
542 'key' => 'ota_revenue',
543 'attr' => array(
544 'class="center"'
545 ),
546 'callback' => function ($val) use ($currency_symb) {
547 return $currency_symb . ' ' . VikBooking::numberFormat($val);
548 },
549 'value' => $ota_revenue,
550 ),
551 array(
552 'key' => 'refunds',
553 'attr' => array(
554 'class="center"'
555 ),
556 'callback' => function ($val) use ($currency_symb) {
557 return $currency_symb . ' ' . VikBooking::numberFormat($val);
558 },
559 'value' => $tot_refunds,
560 ),
561 array(
562 'key' => 'adr',
563 'attr' => array(
564 'class="center"'
565 ),
566 'callback' => function ($val) use ($currency_symb) {
567 return $currency_symb . ' ' . VikBooking::numberFormat($val);
568 },
569 'value' => $adr,
570 ),
571 array(
572 'key' => 'revpar',
573 'attr' => array(
574 'class="center"'
575 ),
576 'callback' => function ($val) use ($currency_symb) {
577 return $currency_symb . ' ' . VikBooking::numberFormat($val);
578 },
579 'value' => $revpar,
580 ),
581 array(
582 'key' => 'taxes',
583 'attr' => array(
584 'class="center"'
585 ),
586 'callback' => function ($val) use ($currency_symb) {
587 return $currency_symb . ' ' . VikBooking::numberFormat($val);
588 },
589 'value' => $taxes,
590 ),
591 array(
592 'key' => 'cmms',
593 'attr' => array(
594 'class="center"'
595 ),
596 'callback' => function ($val) use ($currency_symb) {
597 return $currency_symb . ' ' . VikBooking::numberFormat($val);
598 },
599 'value' => $cmms,
600 ),
601 array(
602 'key' => 'canc_fees',
603 'attr' => array(
604 'class="center"'
605 ),
606 'callback' => function ($val) use ($currency_symb) {
607 return $currency_symb . ' ' . VikBooking::numberFormat($val);
608 },
609 'value' => $canc_fees,
610 ),
611 array(
612 'key' => 'revenue',
613 'attr' => array(
614 'class="center"'
615 ),
616 'callback' => function ($val) use ($currency_symb) {
617 return $currency_symb . ' ' . VikBooking::numberFormat($val);
618 },
619 'value' => ($revenue + $canc_fees),
620 )
621 ));
622
623 // next day iteration
624 $from_info = getdate(mktime(0, 0, 0, $from_info['mon'], ($from_info['mday'] + 1), $from_info['year']));
625 }
626
627 // sort rows
628 $this->sortRows($pkrsort, $pkrorder);
629
630 // loop over the rows to build the footer row with the totals
631 $foot_rooms_sold = 0;
632 $foot_tot_bookings = 0;
633 $foot_ibe_revenue = 0;
634 $foot_ota_revenue = 0;
635 $foot_tot_refunds = 0;
636 $foot_taxes = 0;
637 $foot_cmms = 0;
638 $foot_canc_fees = 0;
639 $foot_revenue = 0;
640
641 foreach ($this->rows as $row) {
642 $foot_rooms_sold += $row[1]['value'];
643 $foot_tot_bookings += $row[2]['value'];
644 $foot_ibe_revenue += $row[4]['value'];
645 $foot_ota_revenue += $row[5]['value'];
646 $foot_tot_refunds += $row[6]['value'];
647 $foot_taxes += $row[9]['value'];
648 $foot_cmms += $row[10]['value'];
649 $foot_canc_fees += $row[11]['value'];
650 $foot_revenue += $row[12]['value'];
651 }
652
653 array_push($this->footerRow, array(
654 array(
655 'attr' => array(
656 'class="vbo-report-total"'
657 ),
658 'value' => '<h3>'.JText::translate('VBOREPORTSTOTALROW').'</h3>',
659 ),
660 array(
661 'attr' => array(
662 'class="center"'
663 ),
664 'value' => $foot_rooms_sold,
665 ),
666 array(
667 'attr' => array(
668 'class="center"'
669 ),
670 'value' => $foot_tot_bookings,
671 ),
672 array(
673 'value' => '',
674 ),
675 array(
676 'attr' => array(
677 'class="center"'
678 ),
679 'callback' => function ($val) use ($currency_symb) {
680 return $currency_symb . ' ' . VikBooking::numberFormat($val);
681 },
682 'value' => $foot_ibe_revenue,
683 ),
684 array(
685 'attr' => array(
686 'class="center"'
687 ),
688 'callback' => function ($val) use ($currency_symb) {
689 return $currency_symb . ' ' . VikBooking::numberFormat($val);
690 },
691 'value' => $foot_ota_revenue,
692 ),
693 array(
694 'attr' => array(
695 'class="center"'
696 ),
697 'callback' => function ($val) use ($currency_symb) {
698 return $currency_symb . ' ' . VikBooking::numberFormat($val);
699 },
700 'value' => $foot_tot_refunds,
701 ),
702 array(
703 'value' => '',
704 ),
705 array(
706 'value' => '',
707 ),
708 array(
709 'attr' => array(
710 'class="center"'
711 ),
712 'callback' => function ($val) use ($currency_symb) {
713 return $currency_symb . ' ' . VikBooking::numberFormat($val);
714 },
715 'value' => $foot_taxes,
716 ),
717 array(
718 'attr' => array(
719 'class="center"'
720 ),
721 'callback' => function ($val) use ($currency_symb) {
722 return $currency_symb . ' ' . VikBooking::numberFormat($val);
723 },
724 'value' => $foot_cmms,
725 ),
726 array(
727 'attr' => array(
728 'class="center"'
729 ),
730 'callback' => function ($val) use ($currency_symb) {
731 return $currency_symb . ' ' . VikBooking::numberFormat($val);
732 },
733 'value' => $foot_canc_fees,
734 ),
735 array(
736 'attr' => array(
737 'class="center"'
738 ),
739 'callback' => function ($val) use ($currency_symb) {
740 return $currency_symb . ' ' . VikBooking::numberFormat($val);
741 },
742 'value' => $foot_revenue,
743 )
744 ));
745
746 // Debug
747 if ($this->debug) {
748 $this->setWarning('path to report file = '.urlencode(dirname(__FILE__)).'<br/>');
749 $this->setWarning('$total_rooms_units = '.$total_rooms_units.'<br/>');
750 $this->setWarning('$bookings:<pre>'.print_r($bookings, true).'</pre><br/>');
751 }
752
753 return true;
754 }
755
756 /**
757 * Registers the name to give to the CSV file being exported.
758 *
759 * @return void
760 *
761 * @since 1.16.1 (J) - 1.6.1 (WP)
762 */
763 private function registerExportCSVFileName()
764 {
765 $pfromdate = VikRequest::getString('fromdate', '', 'request');
766 $ptodate = VikRequest::getString('todate', '', 'request');
767
768 $report_extraname = '';
769 $pchannel = VikRequest::getString('channel', '', 'request');
770 if (strlen($pchannel)) {
771 // set channel name for exported file
772 if ($pchannel == '-1') {
773 $report_extraname = JText::translate('VBORDFROMSITE');
774 } else {
775 $report_extraname = $pchannel;
776 }
777 }
778
779 $this->setExportCSVFileName($this->reportName . (!empty($report_extraname) ? '-' . $report_extraname : '') . '-' . str_replace('/', '_', $pfromdate) . '-' . str_replace('/', '_', $ptodate) . '.csv');
780 }
781 }
782