PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.6.5
VikBooking Hotel Booking Engine & PMS v1.6.5
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_ross1000.php

istat_ross1000.php in VikBooking Hotel Booking Engine & PMS 1.6.5, at admin/helpers/report/istat_ross1000.php

1,918 lines 65.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 srl
6 * @copyright Copyright (C) 2022 E4J srl. 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 ROSS 1000 è valido per diverse regioni. Sicuramente per la Romagna e per il Piemonte.
15 * Sviluppato e mantenuto da GIES (Repubblica di San Marino). Simile a SITRA. Il sistema
16 * supporta diversi URL regionali/cittadini per l'eventuale trasmissione a mezzo WSDL.
17 *
18 * @link Piemonte https://piemontedatiturismo.regione.piemonte.it/ws/checkinV2?wsdl
19 * @link Città Metropolitana di Firenze https://turismo5firenze.regione.toscana.it/ws/checkinV2?wsdl
20 * @link Provincia di Pistoia https://turismo5pistoia.regione.toscana.it/ws/checkinV2?wsdl
21 * @link Provincia di Prato https://turismo5prato.regione.toscana.it/ws/checkinV2?wsdl
22 * @link Abruzzo https://app.regione.abruzzo.it/Turismo5/ws/checkinV2?wsdl
23 * @link Veneto https://flussituristici.regione.veneto.it/ws/checkinV2?wsdl
24 * @link Emilia-Romagna https://datiturismo.regione.emilia-romagna.it/ws/checkinV2?wsdl
25 * @link Marche https://istrice-ross1000.turismo.marche.it/ws/checkinV2?wsdl
26 * @link Lombardia https://www.flussituristici.servizirl.it/Turismo5/app/ws/checkinV2?wsdl
27 * @link Calabria https://sirdat.regione.calabria.it/ws/checkinV2?wsdl
28 * @link Sardegna https://sardegnaturismo.ross1000.it/ws/checkinV2?wsdl
29 *
30 * @since 1.15.4 (J) - 1.5.10 (WP)
31 */
32 class VikBookingReportIstatRoss1000 extends VikBookingReport
33 {
34 /**
35 * Property 'defaultKeySort' is used by the View that renders the report.
36 */
37 public $defaultKeySort = 'idbooking';
38 /**
39 * Property 'defaultKeyOrder' is used by the View that renders the report.
40 */
41 public $defaultKeyOrder = 'ASC';
42 /**
43 * Property 'customExport' is used by the View to display custom export buttons.
44 */
45 public $customExport = '';
46 /**
47 * Debug mode is activated by passing the value 'e4j_debug' > 0
48 */
49 private $debug;
50
51 /**
52 * Other private vars of this sub-class.
53 */
54 private $comuniProvince;
55 private $nazioni;
56 private $documenti;
57 public $tipoTurismo;
58 public $mezzoDiTrasporto;
59
60 /**
61 * Class constructor should define the name of the report and
62 * other vars. Call the parent constructor to define the DB object.
63 */
64 public function __construct()
65 {
66 $this->reportFile = basename(__FILE__, '.php');
67 $this->reportName = JText::translate('ISTAT Ross 1000');
68 $this->reportFilters = array();
69
70 $this->cols = array();
71 $this->rows = array();
72 $this->footerRow = array();
73
74 $this->debug = (VikRequest::getInt('e4j_debug', 0, 'request') > 0);
75
76 $this->comuniProvince = array();
77 $this->nazioni = array();
78 $this->mezzoDiTrasporto = array(
79 '0' => 'Auto',
80 '1' => 'Aereo',
81 '2' => 'Aereo+Pullman',
82 '3' => 'Aereo+Navetta/Taxi/Auto',
83 '4' => 'Aereo+Treno',
84 '5' => 'Treno',
85 '6' => 'Pullman',
86 '7' => 'Caravan/Autocaravan',
87 '8' => 'Barca/Nave/Traghetto',
88 '9' => 'Moto',
89 '10' => 'Bicicletta',
90 '11' => 'A piedi',
91 '12' => 'Altro motivo',
92 '13' => 'Non specificato'
93 );
94 $this->tipoTurismo = array(
95 '0' => 'Culturale',
96 '1' => 'Balneare',
97 '2' => 'Congressuale/Affari',
98 '3' => 'Fieristico',
99 '4' => 'Sportivo/Fitness',
100 '5' => 'Scolastico',
101 '6' => 'Religioso',
102 '7' => 'Sociale',
103 '8' => 'Parchi Tematici',
104 '9' => 'Termale/Trattamenti salute',
105 '10' => 'Enogastronomico',
106 '11' => 'Cicloturismo',
107 '12' => 'Escursionistico/Naturalistico',
108 '13' => 'Altro motivo',
109 '14' => 'Non specificato'
110 );
111
112 $this->registerExportFileName();
113
114 parent::__construct();
115 }
116
117 /**
118 * Returns the name of this report.
119 *
120 * @return string
121 */
122 public function getName()
123 {
124 return $this->reportName;
125 }
126
127 /**
128 * Returns the name of this file without .php.
129 *
130 * @return string
131 */
132 public function getFileName()
133 {
134 return $this->reportFile;
135 }
136
137 /**
138 * Returns the filters of this report.
139 *
140 * @return array
141 */
142 public function getFilters()
143 {
144 if (count($this->reportFilters)) {
145 //do not run this method twice, as it could load JS and CSS files.
146 return $this->reportFilters;
147 }
148 $doc = JFactory::getDocument();
149 $css = '.vbo-report-load-trasporto span,
150 .vbo-report-load-turismo span {
151 display: inline-block;
152 border: 1px solid #dd0000;
153 cursor: pointer;
154 color: #dd0000;
155 padding: 0px 7px;
156 }';
157 $doc->addStyleDeclaration($css);
158 //get VBO Application Object
159 $vbo_app = VikBooking::getVboApplication();
160
161 //load the jQuery UI Datepicker
162 $this->loadDatePicker();
163
164 //custom export button
165 $this->customExport = '<a href="JavaScript: void(0);" onclick="vboDownloadSchedaIstat();" class="vbcsvexport"><i class="'.VikBookingIcons::i('download').'"></i> <span>Download File</span></a>';
166
167 //build the hidden values for the selection of Comuni & Province.
168 $this->comuniProvince = $this->loadComuniProvince();
169 $this->nazioni = $this->loadNazioni();
170 $hidden_vals = '<div id="vbo-report-alloggiati-hidden" style="display: none;">';
171 //Comuni
172 $hidden_vals .= ' <div id="vbo-report-alloggiati-comune" class="vbo-report-alloggiati-selcont" style="display: none;">';
173 $hidden_vals .= ' <select id="choose-comune" onchange="vboReportChosenComune(this);"><option value=""></option>';
174 if (isset($this->comuniProvince['comuni']) && count($this->comuniProvince['comuni'])) {
175 foreach ($this->comuniProvince['comuni'] as $code => $comune) {
176 $hidden_vals .= ' <option value="' . $code . '">' . (is_array($comune) ? $comune['name'] : '') . '</option>'."\n";
177 }
178 }
179 $hidden_vals .= ' </select>';
180 $hidden_vals .= ' </div>';
181 //
182 //Mezzi di Trasporto
183 $hidden_vals .= ' <div id="vbo-report-trasporto" class="vbo-report-alloggiati-selcont" style="display: none;">';
184 $hidden_vals .= ' <select id="choose-trasporto" onchange="vboReportChosenTrasporto(this);"><option value=""></option>';
185 foreach ($this->mezzoDiTrasporto as $key => $value) {
186 $hidden_vals .= ' <option value="'.$value.'">'.$value.'</option>'."\n";
187 }
188 $hidden_vals .= ' </select>';
189 $hidden_vals .= ' </div>';
190 //
191 //Tipo di turismo
192 $hidden_vals .= ' <div id="vbo-report-turismo" class="vbo-report-alloggiati-selcont" style="display: none;">';
193 $hidden_vals .= ' <select id="choose-turismo" onchange="vboReportChosenTurismo(this);"><option value=""></option>';
194 foreach ($this->tipoTurismo as $key => $value) {
195 $hidden_vals .= ' <option value="'.$value.'">'.$value.'</option>'."\n";
196 }
197 $hidden_vals .= ' </select>';
198 $hidden_vals .= ' </div>';
199 //
200 //Province
201 $hidden_vals .= ' <div id="vbo-report-alloggiati-provincia" class="vbo-report-alloggiati-selcont" style="display: none;">';
202 $hidden_vals .= ' <select id="choose-provincia" onchange="vboReportChosenProvincia(this);"><option value=""></option>';
203 if (isset($this->comuniProvince['province']) && count($this->comuniProvince['province'])) {
204 foreach ($this->comuniProvince['province'] as $code => $provincia) {
205 $hidden_vals .= ' <option value="'.$code.'">'.$provincia.'</option>'."\n";
206 }
207 }
208 $hidden_vals .= ' </select>';
209 $hidden_vals .= ' </div>';
210 //
211 //Nazioni
212 $hidden_vals .= ' <div id="vbo-report-alloggiati-nazione" class="vbo-report-alloggiati-selcont" style="display: none;">';
213 $hidden_vals .= ' <select id="choose-nazione" onchange="vboReportChosenNazione(this);"><option value=""></option>';
214 if (count($this->nazioni)) {
215 foreach ($this->nazioni as $code => $nazione) {
216 $hidden_vals .= ' <option value="'.$code.'">'.$nazione['name'].'</option>';
217 }
218 }
219 $hidden_vals .= ' </select>';
220 $hidden_vals .= ' </div>';
221 //
222 //Sesso
223 $hidden_vals .= ' <div id="vbo-report-alloggiati-sesso" class="vbo-report-alloggiati-selcont" style="display: none;">';
224 $hidden_vals .= ' <select id="choose-sesso" onchange="vboReportChosenSesso(this);"><option value=""></option>';
225 $sessos = array(
226 1 => 'M',
227 2 => 'F'
228 );
229 foreach ($sessos as $code => $ses) {
230 $hidden_vals .= ' <option value="'.$code.'">'.$ses.'</option>'."\n";
231 }
232 $hidden_vals .= ' </select>';
233 $hidden_vals .= ' </div>';
234 //
235 //Numero Documento
236 $hidden_vals .= ' <div id="vbo-report-alloggiati-docnum" class="vbo-report-alloggiati-selcont" style="display: none;">';
237 $hidden_vals .= ' <input type="text" size="40" id="choose-docnum" placeholder="Numero Documento..." value="" /><br/>';
238 $hidden_vals .= ' <button type="button" class="btn" onclick="vboReportChosenDocnum(document.getElementById(\'choose-docnum\').value);">'.JText::translate('VBAPPLY').'</button>';
239 $hidden_vals .= ' </div>';
240 //
241 //Data di Nascita
242 $hidden_vals .= ' <div id="vbo-report-alloggiati-dbirth" class="vbo-report-alloggiati-selcont" style="display: none;">';
243 $hidden_vals .= ' <input type="text" size="40" id="choose-dbirth" placeholder="Data di Nascita" value="" /><br/>';
244 $hidden_vals .= ' <button type="button" class="btn" onclick="vboReportChosenDbirth(document.getElementById(\'choose-dbirth\').value);">'.JText::translate('VBAPPLY').'</button>';
245 $hidden_vals .= ' </div>';
246 //
247 $hidden_vals .= '</div>';
248
249 //From Date Filter (with hidden values for the dropdown menus of Comuni, Province, Stati etc..)
250 $filter_opt = array(
251 'label' => '<label for="fromdate">'.JText::translate('VBOREPORTSDATEFROM').'</label>',
252 'html' => '<input type="text" id="fromdate" name="fromdate" value="" class="vbo-report-datepicker vbo-report-datepicker-from" />'.$hidden_vals,
253 'type' => 'calendar',
254 'name' => 'fromdate'
255 );
256 array_push($this->reportFilters, $filter_opt);
257
258 // To Date Filter
259 $filter_opt = array(
260 'label' => '<label for="todate">'.JText::translate('VBOREPORTSDATETO').'</label>',
261 'html' => '<input type="text" id="todate" name="todate" value="" class="vbo-report-datepicker vbo-report-datepicker-to" />',
262 'type' => 'calendar',
263 'name' => 'todate'
264 );
265 array_push($this->reportFilters, $filter_opt);
266
267 // apertura struttura
268 $papertura = VikRequest::getString('apertura', '', 'request');
269 $filter_opt = array(
270 'label' => '<label for="apertura">Apertura Struttura</label>',
271 '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>',
272 'type' => 'text',
273 'name' => 'apertura'
274 );
275 array_push($this->reportFilters, $filter_opt);
276
277 // Filtro Numero Letti
278 $pletti = VikRequest::getInt('numletti', 0, 'request');
279 $filter_opt = array(
280 'label' => '<label for="numletti">Numero Letti Disponibili</label>',
281 'html' => '<input type="number" id="numletti" name="numletti" value="'.$pletti.'" size="10" />',
282 'type' => 'text',
283 'name' => 'numletti'
284 );
285 array_push($this->reportFilters, $filter_opt);
286
287 // Filtro Codice Struttura
288 $pcodstru = VikRequest::getString('codstru', '', 'request');
289 $filter_opt = array(
290 'label' => '<label for="codstru">Codice Struttura</label>',
291 'html' => '<input type="text" id="codstru" name="codstru" value="'.$pcodstru.'" size="10" />',
292 'type' => 'text',
293 'name' => 'codstru'
294 );
295 array_push($this->reportFilters, $filter_opt);
296
297 // append button to save the data when creating manual values
298 $filter_opt = array(
299 'label' => '<label class="vbo-report-ross1000-manualsave" style="display: none;">' . JText::translate('VBOGUESTSDETAILS') . '</label>',
300 'html' => '<button type="button" class="btn vbo-config-btn vbo-report-ross1000-manualsave" style="display: none;" onclick="vboRoss1000SaveData();"><i class="' . VikBookingIcons::i('save') . '"></i> ' . JText::translate('VBSAVE') . '</button>',
301 );
302 array_push($this->reportFilters, $filter_opt);
303
304 // jQuery code for the datepicker calendars, select2 and triggers for the dropdown menus
305 $pfromdate = VikRequest::getString('fromdate', '', 'request');
306 $ptodate = VikRequest::getString('todate', '', 'request');
307
308 $js_ajax_base = VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=invoke_report&report=' . $this->reportFile);
309 $js_save_icn = VikBookingIcons::i('save');
310 $js_saving_icn = VikBookingIcons::i('circle-notch', 'fa-spin fa-fw');
311 $js_saved_icn = VikBookingIcons::i('check-circle');
312
313 $js = 'var reportActiveCell = null, reportObj = {};
314 var vbo_report_js_ajax_base = "' . $js_ajax_base . '";
315 var vbo_ross1000_save_icn = "' . $js_save_icn . '";
316 var vbo_ross1000_saving_icn = "' . $js_saving_icn . '";
317 var vbo_ross1000_saved_icn = "' . $js_saved_icn . '";
318 jQuery(function() {
319 // prepare main filters
320 jQuery(".vbo-report-datepicker:input").datepicker({
321 maxDate: "+1m",
322 dateFormat: "'.$this->getDateFormat('jui').'",
323 onSelect: vboReportCheckDates
324 });
325 '.(!empty($pfromdate) ? 'jQuery(".vbo-report-datepicker-from").datepicker("setDate", "'.$pfromdate.'");' : '').'
326 '.(!empty($ptodate) ? 'jQuery(".vbo-report-datepicker-to").datepicker("setDate", "'.$ptodate.'");' : '').'
327 // prepare filler helpers
328 jQuery("#vbo-report-alloggiati-hidden").children().detach().appendTo(".vbo-info-overlay-report");
329 jQuery("#choose-comune").select2({placeholder: "- Seleziona un Comune -", width: "200px"});
330 jQuery("#choose-provincia").select2({placeholder: "- Seleziona una Provincia -", width: "200px"});
331 jQuery("#choose-nazione").select2({placeholder: "- Seleziona una Nazione -", width: "200px"});
332 jQuery("#choose-sesso").select2({placeholder: "- Seleziona Sesso -", width: "200px"});
333 jQuery("#choose-turismo").select2({placeholder: "- Seleziona Tipo di Turismo -", width: "300px"});
334 jQuery("#choose-trasporto").select2({placeholder: "- Seleziona Mezzo di Trasporto -", width: "300px"});
335
336 jQuery("#choose-dbirth").datepicker({
337 maxDate: 0,
338 dateFormat: "dd/mm/yy",
339 changeMonth: true,
340 changeYear: true,
341 yearRange: "'.(date('Y') - 100).':'.date('Y').'"
342 });
343 // click events
344 jQuery(".vbo-report-load-comune").click(function() {
345 reportActiveCell = this;
346 jQuery(".vbo-report-alloggiati-selcont").hide();
347 jQuery("#vbo-report-alloggiati-comune").show();
348 vboShowOverlay();
349 });
350 jQuery(".vbo-report-load-provincia").click(function() {
351 reportActiveCell = this;
352 jQuery(".vbo-report-alloggiati-selcont").hide();
353 jQuery("#vbo-report-alloggiati-provincia").show();
354 vboShowOverlay();
355 });
356 jQuery(".vbo-report-load-nazione, .vbo-report-load-cittadinanza").click(function() {
357 reportActiveCell = this;
358 jQuery(".vbo-report-alloggiati-selcont").hide();
359 jQuery("#vbo-report-alloggiati-nazione").show();
360 vboShowOverlay();
361 });
362 jQuery(".vbo-report-load-sesso").click(function() {
363 reportActiveCell = this;
364 jQuery(".vbo-report-alloggiati-selcont").hide();
365 jQuery("#vbo-report-alloggiati-sesso").show();
366 vboShowOverlay();
367 });
368 jQuery(".vbo-report-load-turismo").click(function() {
369 reportActiveCell = this;
370 jQuery(".vbo-report-alloggiati-selcont").hide();
371 jQuery("#vbo-report-turismo").show();
372 vboShowOverlay();
373 });
374 jQuery(".vbo-report-load-trasporto").click(function() {
375 reportActiveCell = this;
376 jQuery(".vbo-report-alloggiati-selcont").hide();
377 jQuery("#vbo-report-trasporto").show();
378 vboShowOverlay();
379 });
380 jQuery(".vbo-report-load-dbirth").click(function() {
381 reportActiveCell = this;
382 jQuery(".vbo-report-alloggiati-selcont").hide();
383 jQuery("#vbo-report-alloggiati-dbirth").show();
384 vboShowOverlay();
385 // pretend the overlay is off, or navigating in the datepicker will close the modal.
386 setTimeout(function(){vbo_overlay_on = false;}, 800);
387 });
388 });
389
390 function vboReportCheckDates(selectedDate, inst) {
391 if (selectedDate === null || inst === null) {
392 return;
393 }
394 var cur_from_date = jQuery(this).val();
395 if (jQuery(this).hasClass("vbo-report-datepicker-from") && cur_from_date.length) {
396 var nowstart = jQuery(this).datepicker("getDate");
397 var nowstartdate = new Date(nowstart.getTime());
398 jQuery(".vbo-report-datepicker-to").datepicker("option", {minDate: nowstartdate});
399 }
400 }
401
402 function vboReportChosenComune(comune) {
403 var c_code = comune.value;
404 var c_val = comune.options[comune.selectedIndex].text;
405 if (reportActiveCell !== null) {
406 var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr"));
407 if (isNaN(nowindex) || parseInt(nowindex) < 0) {
408 alert("Error, cannot find element to update.");
409 } else {
410 var rep_act_cell = jQuery(reportActiveCell);
411 rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val);
412 var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid");
413 if (!reportObj.hasOwnProperty(nowindex)) {
414 reportObj[nowindex] = {
415 bid: rep_guest_bid,
416 bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr"))
417 };
418 }
419 if (jQuery(reportActiveCell).hasClass("vbo-report-load-docplace")) {
420 reportObj[nowindex]["docplace"] = c_code;
421 } else {
422 reportObj[nowindex]["comune_s"] = c_code;
423 }
424 }
425 }
426 reportActiveCell = null;
427 vboHideOverlay();
428 jQuery("#choose-comune").val("").select2("data", null, false);
429 jQuery(".vbo-report-ross1000-manualsave").show();
430 }
431
432 function vboReportChosenProvincia(prov) {
433 var c_code = prov.value;
434 var c_val = prov.options[prov.selectedIndex].text;
435 if (reportActiveCell !== null) {
436 var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr"));
437 if (isNaN(nowindex) || parseInt(nowindex) < 0) {
438 alert("Error, cannot find element to update.");
439 } else {
440 var rep_act_cell = jQuery(reportActiveCell);
441 rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val);
442 var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid");
443 if (!reportObj.hasOwnProperty(nowindex)) {
444 reportObj[nowindex] = {
445 bid: rep_guest_bid,
446 bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr"))
447 };
448 }
449 reportObj[nowindex]["comune_s"] = c_code;
450 }
451 }
452 reportActiveCell = null;
453 vboHideOverlay();
454 jQuery("#choose-provincia").val("").select2("data", null, false);
455 jQuery(".vbo-report-ross1000-manualsave").show();
456 }
457
458 function vboReportChosenNazione(naz) {
459 var c_code = naz.value;
460 var c_val = naz.options[naz.selectedIndex].text;
461 if (reportActiveCell !== null) {
462 var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr"));
463 if (isNaN(nowindex) || parseInt(nowindex) < 0) {
464 alert("Error, cannot find element to update.");
465 } else {
466 var rep_act_cell = jQuery(reportActiveCell);
467 rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val);
468 var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid");
469 if (!reportObj.hasOwnProperty(nowindex)) {
470 reportObj[nowindex] = {
471 bid: rep_guest_bid,
472 bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr"))
473 };
474 }
475 if (jQuery(reportActiveCell).hasClass("vbo-report-load-nazione")) {
476 reportObj[nowindex]["country_s"] = c_code;
477 } else if (jQuery(reportActiveCell).hasClass("vbo-report-load-docplace")) {
478 reportObj[nowindex]["docplace"] = c_code;
479 } else {
480 reportObj[nowindex]["country_c"] = c_code;
481 }
482 }
483 }
484 reportActiveCell = null;
485 vboHideOverlay();
486 jQuery("#choose-nazione").val("").select2("data", null, false);
487 jQuery(".vbo-report-ross1000-manualsave").show();
488 }
489
490 function vboReportChosenSesso(sesso) {
491 var c_code = sesso.value;
492 var c_val = sesso.options[sesso.selectedIndex].text;
493 if (reportActiveCell !== null) {
494 var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr"));
495 if (isNaN(nowindex) || parseInt(nowindex) < 0) {
496 alert("Error, cannot find element to update.");
497 } else {
498 var rep_act_cell = jQuery(reportActiveCell);
499 rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val);
500 var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid");
501 if (!reportObj.hasOwnProperty(nowindex)) {
502 reportObj[nowindex] = {
503 bid: rep_guest_bid,
504 bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr"))
505 };
506 }
507 reportObj[nowindex]["gender"] = c_code;
508 }
509 }
510 reportActiveCell = null;
511 vboHideOverlay();
512 jQuery("#choose-sesso").val("").select2("data", null, false);
513 jQuery(".vbo-report-ross1000-manualsave").show();
514 }
515
516 function vboReportChosenTrasporto(trasporto) {
517 var c_code = trasporto.value;
518 var c_val = trasporto.options[trasporto.selectedIndex].text;
519 if (reportActiveCell !== null) {
520 var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr"));
521 if (isNaN(nowindex) || parseInt(nowindex) < 0) {
522 alert("Error, cannot find element to update.");
523 } else {
524 var rep_act_cell = jQuery(reportActiveCell);
525 rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val);
526 var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid");
527 if (!reportObj.hasOwnProperty(nowindex)) {
528 reportObj[nowindex] = {
529 bid: rep_guest_bid,
530 bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr"))
531 };
532 }
533 reportObj[nowindex]["mezzo"] = c_code;
534 }
535 }
536 reportActiveCell = null;
537 vboHideOverlay();
538 jQuery("#choose-trasporto").val("").select2("data", null, false);
539 jQuery(".vbo-report-ross1000-manualsave").show();
540 }
541
542 function vboReportChosenTurismo(turismo) {
543 var c_code = turismo.value;
544 var c_val = turismo.options[turismo.selectedIndex].text;
545 if (reportActiveCell !== null) {
546 var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr"));
547 if (isNaN(nowindex) || parseInt(nowindex) < 0) {
548 alert("Error, cannot find element to update.");
549 } else {
550 var rep_act_cell = jQuery(reportActiveCell);
551 rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val);
552 var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid");
553 if (!reportObj.hasOwnProperty(nowindex)) {
554 reportObj[nowindex] = {
555 bid: rep_guest_bid,
556 bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr"))
557 };
558 }
559 reportObj[nowindex]["turismo"] = c_code;
560 }
561 }
562 reportActiveCell = null;
563 vboHideOverlay();
564 jQuery("#choose-turismo").val("").select2("data", null, false);
565 jQuery(".vbo-report-ross1000-manualsave").show();
566 }
567
568 function vboReportChosenDbirth(val) {
569 var c_code = val, c_val = val;
570 if (reportActiveCell !== null) {
571 var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr"));
572 if (isNaN(nowindex) || parseInt(nowindex) < 0) {
573 alert("Error, cannot find element to update.");
574 } else {
575 var rep_act_cell = jQuery(reportActiveCell);
576 rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val);
577 var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid");
578 if (!reportObj.hasOwnProperty(nowindex)) {
579 reportObj[nowindex] = {
580 bid: rep_guest_bid,
581 bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr"))
582 };
583 }
584 reportObj[nowindex]["date_birth"] = c_code;
585 }
586 }
587 reportActiveCell = null;
588 vboHideOverlay();
589 jQuery("#choose-dbirth").val("");
590 jQuery(".vbo-report-ross1000-manualsave").show();
591 }
592
593 // download function
594 function vboDownloadSchedaIstat() {
595 if (!confirm("Sei sicuro di aver compilato tutti i dati?")) {
596 return false;
597 }
598 document.adminForm.target = "_blank";
599 document.adminForm.action += "&tmpl=component";
600 vboSetFilters({exportreport: "1", filler: JSON.stringify(reportObj)}, true);
601 setTimeout(function() {
602 document.adminForm.target = "";
603 document.adminForm.action = document.adminForm.action.replace("&tmpl=component", "");
604 vboSetFilters({exportreport: "0", filler: ""}, false);
605 }, 1000);
606 }
607
608 // save data after manual fillers
609 function vboRoss1000SaveData() {
610 jQuery("button.vbo-report-ross1000-manualsave").find("i").attr("class", vbo_ross1000_saving_icn);
611 VBOCore.doAjax(
612 vbo_report_js_ajax_base,
613 {
614 call: "updatePaxData",
615 params: reportObj,
616 tmpl: "component"
617 },
618 (response) => {
619 if (!response || !response[0]) {
620 alert("An error occurred.");
621 return false;
622 }
623 jQuery("button.vbo-report-ross1000-manualsave").addClass("btn-success").find("i").attr("class", vbo_ross1000_saved_icn);
624 },
625 (error) => {
626 alert(error.responseText);
627 jQuery("button.vbo-report-ross1000-manualsave").removeClass("btn-success").find("i").attr("class", vbo_ross1000_save_icn);
628 }
629 );
630 }';
631 $this->setScript($js);
632
633 return $this->reportFilters;
634 }
635
636 /**
637 * Loads the report data from the DB.
638 * Returns true in case of success, false otherwise.
639 * Sets the columns and rows for the report to be displayed.
640 *
641 * @return boolean
642 */
643 public function getReportData()
644 {
645 if (strlen($this->getError())) {
646 //Export functions may set errors rather than exiting the process, and the View may continue the execution to attempt to render the report.
647 return false;
648 }
649 //Input fields and other vars
650 $pfromdate = VikRequest::getString('fromdate', '', 'request');
651 $ptodate = VikRequest::getString('todate', '', 'request');
652 $pkrsort = VikRequest::getString('krsort', $this->defaultKeySort, 'request');
653 $pkrsort = empty($pkrsort) ? $this->defaultKeySort : $pkrsort;
654 $pkrorder = VikRequest::getString('krorder', $this->defaultKeyOrder, 'request');
655 $pkrorder = empty($pkrorder) ? $this->defaultKeyOrder : $pkrorder;
656 $pkrorder = $pkrorder == 'DESC' ? 'DESC' : 'ASC';
657 $pcodstru = VikRequest::getString('codstru', '', 'request');
658 $papertura = VikRequest::getString('apertura', '', 'request');
659
660 $q = "SELECT SUM(`units`) AS `sommaunita`, SUM(`totpeople`) AS `numeropersone`, COUNT(*) AS `numerocamere` FROM `#__vikbooking_rooms` WHERE `avail`= '1';";
661 $this->dbo->setQuery($q);
662 $records = $this->dbo->loadAssocList();
663 if (!$records) {
664 return false;
665 }
666
667 $totalBeds = (int)($records[0]['sommaunita'] * ($records[0]['numeropersone'] / $records[0]['numerocamere']));
668 $pletti = VikRequest::getString('numletti', $totalBeds, 'request');
669 $currency_symb = VikBooking::getCurrencySymb();
670 $df = $this->getDateFormat();
671 $datesep = VikBooking::getDateSeparator();
672 if (empty($ptodate)) {
673 $ptodate = $pfromdate;
674 }
675 //Get dates timestamps
676 $from_ts = VikBooking::getDateTimestamp($pfromdate, 0, 0);
677 $to_ts = VikBooking::getDateTimestamp($ptodate, 23, 59, 59);
678 if (empty($pfromdate) || empty($from_ts) || empty($to_ts)) {
679 $this->setError(JText::translate('VBOREPORTSERRNODATES'));
680 return false;
681 }
682 if (empty($pcodstru)) {
683 $this->setError('Inserisci il codice della tua Struttura.<br/>Si tratta di un codice univoco di identificazione che ti viene assegnato dall\'Amministrazione competente.');
684 return false;
685 }
686 if (empty($papertura)) {
687 $this->setError('Devi specificare se la tua struttura è aperta o meno attraverso il menù a tendina qui sopra.');
688 return false;
689 }
690 //Query to obtain the records (all check-ins within the dates filter)
691 $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`,".
692 "`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`,".
693 "`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` ".
694 "FROM `#__vikbooking_orders` AS `o` LEFT JOIN `#__vikbooking_ordersrooms` AS `or` ON `or`.`idorder`=`o`.`id` ".
695 "LEFT JOIN `#__vikbooking_customers_orders` AS `co` ON `co`.`idorder`=`o`.`id` LEFT JOIN `#__vikbooking_customers` AS `c` ON `c`.`id`=`co`.`idcustomer` ".
696 "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.")) ".
697 "ORDER BY `o`.`checkin` ASC, `o`.`id` ASC;";
698 $this->dbo->setQuery($q);
699 $records = $this->dbo->loadAssocList();
700 if (!$records) {
701 $this->setError(JText::translate('VBOREPORTSERRNORESERV'));
702 $this->setError('Nessun check-in nelle date selezionate.');
703 return false;
704 }
705
706 //nest records with multiple rooms booked inside sub-array
707 $bookings = array();
708 foreach ($records as $v) {
709 if (!isset($bookings[$v['id']])) {
710 $bookings[$v['id']] = array();
711 }
712 array_push($bookings[$v['id']], $v);
713 }
714 //define the columns of the report
715 $this->cols = array(
716 //id booking
717 array(
718 'key' => 'idbooking',
719 'attr' => array(
720 'class="center"'
721 ),
722 'label' => 'ID',
723 'sortable' => 1,
724 ),
725 //check-in
726 array(
727 'key' => 'checkin',
728 'attr' => array(
729 'class="center"'
730 ),
731 'sortable' => 1,
732 'label' => JText::translate('VBPICKUPAT')
733 ),
734 //checkout
735 array(
736 'key' => 'checkout',
737 'attr' => array(
738 'class="center"'
739 ),
740 'sortable' => 1,
741 'label' => 'Partenza'
742 ),
743 //cognome
744 array(
745 'key' => 'cognome',
746 'label' => JText::translate('VBTRAVELERLNAME'),
747 'sortable' => 1,
748 ),
749 //nome
750 array(
751 'key' => 'nome',
752 'label' => JText::translate('VBTRAVELERNAME'),
753 'sortable' => 1,
754 ),
755 //sesso
756 array(
757 'key' => 'gender',
758 'attr' => array(
759 'class="center"'
760 ),
761 'label' => JText::translate('VBCUSTOMERGENDER')
762 ),
763 //data di nascita
764 array(
765 'key' => 'dbirth',
766 'attr' => array(
767 'class="center"'
768 ),
769 'label' => JText::translate('VBCUSTOMERBDATE')
770 ),
771 //cittadinanza
772 array(
773 'key' => 'citizen',
774 'attr' => array(
775 'class="center"'
776 ),
777 'sortable' => 1,
778 'label' => 'Cittadinanza'
779 ),
780 //cittadinanza
781 array(
782 'key' => 'stares',
783 'attr' => array(
784 'class="center"'
785 ),
786 'sortable' => 1,
787 'label' => 'Stato di Residenza'
788 ),
789 //comune di residenza
790 array(
791 'key' => 'comres',
792 'attr' => array(
793 'class="center"'
794 ),
795 'sortable' => 1,
796 'label' => 'Comune Residenza',
797 'tip' => 'Inserire il comune di residenza solo se il cittadino è di nazionalità italiana.'
798 ),
799 //tipo
800 array(
801 'key' => 'tipo',
802 'attr' => array(
803 'class="vbo-report-longlbl"'
804 ),
805 'label' => 'Tipo Alloggiato'
806 ),
807 // tipo di trasporto
808 array(
809 'key' => 'mezzo',
810 'attr' => array(
811 'class="center"'
812 ),
813 'label' => 'Mezzo di Trasporto'
814 ),
815 // tipo di turismo
816 array(
817 'key' => 'turismo',
818 'attr' => array(
819 'class="center"'
820 ),
821 'label' => 'Tipo di Turismo'
822 ),
823 //quantità (numero di ospiti)
824 array(
825 'key' => 'guestsnum',
826 'attr' => array(
827 'class="center"'
828 ),
829 'sortable' => 1,
830 'label' => 'Numero Ospiti',
831 'tip' => 'Il numero di ospiti totali (adulti + bambini) per ogni prenotazione è un dato che verrà comunicato all\'ISTAT.',
832 ),
833 array(
834 'key' => 'roomsbooked',
835 'attr' => array(
836 'class="center"'
837 ),
838 'sortable' => 1,
839 'label' => 'Occupazione',
840 'tip' => 'Questo valore indica il numero di camere occupate da ogni prenotazione, ed è un dato che verrà comunicato all\'ISTAT.',
841 ),
842 );
843
844 // loop over the bookings to build the rows of the report
845 $from_info = getdate($from_ts);
846 foreach ($bookings as $gbook) {
847 $guestsnum = 0;
848 $guests_rows = array($gbook[0]);
849 $room_guests = array();
850 $tot_guests_rows = 1;
851
852 $tipo = 16;
853 // Codici Tipo Alloggiato
854 // 16 = Ospite Singolo
855 // 17 = Capofamiglia
856 // 18 = Capogruppo
857 // 19 = Familiare
858 // 20 = Membro Gruppo
859
860 foreach ($gbook as $book) {
861 $guestsnum += $book['adults'] + $book['children'];
862 $room_guests[] = ($book['adults'] + $book['children']);
863 }
864 $pax_data = null;
865 if (!empty($gbook[0]['pax_data'])) {
866 $pax_data = json_decode($gbook[0]['pax_data'], true);
867 if (is_array($pax_data) && count($pax_data)) {
868 $guests_rows[0]['pax_data'] = $pax_data;
869 $tot_guests_rows = 0;
870 foreach ($pax_data as $roomguests) {
871 $tot_guests_rows += count($roomguests);
872 }
873 for ($i = 1; $i < $tot_guests_rows; $i++) {
874 array_push($guests_rows, $guests_rows[0]);
875 }
876 $tipo = count($guests_rows) > 1 ? 17 : $tipo;
877 }
878 }
879
880 //create one row for each guest
881 $guest_ind = 1;
882 foreach ($guests_rows as $ind => $guests) {
883 // prepare row record
884 $insert_row = array();
885
886 // find the actual guest-room-index
887 $guest_room_ind = $this->calcGuestRoomIndex($room_guests, $guest_ind);
888
889 // booking ID
890 array_push($insert_row, array(
891 'key' => 'idbooking',
892 'attr' => array(
893 'class="center"'
894 ),
895 'callback' => function ($val) {
896 // make sure to keep the data-bid attribute as it's used by JS to identify the booking ID
897 return '<a data-bid="' . $val . '" href="index.php?option=com_vikbooking&task=editorder&cid[]=' . $val . '" target="_blank"><i class="' . VikBookingIcons::i('external-link') . '"></i> ' . $val . '</a>';
898 },
899 'callback_export' => function ($val) {
900 return $val;
901 },
902 'value' => $guests['id']
903 ));
904
905 // checkin date
906 array_push($insert_row, array(
907 'key' => 'checkin',
908 'attr' => array(
909 'class="center"'
910 ),
911 'callback' => function ($val) {
912 return date('d/m/Y', $val);
913 },
914 'value' => $guests['checkin']
915 ));
916
917 // checkout date
918 array_push($insert_row,array(
919 'key' => 'checkout',
920 'attr' => array(
921 'class="center"'
922 ),
923 'callback' => function ($val) {
924 return date('d/m/Y', $val);
925 },
926 'value' => $gbook[0]['checkout']
927 ));
928
929 // cognome
930 $cognome = !empty($guests['t_last_name']) ? $guests['t_last_name'] : $guests['last_name'];
931 $pax_cognome = $this->getGuestPaxDataValue($pax_data, $room_guests, $guest_ind, 'last_name');
932 $cognome = !empty($pax_cognome) ? $pax_cognome : $cognome;
933 array_push($insert_row, array(
934 'key' => 'cognome',
935 'value' => $cognome
936 ));
937
938 // nome
939 $nome = !empty($guests['t_first_name']) ? $guests['t_first_name'] : $guests['first_name'];
940 $pax_nome = $this->getGuestPaxDataValue($pax_data, $room_guests, $guest_ind, 'first_name');
941 $nome = !empty($pax_nome) ? $pax_nome : $nome;
942 array_push($insert_row, array(
943 'key' => 'nome',
944 'value' => $nome
945 ));
946
947 // sesso
948 $gender = !empty($guests['gender']) && $guest_ind < 2 ? strtoupper($guests['gender']) : '';
949 $gender = $gender == 'F' ? 2 : ($gender == 'M' ? 1 : $gender);
950 $pax_gender = $this->getGuestPaxDataValue($pax_data, $room_guests, $guest_ind, 'gender');
951 $gender = !empty($pax_gender) ? $pax_gender : $gender;
952 if (is_numeric($gender)) {
953 $gender = (int)$gender;
954 } elseif (!strcasecmp($gender, 'F')) {
955 $gender = 2;
956 } elseif (!strcasecmp($gender, 'M')) {
957 $gender = 1;
958 }
959 array_push($insert_row, array(
960 'key' => 'gender',
961 'attr' => array(
962 'class="center'.(empty($gender) ? ' vbo-report-load-sesso' : '').'"'
963 ),
964 'callback' => function ($val) {
965 return $val == 2 ? 'F' : ($val == 1 ? 'M' : '?');
966 },
967 'callback_export' => function ($val) {
968 return $val == 2 ? 'F' : ($val == 1 ? 'M' : '?');
969 },
970 'value' => $gender
971 ));
972
973 // data di nascita
974 $dbirth = !empty($guests['bdate']) && $guest_ind < 2 ? VikBooking::getDateTimestamp($guests['bdate'], 0, 0) : '';
975 $pax_dbirth = $this->getGuestPaxDataValue($pax_data, $room_guests, $guest_ind, 'date_birth');
976 $dbirth = !empty($pax_dbirth) ? $pax_dbirth : $dbirth;
977 $dbirth = (strpos($dbirth, '/') === false && strpos($dbirth, VikBooking::getDateSeparator()) === false) ? $dbirth : VikBooking::getDateTimestamp($dbirth, 0, 0);
978 array_push($insert_row, array(
979 'key' => 'dbirth',
980 'attr' => array(
981 'class="center'.(empty($dbirth) ? ' vbo-report-load-dbirth' : '').'"'
982 ),
983 'callback' => function ($val) {
984 if (!empty($val) && strpos($val, '/') === false && strpos($val, VikBooking::getDateSeparator()) === false) {
985 return date('d/m/Y', $val);
986 }
987 if (!empty($val) && strpos($val, '/') !== false) {
988 return $val;
989 }
990 return '?';
991 },
992 'no_export_callback' => 1,
993 'value' => $dbirth
994 ));
995
996 // cittadinanza (compatible with pax data field of driver "Italy")
997 $pax_country_c = $this->getGuestPaxDataValue($pax_data, $room_guests, $guest_ind, 'country_c');
998 $citizen = !empty($guests['country']) && $guest_ind < 2 ? $guests['country'] : '';
999 $citizenval = '';
1000 if (!empty($citizen) && $guest_ind < 2) {
1001 $citizenval = $this->checkCountry($citizen);
1002 }
1003
1004 // check nationality field from pre-checkin
1005 $pax_citizen = $this->getGuestPaxDataValue($pax_data, $room_guests, $guest_ind, 'nationality');
1006 $citizen = !empty($pax_citizen) ? $pax_citizen : $citizen;
1007 $citizen = !empty($pax_country_c) ? $pax_country_c : $citizen;
1008 $citizenval = $this->checkCountry((!empty($pax_country_c) ? $pax_country_c : $citizen));
1009 array_push($insert_row, array(
1010 'key' => 'citizen',
1011 'attr' => array(
1012 'class="center'.(empty($citizen) ? ' vbo-report-load-cittadinanza' : '').'"'
1013 ),
1014 'callback' => function ($val) {
1015 return !empty($val) && isset($this->nazioni[$val]) ? $this->nazioni[$val]['name'] : '?';
1016 },
1017 'no_export_callback' => 1,
1018 'value' => !empty($citizenval) ? $citizenval : ''
1019 ));
1020
1021 // stato di residenza
1022 $provstay = '';
1023 $pax_provstay = $this->getGuestPaxDataValue($pax_data, $room_guests, $guest_ind, ($guest_ind < 2 ? 'country_s' : 'country_b'));
1024 $provstay = !empty($pax_provstay) ? $pax_provstay : $provstay;
1025 array_push($insert_row, array(
1026 'key' => 'stares',
1027 'attr' => array(
1028 'class="center'.(empty($provstay) ? ' vbo-report-load-nazione' : '').'"'
1029 ),
1030 'callback' => function($val) {
1031 if (!empty($val) && isset($this->nazioni[$val])) {
1032 return $this->nazioni[$val]['name'];
1033 }
1034 // information is missing and should be provided
1035 return '?';
1036 },
1037 'no_export_callback' => 1,
1038 'value' => $provstay
1039 ));
1040
1041 // comune di residenza
1042 $comstay = '';
1043 $pax_comstay = $this->getGuestPaxDataValue($pax_data, $room_guests, $guest_ind, 'comune_s');
1044 $comstay = !empty($pax_comstay) ? $pax_comstay : $comstay;
1045 array_push($insert_row, array(
1046 'key' => 'comres',
1047 'attr' => array(
1048 'class="center'.(empty($comstay) ? ' vbo-report-load-comune' : '').'"'
1049 ),
1050 'callback' => function($val) {
1051 if (!empty($val) && isset($this->comuniProvince['comuni'][$val])) {
1052 return $this->comuniProvince['comuni'][$val]['name'];
1053 }
1054 // information is missing and should be provided
1055 return '?';
1056 },
1057 'no_export_callback' => 1,
1058 'value' => $comstay
1059 ));
1060
1061 // tipo alloggiato
1062 $use_tipo = $ind > 0 && $tipo == 17 ? 19 : $tipo;
1063 $pax_guest_type = $this->getGuestPaxDataValue($pax_data, $room_guests, $guest_ind, 'guest_type');
1064 $use_tipo = !empty($pax_guest_type) ? $pax_guest_type : $use_tipo;
1065 array_push($insert_row, array(
1066 'key' => 'tipo',
1067 'callback' => function ($val) {
1068 switch ($val) {
1069 case 16:
1070 return 'Ospite Singolo';
1071 case 17:
1072 return 'Capofamiglia';
1073 case 18:
1074 return 'Capogruppo';
1075 case 19:
1076 return 'Familiare';
1077 case 20:
1078 return 'Membro Gruppo';
1079 }
1080 return '?';
1081 },
1082 'no_export_callback' => 1,
1083 'value' => $use_tipo
1084 ));
1085
1086 // mezzo di trasporto
1087 $pax_mezzo = $this->getGuestPaxDataValue($pax_data, $room_guests, $guest_ind, 'mezzo');
1088 array_push($insert_row, array(
1089 'key' => 'mezzo',
1090 'attr' => array(
1091 'class="center' . (empty($pax_mezzo) ? ' vbo-report-load-trasporto' : '') . '"'
1092 ),
1093 'value' => ($pax_mezzo ? $pax_mezzo : '?')
1094 ));
1095
1096 // tipo di turismo
1097 $pax_turismo = $this->getGuestPaxDataValue($pax_data, $room_guests, $guest_ind, 'turismo');
1098 array_push($insert_row, array(
1099 'key' => 'turismo',
1100 'attr' => array(
1101 'class="center' . (empty($pax_turismo) ? ' vbo-report-load-turismo' : '') . '"'
1102 ),
1103 'value' => ($pax_turismo ? $pax_turismo : '?')
1104 ));
1105
1106 // numero persone in prenotazione
1107 array_push($insert_row, array(
1108 'key' => 'guestsnum',
1109 'attr' => array(
1110 'class="center"'
1111 ),
1112 'value' => $guestsnum
1113 ));
1114
1115 // camere prenotate
1116 array_push($insert_row, array(
1117 'key' => 'roomsbooked',
1118 'attr' => array(
1119 'class="center"'
1120 ),
1121 'value' => count($gbook)
1122 ));
1123
1124 // push fields in the rows array as a new row
1125 array_push($this->rows, $insert_row);
1126
1127 // increment guest index
1128 $guest_ind++;
1129 }
1130 }
1131
1132 // do not sort the rows for this report because the lines of the guests of the same booking must be consecutive
1133 // $this->sortRows($pkrsort, $pkrorder);
1134
1135 // the footer row will just print the amount of records to export
1136 array_push($this->footerRow, array(
1137 array(
1138 'attr' => array(
1139 'class="vbo-report-total"'
1140 ),
1141 'value' => '<h3>'.JText::translate('VBOREPORTSTOTALROW').'</h3>'
1142 ),
1143 array(
1144 'attr' => array(
1145 'colspan="'.(count($this->cols) - 1).'"'
1146 ),
1147 'value' => count($this->rows)
1148 )
1149 ));
1150
1151 // Debug
1152 if ($this->debug) {
1153 $this->setWarning('path to report file = '.urlencode(dirname(__FILE__)).'<br/>');
1154 $this->setWarning('$total_rooms_units = '.$total_rooms_units.'<br/>');
1155 $this->setWarning('$bookings:<pre>'.print_r($bookings, true).'</pre><br/>');
1156 }
1157
1158 return true;
1159 }
1160
1161 public function formatXML(&$xml)
1162 {
1163 if (!class_exists('DOMDocument')) {
1164 // we cannot format the XML because DOMDocument is missing
1165 return $xml;
1166 }
1167
1168 $dom = new DOMDocument;
1169 $dom->preserveWhiteSpace = false;
1170 $dom->loadXML($xml);
1171 $dom->formatOutput = true;
1172 $xml = $dom->saveXML();
1173
1174 return $xml;
1175 }
1176
1177 /**
1178 * Generates the report columns and rows, then it outputs a CSV file
1179 * for download. In case of errors, the process is not terminated (exit)
1180 * to let the View display the error message.
1181 * We use customExport() rather than exportCSV() only because we need a
1182 * different download button rather than the classic "Export as CSV".
1183 *
1184 * @param int $export_type the view will pass this argument to the method to call different types of export.
1185 *
1186 * @return mixed void on success with script termination, false otherwise.
1187 */
1188 public function customExport($export_type = 0)
1189 {
1190 if (!$this->getReportData()) {
1191 return false;
1192 }
1193
1194 $pfromdate = VikRequest::getString('fromdate', '', 'request');
1195 $ptodate = VikRequest::getString('todate', '', 'request');
1196 $pcodstru = VikRequest::getString('codstru', '', 'request');
1197 $papertura = VikRequest::getString('apertura', '', 'request');
1198
1199 $q = "SELECT SUM(`units`) AS `sommaunita`, SUM(`totpeople`) AS `numeropersone`, COUNT(*) AS `numerocamere` FROM `#__vikbooking_rooms` WHERE `avail`= '1';";
1200 $this->dbo->setQuery($q);
1201 $records = $this->dbo->loadAssocList();
1202
1203 $totalBeds = (int)($records[0]['sommaunita'] * ($records[0]['numeropersone']/$records[0]['numerocamere']));
1204 // filtro numero letti
1205 $pletti = VikRequest::getString('numletti', $totalBeds, 'request');
1206
1207 // manual values in filler
1208 $pfiller = VikRequest::getString('filler', '', 'request', VIKREQUEST_ALLOWRAW);
1209 $pfiller = !empty($pfiller) ? json_decode($pfiller, true) : array();
1210 $pfiller = !is_array($pfiller) ? array() : $pfiller;
1211
1212 // Debug
1213 if ($this->debug) {
1214 $this->setError('<pre>'.print_r($pfiller, true).'</pre><br/>');
1215 return false;
1216 }
1217
1218 $q = "SELECT SUM(`units`) FROM `#__vikbooking_rooms` WHERE `avail`= '1';";
1219 $this->dbo->setQuery($q);
1220 $this->dbo->execute();
1221 $totalRooms = $this->dbo->loadResult();
1222
1223 // pool of booking IDs to update their history
1224 $booking_ids = [];
1225 // update the history for all bookings affected
1226 foreach ($booking_ids as $bid) {
1227 VikBooking::getBookingHistoryInstance()->setBid($bid)->store('RP', $this->reportName);
1228 }
1229 $date = str_replace('/', '-', $pfromdate);
1230 $dataMovim = date('Ymd', strtotime($date));
1231
1232 $xml = '<?xml version="1.0" encoding="UTF-8"?>'."\n".'<movimenti>'."\n".'<codice>'.$pcodstru.'</codice>'."\n".'<prodotto>VikBooking</prodotto>'."\n".'<movimento>'."\n".'<data>'.$dataMovim.'</data>'."\n";
1233 $numOccupiedrooms = 0;
1234
1235 $from_ts = VikBooking::getDateTimestamp($pfromdate, 0, 0);
1236 $to_ts = VikBooking::getDateTimestamp($pfromdate, 23, 59, 59);
1237
1238 $clienti = [
1239 'arrivi' => [],
1240 'partenze' => [],
1241 'prenotazioni' => [],
1242 ];
1243
1244 $q = "SELECT COUNT(`o`.`id`) AS `occ_rooms`,".
1245 "(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` ".
1246 "FROM `#__vikbooking_orders` AS `o` LEFT JOIN `#__vikbooking_ordersrooms` AS `or` ON `or`.`idorder`=`o`.`id` ".
1247 "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` ".
1248 "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.")) ".
1249 "ORDER BY `o`.`checkin` ASC, `o`.`id` ASC;";
1250
1251 $this->dbo->setQuery($q);
1252 $data = $this->dbo->loadAssoc();
1253
1254 $arrivi = 0;
1255 $partenze = 0;
1256 $prenotazioni = 0;
1257
1258 if ($papertura == 'SI') {
1259 $xml .= '<struttura>' . "\n";
1260 $xml .= '<apertura>' . $papertura . '</apertura>' . "\n";
1261 $xml .= '<camereoccupate>' . $data['occ_rooms'] . '</camereoccupate>' . "\n";
1262 $xml .= '<cameredisponibili>' . $totalRooms . '</cameredisponibili>' . "\n";
1263 $xml .= '<lettidisponibili>' . $pletti . '</lettidisponibili>' . "\n";
1264 $xml .= '</struttura>' . "\n";
1265
1266 // counter for booking IDs
1267 $idswh_map = [];
1268
1269 foreach ($this->rows as $ind => $row) {
1270 $timestamp_in = -1;
1271 $timestamp_out = -1;
1272 $control = -1;
1273 // se il cliente è in arrivo il tipo è 1, se è in partenza 2, se è una nuova prenotazione 3
1274 $type = -1;
1275 $guest_lastname = '';
1276 $guest_firstname = '';
1277
1278 $fields_checkin = '';
1279
1280 foreach ($row as $fk => $field) {
1281 if (isset($field['ignore_export'])) {
1282 continue;
1283 }
1284 // check if a value for this field was filled in manually
1285 if (is_array($pfiller) && isset($pfiller[$ind]) && isset($pfiller[$ind][$field['key']])) {
1286 if (strlen($pfiller[$ind][$field['key']])) {
1287 $field['value'] = $pfiller[$ind][$field['key']];
1288 }
1289 }
1290 // values set to -1 are usually empty and should have been filled in manually
1291 if ($field['value'] === -1) {
1292 // we raise an error in this case without stopping the process
1293 $field['value'] = 0;
1294 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.');
1295 }
1296 if (isset($field['callback_export'])) {
1297 $field['callback'] = $field['callback_export'];
1298 }
1299 $export_value = !isset($field['no_export_callback']) && isset($field['callback']) && is_callable($field['callback']) ? $field['callback']($field['value']) : $field['value'];
1300
1301 if ($field['key'] == 'idbooking') {
1302 $idswh = $export_value;
1303
1304 if (!isset($idswh_map[$idswh])) {
1305 $idswh_map[$idswh] = 0;
1306 }
1307
1308 $idswh_map[$idswh]++;
1309 }
1310
1311 if ($field['key'] == 'checkin') {
1312 $fields_checkin = $export_value;
1313 $timestamp_in = VikBooking::getDateTimestamp($export_value);
1314 }
1315
1316 if ($field['key'] == 'checkout') {
1317 $timestamp_out = VikBooking::getDateTimestamp($export_value);
1318 }
1319
1320 if ($field['key'] == 'cognome') {
1321 $guest_lastname = $export_value;
1322 } elseif ($field['key'] == 'nome') {
1323 $guest_firstname = $export_value;
1324 }
1325
1326 if ($control == -1 && $timestamp_in != -1 && $timestamp_out != -1) {
1327 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)) {
1328 $type = 1;
1329 } 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)) {
1330 $type = 2;
1331 } else {
1332 $type = 3;
1333 }
1334 $control = 0;
1335 }
1336
1337 if ($type == 1) {
1338 $clienti['arrivi'][$arrivi]['idswh'] = $idswh;
1339 if ($field['key'] == 'tipo') {
1340 $clienti['arrivi'][$arrivi]['tipoalloggiato'] = (string)$export_value;
1341 if (in_array($clienti['arrivi'][$arrivi]['tipoalloggiato'], ['19', '20'])) {
1342 // obbligatorio fornire "idcapo"
1343 $clienti['arrivi'][$arrivi]['idcapo'] = $clienti['arrivi'][$arrivi]['idswh'];
1344 } else {
1345 // "idcapo" deve essere un valore vuoto
1346 $clienti['arrivi'][$arrivi]['idcapo'] = '';
1347 }
1348 }
1349
1350 $clienti['arrivi'][$arrivi]['cognome'] = $guest_firstname;
1351 $clienti['arrivi'][$arrivi]['nome'] = $guest_lastname;
1352
1353 if ($field['key'] == 'gender') {
1354 $clienti['arrivi'][$arrivi]['sesso'] = $export_value;
1355 }
1356 if ($field['key'] == 'turismo') {
1357 $clienti['arrivi'][$arrivi]['tipoturismo'] = !empty($export_value) && $export_value != '?' ? strtoupper($export_value) : 'Non specificato';
1358 }
1359 if ($field['key'] == 'mezzo') {
1360 $clienti['arrivi'][$arrivi]['mezzotrasporto'] = !empty($export_value) && $export_value != '?' ? strtoupper($export_value) : 'Non specificato';
1361 }
1362 if ($field['key'] == 'citizen') {
1363 $clienti['arrivi'][$arrivi]['cittadinanza'] = (string)$export_value;
1364 }
1365 if ($field['key'] == 'stares') {
1366 $clienti['arrivi'][$arrivi]['statoresidenza'] = (string)$export_value;
1367 if (empty($clienti['arrivi'][$arrivi]['statoresidenza']) && !empty($clienti['arrivi'][$arrivi]['cittadinanza'])) {
1368 // make sure the value is filled
1369 $clienti['arrivi'][$arrivi]['statoresidenza'] = $clienti['arrivi'][$arrivi]['cittadinanza'];
1370 }
1371 }
1372 if ($field['key'] == 'dbirth') {
1373 $datanascita = date('Ymd', (is_numeric($export_value) ? $export_value : VikBooking::getDateTimestamp($export_value)));
1374 $clienti['arrivi'][$arrivi]['datanascita'] = $datanascita;
1375 }
1376 if (isset($clienti['arrivi'][$arrivi]['statoresidenza']) && $clienti['arrivi'][$arrivi]['statoresidenza'] == '100000100' && $field['key'] == 'comres') {
1377 $clienti['arrivi'][$arrivi]['luogoresidenza'] = (string)$export_value;
1378 } elseif (isset($clienti['arrivi'][$arrivi]['statoresidenza']) && $field['key'] == 'comres') {
1379 // cliente estero, valore vuoto per luogo residenza
1380 $clienti['arrivi'][$arrivi]['luogoresidenza'] = !empty($export_value) ? $export_value : 'NUTS';
1381 }
1382 } elseif ($type == 2) {
1383 $clienti['partenze'][$partenze]['idswh'] = $idswh;
1384 if ($field['key'] == 'tipo') {
1385 $clienti['partenze'][$partenze]['tipoalloggiato'] = (string)$export_value;
1386 }
1387 if ($field['key'] == 'checkin' || $fields_checkin) {
1388 $arrivo = date('Ymd', VikBooking::getDateTimestamp(($fields_checkin ? $fields_checkin : $export_value)));
1389 $clienti['partenze'][$partenze]['arrivo'] = $arrivo;
1390 }
1391 } elseif ($type == 3) {
1392 $clienti['prenotazioni'][$prenotazioni]['idswh'] = $idswh;
1393 if ($field['key'] == 'checkin' || $fields_checkin) {
1394 $prenotazione = date('Ymd', VikBooking::getDateTimestamp(($fields_checkin ? $fields_checkin : $export_value)));
1395 $clienti['prenotazioni'][$prenotazioni]['arrivo'] = $prenotazione;
1396 }
1397 if ($field['key'] == 'checkout') {
1398 $partenza = date('Ymd', VikBooking::getDateTimestamp($export_value));
1399 $clienti['prenotazioni'][$prenotazioni]['partenza'] = $partenza;
1400 }
1401 if ($field['key'] == 'guestsnum') {
1402 $clienti['prenotazioni'][$prenotazioni]['ospiti'] = (string)$export_value;
1403 }
1404 if ($field['key'] == 'roomsbooked') {
1405 $clienti['prenotazioni'][$prenotazioni]['camere'] = (string)$export_value;
1406 }
1407 }
1408 }
1409
1410 if ($type == 1) {
1411 $arrivi++;
1412 } elseif ($type == 2) {
1413 $partenze++;
1414 } elseif ($type == 3){
1415 $prenotazioni++;
1416 }
1417 }
1418
1419 if (count($clienti['arrivi'])) {
1420 // sort fields accordingly
1421 $arrivals_sort = [
1422 'idswh',
1423 'tipoalloggiato',
1424 'idcapo',
1425 'cognome',
1426 'nome',
1427 'sesso',
1428 'cittadinanza',
1429 'statoresidenza',
1430 'luogoresidenza',
1431 'datanascita',
1432 'statonascita',
1433 'comunenascita',
1434 'tipoturismo',
1435 'mezzotrasporto',
1436 'canaleprenotazione',
1437 'titolostudio',
1438 'professione',
1439 'esenzioneimposta',
1440 ];
1441 $arrivals_sorted = [];
1442 foreach ($clienti['arrivi'] as $k => $arrivals) {
1443 $arrivals_sorted[$k] = [];
1444 foreach ($arrivals_sort as $arrive_key) {
1445 if (isset($arrivals[$arrive_key])) {
1446 $arrivals_sorted[$k][$arrive_key] = $arrivals[$arrive_key];
1447 }
1448 }
1449 }
1450 $clienti['arrivi'] = $arrivals_sorted;
1451 }
1452
1453 if (count($clienti['partenze'])) {
1454 // sort fields accordingly
1455 $departures_sort = [
1456 'idswh',
1457 'tipoalloggiato',
1458 'arrivo',
1459 ];
1460 $departures_sorted = [];
1461 foreach ($clienti['partenze'] as $k => $departures) {
1462 $departures_sorted[$k] = [];
1463 foreach ($departures_sort as $depart_key) {
1464 if (isset($departures[$depart_key])) {
1465 $departures_sorted[$k][$depart_key] = $departures[$depart_key];
1466 }
1467 }
1468 }
1469 $clienti['partenze'] = $departures_sorted;
1470 }
1471
1472 $used_idswh = [];
1473 $xml .= '<arrivi>'."\n";
1474 for ($i = 0; $i < count($clienti['arrivi']); $i++) {
1475 $xml .= '<arrivo>'."\n";
1476 foreach ($clienti['arrivi'][$i] as $key => $value) {
1477 $use_value = $value;
1478 if ($key == 'idswh') {
1479 if (!isset($used_idswh[$value])) {
1480 $used_idswh[$value] = 0;
1481 }
1482 $used_idswh[$value]++;
1483 $guest_idswh_num = $used_idswh[$value];
1484 $use_value .= "-{$guest_idswh_num}";
1485 }
1486 $xml .= "<{$key}>{$use_value}</{$key}>\n";
1487 }
1488 $xml .= '</arrivo>'."\n";
1489 }
1490 $xml .= '</arrivi>'."\n";
1491
1492 $xml .= '<partenze>'."\n";
1493 for ($i = 0; $i < count($clienti['partenze']); $i++) {
1494 $xml .= '<partenza>'."\n";
1495 foreach ($clienti['partenze'][$i] as $key => $value) {
1496 $use_value = $value;
1497 if ($key == 'idswh') {
1498 if (!isset($used_idswh[$value])) {
1499 $used_idswh[$value] = 0;
1500 }
1501 $used_idswh[$value]++;
1502 $guest_idswh_num = $used_idswh[$value];
1503 $use_value .= "-{$guest_idswh_num}";
1504 }
1505 $xml .= "<{$key}>{$use_value}</{$key}>\n";
1506 }
1507 $xml .= '</partenza>'."\n";
1508 }
1509 $xml .= '</partenze>'."\n";
1510
1511 if ($clienti['prenotazioni']) {
1512 $xml .= '<prenotazioni>'."\n";
1513 for ($i = 0; $i < count($clienti['prenotazioni']); $i++) {
1514 $xml .= '<prenotazione>'."\n";
1515 foreach ($clienti['prenotazioni'][$i] as $key => $value) {
1516 $use_value = $value;
1517 if ($key == 'idswh') {
1518 if (!isset($used_idswh[$value])) {
1519 $used_idswh[$value] = 0;
1520 }
1521 $used_idswh[$value]++;
1522 $guest_idswh_num = $used_idswh[$value];
1523 $use_value .= "-{$guest_idswh_num}";
1524 }
1525 $xml .= "<{$key}>{$use_value}</{$key}>\n";
1526 }
1527 $xml .= '</prenotazione>'."\n";
1528 }
1529 $xml .= '</prenotazioni>'."\n";
1530 }
1531 } else {
1532 $xml .= '<struttura>'."\n";
1533 $xml .= '<apertura>'.$papertura.'</apertura>'."\n";
1534 $xml .= '<camereoccupate>0</camereoccupate>'."\n";
1535 $xml .= '<cameredisponibili>0</cameredisponibili>'."\n";
1536 $xml .= '<lettidisponibili>0</lettidisponibili>'."\n";
1537 $xml .= '</struttura>'."\n";
1538 }
1539 $xml .= '</movimento> '."\n";
1540 $xml .= '</movimenti>';
1541
1542 // format XML document
1543 $this->formatXML($xml);
1544
1545 /**
1546 * Custom export method supports a custom export handler, if previously set.
1547 *
1548 * @since 1.16.1 (J) - 1.6.1 (WP)
1549 */
1550 if ($this->hasExportHandler()) {
1551 // write data onto the custom file handler
1552 $fp = $this->getExportCSVHandler();
1553 fwrite($fp, $xml);
1554 fclose($fp);
1555
1556 return true;
1557 }
1558
1559 header('Content-Disposition: attachment; filename=' . $this->getExportCSVFileName());
1560 header('Content-type: text/xml');
1561 echo $xml;
1562
1563 exit;
1564 }
1565
1566 /**
1567 * Helper method invoked via AJAX by the controller.
1568 * Needed to save the manual entries for the pax data.
1569 *
1570 * @param array $manual_data the object representation of the manual entries.
1571 *
1572 * @return array one boolean value array with the operation result.
1573 */
1574 public function updatePaxData($manual_data = [])
1575 {
1576 if (!is_array($manual_data) || !$manual_data) {
1577 VBOHttpDocument::getInstance()->close(400, 'Nothing to save!');
1578 }
1579
1580 // re-build manual entries object representation
1581 $bids_guests = [];
1582 foreach ($manual_data as $guest_ind => $guest_data) {
1583 if (!is_numeric($guest_ind) || !is_array($guest_data) || empty($guest_data['bid']) || !isset($guest_data['bid_index']) || count($guest_data) < 2) {
1584 // empty or invalid manual entries array
1585 continue;
1586 }
1587 // the guest index in the reportObj starts from 0
1588 $use_guest_ind = ($guest_ind + 1 - (int)$guest_data['bid_index']);
1589 if (!isset($bids_guests[$guest_data['bid']])) {
1590 $bids_guests[$guest_data['bid']] = [];
1591 }
1592 // set manual entries for this guest number
1593 $bids_guests[$guest_data['bid']][$use_guest_ind] = $guest_data;
1594 // remove the "bid" and "bid_index" keys
1595 unset($bids_guests[$guest_data['bid']][$use_guest_ind]['bid'], $bids_guests[$guest_data['bid']][$use_guest_ind]['bid_index']);
1596 }
1597
1598 if (!$bids_guests) {
1599 VBOHttpDocument::getInstance()->close(400, 'No manual entries to save found');
1600 }
1601
1602 // loop through all bookings to update the data for the various rooms and guests
1603 $bids_updated = 0;
1604 foreach ($bids_guests as $bid => $entries) {
1605 $b_rooms = VikBooking::loadOrdersRoomsData($bid);
1606 if (empty($b_rooms)) {
1607 continue;
1608 }
1609 // count guests per room
1610 $room_guests = [];
1611 foreach ($b_rooms as $b_room) {
1612 $room_guests[] = $b_room['adults'] + $b_room['children'];
1613 }
1614 // get current booking pax data
1615 $pax_data = VBOCheckinPax::getBookingPaxData($bid);
1616 $pax_data = empty($pax_data) ? [] : $pax_data;
1617 foreach ($entries as $guest_ind => $guest_data) {
1618 // find room index for this guest
1619 $room_num = 0;
1620 $use_guest_ind = $guest_ind;
1621 foreach ($room_guests as $room_index => $tot_guests) {
1622 // find the proper guest index for the room to which this belongs
1623 if ($use_guest_ind <= $tot_guests) {
1624 // proper room index found for this guest
1625 $room_num = $room_index;
1626 break;
1627 } else {
1628 // it's probably in a next room
1629 $use_guest_ind -= $tot_guests;
1630 }
1631 }
1632 // push new pax data for this room and guest
1633 if (!isset($pax_data[$room_num])) {
1634 $pax_data[$room_num] = [];
1635 }
1636 if (!isset($pax_data[$room_num][$use_guest_ind])) {
1637 $pax_data[$room_num][$use_guest_ind] = $guest_data;
1638 } else {
1639 $pax_data[$room_num][$use_guest_ind] = array_merge($pax_data[$room_num][$use_guest_ind], $guest_data);
1640 }
1641 }
1642 // update booking pax data
1643 if (VBOCheckinPax::setBookingPaxData($bid, $pax_data)) {
1644 $bids_updated++;
1645 }
1646 }
1647
1648 return $bids_updated ? [true] : [false];
1649 }
1650
1651 /**
1652 * Registers the name to give to the file being exported.
1653 *
1654 * @return void
1655 *
1656 * @since 1.16.1 (J) - 1.6.1 (WP)
1657 */
1658 protected function registerExportFileName()
1659 {
1660 $pfromdate = VikRequest::getString('fromdate', '', 'request');
1661 $ptodate = VikRequest::getString('todate', '', 'request');
1662
1663 $this->setExportCSVFileName(str_replace(' ', '_', $this->reportName) . '-' . str_replace('/', '_', $pfromdate) . '.xml');
1664 }
1665
1666 /**
1667 * Parses the file Comuni.csv and returns two associative
1668 * arrays: one for the Comuni and one for the Province.
1669 * Every line of the CSV is composed of: Codice, Comune, Provincia.
1670 *
1671 * @return array
1672 */
1673 private function loadComuniProvince()
1674 {
1675 $vals = array(
1676 'comuni' => array(
1677 0 => '-- Estero --'
1678 ),
1679 'province' => array(
1680 0 => '-- Estero --'
1681 )
1682 );
1683
1684 $csv = dirname(__FILE__).DIRECTORY_SEPARATOR.'Comuni.csv';
1685 $rows = file($csv);
1686 foreach ($rows as $row) {
1687 if (empty($row)) {
1688 continue;
1689 }
1690 $v = explode(';', $row);
1691 if (count($v) != 3) {
1692 continue;
1693 }
1694 $vals['comuni'][$v[0]]['name'] = $v[1];
1695 $vals['comuni'][$v[0]]['province'] = $v[2];
1696 $vals['province'][$v[2]] = $v[2];
1697 }
1698
1699 return $vals;
1700 }
1701
1702 /**
1703 * Parses the file Nazioni.csv and returns an associative
1704 * array with the code and name of the Nazione.
1705 * Every line of the CSV is composed of: Codice, Nazione.
1706 *
1707 * @return array
1708 */
1709 private function loadNazioni()
1710 {
1711 $nazioni = array();
1712
1713 $csv = dirname(__FILE__).DIRECTORY_SEPARATOR.'Nazioni.csv';
1714 $rows = file($csv);
1715 foreach ($rows as $row) {
1716 if (empty($row)) {
1717 continue;
1718 }
1719 $v = explode(';', $row);
1720 if (count($v) != 3) {
1721 continue;
1722 }
1723
1724 $nazioni[$v[0]]['name'] = $v[1];
1725 $nazioni[$v[0]]['three_code'] = $v[2];
1726
1727 }
1728
1729 return $nazioni;
1730 }
1731
1732 /**
1733 *
1734 * Returns an array that contains both name and key of the comune selected, plus the associated province.
1735 *
1736 * @return array
1737 */
1738 private function checkComune($combirth, $checked, $province)
1739 {
1740 $result = array();
1741 $first_found = '';
1742 if (!count($this->comuniProvince)) {
1743 $this->comuniProvince = $this->loadComuniProvince();
1744 }
1745 if (empty($combirth)) {
1746 return $result;
1747 }
1748 foreach ($this->comuniProvince['comuni'] as $key => $value) {
1749 if (!isset($value['name'])) {
1750 continue;
1751 }
1752 if ($value['name'] == $combirth) {
1753 $result['found'] = true;
1754 $result['combirth'] = $value['name'];
1755 $result['province'] = $value['province'];
1756 $result['comval'] = $key;
1757 $result['similar'] = false;
1758 break;
1759 } else if (strpos($value['name'], trim($combirth)) !== false && empty($first_found)) {
1760 $result['found'] = true;
1761 $result['combirth'] = $value['name'];
1762 $first_found = $key;
1763 $result['similar'] = true;
1764 $result['province'] = $value['province'];
1765 }
1766 }
1767 if (!$result['found']) {
1768 $result['combirth'] = '';
1769 }
1770
1771 if ($checked === true && strlen($province) > 0 && $result['found']) {
1772 $result['province'] = $province;
1773 if($province == $value['province']) {
1774 $result['provinceok'] = true;
1775 $result['province'] = $province;
1776 } else {
1777 $result['provinceok'] = false;
1778 }
1779 }
1780 if ($result['similar'] && $result['found']) {
1781 $result['comval'] = $first_found;
1782 }
1783
1784 return $result;
1785 }
1786
1787 /**
1788 *
1789 * Returns the key of the state selected by the user.
1790 *
1791 * @return string
1792 *
1793 */
1794 private function checkCountry($country)
1795 {
1796 $found = false;
1797 $staval = '';
1798
1799 if (!$this->nazioni) {
1800 $this->nazioni = $this->loadNazioni();
1801 }
1802
1803 if ($country && isset($this->nazioni[$country])) {
1804 return $country;
1805 }
1806
1807 foreach ($this->nazioni as $key => $value) {
1808 if (trim($value['three_code']) == trim($country)) {
1809 $staval = $key;
1810 $found = true;
1811 break;
1812 }
1813 }
1814
1815 if ($found !== true) {
1816 $staval = '';
1817 }
1818
1819 return $staval;
1820 }
1821
1822 /**
1823 * Sanitizes the "Comune": if comune contains also the province, example PRATO (PO),
1824 * then I set both Comune and Province and I check both of them with the checkComune() function.
1825 *
1826 * @return array
1827 */
1828 private function sanitizeComune($combirth)
1829 {
1830 $result = array();
1831
1832 if (strlen($combirth) > 2) {
1833 if (strpos($combirth, "(") !== false) {
1834 $comnas = explode("(", $combirth);
1835 $result['combirth'] = trim($comnas[0]);
1836 $result['province'] = $comnas[1];
1837 $result['province'] = str_replace(")", "", $result['province']);
1838 $result['checked'] = true;
1839 }
1840 } else if(strlen($combirth) > 0){
1841 $result['province'] = trim($combirth);
1842 $result['similar'] = true;
1843 }
1844 return $result;
1845 }
1846
1847 /**
1848 * Helper method to quickly get a pax_data property for the guest.
1849 *
1850 * @param array $pax_data the current pax_data stored.
1851 * @param array $guests list of total guests per room.
1852 * @param int $guest_ind the guest index.
1853 * @param string $key the pax_data key to look for.
1854 *
1855 * @return mixed null on failure or value fetched.
1856 */
1857 private function getGuestPaxDataValue($pax_data, $guests, $guest_ind, $key)
1858 {
1859 if (!is_array($pax_data) || !count($pax_data) || empty($key)) {
1860 return null;
1861 }
1862
1863 // find room index for this guest number
1864 $room_num = 0;
1865 $use_guest_ind = $guest_ind;
1866 foreach ($guests as $room_index => $room_tot_guests) {
1867 // find the proper guest index for the room to which this belongs
1868 if ($use_guest_ind <= $room_tot_guests) {
1869 // proper room index found for this guest
1870 $room_num = $room_index;
1871 break;
1872 } else {
1873 // it's probably in a next room
1874 $use_guest_ind -= $room_tot_guests;
1875 }
1876 }
1877
1878 // check if a value exists for the requested key in the found room and guest indexes
1879 if (isset($pax_data[$room_num]) && isset($pax_data[$room_num][$use_guest_ind])) {
1880 if (isset($pax_data[$room_num][$use_guest_ind][$key])) {
1881 // we've got a value previously stored
1882 return $pax_data[$room_num][$use_guest_ind][$key];
1883 }
1884 }
1885
1886 // nothing was found
1887 return null;
1888 }
1889
1890 /**
1891 * Helper method to determine the exact number for this guest in the room booked.
1892 *
1893 * @param array $guests list of total guests per room.
1894 * @param int $guest_ind the guest index.
1895 *
1896 * @return int the actual guest room index starting from 1.
1897 */
1898 private function calcGuestRoomIndex($guests, $guest_ind)
1899 {
1900 // find room index for this guest number
1901 $room_num = 0;
1902 $use_guest_ind = $guest_ind;
1903 foreach ($guests as $room_index => $room_tot_guests) {
1904 // find the proper guest index for the room to which this belongs
1905 if ($use_guest_ind <= $room_tot_guests) {
1906 // proper room index found for this guest
1907 $room_num = $room_index;
1908 break;
1909 } else {
1910 // it's probably in a next room
1911 $use_guest_ind -= $room_tot_guests;
1912 }
1913 }
1914
1915 return $use_guest_ind;
1916 }
1917 }
1918