PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.6.7
VikBooking Hotel Booking Engine & PMS v1.6.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.6.7, at admin/helpers/report/istat_spot.php

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