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_ross1000.php

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

1,916 lines 65.8 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 });
386 });
387
388 function vboReportCheckDates(selectedDate, inst) {
389 if (selectedDate === null || inst === null) {
390 return;
391 }
392 var cur_from_date = jQuery(this).val();
393 if (jQuery(this).hasClass("vbo-report-datepicker-from") && cur_from_date.length) {
394 var nowstart = jQuery(this).datepicker("getDate");
395 var nowstartdate = new Date(nowstart.getTime());
396 jQuery(".vbo-report-datepicker-to").datepicker("option", {minDate: nowstartdate});
397 }
398 }
399
400 function vboReportChosenComune(comune) {
401 var c_code = comune.value;
402 var c_val = comune.options[comune.selectedIndex].text;
403 if (reportActiveCell !== null) {
404 var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr"));
405 if (isNaN(nowindex) || parseInt(nowindex) < 0) {
406 alert("Error, cannot find element to update.");
407 } else {
408 var rep_act_cell = jQuery(reportActiveCell);
409 rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val);
410 var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid");
411 if (!reportObj.hasOwnProperty(nowindex)) {
412 reportObj[nowindex] = {
413 bid: rep_guest_bid,
414 bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr"))
415 };
416 }
417 if (jQuery(reportActiveCell).hasClass("vbo-report-load-docplace")) {
418 reportObj[nowindex]["docplace"] = c_code;
419 } else {
420 reportObj[nowindex]["comune_s"] = c_code;
421 }
422 }
423 }
424 reportActiveCell = null;
425 vboHideOverlay();
426 jQuery("#choose-comune").val("").select2("data", null, false);
427 jQuery(".vbo-report-ross1000-manualsave").show();
428 }
429
430 function vboReportChosenProvincia(prov) {
431 var c_code = prov.value;
432 var c_val = prov.options[prov.selectedIndex].text;
433 if (reportActiveCell !== null) {
434 var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr"));
435 if (isNaN(nowindex) || parseInt(nowindex) < 0) {
436 alert("Error, cannot find element to update.");
437 } else {
438 var rep_act_cell = jQuery(reportActiveCell);
439 rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val);
440 var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid");
441 if (!reportObj.hasOwnProperty(nowindex)) {
442 reportObj[nowindex] = {
443 bid: rep_guest_bid,
444 bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr"))
445 };
446 }
447 reportObj[nowindex]["comune_s"] = c_code;
448 }
449 }
450 reportActiveCell = null;
451 vboHideOverlay();
452 jQuery("#choose-provincia").val("").select2("data", null, false);
453 jQuery(".vbo-report-ross1000-manualsave").show();
454 }
455
456 function vboReportChosenNazione(naz) {
457 var c_code = naz.value;
458 var c_val = naz.options[naz.selectedIndex].text;
459 if (reportActiveCell !== null) {
460 var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr"));
461 if (isNaN(nowindex) || parseInt(nowindex) < 0) {
462 alert("Error, cannot find element to update.");
463 } else {
464 var rep_act_cell = jQuery(reportActiveCell);
465 rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val);
466 var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid");
467 if (!reportObj.hasOwnProperty(nowindex)) {
468 reportObj[nowindex] = {
469 bid: rep_guest_bid,
470 bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr"))
471 };
472 }
473 if (jQuery(reportActiveCell).hasClass("vbo-report-load-nazione")) {
474 reportObj[nowindex]["country_s"] = c_code;
475 } else if (jQuery(reportActiveCell).hasClass("vbo-report-load-docplace")) {
476 reportObj[nowindex]["docplace"] = c_code;
477 } else {
478 reportObj[nowindex]["country_c"] = c_code;
479 }
480 }
481 }
482 reportActiveCell = null;
483 vboHideOverlay();
484 jQuery("#choose-nazione").val("").select2("data", null, false);
485 jQuery(".vbo-report-ross1000-manualsave").show();
486 }
487
488 function vboReportChosenSesso(sesso) {
489 var c_code = sesso.value;
490 var c_val = sesso.options[sesso.selectedIndex].text;
491 if (reportActiveCell !== null) {
492 var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr"));
493 if (isNaN(nowindex) || parseInt(nowindex) < 0) {
494 alert("Error, cannot find element to update.");
495 } else {
496 var rep_act_cell = jQuery(reportActiveCell);
497 rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val);
498 var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid");
499 if (!reportObj.hasOwnProperty(nowindex)) {
500 reportObj[nowindex] = {
501 bid: rep_guest_bid,
502 bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr"))
503 };
504 }
505 reportObj[nowindex]["gender"] = c_code;
506 }
507 }
508 reportActiveCell = null;
509 vboHideOverlay();
510 jQuery("#choose-sesso").val("").select2("data", null, false);
511 jQuery(".vbo-report-ross1000-manualsave").show();
512 }
513
514 function vboReportChosenTrasporto(trasporto) {
515 var c_code = trasporto.value;
516 var c_val = trasporto.options[trasporto.selectedIndex].text;
517 if (reportActiveCell !== null) {
518 var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr"));
519 if (isNaN(nowindex) || parseInt(nowindex) < 0) {
520 alert("Error, cannot find element to update.");
521 } else {
522 var rep_act_cell = jQuery(reportActiveCell);
523 rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val);
524 var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid");
525 if (!reportObj.hasOwnProperty(nowindex)) {
526 reportObj[nowindex] = {
527 bid: rep_guest_bid,
528 bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr"))
529 };
530 }
531 reportObj[nowindex]["mezzo"] = c_code;
532 }
533 }
534 reportActiveCell = null;
535 vboHideOverlay();
536 jQuery("#choose-trasporto").val("").select2("data", null, false);
537 jQuery(".vbo-report-ross1000-manualsave").show();
538 }
539
540 function vboReportChosenTurismo(turismo) {
541 var c_code = turismo.value;
542 var c_val = turismo.options[turismo.selectedIndex].text;
543 if (reportActiveCell !== null) {
544 var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr"));
545 if (isNaN(nowindex) || parseInt(nowindex) < 0) {
546 alert("Error, cannot find element to update.");
547 } else {
548 var rep_act_cell = jQuery(reportActiveCell);
549 rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val);
550 var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid");
551 if (!reportObj.hasOwnProperty(nowindex)) {
552 reportObj[nowindex] = {
553 bid: rep_guest_bid,
554 bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr"))
555 };
556 }
557 reportObj[nowindex]["turismo"] = c_code;
558 }
559 }
560 reportActiveCell = null;
561 vboHideOverlay();
562 jQuery("#choose-turismo").val("").select2("data", null, false);
563 jQuery(".vbo-report-ross1000-manualsave").show();
564 }
565
566 function vboReportChosenDbirth(val) {
567 var c_code = val, c_val = val;
568 if (reportActiveCell !== null) {
569 var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr"));
570 if (isNaN(nowindex) || parseInt(nowindex) < 0) {
571 alert("Error, cannot find element to update.");
572 } else {
573 var rep_act_cell = jQuery(reportActiveCell);
574 rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val);
575 var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid");
576 if (!reportObj.hasOwnProperty(nowindex)) {
577 reportObj[nowindex] = {
578 bid: rep_guest_bid,
579 bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr"))
580 };
581 }
582 reportObj[nowindex]["date_birth"] = c_code;
583 }
584 }
585 reportActiveCell = null;
586 vboHideOverlay();
587 jQuery("#choose-dbirth").val("");
588 jQuery(".vbo-report-ross1000-manualsave").show();
589 }
590
591 // download function
592 function vboDownloadSchedaIstat() {
593 if (!confirm("Sei sicuro di aver compilato tutti i dati?")) {
594 return false;
595 }
596 document.adminForm.target = "_blank";
597 document.adminForm.action += "&tmpl=component";
598 vboSetFilters({exportreport: "1", filler: JSON.stringify(reportObj)}, true);
599 setTimeout(function() {
600 document.adminForm.target = "";
601 document.adminForm.action = document.adminForm.action.replace("&tmpl=component", "");
602 vboSetFilters({exportreport: "0", filler: ""}, false);
603 }, 1000);
604 }
605
606 // save data after manual fillers
607 function vboRoss1000SaveData() {
608 jQuery("button.vbo-report-ross1000-manualsave").find("i").attr("class", vbo_ross1000_saving_icn);
609 VBOCore.doAjax(
610 vbo_report_js_ajax_base,
611 {
612 call: "updatePaxData",
613 params: reportObj,
614 tmpl: "component"
615 },
616 (response) => {
617 if (!response || !response[0]) {
618 alert("An error occurred.");
619 return false;
620 }
621 jQuery("button.vbo-report-ross1000-manualsave").addClass("btn-success").find("i").attr("class", vbo_ross1000_saved_icn);
622 },
623 (error) => {
624 alert(error.responseText);
625 jQuery("button.vbo-report-ross1000-manualsave").removeClass("btn-success").find("i").attr("class", vbo_ross1000_save_icn);
626 }
627 );
628 }';
629 $this->setScript($js);
630
631 return $this->reportFilters;
632 }
633
634 /**
635 * Loads the report data from the DB.
636 * Returns true in case of success, false otherwise.
637 * Sets the columns and rows for the report to be displayed.
638 *
639 * @return boolean
640 */
641 public function getReportData()
642 {
643 if (strlen($this->getError())) {
644 //Export functions may set errors rather than exiting the process, and the View may continue the execution to attempt to render the report.
645 return false;
646 }
647 //Input fields and other vars
648 $pfromdate = VikRequest::getString('fromdate', '', 'request');
649 $ptodate = VikRequest::getString('todate', '', 'request');
650 $pkrsort = VikRequest::getString('krsort', $this->defaultKeySort, 'request');
651 $pkrsort = empty($pkrsort) ? $this->defaultKeySort : $pkrsort;
652 $pkrorder = VikRequest::getString('krorder', $this->defaultKeyOrder, 'request');
653 $pkrorder = empty($pkrorder) ? $this->defaultKeyOrder : $pkrorder;
654 $pkrorder = $pkrorder == 'DESC' ? 'DESC' : 'ASC';
655 $pcodstru = VikRequest::getString('codstru', '', 'request');
656 $papertura = VikRequest::getString('apertura', '', 'request');
657
658 $q = "SELECT SUM(`units`) AS `sommaunita`, SUM(`totpeople`) AS `numeropersone`, COUNT(*) AS `numerocamere` FROM `#__vikbooking_rooms` WHERE `avail`= '1';";
659 $this->dbo->setQuery($q);
660 $records = $this->dbo->loadAssocList();
661 if (!$records) {
662 return false;
663 }
664
665 $totalBeds = (int)($records[0]['sommaunita'] * ($records[0]['numeropersone'] / $records[0]['numerocamere']));
666 $pletti = VikRequest::getString('numletti', $totalBeds, 'request');
667 $currency_symb = VikBooking::getCurrencySymb();
668 $df = $this->getDateFormat();
669 $datesep = VikBooking::getDateSeparator();
670 if (empty($ptodate)) {
671 $ptodate = $pfromdate;
672 }
673 //Get dates timestamps
674 $from_ts = VikBooking::getDateTimestamp($pfromdate, 0, 0);
675 $to_ts = VikBooking::getDateTimestamp($ptodate, 23, 59, 59);
676 if (empty($pfromdate) || empty($from_ts) || empty($to_ts)) {
677 $this->setError(JText::translate('VBOREPORTSERRNODATES'));
678 return false;
679 }
680 if (empty($pcodstru)) {
681 $this->setError('Inserisci il codice della tua Struttura.<br/>Si tratta di un codice univoco di identificazione che ti viene assegnato dall\'Amministrazione competente.');
682 return false;
683 }
684 if (empty($papertura)) {
685 $this->setError('Devi specificare se la tua struttura è aperta o meno attraverso il menù a tendina qui sopra.');
686 return false;
687 }
688 //Query to obtain the records (all check-ins within the dates filter)
689 $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`,".
690 "`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`,".
691 "`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` ".
692 "FROM `#__vikbooking_orders` AS `o` LEFT JOIN `#__vikbooking_ordersrooms` AS `or` ON `or`.`idorder`=`o`.`id` ".
693 "LEFT JOIN `#__vikbooking_customers_orders` AS `co` ON `co`.`idorder`=`o`.`id` LEFT JOIN `#__vikbooking_customers` AS `c` ON `c`.`id`=`co`.`idcustomer` ".
694 "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.")) ".
695 "ORDER BY `o`.`checkin` ASC, `o`.`id` ASC, `or`.`id` ASC;";
696 $this->dbo->setQuery($q);
697 $records = $this->dbo->loadAssocList();
698 if (!$records) {
699 $this->setError(JText::translate('VBOREPORTSERRNORESERV'));
700 $this->setError('Nessun check-in nelle date selezionate.');
701 return false;
702 }
703
704 //nest records with multiple rooms booked inside sub-array
705 $bookings = array();
706 foreach ($records as $v) {
707 if (!isset($bookings[$v['id']])) {
708 $bookings[$v['id']] = array();
709 }
710 array_push($bookings[$v['id']], $v);
711 }
712 //define the columns of the report
713 $this->cols = array(
714 //id booking
715 array(
716 'key' => 'idbooking',
717 'attr' => array(
718 'class="center"'
719 ),
720 'label' => 'ID',
721 'sortable' => 1,
722 ),
723 //check-in
724 array(
725 'key' => 'checkin',
726 'attr' => array(
727 'class="center"'
728 ),
729 'sortable' => 1,
730 'label' => JText::translate('VBPICKUPAT')
731 ),
732 //checkout
733 array(
734 'key' => 'checkout',
735 'attr' => array(
736 'class="center"'
737 ),
738 'sortable' => 1,
739 'label' => 'Partenza'
740 ),
741 //cognome
742 array(
743 'key' => 'cognome',
744 'label' => JText::translate('VBTRAVELERLNAME'),
745 'sortable' => 1,
746 ),
747 //nome
748 array(
749 'key' => 'nome',
750 'label' => JText::translate('VBTRAVELERNAME'),
751 'sortable' => 1,
752 ),
753 //sesso
754 array(
755 'key' => 'gender',
756 'attr' => array(
757 'class="center"'
758 ),
759 'label' => JText::translate('VBCUSTOMERGENDER')
760 ),
761 //data di nascita
762 array(
763 'key' => 'dbirth',
764 'attr' => array(
765 'class="center"'
766 ),
767 'label' => JText::translate('VBCUSTOMERBDATE')
768 ),
769 //cittadinanza
770 array(
771 'key' => 'citizen',
772 'attr' => array(
773 'class="center"'
774 ),
775 'sortable' => 1,
776 'label' => 'Cittadinanza'
777 ),
778 //cittadinanza
779 array(
780 'key' => 'stares',
781 'attr' => array(
782 'class="center"'
783 ),
784 'sortable' => 1,
785 'label' => 'Stato di Residenza'
786 ),
787 //comune di residenza
788 array(
789 'key' => 'comres',
790 'attr' => array(
791 'class="center"'
792 ),
793 'sortable' => 1,
794 'label' => 'Comune Residenza',
795 'tip' => 'Inserire il comune di residenza solo se il cittadino è di nazionalità italiana.'
796 ),
797 //tipo
798 array(
799 'key' => 'tipo',
800 'attr' => array(
801 'class="vbo-report-longlbl"'
802 ),
803 'label' => 'Tipo Alloggiato'
804 ),
805 // tipo di trasporto
806 array(
807 'key' => 'mezzo',
808 'attr' => array(
809 'class="center"'
810 ),
811 'label' => 'Mezzo di Trasporto'
812 ),
813 // tipo di turismo
814 array(
815 'key' => 'turismo',
816 'attr' => array(
817 'class="center"'
818 ),
819 'label' => 'Tipo di Turismo'
820 ),
821 //quantità (numero di ospiti)
822 array(
823 'key' => 'guestsnum',
824 'attr' => array(
825 'class="center"'
826 ),
827 'sortable' => 1,
828 'label' => 'Numero Ospiti',
829 'tip' => 'Il numero di ospiti totali (adulti + bambini) per ogni prenotazione è un dato che verrà comunicato all\'ISTAT.',
830 ),
831 array(
832 'key' => 'roomsbooked',
833 'attr' => array(
834 'class="center"'
835 ),
836 'sortable' => 1,
837 'label' => 'Occupazione',
838 'tip' => 'Questo valore indica il numero di camere occupate da ogni prenotazione, ed è un dato che verrà comunicato all\'ISTAT.',
839 ),
840 );
841
842 // loop over the bookings to build the rows of the report
843 $from_info = getdate($from_ts);
844 foreach ($bookings as $gbook) {
845 $guestsnum = 0;
846 $guests_rows = array($gbook[0]);
847 $room_guests = array();
848 $tot_guests_rows = 1;
849
850 $tipo = 16;
851 // Codici Tipo Alloggiato
852 // 16 = Ospite Singolo
853 // 17 = Capofamiglia
854 // 18 = Capogruppo
855 // 19 = Familiare
856 // 20 = Membro Gruppo
857
858 foreach ($gbook as $book) {
859 $guestsnum += $book['adults'] + $book['children'];
860 $room_guests[] = ($book['adults'] + $book['children']);
861 }
862 $pax_data = null;
863 if (!empty($gbook[0]['pax_data'])) {
864 $pax_data = json_decode($gbook[0]['pax_data'], true);
865 if (is_array($pax_data) && count($pax_data)) {
866 $guests_rows[0]['pax_data'] = $pax_data;
867 $tot_guests_rows = 0;
868 foreach ($pax_data as $roomguests) {
869 $tot_guests_rows += count($roomguests);
870 }
871 for ($i = 1; $i < $tot_guests_rows; $i++) {
872 array_push($guests_rows, $guests_rows[0]);
873 }
874 $tipo = count($guests_rows) > 1 ? 17 : $tipo;
875 }
876 }
877
878 //create one row for each guest
879 $guest_ind = 1;
880 foreach ($guests_rows as $ind => $guests) {
881 // prepare row record
882 $insert_row = array();
883
884 // find the actual guest-room-index
885 $guest_room_ind = $this->calcGuestRoomIndex($room_guests, $guest_ind);
886
887 // booking ID
888 array_push($insert_row, array(
889 'key' => 'idbooking',
890 'attr' => array(
891 'class="center"'
892 ),
893 'callback' => function ($val) {
894 // make sure to keep the data-bid attribute as it's used by JS to identify the booking ID
895 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>';
896 },
897 'callback_export' => function ($val) {
898 return $val;
899 },
900 'value' => $guests['id']
901 ));
902
903 // checkin date
904 array_push($insert_row, array(
905 'key' => 'checkin',
906 'attr' => array(
907 'class="center"'
908 ),
909 'callback' => function ($val) {
910 return date('d/m/Y', $val);
911 },
912 'value' => $guests['checkin']
913 ));
914
915 // checkout date
916 array_push($insert_row,array(
917 'key' => 'checkout',
918 'attr' => array(
919 'class="center"'
920 ),
921 'callback' => function ($val) {
922 return date('d/m/Y', $val);
923 },
924 'value' => $gbook[0]['checkout']
925 ));
926
927 // cognome
928 $cognome = !empty($guests['t_last_name']) ? $guests['t_last_name'] : $guests['last_name'];
929 $pax_cognome = $this->getGuestPaxDataValue($pax_data, $room_guests, $guest_ind, 'last_name');
930 $cognome = !empty($pax_cognome) ? $pax_cognome : $cognome;
931 array_push($insert_row, array(
932 'key' => 'cognome',
933 'value' => $cognome
934 ));
935
936 // nome
937 $nome = !empty($guests['t_first_name']) ? $guests['t_first_name'] : $guests['first_name'];
938 $pax_nome = $this->getGuestPaxDataValue($pax_data, $room_guests, $guest_ind, 'first_name');
939 $nome = !empty($pax_nome) ? $pax_nome : $nome;
940 array_push($insert_row, array(
941 'key' => 'nome',
942 'value' => $nome
943 ));
944
945 // sesso
946 $gender = !empty($guests['gender']) && $guest_ind < 2 ? strtoupper($guests['gender']) : '';
947 $gender = $gender == 'F' ? 2 : ($gender == 'M' ? 1 : $gender);
948 $pax_gender = $this->getGuestPaxDataValue($pax_data, $room_guests, $guest_ind, 'gender');
949 $gender = !empty($pax_gender) ? $pax_gender : $gender;
950 if (is_numeric($gender)) {
951 $gender = (int)$gender;
952 } elseif (!strcasecmp($gender, 'F')) {
953 $gender = 2;
954 } elseif (!strcasecmp($gender, 'M')) {
955 $gender = 1;
956 }
957 array_push($insert_row, array(
958 'key' => 'gender',
959 'attr' => array(
960 'class="center'.(empty($gender) ? ' vbo-report-load-sesso' : '').'"'
961 ),
962 'callback' => function ($val) {
963 return $val == 2 ? 'F' : ($val == 1 ? 'M' : '?');
964 },
965 'callback_export' => function ($val) {
966 return $val == 2 ? 'F' : ($val == 1 ? 'M' : '?');
967 },
968 'value' => $gender
969 ));
970
971 // data di nascita
972 $dbirth = !empty($guests['bdate']) && $guest_ind < 2 ? VikBooking::getDateTimestamp($guests['bdate'], 0, 0) : '';
973 $pax_dbirth = $this->getGuestPaxDataValue($pax_data, $room_guests, $guest_ind, 'date_birth');
974 $dbirth = !empty($pax_dbirth) ? $pax_dbirth : $dbirth;
975 $dbirth = (strpos($dbirth, '/') === false && strpos($dbirth, VikBooking::getDateSeparator()) === false) ? $dbirth : VikBooking::getDateTimestamp($dbirth, 0, 0);
976 array_push($insert_row, array(
977 'key' => 'dbirth',
978 'attr' => array(
979 'class="center'.(empty($dbirth) ? ' vbo-report-load-dbirth' : '').'"'
980 ),
981 'callback' => function ($val) {
982 if (!empty($val) && strpos($val, '/') === false && strpos($val, VikBooking::getDateSeparator()) === false) {
983 return date('d/m/Y', $val);
984 }
985 if (!empty($val) && strpos($val, '/') !== false) {
986 return $val;
987 }
988 return '?';
989 },
990 'no_export_callback' => 1,
991 'value' => $dbirth
992 ));
993
994 // cittadinanza (compatible with pax data field of driver "Italy")
995 $pax_country_c = $this->getGuestPaxDataValue($pax_data, $room_guests, $guest_ind, 'country_c');
996 $citizen = !empty($guests['country']) && $guest_ind < 2 ? $guests['country'] : '';
997 $citizenval = '';
998 if (!empty($citizen) && $guest_ind < 2) {
999 $citizenval = $this->checkCountry($citizen);
1000 }
1001
1002 // check nationality field from pre-checkin
1003 $pax_citizen = $this->getGuestPaxDataValue($pax_data, $room_guests, $guest_ind, 'nationality');
1004 $citizen = !empty($pax_citizen) ? $pax_citizen : $citizen;
1005 $citizen = !empty($pax_country_c) ? $pax_country_c : $citizen;
1006 $citizenval = $this->checkCountry((!empty($pax_country_c) ? $pax_country_c : $citizen));
1007 array_push($insert_row, array(
1008 'key' => 'citizen',
1009 'attr' => array(
1010 'class="center'.(empty($citizen) ? ' vbo-report-load-cittadinanza' : '').'"'
1011 ),
1012 'callback' => function ($val) {
1013 return !empty($val) && isset($this->nazioni[$val]) ? $this->nazioni[$val]['name'] : '?';
1014 },
1015 'no_export_callback' => 1,
1016 'value' => !empty($citizenval) ? $citizenval : ''
1017 ));
1018
1019 // stato di residenza
1020 $provstay = '';
1021 $pax_provstay = $this->getGuestPaxDataValue($pax_data, $room_guests, $guest_ind, ($guest_ind < 2 ? 'country_s' : 'country_b'));
1022 $provstay = !empty($pax_provstay) ? $pax_provstay : $provstay;
1023 array_push($insert_row, array(
1024 'key' => 'stares',
1025 'attr' => array(
1026 'class="center'.(empty($provstay) ? ' vbo-report-load-nazione' : '').'"'
1027 ),
1028 'callback' => function($val) {
1029 if (!empty($val) && isset($this->nazioni[$val])) {
1030 return $this->nazioni[$val]['name'];
1031 }
1032 // information is missing and should be provided
1033 return '?';
1034 },
1035 'no_export_callback' => 1,
1036 'value' => $provstay
1037 ));
1038
1039 // comune di residenza
1040 $comstay = '';
1041 $pax_comstay = $this->getGuestPaxDataValue($pax_data, $room_guests, $guest_ind, 'comune_s');
1042 $comstay = !empty($pax_comstay) ? $pax_comstay : $comstay;
1043 array_push($insert_row, array(
1044 'key' => 'comres',
1045 'attr' => array(
1046 'class="center'.(empty($comstay) ? ' vbo-report-load-comune' : '').'"'
1047 ),
1048 'callback' => function($val) {
1049 if (!empty($val) && isset($this->comuniProvince['comuni'][$val])) {
1050 return $this->comuniProvince['comuni'][$val]['name'];
1051 }
1052 // information is missing and should be provided
1053 return '?';
1054 },
1055 'no_export_callback' => 1,
1056 'value' => $comstay
1057 ));
1058
1059 // tipo alloggiato
1060 $use_tipo = $ind > 0 && $tipo == 17 ? 19 : $tipo;
1061 $pax_guest_type = $this->getGuestPaxDataValue($pax_data, $room_guests, $guest_ind, 'guest_type');
1062 $use_tipo = !empty($pax_guest_type) ? $pax_guest_type : $use_tipo;
1063 array_push($insert_row, array(
1064 'key' => 'tipo',
1065 'callback' => function ($val) {
1066 switch ($val) {
1067 case 16:
1068 return 'Ospite Singolo';
1069 case 17:
1070 return 'Capofamiglia';
1071 case 18:
1072 return 'Capogruppo';
1073 case 19:
1074 return 'Familiare';
1075 case 20:
1076 return 'Membro Gruppo';
1077 }
1078 return '?';
1079 },
1080 'no_export_callback' => 1,
1081 'value' => $use_tipo
1082 ));
1083
1084 // mezzo di trasporto
1085 $pax_mezzo = $this->getGuestPaxDataValue($pax_data, $room_guests, $guest_ind, 'mezzo');
1086 array_push($insert_row, array(
1087 'key' => 'mezzo',
1088 'attr' => array(
1089 'class="center' . (empty($pax_mezzo) ? ' vbo-report-load-trasporto' : '') . '"'
1090 ),
1091 'value' => ($pax_mezzo ? $pax_mezzo : '?')
1092 ));
1093
1094 // tipo di turismo
1095 $pax_turismo = $this->getGuestPaxDataValue($pax_data, $room_guests, $guest_ind, 'turismo');
1096 array_push($insert_row, array(
1097 'key' => 'turismo',
1098 'attr' => array(
1099 'class="center' . (empty($pax_turismo) ? ' vbo-report-load-turismo' : '') . '"'
1100 ),
1101 'value' => ($pax_turismo ? $pax_turismo : '?')
1102 ));
1103
1104 // numero persone in prenotazione
1105 array_push($insert_row, array(
1106 'key' => 'guestsnum',
1107 'attr' => array(
1108 'class="center"'
1109 ),
1110 'value' => $guestsnum
1111 ));
1112
1113 // camere prenotate
1114 array_push($insert_row, array(
1115 'key' => 'roomsbooked',
1116 'attr' => array(
1117 'class="center"'
1118 ),
1119 'value' => count($gbook)
1120 ));
1121
1122 // push fields in the rows array as a new row
1123 array_push($this->rows, $insert_row);
1124
1125 // increment guest index
1126 $guest_ind++;
1127 }
1128 }
1129
1130 // do not sort the rows for this report because the lines of the guests of the same booking must be consecutive
1131 // $this->sortRows($pkrsort, $pkrorder);
1132
1133 // the footer row will just print the amount of records to export
1134 array_push($this->footerRow, array(
1135 array(
1136 'attr' => array(
1137 'class="vbo-report-total"'
1138 ),
1139 'value' => '<h3>'.JText::translate('VBOREPORTSTOTALROW').'</h3>'
1140 ),
1141 array(
1142 'attr' => array(
1143 'colspan="'.(count($this->cols) - 1).'"'
1144 ),
1145 'value' => count($this->rows)
1146 )
1147 ));
1148
1149 // Debug
1150 if ($this->debug) {
1151 $this->setWarning('path to report file = '.urlencode(dirname(__FILE__)).'<br/>');
1152 $this->setWarning('$total_rooms_units = '.$total_rooms_units.'<br/>');
1153 $this->setWarning('$bookings:<pre>'.print_r($bookings, true).'</pre><br/>');
1154 }
1155
1156 return true;
1157 }
1158
1159 public function formatXML(&$xml)
1160 {
1161 if (!class_exists('DOMDocument')) {
1162 // we cannot format the XML because DOMDocument is missing
1163 return $xml;
1164 }
1165
1166 $dom = new DOMDocument;
1167 $dom->preserveWhiteSpace = false;
1168 $dom->loadXML($xml);
1169 $dom->formatOutput = true;
1170 $xml = $dom->saveXML();
1171
1172 return $xml;
1173 }
1174
1175 /**
1176 * Generates the report columns and rows, then it outputs a CSV file
1177 * for download. In case of errors, the process is not terminated (exit)
1178 * to let the View display the error message.
1179 * We use customExport() rather than exportCSV() only because we need a
1180 * different download button rather than the classic "Export as CSV".
1181 *
1182 * @param string $export_type Differentiates the type of export requested.
1183 *
1184 * @return void|bool Void in case of script termination, boolean otherwise.
1185 */
1186 public function customExport($export_type = 0)
1187 {
1188 if (!$this->getReportData()) {
1189 return false;
1190 }
1191
1192 $pfromdate = VikRequest::getString('fromdate', '', 'request');
1193 $ptodate = VikRequest::getString('todate', '', 'request');
1194 $pcodstru = VikRequest::getString('codstru', '', 'request');
1195 $papertura = VikRequest::getString('apertura', '', 'request');
1196
1197 $q = "SELECT SUM(`units`) AS `sommaunita`, SUM(`totpeople`) AS `numeropersone`, COUNT(*) AS `numerocamere` FROM `#__vikbooking_rooms` WHERE `avail`= '1';";
1198 $this->dbo->setQuery($q);
1199 $records = $this->dbo->loadAssocList();
1200
1201 $totalBeds = (int)($records[0]['sommaunita'] * ($records[0]['numeropersone']/$records[0]['numerocamere']));
1202 // filtro numero letti
1203 $pletti = VikRequest::getString('numletti', $totalBeds, 'request');
1204
1205 // manual values in filler
1206 $pfiller = VikRequest::getString('filler', '', 'request', VIKREQUEST_ALLOWRAW);
1207 $pfiller = !empty($pfiller) ? json_decode($pfiller, true) : array();
1208 $pfiller = !is_array($pfiller) ? array() : $pfiller;
1209
1210 // Debug
1211 if ($this->debug) {
1212 $this->setError('<pre>'.print_r($pfiller, true).'</pre><br/>');
1213 return false;
1214 }
1215
1216 $q = "SELECT SUM(`units`) FROM `#__vikbooking_rooms` WHERE `avail`= '1';";
1217 $this->dbo->setQuery($q);
1218 $this->dbo->execute();
1219 $totalRooms = $this->dbo->loadResult();
1220
1221 // pool of booking IDs to update their history
1222 $booking_ids = [];
1223 // update the history for all bookings affected
1224 foreach ($booking_ids as $bid) {
1225 VikBooking::getBookingHistoryInstance()->setBid($bid)->store('RP', $this->reportName);
1226 }
1227 $date = str_replace('/', '-', $pfromdate);
1228 $dataMovim = date('Ymd', strtotime($date));
1229
1230 $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";
1231 $numOccupiedrooms = 0;
1232
1233 $from_ts = VikBooking::getDateTimestamp($pfromdate, 0, 0);
1234 $to_ts = VikBooking::getDateTimestamp($pfromdate, 23, 59, 59);
1235
1236 $clienti = [
1237 'arrivi' => [],
1238 'partenze' => [],
1239 'prenotazioni' => [],
1240 ];
1241
1242 $q = "SELECT COUNT(`o`.`id`) AS `occ_rooms`,".
1243 "(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` ".
1244 "FROM `#__vikbooking_orders` AS `o` LEFT JOIN `#__vikbooking_ordersrooms` AS `or` ON `or`.`idorder`=`o`.`id` ".
1245 "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` ".
1246 "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.")) ".
1247 "ORDER BY `o`.`checkin` ASC, `o`.`id` ASC, `or`.`id` ASC;";
1248
1249 $this->dbo->setQuery($q);
1250 $data = $this->dbo->loadAssoc();
1251
1252 $arrivi = 0;
1253 $partenze = 0;
1254 $prenotazioni = 0;
1255
1256 if ($papertura == 'SI') {
1257 $xml .= '<struttura>' . "\n";
1258 $xml .= '<apertura>' . $papertura . '</apertura>' . "\n";
1259 $xml .= '<camereoccupate>' . $data['occ_rooms'] . '</camereoccupate>' . "\n";
1260 $xml .= '<cameredisponibili>' . $totalRooms . '</cameredisponibili>' . "\n";
1261 $xml .= '<lettidisponibili>' . $pletti . '</lettidisponibili>' . "\n";
1262 $xml .= '</struttura>' . "\n";
1263
1264 // counter for booking IDs
1265 $idswh_map = [];
1266
1267 foreach ($this->rows as $ind => $row) {
1268 $timestamp_in = -1;
1269 $timestamp_out = -1;
1270 $control = -1;
1271 // se il cliente è in arrivo il tipo è 1, se è in partenza 2, se è una nuova prenotazione 3
1272 $type = -1;
1273 $guest_lastname = '';
1274 $guest_firstname = '';
1275
1276 $fields_checkin = '';
1277
1278 foreach ($row as $fk => $field) {
1279 if (isset($field['ignore_export'])) {
1280 continue;
1281 }
1282 // check if a value for this field was filled in manually
1283 if (is_array($pfiller) && isset($pfiller[$ind]) && isset($pfiller[$ind][$field['key']])) {
1284 if (strlen($pfiller[$ind][$field['key']])) {
1285 $field['value'] = $pfiller[$ind][$field['key']];
1286 }
1287 }
1288 // values set to -1 are usually empty and should have been filled in manually
1289 if ($field['value'] === -1) {
1290 // we raise an error in this case without stopping the process
1291 $field['value'] = 0;
1292 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.');
1293 }
1294 if (isset($field['callback_export'])) {
1295 $field['callback'] = $field['callback_export'];
1296 }
1297 $export_value = !isset($field['no_export_callback']) && isset($field['callback']) && is_callable($field['callback']) ? $field['callback']($field['value']) : $field['value'];
1298
1299 if ($field['key'] == 'idbooking') {
1300 $idswh = $export_value;
1301
1302 if (!isset($idswh_map[$idswh])) {
1303 $idswh_map[$idswh] = 0;
1304 }
1305
1306 $idswh_map[$idswh]++;
1307 }
1308
1309 if ($field['key'] == 'checkin') {
1310 $fields_checkin = $export_value;
1311 $timestamp_in = VikBooking::getDateTimestamp($export_value);
1312 }
1313
1314 if ($field['key'] == 'checkout') {
1315 $timestamp_out = VikBooking::getDateTimestamp($export_value);
1316 }
1317
1318 if ($field['key'] == 'cognome') {
1319 $guest_lastname = $export_value;
1320 } elseif ($field['key'] == 'nome') {
1321 $guest_firstname = $export_value;
1322 }
1323
1324 if ($control == -1 && $timestamp_in != -1 && $timestamp_out != -1) {
1325 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)) {
1326 $type = 1;
1327 } 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)) {
1328 $type = 2;
1329 } else {
1330 $type = 3;
1331 }
1332 $control = 0;
1333 }
1334
1335 if ($type == 1) {
1336 $clienti['arrivi'][$arrivi]['idswh'] = $idswh;
1337 if ($field['key'] == 'tipo') {
1338 $clienti['arrivi'][$arrivi]['tipoalloggiato'] = (string)$export_value;
1339 if (in_array($clienti['arrivi'][$arrivi]['tipoalloggiato'], ['19', '20'])) {
1340 // obbligatorio fornire "idcapo"
1341 $clienti['arrivi'][$arrivi]['idcapo'] = $clienti['arrivi'][$arrivi]['idswh'];
1342 } else {
1343 // "idcapo" deve essere un valore vuoto
1344 $clienti['arrivi'][$arrivi]['idcapo'] = '';
1345 }
1346 }
1347
1348 $clienti['arrivi'][$arrivi]['cognome'] = $guest_firstname;
1349 $clienti['arrivi'][$arrivi]['nome'] = $guest_lastname;
1350
1351 if ($field['key'] == 'gender') {
1352 $clienti['arrivi'][$arrivi]['sesso'] = $export_value;
1353 }
1354 if ($field['key'] == 'turismo') {
1355 $clienti['arrivi'][$arrivi]['tipoturismo'] = !empty($export_value) && $export_value != '?' ? strtoupper($export_value) : 'Non specificato';
1356 }
1357 if ($field['key'] == 'mezzo') {
1358 $clienti['arrivi'][$arrivi]['mezzotrasporto'] = !empty($export_value) && $export_value != '?' ? strtoupper($export_value) : 'Non specificato';
1359 }
1360 if ($field['key'] == 'citizen') {
1361 $clienti['arrivi'][$arrivi]['cittadinanza'] = (string)$export_value;
1362 }
1363 if ($field['key'] == 'stares') {
1364 $clienti['arrivi'][$arrivi]['statoresidenza'] = (string)$export_value;
1365 if (empty($clienti['arrivi'][$arrivi]['statoresidenza']) && !empty($clienti['arrivi'][$arrivi]['cittadinanza'])) {
1366 // make sure the value is filled
1367 $clienti['arrivi'][$arrivi]['statoresidenza'] = $clienti['arrivi'][$arrivi]['cittadinanza'];
1368 }
1369 }
1370 if ($field['key'] == 'dbirth') {
1371 $datanascita = date('Ymd', (is_numeric($export_value) ? $export_value : VikBooking::getDateTimestamp($export_value)));
1372 $clienti['arrivi'][$arrivi]['datanascita'] = $datanascita;
1373 }
1374 if (isset($clienti['arrivi'][$arrivi]['statoresidenza']) && $clienti['arrivi'][$arrivi]['statoresidenza'] == '100000100' && $field['key'] == 'comres') {
1375 $clienti['arrivi'][$arrivi]['luogoresidenza'] = (string)$export_value;
1376 } elseif (isset($clienti['arrivi'][$arrivi]['statoresidenza']) && $field['key'] == 'comres') {
1377 // cliente estero, valore vuoto per luogo residenza
1378 $clienti['arrivi'][$arrivi]['luogoresidenza'] = !empty($export_value) ? $export_value : 'NUTS';
1379 }
1380 } elseif ($type == 2) {
1381 $clienti['partenze'][$partenze]['idswh'] = $idswh;
1382 if ($field['key'] == 'tipo') {
1383 $clienti['partenze'][$partenze]['tipoalloggiato'] = (string)$export_value;
1384 }
1385 if ($field['key'] == 'checkin' || $fields_checkin) {
1386 $arrivo = date('Ymd', VikBooking::getDateTimestamp(($fields_checkin ? $fields_checkin : $export_value)));
1387 $clienti['partenze'][$partenze]['arrivo'] = $arrivo;
1388 }
1389 } elseif ($type == 3) {
1390 $clienti['prenotazioni'][$prenotazioni]['idswh'] = $idswh;
1391 if ($field['key'] == 'checkin' || $fields_checkin) {
1392 $prenotazione = date('Ymd', VikBooking::getDateTimestamp(($fields_checkin ? $fields_checkin : $export_value)));
1393 $clienti['prenotazioni'][$prenotazioni]['arrivo'] = $prenotazione;
1394 }
1395 if ($field['key'] == 'checkout') {
1396 $partenza = date('Ymd', VikBooking::getDateTimestamp($export_value));
1397 $clienti['prenotazioni'][$prenotazioni]['partenza'] = $partenza;
1398 }
1399 if ($field['key'] == 'guestsnum') {
1400 $clienti['prenotazioni'][$prenotazioni]['ospiti'] = (string)$export_value;
1401 }
1402 if ($field['key'] == 'roomsbooked') {
1403 $clienti['prenotazioni'][$prenotazioni]['camere'] = (string)$export_value;
1404 }
1405 }
1406 }
1407
1408 if ($type == 1) {
1409 $arrivi++;
1410 } elseif ($type == 2) {
1411 $partenze++;
1412 } elseif ($type == 3){
1413 $prenotazioni++;
1414 }
1415 }
1416
1417 if (count($clienti['arrivi'])) {
1418 // sort fields accordingly
1419 $arrivals_sort = [
1420 'idswh',
1421 'tipoalloggiato',
1422 'idcapo',
1423 'cognome',
1424 'nome',
1425 'sesso',
1426 'cittadinanza',
1427 'statoresidenza',
1428 'luogoresidenza',
1429 'datanascita',
1430 'statonascita',
1431 'comunenascita',
1432 'tipoturismo',
1433 'mezzotrasporto',
1434 'canaleprenotazione',
1435 'titolostudio',
1436 'professione',
1437 'esenzioneimposta',
1438 ];
1439 $arrivals_sorted = [];
1440 foreach ($clienti['arrivi'] as $k => $arrivals) {
1441 $arrivals_sorted[$k] = [];
1442 foreach ($arrivals_sort as $arrive_key) {
1443 if (isset($arrivals[$arrive_key])) {
1444 $arrivals_sorted[$k][$arrive_key] = $arrivals[$arrive_key];
1445 }
1446 }
1447 }
1448 $clienti['arrivi'] = $arrivals_sorted;
1449 }
1450
1451 if (count($clienti['partenze'])) {
1452 // sort fields accordingly
1453 $departures_sort = [
1454 'idswh',
1455 'tipoalloggiato',
1456 'arrivo',
1457 ];
1458 $departures_sorted = [];
1459 foreach ($clienti['partenze'] as $k => $departures) {
1460 $departures_sorted[$k] = [];
1461 foreach ($departures_sort as $depart_key) {
1462 if (isset($departures[$depart_key])) {
1463 $departures_sorted[$k][$depart_key] = $departures[$depart_key];
1464 }
1465 }
1466 }
1467 $clienti['partenze'] = $departures_sorted;
1468 }
1469
1470 $used_idswh = [];
1471 $xml .= '<arrivi>'."\n";
1472 for ($i = 0; $i < count($clienti['arrivi']); $i++) {
1473 $xml .= '<arrivo>'."\n";
1474 foreach ($clienti['arrivi'][$i] as $key => $value) {
1475 $use_value = $value;
1476 if ($key == 'idswh') {
1477 if (!isset($used_idswh[$value])) {
1478 $used_idswh[$value] = 0;
1479 }
1480 $used_idswh[$value]++;
1481 $guest_idswh_num = $used_idswh[$value];
1482 $use_value .= "-{$guest_idswh_num}";
1483 }
1484 $xml .= "<{$key}>{$use_value}</{$key}>\n";
1485 }
1486 $xml .= '</arrivo>'."\n";
1487 }
1488 $xml .= '</arrivi>'."\n";
1489
1490 $xml .= '<partenze>'."\n";
1491 for ($i = 0; $i < count($clienti['partenze']); $i++) {
1492 $xml .= '<partenza>'."\n";
1493 foreach ($clienti['partenze'][$i] as $key => $value) {
1494 $use_value = $value;
1495 if ($key == 'idswh') {
1496 if (!isset($used_idswh[$value])) {
1497 $used_idswh[$value] = 0;
1498 }
1499 $used_idswh[$value]++;
1500 $guest_idswh_num = $used_idswh[$value];
1501 $use_value .= "-{$guest_idswh_num}";
1502 }
1503 $xml .= "<{$key}>{$use_value}</{$key}>\n";
1504 }
1505 $xml .= '</partenza>'."\n";
1506 }
1507 $xml .= '</partenze>'."\n";
1508
1509 if ($clienti['prenotazioni']) {
1510 $xml .= '<prenotazioni>'."\n";
1511 for ($i = 0; $i < count($clienti['prenotazioni']); $i++) {
1512 $xml .= '<prenotazione>'."\n";
1513 foreach ($clienti['prenotazioni'][$i] as $key => $value) {
1514 $use_value = $value;
1515 if ($key == 'idswh') {
1516 if (!isset($used_idswh[$value])) {
1517 $used_idswh[$value] = 0;
1518 }
1519 $used_idswh[$value]++;
1520 $guest_idswh_num = $used_idswh[$value];
1521 $use_value .= "-{$guest_idswh_num}";
1522 }
1523 $xml .= "<{$key}>{$use_value}</{$key}>\n";
1524 }
1525 $xml .= '</prenotazione>'."\n";
1526 }
1527 $xml .= '</prenotazioni>'."\n";
1528 }
1529 } else {
1530 $xml .= '<struttura>'."\n";
1531 $xml .= '<apertura>'.$papertura.'</apertura>'."\n";
1532 $xml .= '<camereoccupate>0</camereoccupate>'."\n";
1533 $xml .= '<cameredisponibili>0</cameredisponibili>'."\n";
1534 $xml .= '<lettidisponibili>0</lettidisponibili>'."\n";
1535 $xml .= '</struttura>'."\n";
1536 }
1537 $xml .= '</movimento> '."\n";
1538 $xml .= '</movimenti>';
1539
1540 // format XML document
1541 $this->formatXML($xml);
1542
1543 /**
1544 * Custom export method supports a custom export handler, if previously set.
1545 *
1546 * @since 1.16.1 (J) - 1.6.1 (WP)
1547 */
1548 if ($this->hasExportHandler()) {
1549 // write data onto the custom file handler
1550 $fp = $this->getExportCSVHandler();
1551 fwrite($fp, $xml);
1552 fclose($fp);
1553
1554 return true;
1555 }
1556
1557 header('Content-Disposition: attachment; filename=' . $this->getExportCSVFileName());
1558 header('Content-type: text/xml');
1559 echo $xml;
1560
1561 exit;
1562 }
1563
1564 /**
1565 * Helper method invoked via AJAX by the controller.
1566 * Needed to save the manual entries for the pax data.
1567 *
1568 * @param array $manual_data the object representation of the manual entries.
1569 *
1570 * @return array one boolean value array with the operation result.
1571 */
1572 public function updatePaxData($manual_data = [])
1573 {
1574 if (!is_array($manual_data) || !$manual_data) {
1575 VBOHttpDocument::getInstance()->close(400, 'Nothing to save!');
1576 }
1577
1578 // re-build manual entries object representation
1579 $bids_guests = [];
1580 foreach ($manual_data as $guest_ind => $guest_data) {
1581 if (!is_numeric($guest_ind) || !is_array($guest_data) || empty($guest_data['bid']) || !isset($guest_data['bid_index']) || count($guest_data) < 2) {
1582 // empty or invalid manual entries array
1583 continue;
1584 }
1585 // the guest index in the reportObj starts from 0
1586 $use_guest_ind = ($guest_ind + 1 - (int)$guest_data['bid_index']);
1587 if (!isset($bids_guests[$guest_data['bid']])) {
1588 $bids_guests[$guest_data['bid']] = [];
1589 }
1590 // set manual entries for this guest number
1591 $bids_guests[$guest_data['bid']][$use_guest_ind] = $guest_data;
1592 // remove the "bid" and "bid_index" keys
1593 unset($bids_guests[$guest_data['bid']][$use_guest_ind]['bid'], $bids_guests[$guest_data['bid']][$use_guest_ind]['bid_index']);
1594 }
1595
1596 if (!$bids_guests) {
1597 VBOHttpDocument::getInstance()->close(400, 'No manual entries to save found');
1598 }
1599
1600 // loop through all bookings to update the data for the various rooms and guests
1601 $bids_updated = 0;
1602 foreach ($bids_guests as $bid => $entries) {
1603 $b_rooms = VikBooking::loadOrdersRoomsData($bid);
1604 if (empty($b_rooms)) {
1605 continue;
1606 }
1607 // count guests per room
1608 $room_guests = [];
1609 foreach ($b_rooms as $b_room) {
1610 $room_guests[] = $b_room['adults'] + $b_room['children'];
1611 }
1612 // get current booking pax data
1613 $pax_data = VBOCheckinPax::getBookingPaxData($bid);
1614 $pax_data = empty($pax_data) ? [] : $pax_data;
1615 foreach ($entries as $guest_ind => $guest_data) {
1616 // find room index for this guest
1617 $room_num = 0;
1618 $use_guest_ind = $guest_ind;
1619 foreach ($room_guests as $room_index => $tot_guests) {
1620 // find the proper guest index for the room to which this belongs
1621 if ($use_guest_ind <= $tot_guests) {
1622 // proper room index found for this guest
1623 $room_num = $room_index;
1624 break;
1625 } else {
1626 // it's probably in a next room
1627 $use_guest_ind -= $tot_guests;
1628 }
1629 }
1630 // push new pax data for this room and guest
1631 if (!isset($pax_data[$room_num])) {
1632 $pax_data[$room_num] = [];
1633 }
1634 if (!isset($pax_data[$room_num][$use_guest_ind])) {
1635 $pax_data[$room_num][$use_guest_ind] = $guest_data;
1636 } else {
1637 $pax_data[$room_num][$use_guest_ind] = array_merge($pax_data[$room_num][$use_guest_ind], $guest_data);
1638 }
1639 }
1640 // update booking pax data
1641 if (VBOCheckinPax::setBookingPaxData($bid, $pax_data)) {
1642 $bids_updated++;
1643 }
1644 }
1645
1646 return $bids_updated ? [true] : [false];
1647 }
1648
1649 /**
1650 * Registers the name to give to the file being exported.
1651 *
1652 * @return void
1653 *
1654 * @since 1.16.1 (J) - 1.6.1 (WP)
1655 */
1656 protected function registerExportFileName()
1657 {
1658 $pfromdate = VikRequest::getString('fromdate', '', 'request');
1659 $ptodate = VikRequest::getString('todate', '', 'request');
1660
1661 $this->setExportCSVFileName(str_replace(' ', '_', $this->reportName) . '-' . str_replace('/', '_', $pfromdate) . '.xml');
1662 }
1663
1664 /**
1665 * Parses the file Comuni.csv and returns two associative
1666 * arrays: one for the Comuni and one for the Province.
1667 * Every line of the CSV is composed of: Codice, Comune, Provincia.
1668 *
1669 * @return array
1670 */
1671 private function loadComuniProvince()
1672 {
1673 $vals = array(
1674 'comuni' => array(
1675 0 => '-- Estero --'
1676 ),
1677 'province' => array(
1678 0 => '-- Estero --'
1679 )
1680 );
1681
1682 $csv = dirname(__FILE__).DIRECTORY_SEPARATOR.'Comuni.csv';
1683 $rows = file($csv);
1684 foreach ($rows as $row) {
1685 if (empty($row)) {
1686 continue;
1687 }
1688 $v = explode(';', $row);
1689 if (count($v) != 3) {
1690 continue;
1691 }
1692 $vals['comuni'][$v[0]]['name'] = $v[1];
1693 $vals['comuni'][$v[0]]['province'] = $v[2];
1694 $vals['province'][$v[2]] = $v[2];
1695 }
1696
1697 return $vals;
1698 }
1699
1700 /**
1701 * Parses the file Nazioni.csv and returns an associative
1702 * array with the code and name of the Nazione.
1703 * Every line of the CSV is composed of: Codice, Nazione.
1704 *
1705 * @return array
1706 */
1707 private function loadNazioni()
1708 {
1709 $nazioni = array();
1710
1711 $csv = dirname(__FILE__).DIRECTORY_SEPARATOR.'Nazioni.csv';
1712 $rows = file($csv);
1713 foreach ($rows as $row) {
1714 if (empty($row)) {
1715 continue;
1716 }
1717 $v = explode(';', $row);
1718 if (count($v) != 3) {
1719 continue;
1720 }
1721
1722 $nazioni[$v[0]]['name'] = $v[1];
1723 $nazioni[$v[0]]['three_code'] = $v[2];
1724
1725 }
1726
1727 return $nazioni;
1728 }
1729
1730 /**
1731 *
1732 * Returns an array that contains both name and key of the comune selected, plus the associated province.
1733 *
1734 * @return array
1735 */
1736 private function checkComune($combirth, $checked, $province)
1737 {
1738 $result = array();
1739 $first_found = '';
1740 if (!count($this->comuniProvince)) {
1741 $this->comuniProvince = $this->loadComuniProvince();
1742 }
1743 if (empty($combirth)) {
1744 return $result;
1745 }
1746 foreach ($this->comuniProvince['comuni'] as $key => $value) {
1747 if (!isset($value['name'])) {
1748 continue;
1749 }
1750 if ($value['name'] == $combirth) {
1751 $result['found'] = true;
1752 $result['combirth'] = $value['name'];
1753 $result['province'] = $value['province'];
1754 $result['comval'] = $key;
1755 $result['similar'] = false;
1756 break;
1757 } else if (strpos($value['name'], trim($combirth)) !== false && empty($first_found)) {
1758 $result['found'] = true;
1759 $result['combirth'] = $value['name'];
1760 $first_found = $key;
1761 $result['similar'] = true;
1762 $result['province'] = $value['province'];
1763 }
1764 }
1765 if (!$result['found']) {
1766 $result['combirth'] = '';
1767 }
1768
1769 if ($checked === true && strlen($province) > 0 && $result['found']) {
1770 $result['province'] = $province;
1771 if($province == $value['province']) {
1772 $result['provinceok'] = true;
1773 $result['province'] = $province;
1774 } else {
1775 $result['provinceok'] = false;
1776 }
1777 }
1778 if ($result['similar'] && $result['found']) {
1779 $result['comval'] = $first_found;
1780 }
1781
1782 return $result;
1783 }
1784
1785 /**
1786 *
1787 * Returns the key of the state selected by the user.
1788 *
1789 * @return string
1790 *
1791 */
1792 private function checkCountry($country)
1793 {
1794 $found = false;
1795 $staval = '';
1796
1797 if (!$this->nazioni) {
1798 $this->nazioni = $this->loadNazioni();
1799 }
1800
1801 if ($country && isset($this->nazioni[$country])) {
1802 return $country;
1803 }
1804
1805 foreach ($this->nazioni as $key => $value) {
1806 if (trim($value['three_code']) == trim($country)) {
1807 $staval = $key;
1808 $found = true;
1809 break;
1810 }
1811 }
1812
1813 if ($found !== true) {
1814 $staval = '';
1815 }
1816
1817 return $staval;
1818 }
1819
1820 /**
1821 * Sanitizes the "Comune": if comune contains also the province, example PRATO (PO),
1822 * then I set both Comune and Province and I check both of them with the checkComune() function.
1823 *
1824 * @return array
1825 */
1826 private function sanitizeComune($combirth)
1827 {
1828 $result = array();
1829
1830 if (strlen($combirth) > 2) {
1831 if (strpos($combirth, "(") !== false) {
1832 $comnas = explode("(", $combirth);
1833 $result['combirth'] = trim($comnas[0]);
1834 $result['province'] = $comnas[1];
1835 $result['province'] = str_replace(")", "", $result['province']);
1836 $result['checked'] = true;
1837 }
1838 } else if(strlen($combirth) > 0){
1839 $result['province'] = trim($combirth);
1840 $result['similar'] = true;
1841 }
1842 return $result;
1843 }
1844
1845 /**
1846 * Helper method to quickly get a pax_data property for the guest.
1847 *
1848 * @param array $pax_data the current pax_data stored.
1849 * @param array $guests list of total guests per room.
1850 * @param int $guest_ind the guest index.
1851 * @param string $key the pax_data key to look for.
1852 *
1853 * @return mixed null on failure or value fetched.
1854 */
1855 private function getGuestPaxDataValue($pax_data, $guests, $guest_ind, $key)
1856 {
1857 if (!is_array($pax_data) || !count($pax_data) || empty($key)) {
1858 return null;
1859 }
1860
1861 // find room index for this guest number
1862 $room_num = 0;
1863 $use_guest_ind = $guest_ind;
1864 foreach ($guests as $room_index => $room_tot_guests) {
1865 // find the proper guest index for the room to which this belongs
1866 if ($use_guest_ind <= $room_tot_guests) {
1867 // proper room index found for this guest
1868 $room_num = $room_index;
1869 break;
1870 } else {
1871 // it's probably in a next room
1872 $use_guest_ind -= $room_tot_guests;
1873 }
1874 }
1875
1876 // check if a value exists for the requested key in the found room and guest indexes
1877 if (isset($pax_data[$room_num]) && isset($pax_data[$room_num][$use_guest_ind])) {
1878 if (isset($pax_data[$room_num][$use_guest_ind][$key])) {
1879 // we've got a value previously stored
1880 return $pax_data[$room_num][$use_guest_ind][$key];
1881 }
1882 }
1883
1884 // nothing was found
1885 return null;
1886 }
1887
1888 /**
1889 * Helper method to determine the exact number for this guest in the room booked.
1890 *
1891 * @param array $guests list of total guests per room.
1892 * @param int $guest_ind the guest index.
1893 *
1894 * @return int the actual guest room index starting from 1.
1895 */
1896 private function calcGuestRoomIndex($guests, $guest_ind)
1897 {
1898 // find room index for this guest number
1899 $room_num = 0;
1900 $use_guest_ind = $guest_ind;
1901 foreach ($guests as $room_index => $room_tot_guests) {
1902 // find the proper guest index for the room to which this belongs
1903 if ($use_guest_ind <= $room_tot_guests) {
1904 // proper room index found for this guest
1905 $room_num = $room_index;
1906 break;
1907 } else {
1908 // it's probably in a next room
1909 $use_guest_ind -= $room_tot_guests;
1910 }
1911 }
1912
1913 return $use_guest_ind;
1914 }
1915 }
1916