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

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

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