PluginProbe
VikBooking Hotel Booking Engine & PMS / trunk
VikBooking Hotel Booking Engine & PMS vtrunk
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 1.7.3 All 36 releases
vikbooking / admin / helpers / report / transactions_report.php

transactions_report.php in VikBooking Hotel Booking Engine & PMS trunk, at admin/helpers/report/transactions_report.php

431 lines 13.2 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 * Transactions child Class of VikBookingReport
15 */
16 class VikBookingReportTransactionsReport extends VikBookingReport
17 {
18 /**
19 * Property 'defaultKeySort' is used by the View that renders the report.
20 */
21 public $defaultKeySort = 'tot';
22
23 /**
24 * Property 'defaultKeyOrder' is used by the View that renders the report.
25 */
26 public $defaultKeyOrder = 'DESC';
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 // get minimum check-in and maximum check-out for dates filters
134 $df = $this->getDateFormat();
135 $mincheckin = 0;
136 $maxcheckout = 0;
137 $q = "SELECT MIN(`checkin`) AS `mincheckin`, MAX(`checkout`) AS `maxcheckout` FROM `#__vikbooking_orders` WHERE `status`='confirmed' AND `closure`=0;";
138 $this->dbo->setQuery($q);
139 $this->dbo->execute();
140 if ($this->dbo->getNumRows()) {
141 $data = $this->dbo->loadAssoc();
142 if (!empty($data['mincheckin']) && !empty($data['maxcheckout'])) {
143 $mincheckin = $data['mincheckin'];
144 $maxcheckout = $data['maxcheckout'];
145 }
146 }
147 //
148
149 //jQuery code for the datepicker calendars and select2
150 $pfromdate = VikRequest::getString('fromdate', '', 'request');
151 $ptodate = VikRequest::getString('todate', '', 'request');
152 $js = 'jQuery(function() {
153 jQuery(".vbo-report-datepicker:input").datepicker({
154 '.(!empty($mincheckin) ? 'minDate: "'.date($df, $mincheckin).'", ' : '').'
155 '.(!empty($maxcheckout) ? 'maxDate: "'.date($df, $maxcheckout).'", ' : '').'
156 dateFormat: "'.$this->getDateFormat('jui').'",
157 onSelect: vboReportCheckDates
158 });
159 '.(!empty($pfromdate) ? 'jQuery(".vbo-report-datepicker-from").datepicker("setDate", "'.$pfromdate.'");' : '').'
160 '.(!empty($ptodate) ? 'jQuery(".vbo-report-datepicker-to").datepicker("setDate", "'.$ptodate.'");' : '').'
161 });
162 function vboReportCheckDates(selectedDate, inst) {
163 if (selectedDate === null || inst === null) {
164 return;
165 }
166 var cur_from_date = jQuery(this).val();
167 if (jQuery(this).hasClass("vbo-report-datepicker-from") && cur_from_date.length) {
168 var nowstart = jQuery(this).datepicker("getDate");
169 var nowstartdate = new Date(nowstart.getTime());
170 jQuery(".vbo-report-datepicker-to").datepicker("option", {minDate: nowstartdate});
171 }
172 }';
173 $this->setScript($js);
174
175 return $this->reportFilters;
176 }
177
178 /**
179 * Loads the report data from the DB.
180 * Returns true in case of success, false otherwise.
181 * Sets the columns and rows for the report to be displayed.
182 *
183 * @return boolean
184 */
185 public function getReportData()
186 {
187 if (strlen($this->getError())) {
188 //Export functions may set errors rather than exiting the process, and the View may continue the execution to attempt to render the report.
189 return false;
190 }
191 //Input fields and other vars
192 $pfromdate = VikRequest::getString('fromdate', '', 'request');
193 $ptodate = VikRequest::getString('todate', '', 'request');
194 $pidroom = VikRequest::getInt('idroom', '', 'request');
195 $pkrsort = VikRequest::getString('krsort', $this->defaultKeySort, 'request');
196 $pkrsort = empty($pkrsort) ? $this->defaultKeySort : $pkrsort;
197 $pkrorder = VikRequest::getString('krorder', $this->defaultKeyOrder, 'request');
198 $pkrorder = empty($pkrorder) ? $this->defaultKeyOrder : $pkrorder;
199 $pkrorder = $pkrorder == 'DESC' ? 'DESC' : 'ASC';
200 $currency_symb = VikBooking::getCurrencySymb();
201 $df = $this->getDateFormat();
202 $datesep = VikBooking::getDateSeparator();
203 if (empty($ptodate)) {
204 $ptodate = $pfromdate;
205 }
206 //Get dates timestamps
207 $from_ts = VikBooking::getDateTimestamp($pfromdate, 0, 0);
208 $to_ts = VikBooking::getDateTimestamp($ptodate, 23, 59, 59);
209 if (empty($pfromdate) || empty($from_ts) || empty($to_ts)) {
210 $this->setError(JText::translate('VBOREPORTSERRNODATES'));
211 return false;
212 }
213
214 /**
215 * We do not make a left join onto the orders roooms table
216 * or we may obtain multiple records with the query. Since we cannot
217 * group by booking ID as we need all history logs of type PU,
218 * we try to make a sub-query to concatenate all room IDs.
219 */
220
221 // Query to obtain the records
222 $bookings = array();
223 $q = "SELECT `o`.`id`,`o`.`ts`,`o`.`days`,`o`.`checkin`,`o`.`checkout`,`o`.`totpaid`,`o`.`idpayment`,`o`.`roomsnum`,`o`.`total`,`o`.`idorderota`,`o`.`channel`,`o`.`country`,`o`.`tot_taxes`,".
224 "`o`.`tot_city_taxes`,`o`.`tot_fees`,`o`.`cmms`,`h`.`dt`,`h`.`data`, (SELECT GROUP_CONCAT(`or`.`idroom` SEPARATOR ';') FROM `#__vikbooking_ordersrooms` AS `or` WHERE `or`.`idorder`=`o`.`id`) AS `idrooms` ".
225 "FROM `#__vikbooking_orders` AS `o` LEFT JOIN `#__vikbooking_orderhistory` AS `h` ON `h`.`idorder`=`o`.`id` AND `h`.`type`='PU' ".
226 "WHERE `o`.`status`='confirmed' AND `o`.`closure`=0 AND `o`.`totpaid` > 0 ".
227 "AND ((`o`.`ts`>=".$from_ts." AND `o`.`ts`<=".$to_ts.") OR (`h`.`data` IS NOT NULL AND `h`.`dt`>=".$this->dbo->quote(date('Y-m-d H:i:s', $from_ts))." AND `h`.`dt`<=".$this->dbo->quote(date('Y-m-d H:i:s', $to_ts)).")) ".
228 "ORDER BY `o`.`ts` ASC, `h`.`dt` DESC;";
229 $this->dbo->setQuery($q);
230 $this->dbo->execute();
231 if ($this->dbo->getNumRows()) {
232 $bookings = $this->dbo->loadAssocList();
233 // apply room ID filter that was not used via SQL
234 if (!empty($pidroom)) {
235 foreach ($bookings as $k => $gbook) {
236 $roomids = explode(';', $gbook['idrooms']);
237 if (!in_array($pidroom, $roomids)) {
238 unset($bookings[$k]);
239 }
240 }
241 }
242 }
243 if (!count($bookings)) {
244 $this->setError(JText::translate('VBOREPORTSERRNORESERV'));
245 return false;
246 }
247
248 // Debug
249 // $this->setWarning('<pre>'.print_r($bookings, true).'</pre><br/>');
250 //
251
252 //define the columns of the report
253 $this->cols = array(
254 //date
255 array(
256 'key' => 'paymeth',
257 'sortable' => 1,
258 'label' => JText::translate('VBPAYMENTMETHOD')
259 ),
260 //rooms sold
261 array(
262 'key' => 'tot',
263 'attr' => array(
264 'class="center"'
265 ),
266 'sortable' => 1,
267 'label' => JText::translate('VBLIBSIX')
268 ),
269 //bookings affected
270 array(
271 'key' => 'ids',
272 'attr' => array(
273 'class="center"'
274 ),
275 'sortable' => 0,
276 'ignore_export' => 0,
277 'label' => JText::translate('VBMENUTHREE')
278 ),
279 );
280
281 $paystats = array();
282 $allbids = array();
283
284 // loop over the bookings to build the payment stats
285 foreach ($bookings as &$gbook) {
286 if (!in_array($gbook['id'], $allbids)) {
287 array_push($allbids, $gbook['id']);
288 }
289 $payname = null;
290 if (!empty($gbook['data'])) {
291 $paydata = json_decode($gbook['data']);
292 $payname = is_object($paydata) && isset($paydata->payment_method) ? $paydata->payment_method : $payname;
293 // update totpaid if history data available
294 if (is_object($paydata) && isset($paydata->amount_paid) && $paydata->amount_paid > 0) {
295 $gbook['totpaid'] = (float)$paydata->amount_paid;
296 }
297 } elseif (!empty($gbook['idpayment'])) {
298 if (strpos($gbook['idpayment'], '=') !== false) {
299 $parts = explode('=', $gbook['idpayment']);
300 $payname = $parts[1];
301 } else {
302 $payname = $gbook['idpayment'];
303 }
304 } elseif (!empty($gbook['channel']) && !empty($gbook['idorderota'])) {
305 $parts = explode('_', $gbook['channel']);
306 unset($parts[0]);
307 $payname = implode('_', $parts);
308 }
309
310 if (is_null($payname)) {
311 // unknown
312 $payname = JText::translate('VBOREPORTTOPCUNKNC');
313 }
314
315 // update reference
316 $gbook['payment_method'] = $payname;
317
318 // update stats for this payment method
319 if (!isset($paystats[$payname])) {
320 $paystats[$payname] = array(
321 'totpaid' => 0,
322 'bids' => array()
323 );
324 }
325
326 // increase total paid and push booking ID
327 $paystats[$payname]['totpaid'] += $gbook['totpaid'];
328 if (!in_array($gbook['id'], $paystats[$payname]['bids'])) {
329 array_push($paystats[$payname]['bids'], $gbook['id']);
330 }
331 }
332
333 // loop over the stats to build the rows
334 foreach ($paystats as $payname => $stats) {
335 //push fields in the rows array as a new row
336 array_push($this->rows, array(
337 array(
338 'key' => 'paymeth',
339 'value' => $payname
340 ),
341 array(
342 'key' => 'tot',
343 'attr' => array(
344 'class="center"'
345 ),
346 'callback' => function ($val) use ($currency_symb) {
347 return $currency_symb.' '.VikBooking::numberFormat($val);
348 },
349 'export_callback' => function ($val) use ($currency_symb) {
350 return $currency_symb.' '.VikBooking::numberFormat($val);
351 },
352 'value' => $stats['totpaid']
353 ),
354 array(
355 'key' => 'ids',
356 'attr' => array(
357 'class="center"'
358 ),
359 'callback' => function ($val) {
360 $str = '';
361 foreach ($val as $bid) {
362 $str .= '<span style="display: inline-block; margin: 0 2px;"><a href="index.php?option=com_vikbooking&task=editorder&cid[]='.$bid.'" target="_blank"><i class="'.VikBookingIcons::i('external-link').'"></i> '.$bid.'</a></span>';
363 }
364 return $str;
365 },
366 'ignore_export' => 1,
367 'value' => $stats['bids']
368 ),
369 ));
370 }
371
372 // sort rows
373 $this->sortRows($pkrsort, $pkrorder);
374
375 // loop over the rows to build the footer row with the totals
376 $foot_tot_collected = 0;
377 foreach ($this->rows as $row) {
378 $foot_tot_collected += $row[1]['value'];
379 }
380
381 // push footer row
382 array_push($this->footerRow, array(
383 array(
384 'attr' => array(
385 'class="vbo-report-total"'
386 ),
387 'value' => '<h3>'.JText::translate('VBOREPORTSTOTALROW').'</h3>'
388 ),
389 array(
390 'attr' => array(
391 'class="center"'
392 ),
393 'callback' => function ($val) use ($currency_symb) {
394 return $currency_symb.' '.VikBooking::numberFormat($val);
395 },
396 'value' => $foot_tot_collected
397 ),
398 array(
399 'attr' => array(
400 'class="center"'
401 ),
402 'value' => count($allbids)
403 ),
404 ));
405
406 //Debug
407 if ($this->debug) {
408 $this->setWarning('path to report file = '.urlencode(dirname(__FILE__)).'<br/>');
409 $this->setWarning('$bookings:<pre>'.print_r($bookings, true).'</pre><br/>');
410 }
411 //
412
413 return true;
414 }
415
416 /**
417 * Registers the name to give to the CSV file being exported.
418 *
419 * @return void
420 *
421 * @since 1.16.1 (J) - 1.6.1 (WP)
422 */
423 private function registerExportCSVFileName()
424 {
425 $pfromdate = VikRequest::getString('fromdate', '', 'request');
426 $ptodate = VikRequest::getString('todate', '', 'request');
427
428 $this->setExportCSVFileName($this->reportName . '-' . str_replace('/', '_', $pfromdate) . '-' . str_replace('/', '_', $ptodate) . '.csv');
429 }
430 }
431