PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.8.7
VikBooking Hotel Booking Engine & PMS v1.8.7
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 / istat_spot.php

istat_spot.php in VikBooking Hotel Booking Engine & PMS 1.8.7, at admin/helpers/report/istat_spot.php

1,440 lines 48.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) 2019 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 * ISTAT Spot è valido per diverse regioni. Sicuramente per la Puglia.
15 *
16 * @since 1.15.4 (J) - 1.5.10 (WP)
17 */
18 class VikBookingReportIstatSpot extends VikBookingReport
19 {
20 /**
21 * Property 'defaultKeySort' is used by the View that renders the report.
22 */
23 public $defaultKeySort = 'idbooking';
24 /**
25 * Property 'defaultKeyOrder' is used by the View that renders the report.
26 */
27 public $defaultKeyOrder = 'ASC';
28 /**
29 * Property 'customExport' is used by the View to display custom export buttons.
30 */
31 public $customExport = '';
32 /**
33 * Debug mode is activated by passing the value 'e4j_debug' > 0
34 */
35 private $debug;
36
37 /**
38 * Other private vars of this sub-class.
39 */
40 private $comuniProvince;
41 private $nazioni;
42 private $documenti;
43
44 /**
45 * Class constructor should define the name of the report and
46 * other vars. Call the parent constructor to define the DB object.
47 */
48 function __construct()
49 {
50 $this->reportFile = basename(__FILE__, '.php');
51 $this->reportName = JText::translate('ISTAT Spot');
52 $this->reportFilters = array();
53
54 $this->cols = array();
55 $this->rows = array();
56 $this->footerRow = array();
57
58 $this->debug = (VikRequest::getInt('e4j_debug', 0, 'request') > 0);
59
60 $this->comuniProvince = array();
61 $this->nazioni = array();
62
63 $this->registerExportFileName();
64
65 parent::__construct();
66 }
67
68 /**
69 * Returns the name of this report.
70 *
71 * @return string
72 */
73 public function getName()
74 {
75 return $this->reportName;
76 }
77
78 /**
79 * Returns the name of this file without .php.
80 *
81 * @return string
82 */
83 public function getFileName()
84 {
85 return $this->reportFile;
86 }
87
88 /**
89 * Returns the filters of this report.
90 *
91 * @return array
92 */
93 public function getFilters()
94 {
95 if (count($this->reportFilters)) {
96 //do not run this method twice, as it could load JS and CSS files.
97 return $this->reportFilters;
98 }
99
100 //load the jQuery UI Datepicker
101 $this->loadDatePicker();
102
103 //custom export button
104 $this->customExport = '<a href="JavaScript: void(0);" onclick="vboDownloadSchedaIstat();" class="vbcsvexport"><i class="'.VikBookingIcons::i('download').'"></i> <span>Download File</span></a>';
105
106 //build the hidden values for the selection of Comuni & Province.
107 $this->comuniProvince = $this->loadComuniProvince();
108 $this->nazioni = $this->loadNazioni();
109 $hidden_vals = '<div id="vbo-report-alloggiati-hidden" style="display: none;">';
110 //Comuni
111 $hidden_vals .= ' <div id="vbo-report-alloggiati-comune" class="vbo-report-alloggiati-selcont" style="display: none;">';
112 $hidden_vals .= ' <select id="choose-comune" onchange="vboReportChosenComune(this);"><option value=""></option>';
113 if (isset($this->comuniProvince['comuni']) && count($this->comuniProvince['comuni'])) {
114 foreach ($this->comuniProvince['comuni'] as $code => $comune) {
115 $hidden_vals .= ' <option value="' . $code . '">' . (is_array($comune) ? $comune['name'] : '') . '</option>'."\n";
116 }
117 }
118 $hidden_vals .= ' </select>';
119 $hidden_vals .= ' </div>';
120 //
121 //Province
122 $hidden_vals .= ' <div id="vbo-report-alloggiati-provincia" class="vbo-report-alloggiati-selcont" style="display: none;">';
123 $hidden_vals .= ' <select id="choose-provincia" onchange="vboReportChosenProvincia(this);"><option value=""></option>';
124 if (isset($this->comuniProvince['province']) && count($this->comuniProvince['province'])) {
125 foreach ($this->comuniProvince['province'] as $code => $provincia) {
126 $hidden_vals .= ' <option value="'.$code.'">'.$provincia.'</option>'."\n";
127 }
128 }
129 $hidden_vals .= ' </select>';
130 $hidden_vals .= ' </div>';
131 //
132 //Nazioni
133 $hidden_vals .= ' <div id="vbo-report-alloggiati-nazione" class="vbo-report-alloggiati-selcont" style="display: none;">';
134 $hidden_vals .= ' <select id="choose-nazione" onchange="vboReportChosenNazione(this);"><option value=""></option>';
135 if (count($this->nazioni)) {
136 foreach ($this->nazioni as $code => $nazione) {
137 $hidden_vals .= ' <option value="'.$code.'">'.$nazione['name'].'</option>';
138 }
139 }
140 $hidden_vals .= ' </select>';
141 $hidden_vals .= ' </div>';
142 //
143 //Sesso
144 $hidden_vals .= ' <div id="vbo-report-alloggiati-sesso" class="vbo-report-alloggiati-selcont" style="display: none;">';
145 $hidden_vals .= ' <select id="choose-sesso" onchange="vboReportChosenSesso(this);"><option value=""></option>';
146 $sessos = array(
147 1 => 'M',
148 2 => 'F'
149 );
150 foreach ($sessos as $code => $ses) {
151 $hidden_vals .= ' <option value="'.$code.'">'.$ses.'</option>'."\n";
152 }
153 $hidden_vals .= ' </select>';
154 $hidden_vals .= ' </div>';
155 //
156 //Numero Documento
157 $hidden_vals .= ' <div id="vbo-report-alloggiati-docnum" class="vbo-report-alloggiati-selcont" style="display: none;">';
158 $hidden_vals .= ' <input type="text" size="40" id="choose-docnum" placeholder="Numero Documento..." value="" /><br/>';
159 $hidden_vals .= ' <button type="button" class="btn" onclick="vboReportChosenDocnum(document.getElementById(\'choose-docnum\').value);">'.JText::translate('VBAPPLY').'</button>';
160 $hidden_vals .= ' </div>';
161 //
162 //Data di Nascita
163 $hidden_vals .= ' <div id="vbo-report-alloggiati-dbirth" class="vbo-report-alloggiati-selcont" style="display: none;">';
164 $hidden_vals .= ' <input type="text" size="40" id="choose-dbirth" placeholder="Data di Nascita" value="" /><br/>';
165 $hidden_vals .= ' <button type="button" class="btn" onclick="vboReportChosenDbirth(document.getElementById(\'choose-dbirth\').value);">'.JText::translate('VBAPPLY').'</button>';
166 $hidden_vals .= ' </div>';
167 //
168 $hidden_vals .= '</div>';
169
170 //From Date Filter (with hidden values for the dropdown menus of Comuni, Province, Stati etc..)
171 $filter_opt = array(
172 'label' => '<label for="fromdate">'.JText::translate('VBPVIEWORDERSONE').'</label>',
173 'html' => '<input type="text" id="fromdate" name="fromdate" value="" class="vbo-report-datepicker vbo-report-datepicker-from" />'.$hidden_vals,
174 'type' => 'calendar',
175 'name' => 'fromdate'
176 );
177 array_push($this->reportFilters, $filter_opt);
178
179 // apertura struttura
180 $papertura = VikRequest::getString('apertura', '', 'request');
181 $filter_opt = array(
182 'label' => '<label for="apertura">Apertura Struttura</label>',
183 'html' => '<select id="choose-apertura" name="apertura"> <option value="" '.((empty($papertura) || ($papertura != 'SI' && $papertura != 'NO')) ? 'selected="selected"' : '' ).'></option><option value="SI" ' .((!empty($papertura) && $papertura == 'SI') ? 'selected="selected"' : '') .'> La struttura è aperta in questa data. </option> <option value="NO"' .((!empty($papertura) && $papertura == 'NO') ? 'selected="selected"' : '') .'> La struttura non è aperta in questa data. </option> </select>',
184 'type' => 'text',
185 'name' => 'apertura'
186 );
187 array_push($this->reportFilters, $filter_opt);
188
189 // Filtro Numero Letti
190 $pletti = VikRequest::getInt('numletti', 0, 'request');
191 $filter_opt = array(
192 'label' => '<label for="numletti">Numero Letti Disponibili</label>',
193 'html' => '<input type="number" id="numletti" name="numletti" value="'.$pletti.'" size="10" />',
194 'type' => 'text',
195 'name' => 'numletti'
196 );
197 array_push($this->reportFilters, $filter_opt);
198
199 //jQuery code for the datepicker calendars, select2 and triggers for the dropdown menus
200 $pfromdate = VikRequest::getString('fromdate', '', 'request');
201 $ptodate = VikRequest::getString('todate', '', 'request');
202 $js = 'var reportActiveCell = null, reportObj = {};
203 jQuery(function() {
204 //prepare main filters
205 jQuery(".vbo-report-datepicker:input").datepicker({
206 maxDate: "+1m",
207 dateFormat: "'.$this->getDateFormat('jui').'",
208 onSelect: vboReportCheckDates
209 });
210 '.(!empty($pfromdate) ? 'jQuery(".vbo-report-datepicker-from").datepicker("setDate", "'.$pfromdate.'");' : '').'
211 '.(!empty($ptodate) ? 'jQuery(".vbo-report-datepicker-to").datepicker("setDate", "'.$ptodate.'");' : '').'
212 //prepare filler helpers
213 jQuery("#vbo-report-alloggiati-hidden").children().detach().appendTo(".vbo-info-overlay-report");
214 jQuery("#choose-comune").select2({placeholder: "- Seleziona un Comune -", width: "200px"});
215 jQuery("#choose-provincia").select2({placeholder: "- Seleziona una Provincia -", width: "200px"});
216 jQuery("#choose-nazione").select2({placeholder: "- Seleziona una Nazione -", width: "200px"});
217 jQuery("#choose-sesso").select2({placeholder: "- Seleziona Sesso -", width: "200px"});
218
219 jQuery("#choose-dbirth").datepicker({
220 maxDate: 0,
221 dateFormat: "dd/mm/yy",
222 changeMonth: true,
223 changeYear: true,
224 yearRange: "'.(date('Y') - 100).':'.date('Y').'"
225 });
226 //click events
227 jQuery(".vbo-report-load-comune").click(function() {
228 reportActiveCell = this;
229 jQuery(".vbo-report-alloggiati-selcont").hide();
230 jQuery("#vbo-report-alloggiati-comune").show();
231 vboShowOverlay();
232 });
233 jQuery(".vbo-report-load-provincia").click(function() {
234 reportActiveCell = this;
235 jQuery(".vbo-report-alloggiati-selcont").hide();
236 jQuery("#vbo-report-alloggiati-provincia").show();
237 vboShowOverlay();
238 });
239 jQuery(".vbo-report-load-nazione, .vbo-report-load-cittadinanza").click(function() {
240 reportActiveCell = this;
241 jQuery(".vbo-report-alloggiati-selcont").hide();
242 jQuery("#vbo-report-alloggiati-nazione").show();
243 vboShowOverlay();
244 });
245 jQuery(".vbo-report-load-sesso").click(function() {
246 reportActiveCell = this;
247 jQuery(".vbo-report-alloggiati-selcont").hide();
248 jQuery("#vbo-report-alloggiati-sesso").show();
249 vboShowOverlay();
250 });
251 jQuery(".vbo-report-load-dbirth").click(function() {
252 reportActiveCell = this;
253 jQuery(".vbo-report-alloggiati-selcont").hide();
254 jQuery("#vbo-report-alloggiati-dbirth").show();
255 vboShowOverlay();
256 });
257 });
258 function vboReportCheckDates(selectedDate, inst) {
259 if (selectedDate === null || inst === null) {
260 return;
261 }
262 var cur_from_date = jQuery(this).val();
263 if (jQuery(this).hasClass("vbo-report-datepicker-from") && cur_from_date.length) {
264 var nowstart = jQuery(this).datepicker("getDate");
265 var nowstartdate = new Date(nowstart.getTime());
266 jQuery(".vbo-report-datepicker-to").datepicker("option", {minDate: nowstartdate});
267 }
268 }
269 function vboReportChosenComune(comune) {
270 var c_code = comune.value;
271 var c_val = comune.options[comune.selectedIndex].text;
272 if (reportActiveCell !== null) {
273 var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr"));
274 if (isNaN(nowindex) || parseInt(nowindex) < 0) {
275 alert("Error, cannot find element to update.");
276 } else {
277 jQuery(reportActiveCell).addClass("vbo-report-load-elem-filled").find("span").text(c_val);
278 if (!reportObj.hasOwnProperty(nowindex)) {
279 reportObj[nowindex] = {};
280 }
281 if (jQuery(reportActiveCell).hasClass("vbo-report-load-docplace")) {
282 reportObj[nowindex].docplace = c_code;
283 } else {
284 reportObj[nowindex].comres = c_code;
285 }
286 }
287 }
288 reportActiveCell = null;
289 vboHideOverlay();
290 jQuery("#choose-comune").val("").select2("data", null, false);
291 }
292 function vboReportChosenProvincia(prov) {
293 var c_code = prov.value;
294 var c_val = prov.options[prov.selectedIndex].text;
295 if (reportActiveCell !== null) {
296 var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr"));
297 if (isNaN(nowindex) || parseInt(nowindex) < 0) {
298 alert("Error, cannot find element to update.");
299 } else {
300 jQuery(reportActiveCell).addClass("vbo-report-load-elem-filled").find("span").text(c_val);
301 if (!reportObj.hasOwnProperty(nowindex)) {
302 reportObj[nowindex] = {};
303 }
304 reportObj[nowindex].prores = c_code;
305 }
306 }
307 reportActiveCell = null;
308 vboHideOverlay();
309 jQuery("#choose-provincia").val("").select2("data", null, false);
310 }
311 function vboReportChosenNazione(naz) {
312 var c_code = naz.value;
313 var c_val = naz.options[naz.selectedIndex].text;
314 if (reportActiveCell !== null) {
315 var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr"));
316 if (isNaN(nowindex) || parseInt(nowindex) < 0) {
317 alert("Error, cannot find element to update.");
318 } else {
319 jQuery(reportActiveCell).addClass("vbo-report-load-elem-filled").find("span").text(c_val);
320 if (!reportObj.hasOwnProperty(nowindex)) {
321 reportObj[nowindex] = {};
322 }
323 if (jQuery(reportActiveCell).hasClass("vbo-report-load-nazione")) {
324 reportObj[nowindex].stares = c_code;
325 } else if (jQuery(reportActiveCell).hasClass("vbo-report-load-docplace")) {
326 reportObj[nowindex].docplace = c_code;
327 } else {
328 reportObj[nowindex].citizen = c_code;
329 }
330 }
331 }
332 reportActiveCell = null;
333 vboHideOverlay();
334 jQuery("#choose-nazione").val("").select2("data", null, false);
335 }
336 function vboReportChosenSesso(sesso) {
337 var c_code = sesso.value;
338 var c_val = sesso.options[sesso.selectedIndex].text;
339 if (reportActiveCell !== null) {
340 var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr"));
341 if (isNaN(nowindex) || parseInt(nowindex) < 0) {
342 alert("Error, cannot find element to update.");
343 } else {
344 jQuery(reportActiveCell).addClass("vbo-report-load-elem-filled").find("span").text(c_val);
345 if (!reportObj.hasOwnProperty(nowindex)) {
346 reportObj[nowindex] = {};
347 }
348 reportObj[nowindex].gender = c_code;
349 }
350 }
351 reportActiveCell = null;
352 vboHideOverlay();
353 jQuery("#choose-sesso").val("").select2("data", null, false);
354 }
355 function vboReportChosenDbirth(val) {
356 var c_code = val, c_val = val;
357 if (reportActiveCell !== null) {
358 var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr"));
359 if (isNaN(nowindex) || parseInt(nowindex) < 0) {
360 alert("Error, cannot find element to update.");
361 } else {
362 jQuery(reportActiveCell).addClass("vbo-report-load-elem-filled").find("span").text(c_val);
363 if (!reportObj.hasOwnProperty(nowindex)) {
364 reportObj[nowindex] = {};
365 }
366 reportObj[nowindex].dbirth = c_code;
367 }
368 }
369 reportActiveCell = null;
370 vboHideOverlay();
371 jQuery("#choose-dbirth").val("");
372 }
373 //download function
374 function vboDownloadSchedaIstat() {
375 if (!confirm("Sei sicuro di aver compilato tutti i dati?")) {
376 return false;
377 }
378 document.adminForm.target = "_blank";
379 document.adminForm.action += "&tmpl=component";
380 vboSetFilters({exportreport: "1", filler: JSON.stringify(reportObj)}, true);
381 setTimeout(function() {
382 document.adminForm.target = "";
383 document.adminForm.action = document.adminForm.action.replace("&tmpl=component", "");
384 vboSetFilters({exportreport: "0", filler: ""}, false);
385 }, 1000);
386 }
387 ';
388 $this->setScript($js);
389
390 return $this->reportFilters;
391 }
392
393 /**
394 * Loads the report data from the DB.
395 * Returns true in case of success, false otherwise.
396 * Sets the columns and rows for the report to be displayed.
397 *
398 * @return boolean
399 */
400 public function getReportData()
401 {
402 if (strlen($this->getError())) {
403 //Export functions may set errors rather than exiting the process, and the View may continue the execution to attempt to render the report.
404 return false;
405 }
406
407 // get the possibly injected report options
408 $options = $this->getReportOptions();
409
410 //Input fields and other vars
411 $pfromdate = VikRequest::getString('fromdate', '', 'request');
412 $ptodate = VikRequest::getString('todate', '', 'request');
413 $pkrsort = VikRequest::getString('krsort', $this->defaultKeySort, 'request');
414 $pkrsort = empty($pkrsort) ? $this->defaultKeySort : $pkrsort;
415 $pkrorder = VikRequest::getString('krorder', $this->defaultKeyOrder, 'request');
416 $pkrorder = empty($pkrorder) ? $this->defaultKeyOrder : $pkrorder;
417 $pkrorder = $pkrorder == 'DESC' ? 'DESC' : 'ASC';
418 $papertura = VikRequest::getString('apertura', '', 'request');
419 $plistings = ((array) VikRequest::getVar('listings', array())) ?: ((array) $options->get('listings', []));
420 $plistings = array_filter(array_map('intval', $plistings));
421
422 $q = "SELECT SUM(`units`) AS `sommaunita`, SUM(`totpeople`) AS `numeropersone`, COUNT(*) AS `numerocamere` FROM `#__vikbooking_rooms` WHERE `avail`= '1';";
423 $this->dbo->setQuery($q);
424 $records = $this->dbo->loadAssocList();
425
426 $totalBeds = (int)($records[0]['sommaunita'] * ($records[0]['numeropersone'] / $records[0]['numerocamere']));
427 $pletti = VikRequest::getString('numletti', $totalBeds, 'request');
428 $currency_symb = VikBooking::getCurrencySymb();
429 $df = $this->getDateFormat();
430 $datesep = VikBooking::getDateSeparator();
431 if (empty($ptodate)) {
432 $ptodate = $pfromdate;
433 }
434 //Get dates timestamps
435 $from_ts = VikBooking::getDateTimestamp($pfromdate, 0, 0);
436 $to_ts = VikBooking::getDateTimestamp($ptodate, 23, 59, 59);
437 if (empty($pfromdate) || empty($from_ts) || empty($to_ts)) {
438 $this->setError(JText::translate('VBOREPORTSERRNODATES'));
439 return false;
440 }
441 if (empty($papertura)) {
442 $this->setError('Devi specificare se la tua struttura è aperta o meno attraverso il menù a tendina qui sopra.');
443 return false;
444 }
445
446 // query to obtain the records (all reservations or stays within the dates filter)
447 $q = $this->dbo->getQuery(true)
448 ->select([
449 $this->dbo->qn('o.id'),
450 $this->dbo->qn('o.custdata'),
451 $this->dbo->qn('o.ts'),
452 $this->dbo->qn('o.days'),
453 $this->dbo->qn('o.status'),
454 $this->dbo->qn('o.checkin'),
455 $this->dbo->qn('o.checkout'),
456 $this->dbo->qn('o.totpaid'),
457 $this->dbo->qn('o.roomsnum'),
458 $this->dbo->qn('o.total'),
459 $this->dbo->qn('o.idorderota'),
460 $this->dbo->qn('o.channel'),
461 $this->dbo->qn('o.country'),
462 $this->dbo->qn('or.idorder'),
463 $this->dbo->qn('or.idroom'),
464 $this->dbo->qn('or.adults'),
465 $this->dbo->qn('or.children'),
466 $this->dbo->qn('or.t_first_name'),
467 $this->dbo->qn('or.t_last_name'),
468 $this->dbo->qn('or.cust_cost'),
469 $this->dbo->qn('or.cust_idiva'),
470 $this->dbo->qn('or.extracosts'),
471 $this->dbo->qn('or.room_cost'),
472 $this->dbo->qn('co.idcustomer'),
473 $this->dbo->qn('co.pax_data'),
474 $this->dbo->qn('c.first_name'),
475 $this->dbo->qn('c.last_name'),
476 $this->dbo->qn('c.country', 'customer_country'),
477 $this->dbo->qn('c.address'),
478 $this->dbo->qn('c.city'),
479 $this->dbo->qn('c.state'),
480 $this->dbo->qn('c.doctype'),
481 $this->dbo->qn('c.docnum'),
482 $this->dbo->qn('c.gender'),
483 $this->dbo->qn('c.bdate'),
484 $this->dbo->qn('c.pbirth'),
485 ])
486 ->from($this->dbo->qn('#__vikbooking_orders', 'o'))
487 ->leftJoin($this->dbo->qn('#__vikbooking_ordersrooms', 'or') . ' ON ' . $this->dbo->qn('or.idorder') . ' = ' . $this->dbo->qn('o.id'))
488 ->leftJoin($this->dbo->qn('#__vikbooking_customers_orders', 'co') . ' ON ' . $this->dbo->qn('co.idorder') . ' = ' . $this->dbo->qn('o.id'))
489 ->leftJoin($this->dbo->qn('#__vikbooking_customers', 'c') . ' ON ' . $this->dbo->qn('c.id') . ' = ' . $this->dbo->qn('co.idcustomer'))
490 ->where($this->dbo->qn('o.closure') . ' = 0')
491 ->where($this->dbo->qn('o.status') . ' = ' . $this->dbo->q('confirmed'))
492 ->order($this->dbo->qn('o.checkin') . ' ASC')
493 ->order($this->dbo->qn('o.id') . ' ASC')
494 ->order($this->dbo->qn('or.id') . ' ASC');
495
496 if ($plistings) {
497 $q->where($this->dbo->qn('or.idroom') . ' IN (' . implode(', ', $plistings) . ')');
498 }
499
500 // fetch all bookings with a stay date between the interval of dates requested
501 $q->andWhere([
502 '(' . $this->dbo->qn('o.checkin') . ' BETWEEN ' . $from_ts . ' AND ' . $to_ts . ')',
503 '(' . $this->dbo->qn('o.checkout') . ' BETWEEN ' . $from_ts . ' AND ' . $to_ts . ')',
504 '(' . $this->dbo->qn('o.checkin') . ' < ' . $from_ts . ' AND ' . $this->dbo->qn('o.checkout') . ' > ' . $to_ts . ')',
505 ], 'OR');
506
507 $this->dbo->setQuery($q);
508 $records = $this->dbo->loadAssocList();
509
510 if (!$records) {
511 $this->setError(JText::translate('VBOREPORTSERRNORESERV'));
512 $this->setError('Nessuna prenotazione trovata nelle date selezionate.');
513 return false;
514 }
515 //nest records with multiple rooms booked inside sub-array
516 $bookings = array();
517 foreach ($records as $v) {
518 if (!isset($bookings[$v['id']])) {
519 $bookings[$v['id']] = array();
520 }
521 array_push($bookings[$v['id']], $v);
522 }
523 //define the columns of the report
524 $this->cols = array(
525 //id booking
526 array(
527 'key' => 'idbooking',
528 'label' => 'ID',
529 'sortable' => 1,
530 ),
531 //check-in
532 array(
533 'key' => 'checkin',
534 'attr' => array(
535 'class="center"'
536 ),
537 'sortable' => 1,
538 'label' => JText::translate('VBPICKUPAT')
539 ),
540 //checkout
541 array(
542 'key' => 'checkout',
543 'attr' => array(
544 'class="center"'
545 ),
546 'sortable' => 1,
547 'label' => 'Partenza'
548 ),
549 //cognome
550 array(
551 'key' => 'cognome',
552 'label' => JText::translate('VBTRAVELERLNAME'),
553 'sortable' => 1,
554 ),
555 //nome
556 array(
557 'key' => 'nome',
558 'label' => JText::translate('VBTRAVELERNAME'),
559 'sortable' => 1,
560 ),
561 //sesso
562 array(
563 'key' => 'gender',
564 'attr' => array(
565 'class="center"'
566 ),
567 'label' => JText::translate('VBCUSTOMERGENDER')
568 ),
569 //data di nascita
570 array(
571 'key' => 'dbirth',
572 'attr' => array(
573 'class="center"'
574 ),
575 'label' => JText::translate('VBCUSTOMERBDATE')
576 ),
577 //cittadinanza
578 array(
579 'key' => 'citizen',
580 'attr' => array(
581 'class="center"'
582 ),
583 'sortable' => 1,
584 'label' => 'Cittadinanza'
585 ),
586 //cittadinanza
587 array(
588 'key' => 'stares',
589 'attr' => array(
590 'class="center"'
591 ),
592 'sortable' => 1,
593 'label' => 'Stato di Residenza'
594 ),
595 //comune di residenza
596 array(
597 'key' => 'comres',
598 'attr' => array(
599 'class="center"'
600 ),
601 'sortable' => 1,
602 'label' => 'Comune Residenza',
603 'tip' => 'Inserire il comune di residenza solo se il cittadino è di nazionalità italiana.'
604 ),
605 //tipo
606 array(
607 'key' => 'tipo',
608 'attr' => array(
609 'class="vbo-report-longlbl"'
610 ),
611 'label' => 'Tipo Alloggiato'
612 ),
613 //quantità (numero di ospiti)
614 array(
615 'key' => 'guestsnum',
616 'attr' => array(
617 'class="center"'
618 ),
619 'sortable' => 1,
620 'label' => 'Numero Ospiti',
621 'tip' => 'Il numero di ospiti totali (adulti + bambini) per ogni prenotazione è un dato che verrà comunicato all\'ISTAT.',
622 ),
623 );
624
625 //loop over the bookings to build the rows of the report
626 $from_info = getdate($from_ts);
627 foreach ($bookings as $gbook) {
628 $guestsnum = 0;
629 $guests_rows = array($gbook[0]);
630 $room_guests = array();
631 $tot_guests_rows = 1;
632
633 $tipo = 16;
634 //Codici Tipo Alloggiato
635 // 16 = Ospite Singolo
636 // 17 = Capofamiglia
637 // 18 = Capogruppo
638 // 19 = Familiare
639 // 20 = Membro Gruppo
640
641 foreach ($gbook as $book) {
642 $guestsnum += $book['adults'] + $book['children'];
643 $room_guests[] = ($book['adults'] + $book['children']);
644 }
645 $pax_data = null;
646 if (!empty($gbook[0]['pax_data'])) {
647 $pax_data = json_decode($gbook[0]['pax_data'], true);
648 if (is_array($pax_data) && count($pax_data)) {
649 $guests_rows[0]['pax_data'] = $pax_data;
650 $tot_guests_rows = 0;
651 foreach ($pax_data as $roomguests) {
652 $tot_guests_rows += count($roomguests);
653 }
654 for ($i = 1; $i < $tot_guests_rows; $i++) {
655 array_push($guests_rows, $guests_rows[0]);
656 }
657 $tipo = count($guests_rows) > 1 ? 17 : $tipo;
658 }
659 }
660 //create one row for each guest
661 $guest_ind = 1;
662 foreach ($guests_rows as $ind => $guests) {
663 // prepare row record
664 $insert_row = array();
665
666 // find the actual guest-room-index
667 $guest_room_ind = $this->calcGuestRoomIndex($room_guests, $guest_ind);
668
669 // booking ID
670 array_push($insert_row, array(
671 'key' => 'idbooking',
672 'callback' => function ($val) {
673 return '<a href="index.php?option=com_vikbooking&task=editorder&cid[]='.$val.'" target="_blank"><i class="'.VikBookingIcons::i('external-link').'"></i> '.$val.'</a>';
674 },
675 'callback_export' => function ($val) {
676 return $val;
677 },
678 'value' => $guests['id']
679 ));
680
681 // checkin date
682 array_push($insert_row, array(
683 'key' => 'checkin',
684 'attr' => array(
685 'class="center"'
686 ),
687 'callback' => function ($val) {
688 return date('d/m/Y', $val);
689 },
690 'value' => $guests['checkin']
691 ));
692
693 // checkout date
694 array_push($insert_row,array(
695 'key' => 'checkout',
696 'attr' => array(
697 'class="center"'
698 ),
699 'callback' => function ($val) {
700 return date('d/m/Y', $val);
701 },
702 'value' => $gbook[0]['checkout']
703 ));
704
705 // cognome
706 $cognome = !empty($guests['t_last_name']) ? $guests['t_last_name'] : $guests['last_name'];
707 $pax_cognome = $this->getGuestPaxDataValue($pax_data, $room_guests, $guest_ind, 'last_name');
708 $cognome = !empty($pax_cognome) ? $pax_cognome : $cognome;
709 array_push($insert_row, array(
710 'key' => 'cognome',
711 'value' => $cognome
712 ));
713
714 // nome
715 $nome = !empty($guests['t_first_name']) ? $guests['t_first_name'] : $guests['first_name'];
716 $pax_nome = $this->getGuestPaxDataValue($pax_data, $room_guests, $guest_ind, 'first_name');
717 $nome = !empty($pax_nome) ? $pax_nome : $nome;
718 array_push($insert_row, array(
719 'key' => 'nome',
720 'value' => $nome
721 ));
722
723 // sesso
724 $gender = !empty($guests['gender']) && $guest_ind < 2 ? strtoupper($guests['gender']) : '';
725 $gender = $gender == 'F' ? 2 : ($gender == 'M' ? 1 : $gender);
726 $pax_gender = $this->getGuestPaxDataValue($pax_data, $room_guests, $guest_ind, 'gender');
727 $gender = !empty($pax_gender) ? $pax_gender : $gender;
728 if (is_numeric($gender)) {
729 $gender = (int)$gender;
730 } elseif (!strcasecmp($gender, 'F')) {
731 $gender = 2;
732 } elseif (!strcasecmp($gender, 'M')) {
733 $gender = 1;
734 }
735 array_push($insert_row, array(
736 'key' => 'gender',
737 'attr' => array(
738 'class="center'.(empty($gender) ? ' vbo-report-load-sesso' : '').'"'
739 ),
740 'callback' => function ($val) {
741 return $val == 2 ? 'F' : ($val == 1 ? 'M' : '?');
742 },
743 'callback_export' => function ($val) {
744 return $val == 2 ? 'F' : ($val == 1 ? 'M' : '?');
745 },
746 'value' => $gender
747 ));
748
749 // data di nascita
750 $dbirth = !empty($guests['bdate']) && $guest_ind < 2 ? VikBooking::getDateTimestamp($guests['bdate'], 0, 0) : '';
751 $pax_dbirth = $this->getGuestPaxDataValue($pax_data, $room_guests, $guest_ind, 'date_birth');
752 $dbirth = !empty($pax_dbirth) ? $pax_dbirth : $dbirth;
753 $dbirth = (strpos($dbirth, '/') === false && strpos($dbirth, VikBooking::getDateSeparator()) === false) ? $dbirth : VikBooking::getDateTimestamp($dbirth, 0, 0);
754 array_push($insert_row, array(
755 'key' => 'dbirth',
756 'attr' => array(
757 'class="center'.(empty($dbirth) ? ' vbo-report-load-dbirth' : '').'"'
758 ),
759 'callback' => function ($val) {
760 if (!empty($val) && strpos($val, '/') === false && strpos($val, VikBooking::getDateSeparator()) === false) {
761 return date('d/m/Y', $val);
762 }
763 if (!empty($val) && strpos($val, '/') !== false) {
764 return $val;
765 }
766 return '?';
767 },
768 'no_export_callback' => 1,
769 'value' => $dbirth
770 ));
771
772 // cittadinanza (compatible with pax data field of driver "Italy")
773 $pax_country_c = $this->getGuestPaxDataValue($pax_data, $room_guests, $guest_ind, 'country_c');
774 $citizen = !empty($guests['country']) && $guest_ind < 2 ? $guests['country'] : '';
775 $citizenval = '';
776 if (!empty($citizen) && $guest_ind < 2) {
777 $citizenval = $this->checkCountry($citizen);
778 }
779 // check nationality field from pre-checkin
780 $pax_citizen = $this->getGuestPaxDataValue($pax_data, $room_guests, $guest_ind, 'nationality');
781 $citizen = !empty($pax_citizen) ? $pax_citizen : $citizen;
782 $citizen = !empty($pax_country_c) ? $pax_country_c : $citizen;
783 $citizenval = !empty($pax_country_c) ? $pax_country_c : $this->checkCountry($citizen);
784 array_push($insert_row, array(
785 'key' => 'citizen',
786 'attr' => array(
787 'class="center'.(empty($citizen) ? ' vbo-report-load-cittadinanza' : '').'"'
788 ),
789 'callback' => function ($val) {
790 return !empty($val) ? $this->nazioni[$val]['name'] : '?';
791 },
792 'no_export_callback' => 1,
793 'value' => !empty($citizenval) ? $citizenval : ''
794 ));
795
796 // stato di residenza
797 $provstay = '';
798 $pax_provstay = $this->getGuestPaxDataValue($pax_data, $room_guests, $guest_ind, 'country_s');
799 $provstay = !empty($pax_provstay) ? $pax_provstay : $provstay;
800 array_push($insert_row, array(
801 'key' => 'stares',
802 'attr' => array(
803 'class="center'.(empty($provstay) ? ' vbo-report-load-nazione' : '').'"'
804 ),
805 'callback' => function($val) {
806 if (!empty($val) && isset($this->nazioni[$val])) {
807 return $this->nazioni[$val]['name'];
808 }
809 // information is missing and should be provided
810 return '?';
811 },
812 'no_export_callback' => 1,
813 'value' => $provstay
814 ));
815
816 // comune di residenza
817 $comstay = '';
818 $pax_comstay = $this->getGuestPaxDataValue($pax_data, $room_guests, $guest_ind, 'comune_s');
819 $comstay = !empty($pax_comstay) ? $pax_comstay : $comstay;
820 array_push($insert_row, array(
821 'key' => 'comres',
822 'attr' => array(
823 'class="center'.(empty($comstay) ? ' vbo-report-load-comune' : '').'"'
824 ),
825 'callback' => function($val) {
826 if (!empty($val) && isset($this->comuniProvince['comuni'][$val])) {
827 return $this->comuniProvince['comuni'][$val]['name'];
828 }
829 // information is missing and should be provided
830 return '?';
831 },
832 'no_export_callback' => 1,
833 'value' => $comstay
834 ));
835
836 // tipo alloggiato
837 $use_tipo = $ind > 0 && $tipo == 17 ? 19 : $tipo;
838 $pax_guest_type = $this->getGuestPaxDataValue($pax_data, $room_guests, $guest_ind, 'guest_type');
839 $use_tipo = !empty($pax_guest_type) ? $pax_guest_type : $use_tipo;
840 array_push($insert_row, array(
841 'key' => 'tipo',
842 'callback' => function ($val) {
843 switch ($val) {
844 case 16:
845 return 'Ospite Singolo';
846 case 17:
847 return 'Capofamiglia';
848 case 18:
849 return 'Capogruppo';
850 case 19:
851 return 'Familiare';
852 case 20:
853 return 'Membro Gruppo';
854 }
855 return '?';
856 },
857 'no_export_callback' => 1,
858 'value' => $use_tipo
859 ));
860
861 // numero persone in prenotazione
862 array_push($insert_row, array(
863 'key' => 'guestsnum',
864 'attr' => array(
865 'class="center"'
866 ),
867 'value' => $guestsnum
868 ));
869
870 // push fields in the rows array as a new row
871 array_push($this->rows, $insert_row);
872
873 // increment guest index
874 $guest_ind++;
875 }
876 }
877
878 // do not sort the rows for this report because the lines of the guests of the same booking must be consecutive
879 // $this->sortRows($pkrsort, $pkrorder);
880
881 // the footer row will just print the amount of records to export
882 array_push($this->footerRow, array(
883 array(
884 'attr' => array(
885 'class="vbo-report-total"'
886 ),
887 'value' => '<h3>'.JText::translate('VBOREPORTSTOTALROW').'</h3>'
888 ),
889 array(
890 'attr' => array(
891 'colspan="'.(count($this->cols) - 1).'"'
892 ),
893 'value' => count($this->rows)
894 )
895 ));
896
897 // Debug
898 if ($this->debug) {
899 $this->setWarning('path to report file = '.urlencode(dirname(__FILE__)).'<br/>');
900 $this->setWarning('$total_rooms_units = '.$total_rooms_units.'<br/>');
901 $this->setWarning('$bookings:<pre>'.print_r($bookings, true).'</pre><br/>');
902 }
903
904 return true;
905 }
906
907 public function formatXML(&$xml)
908 {
909 if (!class_exists('DOMDocument')) {
910 // we cannot format the XML because DOMDocument is missing
911 return $xml;
912 }
913
914 $dom = new DOMDocument;
915 $dom->preserveWhiteSpace = false;
916 $dom->loadXML($xml);
917 $dom->formatOutput = true;
918 $xml = $dom->saveXML();
919
920 return $xml;
921 }
922
923 /**
924 * Generates the report columns and rows, then it outputs a CSV file
925 * for download. In case of errors, the process is not terminated (exit)
926 * to let the View display the error message.
927 * We use customExport() rather than exportCSV() only because we need a
928 * different download button rather than the classic "Export as CSV".
929 *
930 * @param string $export_type Differentiates the type of export requested.
931 *
932 * @return void|bool Void in case of script termination, boolean otherwise.
933 */
934 public function customExport($export_type = 0)
935 {
936 if (!$this->getReportData()) {
937 return false;
938 }
939
940 $pfromdate = VikRequest::getString('fromdate', '', 'request');
941 $ptodate = VikRequest::getString('todate', '', 'request');
942 $papertura = VikRequest::getString('apertura', '', 'request');
943 $records = array();
944 $q = "SELECT SUM(`units`) AS `sommaunita`, SUM(`totpeople`) AS `numeropersone`, COUNT(*) AS `numerocamere` FROM `#__vikbooking_rooms` WHERE `avail`= '1';";
945 $this->dbo->setQuery($q);
946 $this->dbo->execute();
947 if ($this->dbo->getNumRows() > 0) {
948 $records = $this->dbo->loadAssocList();
949 }
950 $totalBeds = (int)($records[0]['sommaunita'] * ($records[0]['numeropersone'] / $records[0]['numerocamere']));
951 // Filtro Numero Letti
952 $pletti = VikRequest::getString('numletti', $totalBeds, 'request');
953
954 // manual values in filler
955 $pfiller = VikRequest::getString('filler', '', 'request', VIKREQUEST_ALLOWRAW);
956 $pfiller = !empty($pfiller) ? json_decode($pfiller, true) : array();
957 $pfiller = !is_array($pfiller) ? array() : $pfiller;
958
959 //Debug
960 if ($this->debug) {
961 $this->setError('<pre>'.print_r($pfiller, true).'</pre><br/>');
962 return false;
963 }
964
965 $q = "SELECT SUM(`units`) FROM `#__vikbooking_rooms` WHERE `avail`= '1';";
966 $this->dbo->setQuery($q);
967 $this->dbo->execute();
968 $totalRooms = $this->dbo->loadResult();
969
970 // pool of booking IDs to update their history
971 $booking_ids = array();
972 // update the history for all bookings affected
973 foreach ($booking_ids as $bid) {
974 VikBooking::getBookingHistoryInstance()->setBid($bid)->store('RP', $this->reportName);
975 }
976 $date = str_replace('/', '-', $pfromdate);
977 $dataMovim = date('Y-m-d', strtotime($date));
978
979 $xml = '';
980 $xml .= '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
981 $xml .= '<movimenti xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="movimentogiornaliero-0.6.xsd" vendor="VikBooking">' . "\n";
982
983 $numOccupiedrooms = 0;
984
985 $date = new DateTime();
986 $ts = $date->getTimestamp();
987
988 $from_ts = VikBooking::getDateTimestamp($pfromdate, 0, 0);
989 $to_ts = VikBooking::getDateTimestamp($pfromdate, 23, 59, 59);
990
991 $clienti = array(
992 'arrivi' => array(),
993 'partenze' => array(),
994 'prenotazioni' => array(),
995 );
996 $q = "SELECT COUNT(`o`.`id`),".
997 "(SELECT `h`.`dt` FROM `#__vikbooking_orderhistory` AS `h` WHERE `h`.`idorder`=`o`.`id` AND `h`.`type`='RP' AND `h`.`descr`=".$this->dbo->quote($this->reportName)." ORDER BY `h`.`dt` DESC LIMIT 1) AS `history_last` ".
998 "FROM `#__vikbooking_orders` AS `o` LEFT JOIN `#__vikbooking_ordersrooms` AS `or` ON `or`.`idorder`=`o`.`id` ".
999 "LEFT JOIN `#__vikbooking_customers_orders` AS `co` ON `co`.`idorder`=`o`.`id` LEFT JOIN `#__vikbooking_customers` AS `c` ON `c`.`id`=`co`.`idcustomer` LEFT JOIN `#__vikbooking_countries` AS `cy` ON `cy`.`country_3_code`=`c`.`country` ".
1000 "WHERE `o`.`status`='confirmed' AND `o`.`closure`=0 AND ((`o`.`checkin`>=".$from_ts." AND `o`.`checkin`<=".$to_ts.") OR (`o`.`checkout`>=".$from_ts." AND `o`.`checkout`<=".$to_ts.") OR (`o`.`checkin`<=".$from_ts." AND `o`.`checkout`>=".$to_ts.")) ".
1001 "ORDER BY `o`.`checkin` ASC, `o`.`id` ASC, `or`.`id` ASC;";
1002
1003 $this->dbo->setQuery($q);
1004 $camereoccupate = $this->dbo->loadResult();
1005 $arrivi = 0;
1006 $partenze = 0;
1007 $prenotazioni = 0;
1008
1009 if ($papertura == 'SI') {
1010 $xml .= '<movimento type="MP" data="' . $dataMovim . '">' . "\n";
1011 foreach ($this->rows as $ind => $row) {
1012 $idswh = -1;
1013 $timestamp_in = -1;
1014 $timestamp_out = -1;
1015 $control = -1; // mi serve per non ripetere ogni loop il controllo sul tipo di cliente
1016 $type = -1; // se il cliente è in arrivo il tipo è 1, se è in partenza 2, se è una nuova prenotazione 3
1017
1018 foreach ($row as $field) {
1019 if (isset($field['ignore_export'])) {
1020 continue;
1021 }
1022 // check if a value for this field was filled in manually
1023 if (is_array($pfiller) && isset($pfiller[$ind]) && isset($pfiller[$ind][$field['key']])) {
1024 if (strlen($pfiller[$ind][$field['key']])) {
1025 $field['value'] = $pfiller[$ind][$field['key']];
1026 }
1027 }
1028 // values set to -1 are usually empty and should have been filled in manually
1029 if ($field['value'] === -1) {
1030 // we raise an error in this case without stopping the process
1031 $field['value'] = 0;
1032 VikError::raiseWarning('', 'La riga #'.$ind.' ha un valore vuoto che doveva essere riempito manualmente cliccando sul blocco in rosso. Il file potrebbe contenere valori invalidi per questa riga.');
1033 }
1034 if (isset($field['callback_export'])) {
1035 $field['callback'] = $field['callback_export'];
1036 }
1037 $export_value = !isset($field['no_export_callback']) && isset($field['callback']) && is_callable($field['callback']) ? $field['callback']($field['value']) : $field['value'];
1038
1039 if ($field['key'] == 'idbooking') {
1040 $idswh = $export_value;
1041 }
1042 if ($field['key'] == 'checkin') {
1043 $timestamp_in = VikBooking::getDateTimestamp($export_value);
1044 }
1045 if ($field['key'] == 'checkout') {
1046 $timestamp_out = VikBooking::getDateTimestamp($export_value);
1047 }
1048 if ($control == -1 && $timestamp_in != -1 && $timestamp_out != -1) {
1049 if (date('Y-m-d', $timestamp_in) == date('Y-m-d', $from_ts) && date('Y-m-d', $timestamp_in) <= date('Y-m-d', $to_ts)) {
1050 $type = 1;
1051 } elseif (date('Y-m-d', $timestamp_out) == date('Y-m-d', $from_ts) && date('Y-m-d', $timestamp_out) == date('Y-m-d', $to_ts)) {
1052 $type = 2;
1053 } else {
1054 $type = 3;
1055 }
1056 $control = true;
1057 }
1058 if ($type == 1) {
1059 $clienti['arrivi'][$arrivi]['codiceclientesr'] = $idswh;
1060 if ($field['key'] == 'gender') {
1061 $clienti['arrivi'][$arrivi]['sesso'] = $export_value;
1062 }
1063 if ($field['key'] == 'citizen') {
1064 $clienti['arrivi'][$arrivi]['cittadinanza'] = (string)$export_value;
1065 }
1066 if ($field['key'] == 'stares') {
1067 $clienti['arrivi'][$arrivi]['statoresidenza'] = (string)$export_value;
1068 }
1069 if ($field['key'] == 'comres') {
1070 $clienti['arrivi'][$arrivi]['comuneresidenza'] = (string)$export_value;
1071 }
1072 $clienti['arrivi'][$arrivi]['occupazionepostoletto'] = 'si';
1073 $clienti['arrivi'][$arrivi]['dayuse'] = 'no';
1074 if ($field['key'] == 'tipo') {
1075 $clienti['arrivi'][$arrivi]['tipoalloggiato'] = (string)$export_value;
1076 }
1077 if ($field['key'] == 'dbirth' && !empty($export_value) && $export_value != '?') {
1078 // count the age of this client
1079 $ts_birth = VikBooking::getDateTimestamp($export_value, 0, 0, 0);
1080 $birth_obj = new DateTime(date('Y-m-d', $ts_birth));
1081 $diff_obj = $birth_obj->diff(new DateTime(date('Y-m-d')));
1082 $clienti['arrivi'][$arrivi]['eta'] = $diff_obj->format('%y');
1083 }
1084 } elseif ($type == 2) {
1085 $clienti['partenze'][$partenze]['codiceclientesr'] = $idswh;
1086 if ($field['key'] == 'tipo') {
1087 // $clienti['partenze'][$partenze]['tipoalloggiato'] = (string)$export_value;
1088 }
1089 if ($field['key'] == 'checkin') {
1090 $date = str_replace('/', '-', $export_value);
1091 $arrivo = date('Ymd', strtotime($date));
1092 // $clienti['partenze'][$partenze]['arrivo'] = (string)$arrivo;
1093 }
1094 } elseif ($type == 3) {
1095 $clienti['prenotazioni'][$prenotazioni]['codiceclientesr'] = $idswh;
1096 if ($field['key'] == 'checkin') {
1097 $date = str_replace('/', '-', $export_value);
1098 $prenotazione = date('Ymd', strtotime($date));
1099 $clienti['prenotazioni'][$prenotazioni]['arrivo'] = (string)$prenotazione;
1100 }
1101 if ($field['key'] == 'checkout') {
1102 $date = str_replace('/', '-', $export_value);
1103 $partenza = date('Ymd', strtotime($date));
1104 $clienti['prenotazioni'][$prenotazioni]['partenza'] = (string)$partenza;
1105 }
1106 if ($field['key'] == 'guestsnum') {
1107 $clienti['prenotazioni'][$prenotazioni]['ospiti'] = (string)$export_value;
1108 }
1109 }
1110 }
1111 if ($type == 1) {
1112 $arrivi++;
1113 } elseif ($type == 2) {
1114 $partenze++;
1115 } elseif ($type == 3){
1116 $prenotazioni++;
1117 }
1118 }
1119
1120 $xml .= '<arrivi>'."\n";
1121 for ($i = 0; $i < count($clienti['arrivi']); $i++) {
1122 $xml .= '<arrivo>'."\n";
1123 foreach ($clienti['arrivi'][$i] as $key => $value) {
1124 $xml .= '<'.$key.'>'.$value.'</'.$key.'>'."\n";
1125 }
1126 $xml .= '</arrivo>'."\n";
1127 }
1128 $xml .= '</arrivi>'."\n";
1129
1130 $xml .= '<partenze>'."\n";
1131 for ($i = 0; $i < count($clienti['partenze']); $i++) {
1132 $xml .= '<partenza>'."\n";
1133 foreach ($clienti['partenze'][$i] as $key => $value) {
1134 $xml .= '<'.$key.'>'.$value.'</'.$key.'>'."\n";
1135 }
1136 $xml .= '</partenza>'."\n";
1137 }
1138 $xml .= '</partenze>'."\n";
1139
1140 $xml .= '<datistruttura>'."\n";
1141 $xml .= ' <cameredisponibili>'.$totalRooms.'</cameredisponibili>'."\n";
1142 $xml .= ' <postilettodisponibili>'.$pletti.'</postilettodisponibili>'."\n";
1143 $xml .= ' <camereoccupate>'.$camereoccupate.'</camereoccupate>'."\n";
1144 $xml .= '</datistruttura>'."\n";
1145 } else {
1146 $xml .= '<movimento type="EC" data="' . $dataMovim . '">' . "\n";
1147 $xml .= ' <datistruttura>'."\n";
1148 $xml .= ' <cameredisponibili>0</cameredisponibili>'."\n";
1149 $xml .= ' <postilettodisponibili>0</postilettodisponibili>'."\n";
1150 $xml .= ' <camereoccupate>0</camereoccupate>'."\n";
1151 $xml .= ' </datistruttura>'."\n";
1152 }
1153
1154 $xml .= '</movimento> '."\n";
1155 $xml .= '</movimenti>';
1156
1157 // format XML document
1158 $this->formatXML($xml);
1159
1160 /**
1161 * Custom export method supports a custom export handler, if previously set.
1162 *
1163 * @since 1.16.1 (J) - 1.6.1 (WP)
1164 */
1165 if ($this->hasExportHandler()) {
1166 // write data onto the custom file handler
1167 $fp = $this->getExportCSVHandler();
1168 fwrite($fp, $xml);
1169 fclose($fp);
1170
1171 return true;
1172 }
1173
1174 header('Content-Disposition: attachment; filename=' . $this->getExportCSVFileName());
1175 header('Content-type: text/xml');
1176 echo $xml;
1177
1178 exit;
1179 }
1180
1181 /**
1182 * Registers the name to give to the file being exported.
1183 *
1184 * @return void
1185 *
1186 * @since 1.16.1 (J) - 1.6.1 (WP)
1187 */
1188 private function registerExportFileName()
1189 {
1190 $pfromdate = VikRequest::getString('fromdate', '', 'request');
1191
1192 $this->setExportCSVFileName(str_replace(' ', '_', $this->reportName) . '-' . str_replace('/', '_', $pfromdate) . '.xml');
1193 }
1194
1195 /**
1196 * Parses the file Comuni.csv and returns two associative
1197 * arrays: one for the Comuni and one for the Province.
1198 * Every line of the CSV is composed of: Codice, Comune, Provincia.
1199 *
1200 * @return array
1201 */
1202 private function loadComuniProvince()
1203 {
1204 $vals = array(
1205 'comuni' => array(
1206 0 => '-- Estero --'
1207 ),
1208 'province' => array(
1209 0 => '-- Estero --'
1210 )
1211 );
1212
1213 $csv = dirname(__FILE__).DIRECTORY_SEPARATOR.'Comuni.csv';
1214 $rows = file($csv);
1215 foreach ($rows as $row) {
1216 if (empty($row)) {
1217 continue;
1218 }
1219 $v = explode(';', $row);
1220 if (count($v) != 3) {
1221 continue;
1222 }
1223 $vals['comuni'][$v[0]]['name'] = $v[1];
1224 $vals['comuni'][$v[0]]['province'] = $v[2];
1225 $vals['province'][$v[2]] = $v[2];
1226 }
1227
1228 return $vals;
1229 }
1230
1231 /**
1232 * Parses the file Nazioni.csv and returns an associative
1233 * array with the code and name of the Nazione.
1234 * Every line of the CSV is composed of: Codice, Nazione.
1235 *
1236 * @return array
1237 */
1238 private function loadNazioni()
1239 {
1240 $nazioni = array();
1241
1242 $csv = dirname(__FILE__).DIRECTORY_SEPARATOR.'Nazioni.csv';
1243 $rows = file($csv);
1244 foreach ($rows as $row) {
1245 if (empty($row)) {
1246 continue;
1247 }
1248 $v = explode(';', $row);
1249 if (count($v) != 3) {
1250 continue;
1251 }
1252
1253 $nazioni[$v[0]]['name'] = $v[1];
1254 $nazioni[$v[0]]['three_code'] = $v[2];
1255
1256 }
1257
1258 return $nazioni;
1259 }
1260
1261 /**
1262 *
1263 * Returns an array that contains both name and key of the comune selected, plus the associated province.
1264 *
1265 * @return array
1266 */
1267 private function checkComune($combirth, $checked, $province)
1268 {
1269 $result = array();
1270 $first_found = '';
1271 if (!count($this->comuniProvince)) {
1272 $this->comuniProvince = $this->loadComuniProvince();
1273 }
1274 if (empty($combirth)) {
1275 return $result;
1276 }
1277 foreach ($this->comuniProvince['comuni'] as $key => $value) {
1278 if (!isset($value['name'])) {
1279 continue;
1280 }
1281 if ($value['name'] == $combirth) {
1282 $result['found'] = true;
1283 $result['combirth'] = $value['name'];
1284 $result['province'] = $value['province'];
1285 $result['comval'] = $key;
1286 $result['similar'] = false;
1287 break;
1288 } else if (strpos($value['name'], trim($combirth)) !== false && empty($first_found)) {
1289 $result['found'] = true;
1290 $result['combirth'] = $value['name'];
1291 $first_found = $key;
1292 $result['similar'] = true;
1293 $result['province'] = $value['province'];
1294 }
1295 }
1296 if (!$result['found']) {
1297 $result['combirth'] = '';
1298 }
1299
1300 if ($checked === true && strlen($province) > 0 && $result['found']) {
1301 $result['province'] = $province;
1302 if($province == $value['province']) {
1303 $result['provinceok'] = true;
1304 $result['province'] = $province;
1305 } else {
1306 $result['provinceok'] = false;
1307 }
1308 }
1309 if ($result['similar'] && $result['found']) {
1310 $result['comval'] = $first_found;
1311 }
1312
1313 return $result;
1314 }
1315
1316 /**
1317 *
1318 * Returns the key of the state selected by the user.
1319 *
1320 * @return string
1321 */
1322 private function checkCountry($country)
1323 {
1324 $found = false;
1325 $staval = '';
1326 if (!count($this->nazioni)) {
1327 $this->nazioni = $this->loadNazioni();
1328 }
1329 foreach ($this->nazioni as $key => $value) {
1330 if (trim($value['three_code']) == trim($country)) {
1331 $staval = $key;
1332 $found = true;
1333 break;
1334 }
1335 }
1336 if ($found !== true) {
1337 $staval = '';
1338 }
1339 return $staval;
1340 }
1341
1342 /**
1343 *
1344 * Sanitizes the "Comune": if comune contains also the province, example PRATO (PO),
1345 * then I set both Comune and Province and I check both of them with the checkComune() function.
1346 *
1347 * @return array
1348 */
1349 private function sanitizeComune($combirth)
1350 {
1351 $result = array();
1352
1353 if (strlen($combirth) > 2) {
1354 if (strpos($combirth, "(") !== false) {
1355 $comnas = explode("(", $combirth);
1356 $result['combirth'] = trim($comnas[0]);
1357 $result['province'] = $comnas[1];
1358 $result['province'] = str_replace(")", "", $result['province']);
1359 $result['checked'] = true;
1360 }
1361 } else if(strlen($combirth) > 0){
1362 $result['province'] = trim($combirth);
1363 $result['similar'] = true;
1364 }
1365
1366 return $result;
1367 }
1368
1369 /**
1370 * Helper method to quickly get a pax_data property for the guest.
1371 *
1372 * @param array $pax_data the current pax_data stored.
1373 * @param array $guests list of total guests per room.
1374 * @param int $guest_ind the guest index.
1375 * @param string $key the pax_data key to look for.
1376 *
1377 * @return mixed null on failure or value fetched.
1378 */
1379 private function getGuestPaxDataValue($pax_data, $guests, $guest_ind, $key)
1380 {
1381 if (!is_array($pax_data) || !count($pax_data) || empty($key)) {
1382 return null;
1383 }
1384
1385 // find room index for this guest number
1386 $room_num = 0;
1387 $use_guest_ind = $guest_ind;
1388 foreach ($guests as $room_index => $room_tot_guests) {
1389 // find the proper guest index for the room to which this belongs
1390 if ($use_guest_ind <= $room_tot_guests) {
1391 // proper room index found for this guest
1392 $room_num = $room_index;
1393 break;
1394 } else {
1395 // it's probably in a next room
1396 $use_guest_ind -= $room_tot_guests;
1397 }
1398 }
1399
1400 // check if a value exists for the requested key in the found room and guest indexes
1401 if (isset($pax_data[$room_num]) && isset($pax_data[$room_num][$use_guest_ind])) {
1402 if (isset($pax_data[$room_num][$use_guest_ind][$key])) {
1403 // we've got a value previously stored
1404 return $pax_data[$room_num][$use_guest_ind][$key];
1405 }
1406 }
1407
1408 // nothing was found
1409 return null;
1410 }
1411
1412 /**
1413 * Helper method to determine the exact number for this guest in the room booked.
1414 *
1415 * @param array $guests list of total guests per room.
1416 * @param int $guest_ind the guest index.
1417 *
1418 * @return int the actual guest room index starting from 1.
1419 */
1420 private function calcGuestRoomIndex($guests, $guest_ind)
1421 {
1422 // find room index for this guest number
1423 $room_num = 0;
1424 $use_guest_ind = $guest_ind;
1425 foreach ($guests as $room_index => $room_tot_guests) {
1426 // find the proper guest index for the room to which this belongs
1427 if ($use_guest_ind <= $room_tot_guests) {
1428 // proper room index found for this guest
1429 $room_num = $room_index;
1430 break;
1431 } else {
1432 // it's probably in a next room
1433 $use_guest_ind -= $room_tot_guests;
1434 }
1435 }
1436
1437 return $use_guest_ind;
1438 }
1439 }
1440