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

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

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