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 / es_mossos_desquadra.php

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

2,588 lines 87.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package VikBooking
4 * @subpackage com_vikbooking
5 * @author Alessio Gaggii - E4J srl
6 * @copyright Copyright (C) 2025 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 * VikBookingReport implementation for (Catalonia - Spain) Mossos d'Esquadra.
15 *
16 * Property Managers from Catalonia are obliged to upload check-in information
17 * in TXT format to Mossos d'Esquadra, not to "SES Hospedajes" like the rest of Spain.
18 *
19 * @link https://registreviatgers.mossos.gencat.cat/mossos_hotels/AppJava/info.do?reqCode=listDocuments&docIdPare=2#reqCode=listDocuments&docIdPare=2
20 *
21 * @since 1.17.7 (J) - 1.7.7 (WP)
22 */
23 class VikBookingReportEsMossosDesquadra extends VikBookingReport
24 {
25 /**
26 * Property 'defaultKeySort' is used by the View that renders the report.
27 *
28 * @var string
29 */
30 public $defaultKeySort = 'idbooking';
31
32 /**
33 * Property 'defaultKeyOrder' is used by the View that renders the report.
34 *
35 * @var string
36 */
37 public $defaultKeyOrder = 'ASC';
38
39 /**
40 * Property 'customExport' is used by the View to display custom export buttons.
41 *
42 * @var string
43 */
44 public $customExport = '';
45
46 /**
47 * List of booking IDs affected by the export.
48 *
49 * @var array
50 */
51 protected $export_booking_ids = [];
52
53 /**
54 * Associative list of RELACIÓN DE PARENTESCO
55 *
56 * @var array
57 */
58 protected $relacion_de_parentesco = [
59 'AB' => 'Abuelo/a',
60 'BA' => 'Bisabuelo/a',
61 'BN' => 'Bisnieto/a',
62 'CD' => 'Cuñado/a',
63 'CY' => 'Cónyuge',
64 'HJ' => 'Hijo/a',
65 'HR' => 'Hermano/a',
66 'NI' => 'Nieto/a',
67 'PM' => 'Padre o madre',
68 'SB' => 'Sobrino/a',
69 'SG' => 'Suegro/a',
70 'TI' => 'Tío/a',
71 'YN' => 'Yerno o nuera',
72 'TU' => 'Tutor/a',
73 'OT' => 'Otro',
74 ];
75
76 /**
77 * Associative list of SEXO
78 *
79 * @var array
80 */
81 protected $sexo = [
82 'H' => 'Hombre',
83 'M' => 'Mujer',
84 'O' => 'Otro',
85 ];
86
87 /**
88 * Associative list of TIPOS DE DOCUMENTO
89 *
90 * @var array
91 */
92 protected $tipos_de_documento = [
93 'NIF' => 'NIF - Número de Identificación Fiscal',
94 'NIE' => 'NIE - Número de Identidad de Extranjero',
95 'PAS' => 'Número de pasaporte',
96 'OTRO' => 'Otro',
97 ];
98
99 /**
100 * Associative list of TIPOS DE ESTABLECIMIENTO
101 *
102 * @var array
103 */
104 protected $tipos_de_establecimiento = [
105 'ALBERGUE' => 'Albergue',
106 'APART' => 'Apartamento',
107 'APARTHOTEL' => 'Apartahotel',
108 'AP_RURAL' => 'Apartamento rural',
109 'BALNEARIO' => 'Balneario',
110 'CAMPING' => 'Camping',
111 'CASA_HUESP' => 'Casa de huéspedes',
112 'CASA_RURAL' => 'Casa rural',
113 'HOSTAL' => 'Hostal',
114 'HOTEL' => 'Hotel',
115 'H_RURAL' => 'Hotel rural',
116 'MOTEL' => 'Motel',
117 'OFIC_VEHIC' => 'Oficina de alquiler de vehículos',
118 'OTROS' => 'Otro',
119 'PARADOR' => 'Parador de turismo',
120 'PENSION' => 'Pensión',
121 'RESIDENCIA' => 'Residencia',
122 ];
123
124 /**
125 * Associative list of TIPOS DE PAGO
126 *
127 * @var array
128 */
129 protected $tipos_de_pago = [
130 'EFECT' => 'Efectivo',
131 'TARJT' => 'Tarjeta de crédito',
132 'PLATF' => 'Plataforma de pago',
133 'TRANS' => 'Transferencia',
134 'MOVIL' => 'Pago por móvil',
135 'TREG' => 'Tarjeta regalo',
136 'DESTI' => 'Pago en destino',
137 'OTRO' => 'Otros medios de pago',
138 ];
139
140 /**
141 * Class constructor should define the name of the report and
142 * other vars. Call the parent constructor to define the DB object.
143 */
144 public function __construct()
145 {
146 $this->reportFile = basename(__FILE__, '.php');
147 $this->reportName = 'Mossos d\'Esquadra - Catalonia';
148 $this->reportFilters = [];
149
150 $this->cols = [];
151 $this->rows = [];
152 $this->footerRow = [];
153
154 $this->registerExportFileName();
155
156 parent::__construct();
157 }
158
159 /**
160 * Returns the name of this report.
161 *
162 * @return string
163 */
164 public function getName()
165 {
166 return $this->reportName;
167 }
168
169 /**
170 * Returns the name of this file without .php.
171 *
172 * @return string
173 */
174 public function getFileName()
175 {
176 return $this->reportFile;
177 }
178
179 /**
180 * @inheritDoc
181 */
182 public function getSettingFields()
183 {
184 return [
185 'codigo' => [
186 'type' => 'text',
187 'label' => 'Código del establecimiento',
188 'help' => 'Identificador del establecimiento facilitado por los Mossos d\'Esquadra y que consta de 9 o 10 caracteres.',
189 ],
190 'nombre' => [
191 'type' => 'text',
192 'label' => 'Nombre establecimiento',
193 'help' => 'Insertar el nombre del establecimiento.',
194 ],
195 'sequence' => [
196 'type' => 'number',
197 'label' => 'Secuencia numérica transmisión',
198 'help' => 'Secuencia numérica para generar el siguiente archivo. El valor se incrementará automáticamente con cada generación del archivo.',
199 'default' => 1,
200 ],
201 ];
202 }
203
204 /**
205 * Returns the filters of this report.
206 *
207 * @return array
208 */
209 public function getFilters()
210 {
211 if ($this->reportFilters) {
212 // do not run this method twice, as it could load JS and CSS files.
213 return $this->reportFilters;
214 }
215
216 // get VBO Application Object
217 $vbo_app = VikBooking::getVboApplication();
218
219 // load the jQuery UI Datepicker
220 $this->loadDatePicker();
221
222 // custom export button
223 $this->customExport = '<a href="JavaScript: void(0);" onclick="vboDownloadMossosDesquadra();" class="vbcsvexport"><i class="'.VikBookingIcons::i('download').'"></i> <span>Download TXT</span></a>';
224
225 // build the hidden values for the selection of various fields.
226 $hidden_vals = '<div id="vbo-report-mossosdesquadra-hidden" style="display: none;">';
227
228 // build params container HTML structure
229 $hidden_vals .= '<div class="vbo-admin-container vbo-admin-container-full vbo-admin-container-compact">';
230 $hidden_vals .= ' <div class="vbo-params-wrap">';
231 $hidden_vals .= ' <div class="vbo-params-container">';
232 $hidden_vals .= ' <div class="vbo-params-block vbo-params-block-noborder">';
233
234 // tipos de pago
235 $hidden_vals .= ' <div id="vbo-report-mossosdesquadra-paytype" class="vbo-report-mossosdesquadra-selcont vbo-param-container" style="display: none;">';
236 $hidden_vals .= ' <div class="vbo-param-label">Tipo de pago</div>';
237 $hidden_vals .= ' <div class="vbo-param-setting">';
238 $hidden_vals .= ' <select id="choose-paytype" onchange="vboReportChosenTipodepago(this);"><option value=""></option>';
239 foreach ($this->tipos_de_pago as $code => $pago) {
240 $hidden_vals .= ' <option value="' . $code . '">' . $pago . '</option>' . "\n";
241 }
242 $hidden_vals .= ' </select>';
243 $hidden_vals .= ' </div>';
244 $hidden_vals .= ' </div>';
245
246 // Nacionalidad
247 $hidden_vals .= ' <div id="vbo-report-mossosdesquadra-nazione" class="vbo-report-mossosdesquadra-selcont vbo-param-container" style="display: none;">';
248 $hidden_vals .= ' <div class="vbo-param-label">Pais</div>';
249 $hidden_vals .= ' <div class="vbo-param-setting">';
250 $hidden_vals .= ' <select id="choose-nazione" onchange="vboReportChosenNacionalidad(this);"><option value=""></option>';
251 foreach (VikBooking::getCountriesArray() as $code => $country) {
252 $hidden_vals .= ' <option value="' . $code . '">' . $country['country_name'] . '</option>'."\n";
253 }
254 $hidden_vals .= ' </select>';
255 $hidden_vals .= ' </div>';
256 $hidden_vals .= ' </div>';
257
258 // tipos de documento
259 $hidden_vals .= ' <div id="vbo-report-mossosdesquadra-doctype" class="vbo-report-mossosdesquadra-selcont vbo-param-container" style="display: none;">';
260 $hidden_vals .= ' <div class="vbo-param-label">Tipos de documento</div>';
261 $hidden_vals .= ' <div class="vbo-param-setting">';
262 $hidden_vals .= ' <select id="choose-documento" onchange="vboReportChosenDocumento(this);"><option value=""></option>';
263 foreach ($this->tipos_de_documento as $code => $documento) {
264 $hidden_vals .= ' <option value="' . $code . '">' . $documento . '</option>' . "\n";
265 }
266 $hidden_vals .= ' </select>';
267 $hidden_vals .= ' </div>';
268 $hidden_vals .= ' </div>';
269
270 // relacion de parentesco
271 $hidden_vals .= ' <div id="vbo-report-mossosdesquadra-parentesco" class="vbo-report-mossosdesquadra-selcont vbo-param-container" style="display: none;">';
272 $hidden_vals .= ' <div class="vbo-param-label">Relacion de parentesco</div>';
273 $hidden_vals .= ' <div class="vbo-param-setting">';
274 $hidden_vals .= ' <select id="choose-parentesco" onchange="vboReportChosenParentesco(this);"><option value=""></option>';
275 foreach ($this->relacion_de_parentesco as $code => $val) {
276 $hidden_vals .= ' <option value="' . $code . '">' . $val . '</option>' . "\n";
277 }
278 $hidden_vals .= ' </select>';
279 $hidden_vals .= ' </div>';
280 $hidden_vals .= ' </div>';
281
282 // sexo
283 $hidden_vals .= ' <div id="vbo-report-mossosdesquadra-sesso" class="vbo-report-mossosdesquadra-selcont vbo-param-container" style="display: none;">';
284 $hidden_vals .= ' <div class="vbo-param-label">Sexo</div>';
285 $hidden_vals .= ' <div class="vbo-param-setting">';
286 $hidden_vals .= ' <select id="choose-sesso" onchange="vboReportChosenSesso(this);"><option value=""></option>';
287 foreach ($this->sexo as $code => $ses) {
288 $hidden_vals .= ' <option value="' . $code . '">' . $ses . '</option>' . "\n";
289 }
290 $hidden_vals .= ' </select>';
291 $hidden_vals .= ' </div>';
292 $hidden_vals .= ' </div>';
293
294 // id number
295 $hidden_vals .= ' <div id="vbo-report-mossosdesquadra-docnum" class="vbo-report-mossosdesquadra-selcont vbo-param-container" style="display: none;">';
296 $hidden_vals .= ' <div class="vbo-param-label">Número de documento</div>';
297 $hidden_vals .= ' <div class="vbo-param-setting">';
298 $hidden_vals .= ' <input type="text" size="40" id="choose-docnum" value="" />';
299 $hidden_vals .= ' </div>';
300 $hidden_vals .= ' </div>';
301
302 // número de soporte del documento
303 $hidden_vals .= ' <div id="vbo-report-mossosdesquadra-docsoporte" class="vbo-report-mossosdesquadra-selcont vbo-param-container" style="display: none;">';
304 $hidden_vals .= ' <div class="vbo-param-label">Número de soporte del documento</div>';
305 $hidden_vals .= ' <div class="vbo-param-setting">';
306 $hidden_vals .= ' <input type="text" size="40" id="choose-docsoporte" value="" />';
307 $hidden_vals .= ' <span class="vbo-param-setting-comment">Obligatorio si el tipo de documento es NIF, NIE.</span>';
308 $hidden_vals .= ' </div>';
309 $hidden_vals .= ' </div>';
310
311 // address
312 $hidden_vals .= ' <div id="vbo-report-mossosdesquadra-address" class="vbo-report-mossosdesquadra-selcont vbo-param-container" style="display: none;">';
313 $hidden_vals .= ' <div class="vbo-param-label">Direccion</div>';
314 $hidden_vals .= ' <div class="vbo-param-setting">';
315 $hidden_vals .= ' <input type="text" size="40" id="choose-address" value="" />';
316 $hidden_vals .= ' <span class="vbo-param-setting-comment">Calle, número, escalera, piso, puerta, y demás campos que indiquen la dirección.</span>';
317 $hidden_vals .= ' </div>';
318 $hidden_vals .= ' </div>';
319
320 // codigo municipio
321 $hidden_vals .= ' <div id="vbo-report-mossosdesquadra-municipio" class="vbo-report-mossosdesquadra-selcont vbo-param-container" style="display: none;">';
322 $hidden_vals .= ' <div class="vbo-param-label">Código de municipio</div>';
323 $hidden_vals .= ' <div class="vbo-param-setting">';
324 $hidden_vals .= ' <select id="choose-municipio" onchange="vboReportChosenMunicipio(this);"><option value=""></option>';
325 foreach (VBOCheckinPaxfieldTypeSpainMunicipio::loadMunicipioCodes() as $code => $val) {
326 $hidden_vals .= ' <option value="' . $code . '">' . $val . '</option>' . "\n";
327 }
328 $hidden_vals .= ' </select>';
329 $hidden_vals .= ' <span class="vbo-param-setting-comment">Este campo irá codificado con los códigos de municipios del INE (5 dígitos). Obligatorio cuando el país es España.</span>';
330 $hidden_vals .= ' </div>';
331 $hidden_vals .= ' </div>';
332
333 // city
334 $hidden_vals .= ' <div id="vbo-report-mossosdesquadra-city" class="vbo-report-mossosdesquadra-selcont vbo-param-container" style="display: none;">';
335 $hidden_vals .= ' <div class="vbo-param-label">Nombre del municipio</div>';
336 $hidden_vals .= ' <div class="vbo-param-setting">';
337 $hidden_vals .= ' <input type="text" size="40" id="choose-city" value="" />';
338 $hidden_vals .= ' <span class="vbo-param-setting-comment">Nombre del municipio, ciudad, estado, etc.. Obligatorio cuando el país no es España.</span>';
339 $hidden_vals .= ' </div>';
340 $hidden_vals .= ' </div>';
341
342 // postal code
343 $hidden_vals .= ' <div id="vbo-report-mossosdesquadra-postalcode" class="vbo-report-mossosdesquadra-selcont vbo-param-container" style="display: none;">';
344 $hidden_vals .= ' <div class="vbo-param-label">Código postal</div>';
345 $hidden_vals .= ' <div class="vbo-param-setting">';
346 $hidden_vals .= ' <input type="text" size="40" id="choose-postalcode" value="" />';
347 $hidden_vals .= ' </div>';
348 $hidden_vals .= ' </div>';
349
350 // phone
351 $hidden_vals .= ' <div id="vbo-report-mossosdesquadra-phone" class="vbo-report-mossosdesquadra-selcont vbo-param-container" style="display: none;">';
352 $hidden_vals .= ' <div class="vbo-param-label">Teléfono</div>';
353 $hidden_vals .= ' <div class="vbo-param-setting">';
354 $hidden_vals .= ' <input type="tel" size="40" id="choose-phone" value="" />';
355 $hidden_vals .= ' </div>';
356 $hidden_vals .= ' </div>';
357
358 // email
359 $hidden_vals .= ' <div id="vbo-report-mossosdesquadra-email" class="vbo-report-mossosdesquadra-selcont vbo-param-container" style="display: none;">';
360 $hidden_vals .= ' <div class="vbo-param-label">Dirección de correo electrónico</div>';
361 $hidden_vals .= ' <div class="vbo-param-setting">';
362 $hidden_vals .= ' <input type="email" size="40" id="choose-email" value="" />';
363 $hidden_vals .= ' </div>';
364 $hidden_vals .= ' </div>';
365
366 // birth date
367 $hidden_vals .= ' <div id="vbo-report-mossosdesquadra-dbirth" class="vbo-report-mossosdesquadra-selcont vbo-param-container" style="display: none;">';
368 $hidden_vals .= ' <div class="vbo-param-label">Data di nascita</div>';
369 $hidden_vals .= ' <div class="vbo-param-setting">';
370 $hidden_vals .= ' <input type="text" size="40" id="choose-dbirth" value="" />';
371 $hidden_vals .= ' </div>';
372 $hidden_vals .= ' </div>';
373
374 // close params container HTML structure
375 $hidden_vals .= ' </div>';
376 $hidden_vals .= ' </div>';
377 $hidden_vals .= ' </div>';
378 $hidden_vals .= '</div>';
379
380 // close hidden values container
381 $hidden_vals .= '</div>';
382
383 // From Date Filter (with hidden values for the dropdown menus of Comuni, Province, Stati etc..)
384 $filter_opt = array(
385 'label' => '<label for="fromdate">' . JText::translate('VBOREPORTSDATEFROM') . '</label>',
386 'html' => '<input type="text" id="fromdate" name="fromdate" value="" class="vbo-report-datepicker vbo-report-datepicker-from" />' . $hidden_vals,
387 'type' => 'calendar',
388 'name' => 'fromdate'
389 );
390 array_push($this->reportFilters, $filter_opt);
391
392 // To Date Filter
393 $filter_opt = array(
394 'label' => '<label for="todate">' . JText::translate('VBOREPORTSDATETO') . '</label>',
395 'html' => '<input type="text" id="todate" name="todate" value="" class="vbo-report-datepicker vbo-report-datepicker-to" />',
396 'type' => 'calendar',
397 'name' => 'todate'
398 );
399 array_push($this->reportFilters, $filter_opt);
400
401 // append button to save the data when creating manual values
402 $filter_opt = array(
403 'label' => '<label class="vbo-report-mossosdesquadra-manualsave" style="display: none;">Guests data</label>',
404 'html' => '<button type="button" class="btn vbo-config-btn vbo-report-mossosdesquadra-manualsave" style="display: none;" onclick="vboMossosDesquadraSaveData();"><i class="' . VikBookingIcons::i('save') . '"></i> ' . JText::translate('VBSAVE') . '</button>',
405 );
406 array_push($this->reportFilters, $filter_opt);
407
408 // datepicker calendars, select2 and triggers for the dropdown menus
409 $pfromdate = VikRequest::getString('fromdate', '', 'request');
410 $ptodate = VikRequest::getString('todate', '', 'request');
411
412 $js = 'var reportActiveCell = null, reportObj = {};
413 var vbo_mossosdesquadra_ajax_uri = "' . VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=invoke_report&report=' . $this->reportFile) . '";
414 var vbo_mossosdesquadra_save_icn = "' . VikBookingIcons::i('save') . '";
415 var vbo_mossosdesquadra_saving_icn = "' . VikBookingIcons::i('circle-notch', 'fa-spin fa-fw') . '";
416 var vbo_mossosdesquadra_saved_icn = "' . VikBookingIcons::i('check-circle') . '";
417 jQuery(function() {
418 //prepare main filters
419 jQuery(".vbo-report-datepicker:input").datepicker({
420 maxDate: "+7 days",
421 dateFormat: "'.$this->getDateFormat('jui').'",
422 onSelect: vboReportCheckDates
423 });
424 '.(!empty($pfromdate) ? 'jQuery(".vbo-report-datepicker-from").datepicker("setDate", "'.$pfromdate.'");' : '').'
425 '.(!empty($ptodate) ? 'jQuery(".vbo-report-datepicker-to").datepicker("setDate", "'.$ptodate.'");' : '').'
426 //prepare filler helpers
427 jQuery("#vbo-report-mossosdesquadra-hidden").children().detach().appendTo(".vbo-info-overlay-report");
428 jQuery("#choose-paytype").select2({placeholder: "- Tipo de pago -", width: "200px"});
429 jQuery("#choose-nazione").select2({placeholder: "- Seleccione un país -", width: "200px"});
430 jQuery("#choose-documento").select2({placeholder: "- Seleccione un tipo de documento -", width: "200px"});
431 jQuery("#choose-parentesco").select2({placeholder: "----", width: "200px"});
432 jQuery("#choose-municipio").select2({placeholder: "----", width: "200px"});
433 jQuery("#choose-sesso").select2({placeholder: "- Seleccione sexo -", width: "200px"});
434 jQuery("#choose-dbirth").datepicker({
435 maxDate: 0,
436 dateFormat: "dd/mm/yy",
437 changeMonth: true,
438 changeYear: true,
439 yearRange: "'.(date('Y') - 100).':'.date('Y').'"
440 });
441 //click events
442 jQuery(".vbo-report-load-nazione, .vbo-report-load-nazione-stay, .vbo-report-load-cittadinanza , .vbo-report-load-countrystay").click(function() {
443 reportActiveCell = this;
444 jQuery(".vbo-report-mossosdesquadra-selcont").hide();
445 jQuery("#vbo-report-mossosdesquadra-nazione").show();
446 vboShowOverlay({
447 title: "Completa la información",
448 extra_class: "vbo-modal-rounded vbo-modal-dialog vbo-modal-nofooter",
449 });
450 });
451 jQuery(".vbo-report-load-doctype").click(function() {
452 reportActiveCell = this;
453 jQuery(".vbo-report-mossosdesquadra-selcont").hide();
454 jQuery("#vbo-report-mossosdesquadra-doctype").show();
455 vboShowOverlay({
456 title: "Completa la información",
457 extra_class: "vbo-modal-rounded vbo-modal-dialog vbo-modal-nofooter",
458 });
459 });
460 jQuery(".vbo-report-load-paytype").click(function() {
461 reportActiveCell = this;
462 jQuery(".vbo-report-mossosdesquadra-selcont").hide();
463 jQuery("#vbo-report-mossosdesquadra-paytype").show();
464 vboShowOverlay({
465 title: "Completa la información",
466 extra_class: "vbo-modal-rounded vbo-modal-dialog vbo-modal-nofooter",
467 });
468 });
469 jQuery(".vbo-report-load-sesso").click(function() {
470 reportActiveCell = this;
471 jQuery(".vbo-report-mossosdesquadra-selcont").hide();
472 jQuery("#vbo-report-mossosdesquadra-sesso").show();
473 vboShowOverlay({
474 title: "Completa la información",
475 extra_class: "vbo-modal-rounded vbo-modal-dialog vbo-modal-nofooter",
476 });
477 });
478 jQuery(".vbo-report-load-docnum").click(function() {
479 reportActiveCell = this;
480 jQuery(".vbo-report-mossosdesquadra-selcont").hide();
481 jQuery("#vbo-report-mossosdesquadra-docnum").show();
482 vboShowOverlay({
483 title: "Completa la información",
484 extra_class: "vbo-modal-rounded vbo-modal-dialog",
485 footer_right: "<button type=\"button\" class=\"btn btn-success\" onclick=\"vboReportChosenDocnum(document.getElementById(\'choose-docnum\').value);\">Guardar</button>",
486 });
487 setTimeout(function(){jQuery("#choose-docnum").focus();}, 500);
488 });
489 jQuery(".vbo-report-load-docsoporte").click(function() {
490 reportActiveCell = this;
491 jQuery(".vbo-report-mossosdesquadra-selcont").hide();
492 jQuery("#vbo-report-mossosdesquadra-docsoporte").show();
493 vboShowOverlay({
494 title: "Completa la información",
495 extra_class: "vbo-modal-rounded vbo-modal-dialog",
496 footer_right: "<button type=\"button\" class=\"btn btn-success\" onclick=\"vboReportChosenDocsoporte(document.getElementById(\'choose-docsoporte\').value);\">Guardar</button>",
497 });
498 setTimeout(function(){jQuery("#choose-docsoporte").focus();}, 500);
499 });
500 jQuery(".vbo-report-load-address").click(function() {
501 reportActiveCell = this;
502 jQuery(".vbo-report-mossosdesquadra-selcont").hide();
503 jQuery("#vbo-report-mossosdesquadra-address").show();
504 vboShowOverlay({
505 title: "Completa la información",
506 extra_class: "vbo-modal-rounded vbo-modal-dialog",
507 footer_right: "<button type=\"button\" class=\"btn btn-success\" onclick=\"vboReportChosenAddress(document.getElementById(\'choose-address\').value);\">Guardar</button>",
508 });
509 setTimeout(function(){jQuery("#choose-address").focus();}, 500);
510 });
511 jQuery(".vbo-report-load-parentesco").click(function() {
512 reportActiveCell = this;
513 jQuery(".vbo-report-mossosdesquadra-selcont").hide();
514 jQuery("#vbo-report-mossosdesquadra-parentesco").show();
515 vboShowOverlay({
516 title: "Completa la información",
517 extra_class: "vbo-modal-rounded vbo-modal-dialog",
518 footer_right: "<button type=\"button\" class=\"btn btn-success\" onclick=\"vboReportChosenParentesco(document.getElementById(\'choose-parentesco\').value);\">Guardar</button>",
519 });
520 setTimeout(function(){jQuery("#choose-parentesco").focus();}, 500);
521 });
522 jQuery(".vbo-report-load-municipio").click(function() {
523 reportActiveCell = this;
524 jQuery(".vbo-report-mossosdesquadra-selcont").hide();
525 jQuery("#vbo-report-mossosdesquadra-municipio").show();
526 vboShowOverlay({
527 title: "Completa la información",
528 extra_class: "vbo-modal-rounded vbo-modal-dialog",
529 footer_right: "<button type=\"button\" class=\"btn btn-success\" onclick=\"vboReportChosenMunicipio(document.getElementById(\'choose-municipio\').value);\">Guardar</button>",
530 });
531 setTimeout(function(){jQuery("#choose-municipio").focus();}, 500);
532 });
533 jQuery(".vbo-report-load-city").click(function() {
534 reportActiveCell = this;
535 jQuery(".vbo-report-mossosdesquadra-selcont").hide();
536 jQuery("#vbo-report-mossosdesquadra-city").show();
537 vboShowOverlay({
538 title: "Completa la información",
539 extra_class: "vbo-modal-rounded vbo-modal-dialog",
540 footer_right: "<button type=\"button\" class=\"btn btn-success\" onclick=\"vboReportChosenCity(document.getElementById(\'choose-city\').value);\">Guardar</button>",
541 });
542 setTimeout(function(){jQuery("#choose-city").focus();}, 500);
543 });
544 jQuery(".vbo-report-load-postalcode").click(function() {
545 reportActiveCell = this;
546 jQuery(".vbo-report-mossosdesquadra-selcont").hide();
547 jQuery("#vbo-report-mossosdesquadra-postalcode").show();
548 vboShowOverlay({
549 title: "Completa la información",
550 extra_class: "vbo-modal-rounded vbo-modal-dialog",
551 footer_right: "<button type=\"button\" class=\"btn btn-success\" onclick=\"vboReportChosenPostalcode(document.getElementById(\'choose-postalcode\').value);\">Guardar</button>",
552 });
553 setTimeout(function(){jQuery("#choose-postalcode").focus();}, 500);
554 });
555 jQuery(".vbo-report-load-phone").click(function() {
556 reportActiveCell = this;
557 jQuery(".vbo-report-mossosdesquadra-selcont").hide();
558 jQuery("#vbo-report-mossosdesquadra-phone").show();
559 vboShowOverlay({
560 title: "Completa la información",
561 extra_class: "vbo-modal-rounded vbo-modal-dialog",
562 footer_right: "<button type=\"button\" class=\"btn btn-success\" onclick=\"vboReportChosenPhone(document.getElementById(\'choose-phone\').value);\">Guardar</button>",
563 });
564 setTimeout(function(){jQuery("#choose-phone").focus();}, 500);
565 });
566 jQuery(".vbo-report-load-email").click(function() {
567 reportActiveCell = this;
568 jQuery(".vbo-report-mossosdesquadra-selcont").hide();
569 jQuery("#vbo-report-mossosdesquadra-email").show();
570 vboShowOverlay({
571 title: "Completa la información",
572 extra_class: "vbo-modal-rounded vbo-modal-dialog",
573 footer_right: "<button type=\"button\" class=\"btn btn-success\" onclick=\"vboReportChosenEmail(document.getElementById(\'choose-email\').value);\">Guardar</button>",
574 });
575 setTimeout(function(){jQuery("#choose-email").focus();}, 500);
576 });
577 jQuery(".vbo-report-load-dbirth").click(function() {
578 reportActiveCell = this;
579 jQuery(".vbo-report-mossosdesquadra-selcont").hide();
580 jQuery("#vbo-report-mossosdesquadra-dbirth").show();
581 vboShowOverlay({
582 title: "Completa la información",
583 extra_class: "vbo-modal-rounded vbo-modal-dialog",
584 footer_right: "<button type=\"button\" class=\"btn btn-success\" onclick=\"vboReportChosenDbirth(document.getElementById(\'choose-dbirth\').value);\">Guardar</button>",
585 });
586 });
587 });
588 function vboReportCheckDates(selectedDate, inst) {
589 if (selectedDate === null || inst === null) {
590 return;
591 }
592 var cur_from_date = jQuery(this).val();
593 if (jQuery(this).hasClass("vbo-report-datepicker-from") && cur_from_date.length) {
594 var nowstart = jQuery(this).datepicker("getDate");
595 var nowstartdate = new Date(nowstart.getTime());
596 jQuery(".vbo-report-datepicker-to").datepicker("option", {minDate: nowstartdate});
597 }
598 }
599 function vboReportChosenTipodepago(pago) {
600 var c_code = pago.value;
601 var c_val = pago.options[pago.selectedIndex].text;
602
603 // apply the selected value to all guests of this booking
604 if (reportActiveCell !== null) {
605 var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr"));
606 if (isNaN(nowindex) || parseInt(nowindex) < 0) {
607 alert("Error, cannot find element to update.");
608 return false;
609 }
610 var rep_act_cell = jQuery(reportActiveCell);
611 var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid");
612 jQuery(\'[data-field="paytype"][data-fieldbid="\' + rep_guest_bid + \'"]\').each(function(k, v) {
613 let nowcell = jQuery(v);
614 nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(nowcell).closest("tr"));
615 nowcell.addClass("vbo-report-load-elem-filled").find("span").text(c_val);
616 if (!reportObj.hasOwnProperty(nowindex)) {
617 reportObj[nowindex] = {
618 bid: rep_guest_bid,
619 bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr"))
620 };
621 }
622 reportObj[nowindex]["paytype"] = c_code;
623 });
624 }
625
626 reportActiveCell = null;
627 vboHideOverlay();
628 jQuery("#choose-paytype").val("").select2("data", null, false);
629 jQuery(".vbo-report-mossosdesquadra-manualsave").show();
630 }
631 function vboReportChosenNacionalidad(naz) {
632 var c_code = naz.value;
633 var c_val = naz.options[naz.selectedIndex].text;
634 if (reportActiveCell !== null) {
635 var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr"));
636 if (isNaN(nowindex) || parseInt(nowindex) < 0) {
637 alert("Error, cannot find element to update.");
638 } else {
639 var rep_act_cell = jQuery(reportActiveCell);
640 rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val);
641 var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid");
642 if (!reportObj.hasOwnProperty(nowindex)) {
643 reportObj[nowindex] = {
644 bid: rep_guest_bid,
645 bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr"))
646 };
647 }
648 if (jQuery(reportActiveCell).hasClass("vbo-report-load-nazione")) {
649 reportObj[nowindex]["country_b"] = c_code;
650 } else if (jQuery(reportActiveCell).hasClass("vbo-report-load-nazione-stay")) {
651 reportObj[nowindex]["country_s"] = c_code;
652 } else if (jQuery(reportActiveCell).hasClass("vbo-report-load-docplace")) {
653 reportObj[nowindex]["docplace"] = c_code;
654 } else if (jQuery(reportActiveCell).hasClass("vbo-report-load-countrystay")) {
655 reportObj[nowindex]["country_s"] = c_code;
656 } else {
657 reportObj[nowindex]["country_c"] = c_code;
658 }
659 }
660 }
661 reportActiveCell = null;
662 vboHideOverlay();
663 jQuery("#choose-nazione").val("").select2("data", null, false);
664 jQuery(".vbo-report-mossosdesquadra-manualsave").show();
665 }
666 function vboReportChosenDocumento(doctype) {
667 var c_code = doctype.value;
668 var c_val = doctype.options[doctype.selectedIndex].text;
669 if (reportActiveCell !== null) {
670 var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr"));
671 if (isNaN(nowindex) || parseInt(nowindex) < 0) {
672 alert("Error, cannot find element to update.");
673 } else {
674 var rep_act_cell = jQuery(reportActiveCell);
675 rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val);
676 var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid");
677 if (!reportObj.hasOwnProperty(nowindex)) {
678 reportObj[nowindex] = {
679 bid: rep_guest_bid,
680 bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr"))
681 };
682 }
683 reportObj[nowindex]["doctype"] = c_code;
684 }
685 }
686 reportActiveCell = null;
687 vboHideOverlay();
688 jQuery("#choose-documento").val("").select2("data", null, false);
689 jQuery(".vbo-report-mossosdesquadra-manualsave").show();
690 }
691 function vboReportChosenParentesco(parentesco) {
692 var c_code = parentesco.value;
693 var c_val = parentesco.options[parentesco.selectedIndex].text;
694 if (reportActiveCell !== null) {
695 var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr"));
696 if (isNaN(nowindex) || parseInt(nowindex) < 0) {
697 alert("Error, cannot find element to update.");
698 } else {
699 var rep_act_cell = jQuery(reportActiveCell);
700 rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val);
701 var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid");
702 if (!reportObj.hasOwnProperty(nowindex)) {
703 reportObj[nowindex] = {
704 bid: rep_guest_bid,
705 bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr"))
706 };
707 }
708 reportObj[nowindex]["parentesco"] = c_code;
709 }
710 }
711 reportActiveCell = null;
712 vboHideOverlay();
713 jQuery("#choose-parentesco").val("").select2("data", null, false);
714 jQuery(".vbo-report-mossosdesquadra-manualsave").show();
715 }
716 function vboReportChosenSesso(sesso) {
717 var c_code = sesso.value;
718 var c_val = sesso.options[sesso.selectedIndex].text;
719 if (reportActiveCell !== null) {
720 var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr"));
721 if (isNaN(nowindex) || parseInt(nowindex) < 0) {
722 alert("Error, cannot find element to update.");
723 } else {
724 var rep_act_cell = jQuery(reportActiveCell);
725 rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val);
726 var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid");
727 if (!reportObj.hasOwnProperty(nowindex)) {
728 reportObj[nowindex] = {
729 bid: rep_guest_bid,
730 bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr"))
731 };
732 }
733 reportObj[nowindex]["gender"] = c_code;
734 }
735 }
736 reportActiveCell = null;
737 vboHideOverlay();
738 jQuery("#choose-sesso").val("").select2("data", null, false);
739 jQuery(".vbo-report-mossosdesquadra-manualsave").show();
740 }
741 function vboReportChosenDocnum(val) {
742 var c_code = val, c_val = val;
743 if (reportActiveCell !== null) {
744 var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr"));
745 if (isNaN(nowindex) || parseInt(nowindex) < 0) {
746 alert("Error, cannot find element to update.");
747 } else {
748 var rep_act_cell = jQuery(reportActiveCell);
749 rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val);
750 var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid");
751 if (!reportObj.hasOwnProperty(nowindex)) {
752 reportObj[nowindex] = {
753 bid: rep_guest_bid,
754 bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr"))
755 };
756 }
757 reportObj[nowindex]["docnum"] = c_code;
758 }
759 }
760 reportActiveCell = null;
761 vboHideOverlay();
762 jQuery("#choose-docnum").val("");
763 jQuery(".vbo-report-mossosdesquadra-manualsave").show();
764 }
765 function vboReportChosenDocsoporte(val) {
766 var c_code = val, c_val = val;
767 if (reportActiveCell !== null) {
768 var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr"));
769 if (isNaN(nowindex) || parseInt(nowindex) < 0) {
770 alert("Error, cannot find element to update.");
771 } else {
772 var rep_act_cell = jQuery(reportActiveCell);
773 rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val);
774 var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid");
775 if (!reportObj.hasOwnProperty(nowindex)) {
776 reportObj[nowindex] = {
777 bid: rep_guest_bid,
778 bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr"))
779 };
780 }
781 reportObj[nowindex]["docsoporte"] = c_code;
782 }
783 }
784 reportActiveCell = null;
785 vboHideOverlay();
786 jQuery("#choose-docsoporte").val("");
787 jQuery(".vbo-report-mossosdesquadra-manualsave").show();
788 }
789 function vboReportChosenAddress(val) {
790 var c_code = val, c_val = val;
791 if (reportActiveCell !== null) {
792 var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr"));
793 if (isNaN(nowindex) || parseInt(nowindex) < 0) {
794 alert("Error, cannot find element to update.");
795 } else {
796 var rep_act_cell = jQuery(reportActiveCell);
797 rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val);
798 var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid");
799 if (!reportObj.hasOwnProperty(nowindex)) {
800 reportObj[nowindex] = {
801 bid: rep_guest_bid,
802 bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr"))
803 };
804 }
805 reportObj[nowindex]["address"] = c_code;
806 }
807 }
808 reportActiveCell = null;
809 vboHideOverlay();
810 jQuery("#choose-address").val("");
811 jQuery(".vbo-report-mossosdesquadra-manualsave").show();
812 }
813 function vboReportChosenMunicipio(municipio) {
814 var c_code = municipio.value;
815 var c_val = municipio.options[municipio.selectedIndex].text;
816 if (reportActiveCell !== null) {
817 var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr"));
818 if (isNaN(nowindex) || parseInt(nowindex) < 0) {
819 alert("Error, cannot find element to update.");
820 } else {
821 var rep_act_cell = jQuery(reportActiveCell);
822 rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val);
823 var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid");
824 if (!reportObj.hasOwnProperty(nowindex)) {
825 reportObj[nowindex] = {
826 bid: rep_guest_bid,
827 bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr"))
828 };
829 }
830 reportObj[nowindex]["municipio"] = c_code;
831 }
832 }
833 reportActiveCell = null;
834 vboHideOverlay();
835 jQuery("#choose-municipio").val("").select2("data", null, false);
836 jQuery(".vbo-report-mossosdesquadra-manualsave").show();
837 }
838 function vboReportChosenCity(val) {
839 var c_code = val, c_val = val;
840 if (reportActiveCell !== null) {
841 var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr"));
842 if (isNaN(nowindex) || parseInt(nowindex) < 0) {
843 alert("Error, cannot find element to update.");
844 } else {
845 var rep_act_cell = jQuery(reportActiveCell);
846 rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val);
847 var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid");
848 if (!reportObj.hasOwnProperty(nowindex)) {
849 reportObj[nowindex] = {
850 bid: rep_guest_bid,
851 bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr"))
852 };
853 }
854 reportObj[nowindex]["city"] = c_code;
855 }
856 }
857 reportActiveCell = null;
858 vboHideOverlay();
859 jQuery("#choose-city").val("");
860 jQuery(".vbo-report-mossosdesquadra-manualsave").show();
861 }
862 function vboReportChosenPostalcode(val) {
863 var c_code = val, c_val = val;
864 if (reportActiveCell !== null) {
865 var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr"));
866 if (isNaN(nowindex) || parseInt(nowindex) < 0) {
867 alert("Error, cannot find element to update.");
868 } else {
869 var rep_act_cell = jQuery(reportActiveCell);
870 rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val);
871 var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid");
872 if (!reportObj.hasOwnProperty(nowindex)) {
873 reportObj[nowindex] = {
874 bid: rep_guest_bid,
875 bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr"))
876 };
877 }
878 reportObj[nowindex]["postalcode"] = c_code;
879 }
880 }
881 reportActiveCell = null;
882 vboHideOverlay();
883 jQuery("#choose-postalcode").val("");
884 jQuery(".vbo-report-mossosdesquadra-manualsave").show();
885 }
886 function vboReportChosenPhone(val) {
887 var c_code = val, c_val = val;
888 if (reportActiveCell !== null) {
889 var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr"));
890 if (isNaN(nowindex) || parseInt(nowindex) < 0) {
891 alert("Error, cannot find element to update.");
892 } else {
893 var rep_act_cell = jQuery(reportActiveCell);
894 rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val);
895 var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid");
896 if (!reportObj.hasOwnProperty(nowindex)) {
897 reportObj[nowindex] = {
898 bid: rep_guest_bid,
899 bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr"))
900 };
901 }
902 reportObj[nowindex]["phone"] = c_code;
903 }
904 }
905 reportActiveCell = null;
906 vboHideOverlay();
907 jQuery("#choose-phone").val("");
908 jQuery(".vbo-report-mossosdesquadra-manualsave").show();
909 }
910 function vboReportChosenEmail(val) {
911 var c_code = val, c_val = val;
912 if (reportActiveCell !== null) {
913 var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr"));
914 if (isNaN(nowindex) || parseInt(nowindex) < 0) {
915 alert("Error, cannot find element to update.");
916 } else {
917 var rep_act_cell = jQuery(reportActiveCell);
918 rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val);
919 var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid");
920 if (!reportObj.hasOwnProperty(nowindex)) {
921 reportObj[nowindex] = {
922 bid: rep_guest_bid,
923 bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr"))
924 };
925 }
926 reportObj[nowindex]["email"] = c_code;
927 }
928 }
929 reportActiveCell = null;
930 vboHideOverlay();
931 jQuery("#choose-email").val("");
932 jQuery(".vbo-report-mossosdesquadra-manualsave").show();
933 }
934 function vboReportChosenDbirth(val) {
935 var c_code = val, c_val = val;
936 if (reportActiveCell !== null) {
937 var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr"));
938 if (isNaN(nowindex) || parseInt(nowindex) < 0) {
939 alert("Error, cannot find element to update.");
940 } else {
941 var rep_act_cell = jQuery(reportActiveCell);
942 rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val);
943 var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid");
944 if (!reportObj.hasOwnProperty(nowindex)) {
945 reportObj[nowindex] = {
946 bid: rep_guest_bid,
947 bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr"))
948 };
949 }
950 reportObj[nowindex]["date_birth"] = c_code;
951 }
952 }
953 reportActiveCell = null;
954 vboHideOverlay();
955 jQuery("#choose-dbirth").val("");
956 jQuery(".vbo-report-mossosdesquadra-manualsave").show();
957 }
958 //download function
959 function vboDownloadMossosDesquadra(type, report_type) {
960 if (!confirm("¿Estás seguro de que quieres continuar?")) {
961 return false;
962 }
963
964 let use_blank = true;
965 if (typeof type === "undefined") {
966 type = 1;
967 } else {
968 use_blank = false;
969 }
970
971 if (typeof report_type !== "undefined") {
972 jQuery(\'#adminForm\').find(\'select[name="type"]\').val(report_type).trigger(\'change\');
973 }
974
975 if (use_blank) {
976 document.adminForm.target = "_blank";
977 document.adminForm.action += "&tmpl=component";
978 }
979
980 vboSetFilters({exportreport: type, filler: JSON.stringify(reportObj)}, true);
981
982 setTimeout(function() {
983 document.adminForm.target = "";
984 document.adminForm.action = document.adminForm.action.replace("&tmpl=component", "");
985 vboSetFilters({exportreport: "0", filler: ""}, false);
986 }, 1000);
987 }
988 // save data function
989 function vboMossosDesquadraSaveData() {
990 jQuery("button.vbo-report-mossosdesquadra-manualsave").find("i").attr("class", vbo_mossosdesquadra_saving_icn);
991 VBOCore.doAjax(
992 vbo_mossosdesquadra_ajax_uri,
993 {
994 call: "updatePaxData",
995 params: reportObj,
996 tmpl: "component"
997 },
998 function(response) {
999 if (!response || !response[0]) {
1000 alert("An error occurred.");
1001 return false;
1002 }
1003 jQuery("button.vbo-report-mossosdesquadra-manualsave").addClass("btn-success").find("i").attr("class", vbo_mossosdesquadra_saved_icn);
1004 },
1005 function(error) {
1006 alert(error.responseText);
1007 jQuery("button.vbo-report-mossosdesquadra-manualsave").removeClass("btn-success").find("i").attr("class", vbo_mossosdesquadra_save_icn);
1008 }
1009 );
1010 }
1011 ';
1012 $this->setScript($js);
1013
1014 return $this->reportFilters;
1015 }
1016
1017 /**
1018 * Loads the report data from the DB.
1019 * Returns true in case of success, false otherwise.
1020 * Sets the columns and rows for the report to be displayed.
1021 *
1022 * @return boolean
1023 */
1024 public function getReportData()
1025 {
1026 if ($this->getError()) {
1027 // export functions may set errors rather than exiting the process, and
1028 // the View may continue the execution to attempt to render the report.
1029 return false;
1030 }
1031
1032 if ($this->rows) {
1033 // method must have run already
1034 return true;
1035 }
1036
1037 // get the possibly injected report options
1038 $options = $this->getReportOptions();
1039
1040 // injected options will replace request variables, if any
1041 $opt_fromdate = $options->get('fromdate', '');
1042 $opt_todate = $options->get('todate', '');
1043
1044 // input fields and other vars
1045 $pfromdate = $opt_fromdate ?: VikRequest::getString('fromdate', '', 'request');
1046 $ptodate = $opt_todate ?: VikRequest::getString('todate', '', 'request');
1047
1048 $pkrsort = VikRequest::getString('krsort', $this->defaultKeySort, 'request');
1049 $pkrsort = empty($pkrsort) ? $this->defaultKeySort : $pkrsort;
1050 $pkrorder = VikRequest::getString('krorder', $this->defaultKeyOrder, 'request');
1051 $pkrorder = empty($pkrorder) ? $this->defaultKeyOrder : $pkrorder;
1052 $pkrorder = $pkrorder == 'DESC' ? 'DESC' : 'ASC';
1053
1054 $currency_symb = VikBooking::getCurrencySymb();
1055 $df = $this->getDateFormat();
1056 $datesep = VikBooking::getDateSeparator();
1057
1058 if (empty($ptodate)) {
1059 $ptodate = $pfromdate;
1060 }
1061
1062 // get date timestamps
1063 $from_ts = VikBooking::getDateTimestamp($pfromdate, 0, 0);
1064 $to_ts = VikBooking::getDateTimestamp($ptodate, 23, 59, 59);
1065 if (empty($pfromdate) || empty($from_ts) || empty($to_ts)) {
1066 $this->setError(JText::translate('VBOREPORTSERRNODATES'));
1067 return false;
1068 }
1069
1070 // query to obtain the records (all check-ins or reservations created within the dates filter)
1071 $q = $this->dbo->getQuery(true)
1072 ->select([
1073 $this->dbo->qn('o.id'),
1074 $this->dbo->qn('o.custdata'),
1075 $this->dbo->qn('o.ts'),
1076 $this->dbo->qn('o.days'),
1077 $this->dbo->qn('o.checkin'),
1078 $this->dbo->qn('o.checkout'),
1079 $this->dbo->qn('o.totpaid'),
1080 $this->dbo->qn('o.roomsnum'),
1081 $this->dbo->qn('o.total'),
1082 $this->dbo->qn('o.idorderota'),
1083 $this->dbo->qn('o.channel'),
1084 $this->dbo->qn('o.country'),
1085 $this->dbo->qn('o.custmail'),
1086 $this->dbo->qn('o.phone'),
1087 $this->dbo->qn('or.idorder'),
1088 $this->dbo->qn('or.idroom'),
1089 $this->dbo->qn('or.adults'),
1090 $this->dbo->qn('or.children'),
1091 $this->dbo->qn('or.t_first_name'),
1092 $this->dbo->qn('or.t_last_name'),
1093 $this->dbo->qn('or.cust_cost'),
1094 $this->dbo->qn('or.cust_idiva'),
1095 $this->dbo->qn('or.extracosts'),
1096 $this->dbo->qn('or.room_cost'),
1097 $this->dbo->qn('co.idcustomer'),
1098 $this->dbo->qn('co.pax_data'),
1099 $this->dbo->qn('c.first_name'),
1100 $this->dbo->qn('c.last_name'),
1101 $this->dbo->qn('c.country', 'customer_country'),
1102 $this->dbo->qn('c.address'),
1103 $this->dbo->qn('c.doctype'),
1104 $this->dbo->qn('c.docnum'),
1105 $this->dbo->qn('c.gender'),
1106 $this->dbo->qn('c.bdate'),
1107 $this->dbo->qn('c.pbirth'),
1108 ])
1109 ->from($this->dbo->qn('#__vikbooking_orders', 'o'))
1110 ->leftJoin($this->dbo->qn('#__vikbooking_ordersrooms', 'or') . ' ON ' . $this->dbo->qn('or.idorder') . ' = ' . $this->dbo->qn('o.id'))
1111 ->leftJoin($this->dbo->qn('#__vikbooking_customers_orders', 'co') . ' ON ' . $this->dbo->qn('co.idorder') . ' = ' . $this->dbo->qn('o.id'))
1112 ->leftJoin($this->dbo->qn('#__vikbooking_customers', 'c') . ' ON ' . $this->dbo->qn('c.id') . ' = ' . $this->dbo->qn('co.idcustomer'))
1113 ->where($this->dbo->qn('o.status') . ' = ' . $this->dbo->q('confirmed'))
1114 ->where($this->dbo->qn('o.closure') . ' = 0')
1115 ->where($this->dbo->qn('o.checkin') . ' >= ' . $from_ts)
1116 ->where($this->dbo->qn('o.checkin') . ' <= ' . $to_ts)
1117 ->order($this->dbo->qn('o.checkin') . ' ASC')
1118 ->order($this->dbo->qn('o.id') . ' ASC')
1119 ->order($this->dbo->qn('or.id') . ' ASC');
1120
1121 $this->dbo->setQuery($q);
1122 $records = $this->dbo->loadAssocList();
1123
1124 if (!$records) {
1125 $this->setError(JText::translate('VBOREPORTSERRNORESERV'));
1126 $this->setError('No hay reservas con los filtros seleccionados.');
1127 return false;
1128 }
1129
1130 // nest records with multiple rooms booked inside sub-array
1131 $bookings = [];
1132 foreach ($records as $v) {
1133 if (!isset($bookings[$v['id']])) {
1134 $bookings[$v['id']] = [];
1135 }
1136 array_push($bookings[$v['id']], $v);
1137 }
1138
1139 // free some memory up
1140 unset($records);
1141
1142 // define the columns of the report
1143 $this->cols = array(
1144 // first name
1145 array(
1146 'key' => 'first_name',
1147 'label' => JText::translate('VBTRAVELERNAME'),
1148 ),
1149 // last name
1150 array(
1151 'key' => 'last_name',
1152 'label' => JText::translate('VBTRAVELERLNAME'),
1153 ),
1154 // reservation date
1155 array(
1156 'key' => 'resdate',
1157 'attr' => array(
1158 'class="center"'
1159 ),
1160 'label' => JText::translate('VBPCHOOSEBUSYORDATE'),
1161 'ignore_view' => 1,
1162 ),
1163 // check-in date
1164 array(
1165 'key' => 'checkindate',
1166 'attr' => array(
1167 'class="center"'
1168 ),
1169 'label' => JText::translate('VBPICKUPAT'),
1170 'ignore_view' => 1,
1171 ),
1172 // check-in time
1173 array(
1174 'key' => 'checkintime',
1175 'attr' => array(
1176 'class="center"'
1177 ),
1178 'label' => 'Check-in time',
1179 'ignore_view' => 1,
1180 ),
1181 // check-out date
1182 array(
1183 'key' => 'checkoutdate',
1184 'attr' => array(
1185 'class="center"'
1186 ),
1187 'label' => JText::translate('VBRELEASEAT'),
1188 'ignore_view' => 1,
1189 ),
1190 // check-out time
1191 array(
1192 'key' => 'checkouttime',
1193 'attr' => array(
1194 'class="center"'
1195 ),
1196 'label' => 'Check-out time',
1197 'ignore_view' => 1,
1198 ),
1199 // number of guests
1200 array(
1201 'key' => 'numguests',
1202 'attr' => array(
1203 'class="center"'
1204 ),
1205 'label' => JText::translate('VBPVIEWORDERSPEOPLE'),
1206 'ignore_view' => 1,
1207 ),
1208 // sexo
1209 array(
1210 'key' => 'gender',
1211 'attr' => array(
1212 'class="center"'
1213 ),
1214 'label' => JText::translate('VBCUSTOMERGENDER'),
1215 ),
1216 // id type
1217 array(
1218 'key' => 'doctype',
1219 'attr' => array(
1220 'class="center"'
1221 ),
1222 'label' => JText::translate('VBCUSTOMERDOCTYPE'),
1223 ),
1224 // id number
1225 array(
1226 'key' => 'docnum',
1227 'attr' => array(
1228 'class="center"'
1229 ),
1230 'label' => JText::translate('VBCUSTOMERDOCNUM'),
1231 ),
1232 // número de soporte del documento
1233 array(
1234 'key' => 'docsoporte',
1235 'attr' => array(
1236 'class="center"'
1237 ),
1238 'label' => 'Número de soporte',
1239 'tip' => 'Número de soporte del documento. Obligatorio si el tipo de documento es NIF, NIE.',
1240 ),
1241 // birth date
1242 array(
1243 'key' => 'date_birth',
1244 'attr' => array(
1245 'class="center"'
1246 ),
1247 'label' => JText::translate('VBCUSTOMERBDATE'),
1248 ),
1249 // parentesco
1250 array(
1251 'key' => 'parentesco',
1252 'label' => 'Parentesco',
1253 'attr' => array(
1254 'class="center"'
1255 ),
1256 'tip' => 'Si alguna de las personas es menor de edad, al menos una de las personas mayores de edad ha de tener informada su relación de parentesco con esta persona menor de edad.',
1257 ),
1258 // address
1259 array(
1260 'key' => 'address',
1261 'attr' => array(
1262 'class="center"'
1263 ),
1264 'label' => JText::translate('ORDER_ADDRESS'),
1265 ),
1266 // codigo municipio
1267 array(
1268 'key' => 'municipio',
1269 'label' => 'Municipio',
1270 'attr' => array(
1271 'class="center"'
1272 ),
1273 'tip' => 'Código de municipio del INE (5 dígitos). Obligatorio cuando el país es España.',
1274 ),
1275 // city
1276 array(
1277 'key' => 'city',
1278 'label' => JText::translate('ORDER_CITY'),
1279 ),
1280 // postal code
1281 array(
1282 'key' => 'postalcode',
1283 'attr' => array(
1284 'class="center"'
1285 ),
1286 'label' => JText::translate('ORDER_ZIP'),
1287 ),
1288 // country of stay
1289 array(
1290 'key' => 'country_s',
1291 'attr' => array(
1292 'class="center"'
1293 ),
1294 'label' => JText::translate('ORDER_STATE'),
1295 ),
1296 // citizenship
1297 array(
1298 'key' => 'country_c',
1299 'attr' => array(
1300 'class="center"'
1301 ),
1302 'label' => JText::translate('VBCUSTOMERNATION'),
1303 ),
1304 // phone
1305 array(
1306 'key' => 'phone',
1307 'attr' => array(
1308 'class="center"'
1309 ),
1310 'label' => JText::translate('ORDER_PHONE'),
1311 ),
1312 // email
1313 array(
1314 'key' => 'email',
1315 'attr' => array(
1316 'class="center"'
1317 ),
1318 'label' => JText::translate('ORDER_EMAIL'),
1319 ),
1320 // payment type
1321 array(
1322 'key' => 'paytype',
1323 'attr' => array(
1324 'class="center"'
1325 ),
1326 'label' => JText::translate('VBLIBPAYNAME'),
1327 ),
1328 // check-in
1329 array(
1330 'key' => 'checkin',
1331 'attr' => array(
1332 'class="center"'
1333 ),
1334 'label' => JText::translate('VBPICKUPAT'),
1335 ),
1336 // check-out
1337 array(
1338 'key' => 'checkout',
1339 'attr' => array(
1340 'class="center"'
1341 ),
1342 'label' => JText::translate('VBRELEASEAT'),
1343 ),
1344 // id booking
1345 array(
1346 'key' => 'idbooking',
1347 'attr' => array(
1348 'class="center"'
1349 ),
1350 'label' => 'ID',
1351 ),
1352 );
1353
1354 // codigo municipio list
1355 $municipio_codes_list = VBOCheckinPaxfieldTypeSpainMunicipio::loadMunicipioCodes();
1356
1357 // codigo municipio 6-digit list
1358 $municipio_sixdigit_codes_list = VBOCheckinPaxfieldTypeSpainMunicipio::loadMunicipioSixDigitCodes();
1359
1360 // loop over the bookings to build the rows of the report
1361 $from_info = getdate($from_ts);
1362 foreach ($bookings as $gbook) {
1363 // count the total number of guests for all rooms of this booking
1364 $tot_booking_guests = 0;
1365 $tot_booking_adults = 0;
1366 $tot_booking_children = 0;
1367 $room_guests = [];
1368 foreach ($gbook as $rbook) {
1369 $tot_booking_guests += ($rbook['adults'] + $rbook['children']);
1370 $tot_booking_adults += $rbook['adults'];
1371 $tot_booking_children += $rbook['children'];
1372 $room_guests[] = ($rbook['adults'] + $rbook['children']);
1373 }
1374
1375 // make sure to decode the current pax data
1376 if (!empty($gbook[0]['pax_data'])) {
1377 $gbook[0]['pax_data'] = (array) json_decode($gbook[0]['pax_data'], true);
1378 }
1379
1380 // push a copy of the booking for each guest (adults and children)
1381 $guests_rows = [];
1382 for ($i = 1; $i <= $tot_booking_guests; $i++) {
1383 array_push($guests_rows, $gbook[0]);
1384 }
1385
1386 // create one row for each guest
1387 $guest_ind = 1;
1388 foreach ($guests_rows as $ind => $guests) {
1389 // prepare row record for this room-guest
1390 $insert_row = [];
1391
1392 // find the actual guest-room-index
1393 $guest_room_ind = $this->calcGuestRoomIndex($room_guests, $guest_ind);
1394
1395 // name
1396 $nome = !empty($guests['t_first_name']) ? $guests['t_first_name'] : $guests['first_name'];
1397 $pax_nome = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'first_name');
1398 $nome = !empty($pax_nome) ? $pax_nome : $nome;
1399 array_push($insert_row, array(
1400 'key' => 'first_name',
1401 'value' => $nome,
1402 ));
1403
1404 // last name
1405 $cognome = !empty($guests['t_last_name']) ? $guests['t_last_name'] : $guests['last_name'];
1406 $pax_cognome = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'last_name');
1407 $cognome = !empty($pax_cognome) ? $pax_cognome : $cognome;
1408 array_push($insert_row, array(
1409 'key' => 'last_name',
1410 'value' => $cognome,
1411 ));
1412
1413 // reservation date
1414 array_push($insert_row, array(
1415 'key' => 'resdate',
1416 'attr' => array(
1417 'class="center"'
1418 ),
1419 'callback' => function($val) {
1420 return date('Ymd', $val);
1421 },
1422 'value' => $guests['ts'],
1423 'ignore_view' => 1,
1424 ));
1425
1426 // check-in date
1427 array_push($insert_row, array(
1428 'key' => 'checkindate',
1429 'attr' => array(
1430 'class="center"'
1431 ),
1432 'callback' => function($val) {
1433 return date('Ymd', $val);
1434 },
1435 'value' => $guests['checkin'],
1436 'ignore_view' => 1,
1437 ));
1438
1439 // check-in time
1440 array_push($insert_row, array(
1441 'key' => 'checkintime',
1442 'attr' => array(
1443 'class="center"'
1444 ),
1445 'callback' => function($val) {
1446 return date('Hi', $val);
1447 },
1448 'value' => $guests['checkin'],
1449 'ignore_view' => 1,
1450 ));
1451
1452 // check-out date
1453 array_push($insert_row, array(
1454 'key' => 'checkoutdate',
1455 'attr' => array(
1456 'class="center"'
1457 ),
1458 'callback' => function($val) {
1459 return date('Ymd', $val);
1460 },
1461 'value' => $guests['checkout'],
1462 'ignore_view' => 1,
1463 ));
1464
1465 // check-out time
1466 array_push($insert_row, array(
1467 'key' => 'checkouttime',
1468 'attr' => array(
1469 'class="center"'
1470 ),
1471 'callback' => function($val) {
1472 return date('Hi', $val);
1473 },
1474 'value' => $guests['checkout'],
1475 'ignore_view' => 1,
1476 ));
1477
1478 // number of guests
1479 array_push($insert_row, array(
1480 'key' => 'numguests',
1481 'attr' => array(
1482 'class="center"'
1483 ),
1484 'value' => $tot_booking_guests,
1485 'ignore_view' => 1,
1486 ));
1487
1488 // Sexo
1489 $gender = !empty($guests['gender']) && $guest_ind < 2 ? strtoupper($guests['gender']) : '';
1490 $pax_gender = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'gender');
1491 $gender = !empty($pax_gender) ? $pax_gender : $gender;
1492
1493 /**
1494 * We make sure the gender will be compatible with both back-end and front-end
1495 * check-in/registration data collection driver and processes.
1496 */
1497 if (is_numeric($gender)) {
1498 $gender = (int) $gender;
1499 } elseif (!strcasecmp($gender, 'H')) {
1500 $gender = 1;
1501 } elseif (!strcasecmp($gender, 'F') || !strcasecmp($gender, 'M')) {
1502 $gender = 2;
1503 } elseif (!strcasecmp($gender, 'O')) {
1504 $gender = -1;
1505 }
1506
1507 // normalize value to hospedajes codes
1508 switch ($gender) {
1509 case 2:
1510 // mujer
1511 $spain_gender = 'M';
1512 break;
1513
1514 case 1:
1515 // hombre
1516 $spain_gender = 'H';
1517 break;
1518
1519 default:
1520 // otro
1521 $spain_gender = 'O';
1522 break;
1523 }
1524
1525 $sexo_elem_class = '';
1526 if (empty($gender)) {
1527 // optional selection style
1528 $sexo_elem_class = ' vbo-report-load-sesso vbo-report-load-field-optional';
1529 } else {
1530 // rectify selection style
1531 $sexo_elem_class = ' vbo-report-load-sesso vbo-report-load-elem-filled';
1532 }
1533
1534 array_push($insert_row, array(
1535 'key' => 'gender',
1536 'attr' => array(
1537 'class="center' . $sexo_elem_class . '"'
1538 ),
1539 'callback' => function($val) {
1540 return $this->sexo[$val] ?? 'O';
1541 },
1542 'export_callback' => function($val) {
1543 if ($val == 'H') {
1544 // for "Hombre" return "M" (Male)
1545 return 'M';
1546 }
1547 if ($val == 'M') {
1548 // for "Mujer" return "F" (Female)
1549 return 'F';
1550 }
1551 // return "O" (Other) by default
1552 return 'O';
1553 },
1554 'value' => $spain_gender,
1555 ));
1556
1557 // document type
1558 $pax_doctype = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'doctype');
1559
1560 $doctype = $pax_doctype ?: '';
1561
1562 if (strlen((string) $doctype) === 1) {
1563 // try to normalize the doc-type value from pre-checkin
1564 switch ($doctype) {
1565 case 'D':
1566 case 'C':
1567 case 'I':
1568 $doctype = 'NIF';
1569 break;
1570
1571 case 'N':
1572 case 'X':
1573 $doctype = 'NIE';
1574 break;
1575
1576 case 'P':
1577 $doctype = 'PAS';
1578 break;
1579
1580 default:
1581 $doctype = $doctype;
1582 break;
1583 }
1584 }
1585
1586 $doctype_elem_class = '';
1587 if (empty($doctype)) {
1588 // optional selection style
1589 $doctype_elem_class = ' vbo-report-load-doctype vbo-report-load-field-optional';
1590 } else {
1591 // rectify selection style
1592 $doctype_elem_class = ' vbo-report-load-doctype vbo-report-load-elem-filled';
1593 }
1594
1595 array_push($insert_row, array(
1596 'key' => 'doctype',
1597 'attr' => array(
1598 'class="center' . $doctype_elem_class . '"'
1599 ),
1600 'callback' => function($val) {
1601 return empty($val) ? '?' : $val;
1602 },
1603 'export_callback' => function($val) {
1604 if (empty($val)) {
1605 // other documents
1606 return 'O';
1607 }
1608 if ($val == 'NIF' || $val == 'DNI' || $val == 'TIE') {
1609 // NIF / DNI / TIE
1610 return 'D';
1611 }
1612 if ($val == 'NIE') {
1613 // NIE
1614 return 'N';
1615 }
1616 if ($val == 'PAS') {
1617 // PAS
1618 return 'P';
1619 }
1620 if ($val == 'OTRO') {
1621 // OTRO
1622 return 'O';
1623 }
1624 return $val;
1625 },
1626 'value' => $doctype,
1627 ));
1628
1629 // document number
1630 $pax_docnum = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'docnum');
1631
1632 $docnum = $pax_docnum ?: '';
1633
1634 $docnum_elem_class = '';
1635 if (empty($docnum)) {
1636 // optional selection style
1637 $docnum_elem_class = ' vbo-report-load-docnum vbo-report-load-field-optional';
1638 } else {
1639 // rectify selection style
1640 $docnum_elem_class = ' vbo-report-load-docnum vbo-report-load-elem-filled';
1641 }
1642
1643 array_push($insert_row, array(
1644 'key' => 'docnum',
1645 'attr' => array(
1646 'class="center' . $docnum_elem_class . '"'
1647 ),
1648 'callback' => function($val) {
1649 return empty($val) ? '?' : $val;
1650 },
1651 'no_export_callback' => 1,
1652 'value' => trim($docnum),
1653 ));
1654
1655 // número de soporte del documento
1656 $pax_docsoporte = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'docsoporte');
1657
1658 $docsoporte = $pax_docsoporte ?: '';
1659
1660 $docsoporte_elem_class = '';
1661 if (empty($docsoporte)) {
1662 // optional selection style
1663 $docsoporte_elem_class = ' vbo-report-load-docsoporte vbo-report-load-field-optional';
1664 } else {
1665 // rectify selection style
1666 $docsoporte_elem_class = ' vbo-report-load-docsoporte vbo-report-load-elem-filled';
1667 }
1668
1669 array_push($insert_row, array(
1670 'key' => 'docsoporte',
1671 'attr' => array(
1672 'class="center' . $docsoporte_elem_class . '"'
1673 ),
1674 'callback' => function($val) {
1675 return empty($val) ? '?' : $val;
1676 },
1677 'no_export_callback' => 1,
1678 'value' => $docsoporte,
1679 ));
1680
1681 // birth date (attempt to convert it into a timestamp to support any date format)
1682 $dbirth = !empty($guests['bdate']) && $guest_ind < 2 ? VikBooking::getDateTimestamp($guests['bdate'], 0, 0) : '';
1683 $pax_dbirth = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'date_birth');
1684 $dbirth = $pax_dbirth ?: $dbirth;
1685 $dbirth = !is_numeric($dbirth) ? VikBooking::getDateTimestamp($dbirth) : $dbirth;
1686
1687 $dbirth_elem_class = '';
1688 if (empty($dbirth)) {
1689 // optional selection style
1690 $dbirth_elem_class = ' vbo-report-load-dbirth vbo-report-load-field-optional';
1691 } else {
1692 // rectify selection style
1693 $dbirth_elem_class = ' vbo-report-load-dbirth vbo-report-load-elem-filled';
1694 }
1695
1696 array_push($insert_row, array(
1697 'key' => 'date_birth',
1698 'attr' => array(
1699 'class="center' . $dbirth_elem_class . '"'
1700 ),
1701 'callback' => function($val) {
1702 if (!empty($val) && is_numeric($val)) {
1703 return date('Ymd', $val);
1704 }
1705 return $val ?: '?';
1706 },
1707 'export_callback' => function($val) {
1708 if (!empty($val) && is_numeric($val)) {
1709 return date('Ymd', $val);
1710 }
1711 if (!empty($val) && strlen($val) > 8) {
1712 return date('Ymd', strtotime($val));
1713 }
1714 return $val ?: '?';
1715 },
1716 'value' => $dbirth,
1717 ));
1718
1719 // parentesco
1720 $pax_parentesco = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'parentesco');
1721
1722 $parentesco = $pax_parentesco ?: '';
1723
1724 $parentesco_elem_class = '';
1725 if (empty($parentesco)) {
1726 // optional selection style
1727 $parentesco_elem_class = ' vbo-report-load-parentesco vbo-report-load-field vbo-report-load-field-optional';
1728 } else {
1729 // rectify selection style
1730 $parentesco_elem_class = ' vbo-report-load-parentesco vbo-report-load-field vbo-report-load-elem-filled';
1731 }
1732
1733 array_push($insert_row, array(
1734 'key' => 'parentesco',
1735 'attr' => array(
1736 'class="center' . $parentesco_elem_class . '"'
1737 ),
1738 'callback' => function($val) use ($tot_booking_children) {
1739 if (!$tot_booking_children) {
1740 return '';
1741 }
1742 return empty($val) ? '?' : ($this->relacion_de_parentesco[$val] ?? $val);
1743 },
1744 'no_export_callback' => 1,
1745 'value' => $parentesco,
1746 ));
1747
1748 // address
1749 $pax_address = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'address');
1750
1751 $address = $pax_address ?: '';
1752
1753 $address_elem_class = '';
1754 if (empty($address)) {
1755 // optional selection style
1756 $address_elem_class = ' vbo-report-load-address vbo-report-load-field vbo-report-load-field-optional';
1757 } else {
1758 // rectify selection style
1759 $address_elem_class = ' vbo-report-load-address vbo-report-load-field vbo-report-load-elem-filled';
1760 }
1761
1762 array_push($insert_row, array(
1763 'key' => 'address',
1764 'attr' => array(
1765 'class="center' . $address_elem_class . '"'
1766 ),
1767 'callback' => function($val) {
1768 return empty($val) ? '?' : $val;
1769 },
1770 'no_export_callback' => 1,
1771 'value' => $address,
1772 ));
1773
1774 // codigo municipio
1775 $pax_municipio = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'municipio');
1776
1777 $municipio = $pax_municipio ?: '';
1778
1779 $municipio_elem_class = '';
1780 if (empty($municipio)) {
1781 // optional selection style
1782 $municipio_elem_class = ' vbo-report-load-municipio vbo-report-load-field vbo-report-load-field-optional';
1783 } else {
1784 // rectify selection style
1785 $municipio_elem_class = ' vbo-report-load-municipio vbo-report-load-field vbo-report-load-elem-filled';
1786 }
1787
1788 array_push($insert_row, array(
1789 'key' => 'municipio',
1790 'attr' => array(
1791 'class="center' . $municipio_elem_class . '"'
1792 ),
1793 'callback' => function($val) use ($municipio_codes_list) {
1794 return empty($val) ? '?' : ($municipio_codes_list[$val] ?? $val);
1795 },
1796 'export_callback' => function($val) use ($municipio_codes_list, $municipio_sixdigit_codes_list) {
1797 // the 6-digit municipality code is required for export, so we try to map it
1798 if (strlen((string) $val) === 6 || !isset($municipio_codes_list[$val])) {
1799 return $val;
1800 }
1801 if (strlen((string) $val) === 5) {
1802 // must be the 5-digit municipality code from SES Hospedajes, try to map it with the 6 digit
1803 $municipio_name = $municipio_codes_list[$val];
1804 foreach ($municipio_sixdigit_codes_list as $sixd_code => $sixd_municipio_name) {
1805 if (!strcasecmp($municipio_name, $sixd_municipio_name)) {
1806 return $sixd_code;
1807 }
1808 if (!strcasecmp(preg_replace('/[^a-z]/i', '', $municipio_name), preg_replace('/[^a-z]/i', '', $sixd_municipio_name))) {
1809 return $sixd_code;
1810 }
1811 }
1812 }
1813 return $val;
1814 },
1815 'value' => $municipio,
1816 ));
1817
1818 // city
1819 $pax_city = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'city');
1820
1821 $city = $pax_city ?: '';
1822
1823 $city_elem_class = '';
1824 if (empty($city)) {
1825 // optional selection style
1826 $city_elem_class = ' vbo-report-load-city vbo-report-load-field vbo-report-load-field-optional';
1827 } else {
1828 // rectify selection style
1829 $city_elem_class = ' vbo-report-load-city vbo-report-load-field vbo-report-load-elem-filled';
1830 }
1831
1832 array_push($insert_row, array(
1833 'key' => 'city',
1834 'attr' => array(
1835 'class="center' . $city_elem_class . '"'
1836 ),
1837 'callback' => function($val) {
1838 return empty($val) ? '?' : $val;
1839 },
1840 'no_export_callback' => 1,
1841 'value' => $city,
1842 ));
1843
1844 // postal code
1845 $pax_postalcode = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'postalcode');
1846
1847 $postalcode = $pax_postalcode ?: '';
1848
1849 $postalcode_elem_class = '';
1850 if (empty($postalcode)) {
1851 // optional selection style
1852 $postalcode_elem_class = ' vbo-report-load-postalcode vbo-report-load-field vbo-report-load-field-optional';
1853 } else {
1854 // rectify selection style
1855 $postalcode_elem_class = ' vbo-report-load-postalcode vbo-report-load-field vbo-report-load-elem-filled';
1856 }
1857
1858 array_push($insert_row, array(
1859 'key' => 'postalcode',
1860 'attr' => array(
1861 'class="center' . $postalcode_elem_class . '"'
1862 ),
1863 'callback' => function($val) {
1864 return empty($val) ? '?' : $val;
1865 },
1866 'no_export_callback' => 1,
1867 'value' => $postalcode,
1868 ));
1869
1870 // country of stay
1871 $pax_country_s = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'country_s');
1872
1873 // check country field from pre-checkin
1874 $pax_citizen = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'country');
1875
1876 $countrystay = !empty($guests['country']) ? $guests['country'] : '';
1877 $countrystay = $pax_citizen ?: $countrystay;
1878 $countrystay = $pax_country_s ?: $countrystay;
1879
1880 $country_elem_class = '';
1881 if (empty($countrystay)) {
1882 // optional selection style
1883 $country_elem_class = ' vbo-report-load-countrystay vbo-report-load-field-optional';
1884 } else {
1885 // rectify selection style
1886 $country_elem_class = ' vbo-report-load-countrystay vbo-report-load-elem-filled';
1887 }
1888
1889 array_push($insert_row, array(
1890 'key' => 'country_s',
1891 'attr' => array(
1892 'class="center' . $country_elem_class . '"'
1893 ),
1894 'callback' => function($val) {
1895 return $val ?: '---';
1896 },
1897 'no_export_callback' => 1,
1898 'value' => $countrystay,
1899 ));
1900
1901 // citizenship
1902 $pax_country_c = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'country_c');
1903
1904 // check country field from pre-checkin
1905 $pax_citizen = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'country');
1906
1907 $citizen = !empty($guests['country']) ? $guests['country'] : '';
1908 $citizen = $pax_citizen ?: $citizen;
1909 $citizen = $pax_country_c ?: $citizen;
1910
1911 $country_elem_class = '';
1912 if (empty($citizen)) {
1913 // optional selection style
1914 $country_elem_class = ' vbo-report-load-cittadinanza vbo-report-load-field-optional';
1915 } else {
1916 // rectify selection style
1917 $country_elem_class = ' vbo-report-load-cittadinanza vbo-report-load-elem-filled';
1918 }
1919
1920 array_push($insert_row, array(
1921 'key' => 'country_c',
1922 'attr' => array(
1923 'class="center' . $country_elem_class . '"'
1924 ),
1925 'callback' => function($val) {
1926 return $val ?: '---';
1927 },
1928 'no_export_callback' => 1,
1929 'value' => $citizen,
1930 ));
1931
1932 // direccion (phone number or email address from pre-checkin fields)
1933 $pax_direccion = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'direccion');
1934
1935 $direccion_phone = preg_match("/^[0-9\+\s]+$/", (string) $pax_direccion) ? $pax_direccion : '';
1936
1937 // phone number
1938 $pax_phone = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'phone');
1939
1940 $phone = $direccion_phone;
1941 $phone = empty($phone) && !empty($guests['phone']) ? $guests['phone'] : $phone;
1942 $phone = $pax_phone ?: $phone;
1943
1944 $phone_elem_class = '';
1945 if (empty($phone)) {
1946 // optional selection style
1947 $phone_elem_class = ' vbo-report-load-phone vbo-report-load-field vbo-report-load-field-optional';
1948 } else {
1949 // rectify selection style
1950 $phone_elem_class = ' vbo-report-load-phone vbo-report-load-field vbo-report-load-elem-filled';
1951 }
1952
1953 array_push($insert_row, array(
1954 'key' => 'phone',
1955 'attr' => array(
1956 'class="center' . $phone_elem_class . '"'
1957 ),
1958 'callback' => function($val) {
1959 return $val ?: '---';
1960 },
1961 'export_callback' => function($val) {
1962 if (substr((string) $val, 0, 1) == '+') {
1963 // phone number should not include the + symbol
1964 $val = substr($val, 1);
1965 }
1966 // maximum allowed length is 20 chars
1967 return substr((string) $val, 0, 20);
1968 },
1969 'value' => $phone,
1970 ));
1971
1972 // direccion (phone number or email address from pre-checkin fields)
1973 $pax_direccion = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'direccion');
1974
1975 $direccion_email = preg_match("/^.+@.+\..+$/", (string) $pax_direccion) ? $pax_direccion : '';
1976
1977 // email
1978 $pax_email = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'email');
1979
1980 $email = $direccion_email;
1981 $email = empty($email) && !empty($guests['custmail']) ? $guests['custmail'] : $email;
1982 $email = $pax_email ?: $email;
1983
1984 $email_elem_class = '';
1985 if (empty($email)) {
1986 // optional selection style
1987 $email_elem_class = ' vbo-report-load-email vbo-report-load-field vbo-report-load-field-optional';
1988 } else {
1989 // rectify selection style
1990 $email_elem_class = ' vbo-report-load-email vbo-report-load-field vbo-report-load-elem-filled';
1991 }
1992
1993 array_push($insert_row, array(
1994 'key' => 'email',
1995 'attr' => array(
1996 'class="center' . $email_elem_class . '"'
1997 ),
1998 'callback' => function($val) {
1999 return $val ?: '---';
2000 },
2001 'no_export_callback' => 1,
2002 'value' => $email,
2003 ));
2004
2005 // payment type
2006 $pax_paytype = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'paytype') ?: 'TARJT';
2007
2008 $paytype_elem_class = '';
2009 if ($guest_room_ind < 2 && empty($pax_paytype)) {
2010 // mandatory selection style
2011 $paytype_elem_class = ' vbo-report-load-paytype vbo-report-load-field';
2012 } elseif (empty($pax_paytype)) {
2013 // optional selection style
2014 $paytype_elem_class = ' vbo-report-load-paytype vbo-report-load-field vbo-report-load-field-optional';
2015 } elseif (!empty($pax_paytype)) {
2016 // rectify selection style
2017 $paytype_elem_class = ' vbo-report-load-paytype vbo-report-load-field vbo-report-load-elem-filled';
2018 }
2019
2020 array_push($insert_row, array(
2021 'key' => 'paytype',
2022 'attr' => array(
2023 'class="center' . $paytype_elem_class . '"',
2024 'data-field="paytype"',
2025 'data-fieldbid="' . $guests['id'] . '"',
2026 ),
2027 'callback' => function($val) {
2028 return $this->tipos_de_pago[$val] ?? $val;
2029 },
2030 'no_export_callback' => 1,
2031 'value' => $pax_paytype,
2032 ));
2033
2034 // check-in
2035 array_push($insert_row, array(
2036 'key' => 'checkin',
2037 'attr' => array(
2038 'class="center"'
2039 ),
2040 'callback' => function($val) {
2041 return date('Y-m-d\TH:i:s', $val);
2042 },
2043 'value' => $guests['checkin'],
2044 ));
2045
2046 // check-out
2047 array_push($insert_row, array(
2048 'key' => 'checkout',
2049 'attr' => array(
2050 'class="center"'
2051 ),
2052 'callback' => function($val) {
2053 return date('Y-m-d\TH:i:s', $val);
2054 },
2055 'value' => $guests['checkout'],
2056 ));
2057
2058 // id booking
2059 array_push($insert_row, array(
2060 'key' => 'idbooking',
2061 'attr' => array(
2062 'class="center"'
2063 ),
2064 'callback' => function($val) {
2065 // make sure to keep the data-bid attribute as it's used by JS to identify the booking ID
2066 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>';
2067 },
2068 'no_export_callback' => 1,
2069 'value' => $guests['id'],
2070 ));
2071
2072 // push fields in the rows array as a new row
2073 array_push($this->rows, $insert_row);
2074
2075 // increment guest index
2076 $guest_ind++;
2077 }
2078 }
2079
2080 // do not sort the rows for this report because the lines of the guests of the same booking must be consecutive
2081 // $this->sortRows($pkrsort, $pkrorder);
2082
2083 // the footer row will just print the amount of records to export
2084 array_push($this->footerRow, array(
2085 array(
2086 'attr' => array(
2087 'class="vbo-report-total"',
2088 ),
2089 'value' => '<h3>' . JText::translate('VBOREPORTSTOTALROW') . '</h3>',
2090 ),
2091 array(
2092 'attr' => array(
2093 'colspan="' . (count($this->cols) - 1) . '"',
2094 ),
2095 'value' => count($this->rows),
2096 )
2097 ));
2098
2099 return true;
2100 }
2101
2102 /**
2103 * Generates the authority file, then sends it to output for download.
2104 * In case of errors, the process is not terminated (exit) to let the View display the
2105 * error message(s). The export type argument can eventually determine an action to run.
2106 *
2107 * @param string $export_type Differentiates the type of export requested.
2108 *
2109 * @return void|bool Void in case of script termination, boolean otherwise.
2110 */
2111 public function customExport($export_type = null)
2112 {
2113 // build the TXT file
2114 $txt = $this->buildTXTFile();
2115
2116 // proceed with the regular export function (write on file through cron or download file through web)
2117
2118 if (!$txt) {
2119 // abort
2120 return false;
2121 }
2122
2123 // update history for all bookings affected before exporting
2124 foreach ($this->export_booking_ids as $bid) {
2125 VikBooking::getBookingHistoryInstance($bid)->store('RP', $this->reportName . ' - Export');
2126 }
2127
2128 // custom export method supports a custom export handler, if previously set.
2129 if ($this->hasExportHandler()) {
2130 // write data onto the custom file handler
2131 $fp = $this->getExportCSVHandler();
2132 fwrite($fp, $txt);
2133 fclose($fp);
2134
2135 // update sequence for the next download
2136 $this->increaseTransmissionSequence();
2137
2138 // return true as data was written
2139 return true;
2140 }
2141
2142 // force text file download in case of regular export
2143 header("Content-type: text/plain");
2144 header("Cache-Control: no-store, no-cache");
2145 header('Content-Disposition: attachment; filename="' . $this->getExportCSVFileName() . '"');
2146 echo $txt;
2147
2148 // update sequence for the next download
2149 $this->increaseTransmissionSequence();
2150
2151 exit;
2152 }
2153
2154 /**
2155 * Helper method invoked via AJAX by the controller.
2156 * Needed to save the manual entries for the pax data.
2157 *
2158 * @param array $manual_data the object representation of the manual entries.
2159 *
2160 * @return array one boolean value array with the operation result.
2161 */
2162 public function updatePaxData($manual_data = [])
2163 {
2164 if (!is_array($manual_data) || !$manual_data) {
2165 VBOHttpDocument::getInstance()->close(400, 'Nothing to save!');
2166 }
2167
2168 // re-build manual entries object representation
2169 $bids_guests = [];
2170 foreach ($manual_data as $guest_ind => $guest_data) {
2171 if (!is_numeric($guest_ind) || !is_array($guest_data) || empty($guest_data['bid']) || !isset($guest_data['bid_index']) || count($guest_data) < 2) {
2172 // empty or invalid manual entries array
2173 continue;
2174 }
2175 // the guest index in the reportObj starts from 0
2176 $use_guest_ind = ($guest_ind + 1 - (int)$guest_data['bid_index']);
2177 if (!isset($bids_guests[$guest_data['bid']])) {
2178 $bids_guests[$guest_data['bid']] = [];
2179 }
2180 // set manual entries for this guest number
2181 $bids_guests[$guest_data['bid']][$use_guest_ind] = $guest_data;
2182 // remove the "bid" and "bid_index" keys
2183 unset($bids_guests[$guest_data['bid']][$use_guest_ind]['bid'], $bids_guests[$guest_data['bid']][$use_guest_ind]['bid_index']);
2184 }
2185
2186 if (!$bids_guests) {
2187 VBOHttpDocument::getInstance()->close(400, 'No manual entries to save found');
2188 }
2189
2190 // loop through all bookings to update the data for the various rooms and guests
2191 $bids_updated = 0;
2192 foreach ($bids_guests as $bid => $entries) {
2193 $b_rooms = VikBooking::loadOrdersRoomsData($bid);
2194 if (empty($b_rooms)) {
2195 continue;
2196 }
2197 // count guests per room (adults + children)
2198 $room_guests = [];
2199 foreach ($b_rooms as $b_room) {
2200 $room_guests[] = $b_room['adults'] + $b_room['children'];
2201 }
2202 // get current booking pax data
2203 $pax_data = VBOCheckinPax::getBookingPaxData($bid);
2204 $pax_data = empty($pax_data) ? [] : $pax_data;
2205 foreach ($entries as $guest_ind => $guest_data) {
2206 // find room index for this guest
2207 $room_num = 0;
2208 $use_guest_ind = $guest_ind;
2209 foreach ($room_guests as $room_index => $tot_guests) {
2210 // find the proper guest index for the room to which this belongs
2211 if ($use_guest_ind <= $tot_guests) {
2212 // proper room index found for this guest
2213 $room_num = $room_index;
2214 break;
2215 } else {
2216 // it's probably in a next room
2217 $use_guest_ind -= $tot_guests;
2218 }
2219 }
2220 // push new pax data for this room and guest
2221 if (!isset($pax_data[$room_num])) {
2222 $pax_data[$room_num] = [];
2223 }
2224 if (!isset($pax_data[$room_num][$use_guest_ind])) {
2225 $pax_data[$room_num][$use_guest_ind] = $guest_data;
2226 } else {
2227 $pax_data[$room_num][$use_guest_ind] = array_merge($pax_data[$room_num][$use_guest_ind], $guest_data);
2228 }
2229 }
2230 // update booking pax data
2231 if (VBOCheckinPax::setBookingPaxData($bid, $pax_data)) {
2232 $bids_updated++;
2233 }
2234 }
2235
2236 return $bids_updated ? [true] : [false];
2237 }
2238
2239 /**
2240 * Builds the TXT file for export.
2241 *
2242 * @return string Empty string in case of errors, TXT otherwise.
2243 */
2244 protected function buildTXTFile()
2245 {
2246 if (!$this->getReportData()) {
2247 return '';
2248 }
2249
2250 // load report settings
2251 $settings = $this->loadSettings();
2252
2253 // get the possibly injected report options
2254 $options = $this->getReportOptions();
2255
2256 // access manually filled values, if any
2257 $pfiller = VikRequest::getString('filler', '', 'request', VIKREQUEST_ALLOWRAW);
2258 $pfiller = !empty($pfiller) ? (array) json_decode($pfiller, true) : [];
2259
2260 // define the lines separator character (carriage return + new line feed)
2261 $lines_separator = "\r\n";
2262
2263 // define the data separator character (pipe)
2264 $data_separator = '|';
2265
2266 // start building the text file content
2267 $file_content = '';
2268
2269 // add first line (LÍNEA AGRUPACIÓN) to text file content
2270 // use 0 for the line identifier, then the number of establishments, which is 1 by default
2271 $file_content .= implode($data_separator, [0, 1]) . $lines_separator;
2272
2273 // add second line (LÍNEA ESTABLECIMIENTO) to text file content
2274 $file_content .= implode($data_separator, [
2275 1,
2276 ($settings['codigo'] ?? ''),
2277 substr(($settings['nombre'] ?? ''), 0, 40),
2278 date('Ymd'),
2279 date('Hi'),
2280 count($this->rows),
2281 'V24',
2282 ]) . $lines_separator;
2283
2284 // group all rows by booking id
2285 $booking_rows = [];
2286 foreach ($this->rows as $ind => $row) {
2287 $bid = 0;
2288 foreach ($row as $row_ind => $field) {
2289 if ($field['key'] == 'idbooking') {
2290 // set booking ID
2291 $bid = (int) $field['value'];
2292
2293 if (!isset($booking_rows[$bid])) {
2294 // start booking rows container
2295 $booking_rows[$bid] = [];
2296 }
2297
2298 // check for manual report value
2299 if (strlen((string) ($pfiller[$ind][$field['key']] ?? ''))) {
2300 $row[$row_ind]['value'] = $pfiller[$ind][$field['key']];
2301 }
2302
2303 // break this one loop
2304 break;
2305 }
2306 }
2307 // push booking row
2308 $booking_rows[$bid][] = $row;
2309 }
2310
2311 // scan all booking rows
2312 foreach ($booking_rows as $bid => $rows) {
2313 // scan all guest rows for this reservation to build the various <persona> nodes
2314 foreach ($rows as $row) {
2315 // get the associative list of guest data from the current row
2316 $row_data = $this->getAssocRowData($row);
2317
2318 // build guest line contents (Tipo registro = 2)
2319 $guest_line = [2];
2320
2321 // tell whether the guest is Spanish
2322 $is_spanish = !empty($row_data['doctype']) && (!strcasecmp($row_data['doctype'], 'NIF') || !strcasecmp($row_data['doctype'], 'D'));
2323
2324 // Número de documento español
2325 $guest_line[] = $is_spanish ? $row_data['docnum'] : '';
2326
2327 // Número de documento estranjero
2328 $guest_line[] = !$is_spanish ? $row_data['docnum'] : '';
2329
2330 // Tipo de documento identificador
2331 $guest_line[] = $row_data['doctype'];
2332
2333 // document issue date is not mandatory, but we need to fill the empty value
2334 $guest_line[] = '';
2335
2336 // last name parts
2337 $last_name_parts = explode(' ', (string) $row_data['last_name']);
2338 if (count($last_name_parts) === 1) {
2339 $last_name_one = $last_name_parts[0];
2340 $last_name_two = $last_name_parts[0];
2341 } else {
2342 $last_name_two = $last_name_parts[count($last_name_parts) - 1];
2343 unset($last_name_parts[count($last_name_parts) - 1]);
2344 $last_name_one = implode(' ', $last_name_parts);
2345 }
2346
2347 // Primer apellido (main/first last name)
2348 $guest_line[] = strtoupper($this->transliterateToAscii($last_name_one));
2349
2350 // Segundo apellido (second last name)
2351 if ($last_name_one != $last_name_two || $is_spanish) {
2352 $guest_line[] = strtoupper($this->transliterateToAscii($last_name_two));
2353 } else {
2354 $guest_line[] = '';
2355 }
2356
2357 // Nombre (first name)
2358 $guest_line[] = strtoupper($this->transliterateToAscii((string) $row_data['first_name']));
2359
2360 // Sexo
2361 $guest_line[] = $row_data['gender'];
2362
2363 // Fecha Nacimiento
2364 $guest_line[] = $row_data['date_birth'];
2365
2366 // Pais nacionalidad
2367 $guest_line[] = $row_data['country_c'] ?: $row_data['country_s'];
2368
2369 // Fecha entrada
2370 $guest_line[] = $row_data['checkindate'];
2371
2372 // Hora entrada
2373 $guest_line[] = $row_data['checkintime'];
2374
2375 // Fecha salida
2376 $guest_line[] = $row_data['checkoutdate'];
2377
2378 // Hora salida
2379 $guest_line[] = $row_data['checkouttime'];
2380
2381 // Fecha contracto
2382 $guest_line[] = $row_data['resdate'];
2383
2384 // Tipo contracte (C = Contrato en curso, R = Reserva)
2385 $guest_line[] = 'R';
2386
2387 // Número contracto
2388 $guest_line[] = $row_data['idbooking'];
2389
2390 // Número viajeros
2391 $guest_line[] = $row_data['numguests'];
2392
2393 // Número habitaciones
2394 $guest_line[] = 1;
2395
2396 // El hotel dispone de internet (S = Si, N = No)
2397 $guest_line[] = 'S';
2398
2399 // Tipo pago
2400 $guest_line[] = $row_data['paytype'];
2401
2402 // Teléfono
2403 $guest_line[] = $row_data['phone'];
2404
2405 // Relación de parentesco
2406 $guest_line[] = $row_data['parentesco'];
2407
2408 // Email
2409 $guest_line[] = $row_data['email'];
2410
2411 // Número soporte documento identificativo
2412 $guest_line[] = $row_data['docsoporte'];
2413
2414 // Dirección postal
2415 $guest_line[] = substr((string) $row_data['address'], 0, 100);
2416
2417 // Provincia postal
2418 $guest_line[] = substr((string) $row_data['municipio'], 0, 2);
2419
2420 // Municipio postal
2421 $guest_line[] = $row_data['municipio'];
2422
2423 // Localitat postal
2424 $guest_line[] = '';
2425
2426 // Pais postal
2427 $guest_line[] = $row_data['country_s'] ?: $row_data['country_c'];
2428
2429 // Código postal
2430 $guest_line[] = $row_data['postalcode'];
2431
2432 // last field also needs to be separated by a pipe character so we push an empty string
2433 $guest_line[] = '';
2434
2435 // add guest line (LÍNEA VIAJERO) to text file content
2436 $file_content .= implode($data_separator, $guest_line) . $lines_separator;
2437 }
2438 }
2439
2440 // set pool of booking IDs to update their history
2441 $this->export_booking_ids = array_keys($booking_rows);
2442
2443 // return the final TXT file string
2444 return rtrim($file_content, $lines_separator);
2445 }
2446
2447 /**
2448 * Increases the current configuration setting for the transmission sequence.
2449 * The transmission sequence is needed to give the export file a proper name.
2450 *
2451 * @return void
2452 */
2453 protected function increaseTransmissionSequence()
2454 {
2455 // get report settings
2456 $settings = $this->loadSettings();
2457
2458 // get current sequence
2459 $current_sequence = (int) ($settings['sequence'] ?? 1);
2460
2461 // update report settings with the increased sequence
2462 $settings['sequence'] = ++$current_sequence;
2463
2464 $this->saveSettings($settings);
2465 }
2466
2467 /**
2468 * Parses a report row into an associative list of key-value pairs.
2469 *
2470 * @param array $row The report row to parse.
2471 *
2472 * @return array
2473 */
2474 protected function getAssocRowData(array $row)
2475 {
2476 $row_data = [];
2477
2478 foreach ($row as $field) {
2479 $field_val = $field['value'];
2480 if (!($field['no_export_callback'] ?? 0) && is_callable($field['export_callback'] ?? null)) {
2481 $field_val = $field['export_callback']($field_val);
2482 } elseif (!($field['no_export_callback'] ?? 0) && is_callable($field['callback'] ?? null)) {
2483 $field_val = $field['callback']($field_val);
2484 }
2485 $row_data[$field['key']] = $field_val;
2486 }
2487
2488 return $row_data;
2489 }
2490
2491 /**
2492 * Registers the name to give to the file being exported.
2493 *
2494 * @return void
2495 */
2496 protected function registerExportFileName()
2497 {
2498 // load report settings
2499 $settings = $this->loadSettings();
2500
2501 $pfromdate = VikRequest::getString('fromdate', '', 'request');
2502 $ptodate = VikRequest::getString('todate', '', 'request');
2503
2504 // build report file name (property code (dot) 3-digit sequence (dot) txt)
2505 $export_name = ($settings['codigo'] ?? '') ?: '0000000000';
2506
2507 // build current sequence for progressive transmission without incrementing
2508 $sequence_int = (int) ($settings['sequence'] ?? 1);
2509 $sequence_int = $sequence_int > 999 ? 1 : $sequence_int;
2510 $sequence_int = $sequence_int < 0 ? 1 : $sequence_int;
2511
2512 $sequence_str = str_pad((string) $sequence_int, 3, '0', STR_PAD_LEFT);
2513
2514 $this->setExportCSVFileName($export_name . '.' . $sequence_str . '.txt');
2515 }
2516
2517 /**
2518 * Helper method to quickly get a pax_data property for the guest.
2519 *
2520 * @param array $pax_data the current pax_data stored.
2521 * @param array $guests list of total guests per room.
2522 * @param int $guest_ind the guest index.
2523 * @param string $key the pax_data key to look for.
2524 *
2525 * @return mixed null on failure or value fetched.
2526 */
2527 protected function getGuestPaxDataValue($pax_data, $guests, $guest_ind, $key)
2528 {
2529 if (!is_array($pax_data) || !$pax_data || empty($key)) {
2530 return null;
2531 }
2532
2533 // find room index for this guest number
2534 $room_num = 0;
2535 $use_guest_ind = $guest_ind;
2536 foreach ($guests as $room_index => $room_tot_guests) {
2537 // find the proper guest index for the room to which this belongs
2538 if ($use_guest_ind <= $room_tot_guests) {
2539 // proper room index found for this guest
2540 $room_num = $room_index;
2541 break;
2542 } else {
2543 // it's probably in a next room
2544 $use_guest_ind -= $room_tot_guests;
2545 }
2546 }
2547
2548 // check if a value exists for the requested key in the found room and guest indexes
2549 if (isset($pax_data[$room_num]) && isset($pax_data[$room_num][$use_guest_ind])) {
2550 if (isset($pax_data[$room_num][$use_guest_ind][$key])) {
2551 // we've got a value previously stored
2552 return $pax_data[$room_num][$use_guest_ind][$key];
2553 }
2554 }
2555
2556 // nothing was found
2557 return null;
2558 }
2559
2560 /**
2561 * Helper method to determine the exact number for this guest in the room booked.
2562 *
2563 * @param array $guests list of total guests per room.
2564 * @param int $guest_ind the guest index.
2565 *
2566 * @return int the actual guest room index starting from 1.
2567 */
2568 protected function calcGuestRoomIndex($guests, $guest_ind)
2569 {
2570 // find room index for this guest number
2571 $room_num = 0;
2572 $use_guest_ind = $guest_ind;
2573 foreach ($guests as $room_index => $room_tot_guests) {
2574 // find the proper guest index for the room to which this belongs
2575 if ($use_guest_ind <= $room_tot_guests) {
2576 // proper room index found for this guest
2577 $room_num = $room_index;
2578 break;
2579 } else {
2580 // it's probably in a next room
2581 $use_guest_ind -= $room_tot_guests;
2582 }
2583 }
2584
2585 return $use_guest_ind;
2586 }
2587 }
2588