| 1 |
<?php |
| 2 |
/** |
| 3 |
* @package VikBooking |
| 4 |
* @subpackage com_vikbooking |
| 5 |
* @author Alessio Gaggii - E4J srl |
| 6 |
* @copyright Copyright (C) 2024 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 (Spain) Hospedajes - Ministerio del Interior. |
| 15 |
* |
| 16 |
* This report supports two different types of registration, one based on the reservation |
| 17 |
* date (Reservas de hospedaje) and another based on the check-in date (Partes de viajeros). |
| 18 |
* This report also provides some custom scoped actions for the electronic operations. |
| 19 |
* |
| 20 |
* @see Instrucciones-hospedajes.pdf |
| 21 |
* @see MIR-HOSPE-DSI-WS-Servicio-de-Hospedajes---Comunicaciones-v3.1.2.pdf |
| 22 |
* |
| 23 |
* @since 1.17.2 (J) - 1.7.2 (WP) |
| 24 |
*/ |
| 25 |
class VikBookingReportEsHospedajes extends VikBookingReport |
| 26 |
{ |
| 27 |
/** |
| 28 |
* Property 'defaultKeySort' is used by the View that renders the report. |
| 29 |
* |
| 30 |
* @var string |
| 31 |
*/ |
| 32 |
public $defaultKeySort = 'idbooking'; |
| 33 |
|
| 34 |
/** |
| 35 |
* Property 'defaultKeyOrder' is used by the View that renders the report. |
| 36 |
* |
| 37 |
* @var string |
| 38 |
*/ |
| 39 |
public $defaultKeyOrder = 'ASC'; |
| 40 |
|
| 41 |
/** |
| 42 |
* Property 'customExport' is used by the View to display custom export buttons. |
| 43 |
* |
| 44 |
* @var string |
| 45 |
*/ |
| 46 |
public $customExport = ''; |
| 47 |
|
| 48 |
/** |
| 49 |
* List of booking IDs affected by the export. |
| 50 |
* |
| 51 |
* @var array |
| 52 |
*/ |
| 53 |
protected $export_booking_ids = []; |
| 54 |
|
| 55 |
/** |
| 56 |
* List of exported check-in dates (range). |
| 57 |
* |
| 58 |
* @var array |
| 59 |
*/ |
| 60 |
protected $exported_checkin_dates = []; |
| 61 |
|
| 62 |
/** |
| 63 |
* The development (test, pruebas) endpoint. |
| 64 |
* |
| 65 |
* @var string |
| 66 |
*/ |
| 67 |
protected $endpoint_test = 'https://hospedajes.pre-ses.mir.es/hospedajes-web/ws/v1/comunicacion'; |
| 68 |
|
| 69 |
/** |
| 70 |
* The production (live, producción) endpoint. |
| 71 |
* |
| 72 |
* @var string |
| 73 |
*/ |
| 74 |
protected $endpoint_production = 'https://hospedajes.ses.mir.es/hospedajes-web/ws/v1/comunicacion'; |
| 75 |
|
| 76 |
/** |
| 77 |
* The path to the temporary directory used by this report. |
| 78 |
* |
| 79 |
* @var string |
| 80 |
*/ |
| 81 |
protected $report_tmp_path = ''; |
| 82 |
|
| 83 |
/** |
| 84 |
* The software application name. |
| 85 |
* |
| 86 |
* @var string |
| 87 |
*/ |
| 88 |
protected $software_application_name = 'VikBooking - E4jConnect'; |
| 89 |
|
| 90 |
/** |
| 91 |
* Associative list of RELACIÓN DE PARENTESCO |
| 92 |
* |
| 93 |
* @var array |
| 94 |
*/ |
| 95 |
protected $relacion_de_parentesco = [ |
| 96 |
'AB' => 'Abuelo/a', |
| 97 |
'BA' => 'Bisabuelo/a', |
| 98 |
'BN' => 'Bisnieto/a', |
| 99 |
'CD' => 'Cuñado/a', |
| 100 |
'CY' => 'Cónyuge', |
| 101 |
'HJ' => 'Hijo/a', |
| 102 |
'HR' => 'Hermano/a', |
| 103 |
'NI' => 'Nieto/a', |
| 104 |
'PM' => 'Padre o madre', |
| 105 |
'SB' => 'Sobrino/a', |
| 106 |
'SG' => 'Suegro/a', |
| 107 |
'TI' => 'TÃo/a', |
| 108 |
'YN' => 'Yerno o nuera', |
| 109 |
'TU' => 'Tutor/a', |
| 110 |
'OT' => 'Otro', |
| 111 |
]; |
| 112 |
|
| 113 |
/** |
| 114 |
* Associative list of SEXO |
| 115 |
* |
| 116 |
* @var array |
| 117 |
*/ |
| 118 |
protected $sexo = [ |
| 119 |
'H' => 'Hombre', |
| 120 |
'M' => 'Mujer', |
| 121 |
'O' => 'Otro', |
| 122 |
]; |
| 123 |
|
| 124 |
/** |
| 125 |
* Associative list of TIPOS DE DOCUMENTO |
| 126 |
* |
| 127 |
* @var array |
| 128 |
*/ |
| 129 |
protected $tipos_de_documento = [ |
| 130 |
'NIF' => 'NIF - Número de Identificación Fiscal', |
| 131 |
'NIE' => 'NIE - Número de Identidad de Extranjero', |
| 132 |
'PAS' => 'Número de pasaporte', |
| 133 |
'OTRO' => 'Otro', |
| 134 |
]; |
| 135 |
|
| 136 |
/** |
| 137 |
* Associative list of TIPOS DE ESTABLECIMIENTO |
| 138 |
* |
| 139 |
* @var array |
| 140 |
*/ |
| 141 |
protected $tipos_de_establecimiento = [ |
| 142 |
'ALBERGUE' => 'Albergue', |
| 143 |
'APART' => 'Apartamento', |
| 144 |
'APARTHOTEL' => 'Apartahotel', |
| 145 |
'AP_RURAL' => 'Apartamento rural', |
| 146 |
'BALNEARIO' => 'Balneario', |
| 147 |
'CAMPING' => 'Camping', |
| 148 |
'CASA_HUESP' => 'Casa de huéspedes', |
| 149 |
'CASA_RURAL' => 'Casa rural', |
| 150 |
'HOSTAL' => 'Hostal', |
| 151 |
'HOTEL' => 'Hotel', |
| 152 |
'H_RURAL' => 'Hotel rural', |
| 153 |
'MOTEL' => 'Motel', |
| 154 |
'OFIC_VEHIC' => 'Oficina de alquiler de vehÃculos', |
| 155 |
'OTROS' => 'Otro', |
| 156 |
'PARADOR' => 'Parador de turismo', |
| 157 |
'PENSION' => 'Pensión', |
| 158 |
'RESIDENCIA' => 'Residencia', |
| 159 |
]; |
| 160 |
|
| 161 |
/** |
| 162 |
* Associative list of TIPOS DE PAGO |
| 163 |
* |
| 164 |
* @var array |
| 165 |
*/ |
| 166 |
protected $tipos_de_pago = [ |
| 167 |
'EFECT' => 'Efectivo', |
| 168 |
'TARJT' => 'Tarjeta de crédito', |
| 169 |
'PLATF' => 'Plataforma de pago', |
| 170 |
'TRANS' => 'Transferencia', |
| 171 |
'MOVIL' => 'Pago por móvil', |
| 172 |
'TREG' => 'Tarjeta regalo', |
| 173 |
'DESTI' => 'Pago en destino', |
| 174 |
'OTRO' => 'Otros medios de pago', |
| 175 |
]; |
| 176 |
|
| 177 |
/** |
| 178 |
* Associative list of guest types. |
| 179 |
* |
| 180 |
* @var array |
| 181 |
*/ |
| 182 |
protected $guest_types = [ |
| 183 |
'TI' => 'Titular', |
| 184 |
'VI' => 'Viajero', |
| 185 |
]; |
| 186 |
|
| 187 |
/** |
| 188 |
* Class constructor should define the name of the report and |
| 189 |
* other vars. Call the parent constructor to define the DB object. |
| 190 |
*/ |
| 191 |
public function __construct() |
| 192 |
{ |
| 193 |
$this->reportFile = basename(__FILE__, '.php'); |
| 194 |
$this->reportName = 'SES Hospedajes - Ministerio del Interior'; |
| 195 |
$this->reportFilters = []; |
| 196 |
|
| 197 |
$this->cols = []; |
| 198 |
$this->rows = []; |
| 199 |
$this->footerRow = []; |
| 200 |
|
| 201 |
$this->registerExportFileName(); |
| 202 |
|
| 203 |
// set the temporary report directory path |
| 204 |
$this->report_tmp_path = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'hospedajes_tmp'; |
| 205 |
|
| 206 |
parent::__construct(); |
| 207 |
} |
| 208 |
|
| 209 |
/** |
| 210 |
* Returns the name of this report. |
| 211 |
* |
| 212 |
* @return string |
| 213 |
*/ |
| 214 |
public function getName() |
| 215 |
{ |
| 216 |
return $this->reportName; |
| 217 |
} |
| 218 |
|
| 219 |
/** |
| 220 |
* Returns the name of this file without .php. |
| 221 |
* |
| 222 |
* @return string |
| 223 |
*/ |
| 224 |
public function getFileName() |
| 225 |
{ |
| 226 |
return $this->reportFile; |
| 227 |
} |
| 228 |
|
| 229 |
/** |
| 230 |
* @inheritDoc |
| 231 |
* |
| 232 |
* @since 1.18.0 (J) - 1.8.0 (WP) |
| 233 |
*/ |
| 234 |
public function allowsProfileSettings() |
| 235 |
{ |
| 236 |
// allow multiple report profile settings |
| 237 |
return true; |
| 238 |
} |
| 239 |
|
| 240 |
/** |
| 241 |
* @inheritDoc |
| 242 |
*/ |
| 243 |
public function getSettingFields() |
| 244 |
{ |
| 245 |
return [ |
| 246 |
'codigo' => [ |
| 247 |
'type' => 'text', |
| 248 |
'label' => 'Código del establecimiento', |
| 249 |
'help' => 'Se deberá informar, si se conoce, el código del establecimiento asignado por el Sistema de Hospedajes en el momento del registro.', |
| 250 |
], |
| 251 |
'tipo_establecimiento' => [ |
| 252 |
'type' => 'select', |
| 253 |
'label' => 'Tipo de establecimiento', |
| 254 |
'help' => 'Datos del establecimento en caso de no disponer de un código de establecimiento en el Sistema de Hospedajes.', |
| 255 |
'options' => $this->tipos_de_establecimiento, |
| 256 |
'default' => 'OTROS', |
| 257 |
], |
| 258 |
'nombre_establecimiento' => [ |
| 259 |
'type' => 'text', |
| 260 |
'label' => 'Nombre del establecimiento', |
| 261 |
'help' => 'Datos del establecimento en caso de no disponer de un código de establecimiento en el Sistema de Hospedajes.', |
| 262 |
'attributes' => [ |
| 263 |
'maxlength' => 50, |
| 264 |
], |
| 265 |
'default' => strip_tags((string) VikBooking::getFrontTitle()), |
| 266 |
], |
| 267 |
'direccion' => [ |
| 268 |
'type' => 'text', |
| 269 |
'label' => 'Dirección del establecimiento', |
| 270 |
'help' => 'Datos del establecimento en caso de no disponer de un código de establecimiento en el Sistema de Hospedajes.', |
| 271 |
], |
| 272 |
'codigo_postal' => [ |
| 273 |
'type' => 'text', |
| 274 |
'label' => 'Código postal', |
| 275 |
'help' => 'Datos del establecimento en caso de no disponer de un código de establecimiento en el Sistema de Hospedajes.', |
| 276 |
'attributes' => [ |
| 277 |
'maxlength' => 20, |
| 278 |
], |
| 279 |
], |
| 280 |
'pais' => [ |
| 281 |
'type' => 'text', |
| 282 |
'label' => 'Código del paÃs', |
| 283 |
'help' => 'Este campo va codificado según la norma ISO 3166-1 Alfa-3.', |
| 284 |
'default' => 'ESP', |
| 285 |
'attributes' => [ |
| 286 |
'maxlength' => 3, |
| 287 |
], |
| 288 |
], |
| 289 |
'codigo_municipio' => [ |
| 290 |
'type' => 'text', |
| 291 |
'label' => 'Código municipio', |
| 292 |
'help' => 'Este campo irá codificado con los códigos de municipios del INE (5 dÃgitos). Obligatorio cuando el paÃs es España.', |
| 293 |
'attributes' => [ |
| 294 |
'maxlength' => 5, |
| 295 |
], |
| 296 |
], |
| 297 |
'nombre_municipio' => [ |
| 298 |
'type' => 'text', |
| 299 |
'label' => 'Nombre municipio', |
| 300 |
'help' => 'Nombre del municipio, ciudad, estado, etc.. Obligatorio cuando el paÃs no es España.', |
| 301 |
'attributes' => [ |
| 302 |
'maxlength' => 100, |
| 303 |
], |
| 304 |
], |
| 305 |
'service_test_mode' => [ |
| 306 |
'type' => 'checkbox', |
| 307 |
'label' => 'Endpoint pruebas', |
| 308 |
'help' => 'Datos de acceso al Servicio de Comunicación. Pruebas o Producción.', |
| 309 |
'default' => 0, |
| 310 |
], |
| 311 |
'service_arrendador' => [ |
| 312 |
'type' => 'text', |
| 313 |
'label' => 'Arrendador', |
| 314 |
'help' => 'Código del arrendador asignado por el Sistema de Hospedajes en el momento del registro.', |
| 315 |
], |
| 316 |
'service_username' => [ |
| 317 |
'type' => 'text', |
| 318 |
'label' => 'Usuario', |
| 319 |
'help' => 'Datos de acceso al Servicio de Comunicación. Usuario.', |
| 320 |
], |
| 321 |
'service_password' => [ |
| 322 |
'type' => 'password', |
| 323 |
'label' => 'Contraseña', |
| 324 |
'help' => 'Datos de acceso al Servicio de Comunicación. Contraseña.', |
| 325 |
], |
| 326 |
]; |
| 327 |
} |
| 328 |
|
| 329 |
/** |
| 330 |
* @inheritDoc |
| 331 |
*/ |
| 332 |
public function getScopedActions($scope = null, $visible = true) |
| 333 |
{ |
| 334 |
// list of custom actions for this report |
| 335 |
$actions = [ |
| 336 |
[ |
| 337 |
'id' => 'registerTravelerParts', |
| 338 |
'name' => 'Alta de partes de viajeros', |
| 339 |
'icon' => VikBookingIcons::i('cloud-upload-alt'), |
| 340 |
// flag to indicate that it requires the report data (lines) |
| 341 |
'export_data' => true, |
| 342 |
'scopes' => [ |
| 343 |
'web', |
| 344 |
'cron', |
| 345 |
], |
| 346 |
], |
| 347 |
[ |
| 348 |
'id' => 'registerAccommodationReservations', |
| 349 |
'name' => 'Alta de reservas de hospedaje', |
| 350 |
'icon' => VikBookingIcons::i('cloud-upload-alt'), |
| 351 |
// flag to indicate that it requires the report data (lines) |
| 352 |
'export_data' => true, |
| 353 |
'scopes' => [ |
| 354 |
'web', |
| 355 |
'cron', |
| 356 |
], |
| 357 |
], |
| 358 |
[ |
| 359 |
'id' => 'batchArchive', |
| 360 |
'name' => 'Archivo lotes', |
| 361 |
'help' => 'Archivo de lotes obtenidos como resultado de transmisiones de datos de huéspedes.', |
| 362 |
'icon' => VikBookingIcons::i('folder-open'), |
| 363 |
'scopes' => [ |
| 364 |
'web', |
| 365 |
], |
| 366 |
'params' => [ |
| 367 |
'op_month' => [ |
| 368 |
'type' => 'calendar', |
| 369 |
'label' => 'Mes de la comunicación', |
| 370 |
'help' => 'Seleccione el mes en el que se produjo la comunicación.', |
| 371 |
'default' => date('Y-m-01'), |
| 372 |
], |
| 373 |
'rp_type' => [ |
| 374 |
'type' => 'select', |
| 375 |
'label' => 'Tipo de comunicación', |
| 376 |
'help' => 'Filtro opcional por tipo de comunicación.', |
| 377 |
'options' => [ |
| 378 |
'0' => '', |
| 379 |
'PV' => 'Alta de partes de viajeros', |
| 380 |
'HR' => 'Alta de reservas de hospedaje', |
| 381 |
], |
| 382 |
'default' => '0', |
| 383 |
], |
| 384 |
], |
| 385 |
'params_submit_lbl' => 'Búsqueda lotes', |
| 386 |
], |
| 387 |
[ |
| 388 |
'id' => 'checkBatchStatus', |
| 389 |
'name' => 'Consulta de lotes', |
| 390 |
'help' => 'Consultar el estado de los lotes obtenidos de transmisiones de datos anteriores.', |
| 391 |
'icon' => VikBookingIcons::i('user-check'), |
| 392 |
'scopes' => [ |
| 393 |
'web', |
| 394 |
'cron', |
| 395 |
], |
| 396 |
'params' => [ |
| 397 |
'batch_sequence' => [ |
| 398 |
'type' => 'text', |
| 399 |
'label' => 'Lote', |
| 400 |
'help' => 'Ingrese el número de lote a buscar.', |
| 401 |
], |
| 402 |
'op_date' => [ |
| 403 |
'type' => 'calendar', |
| 404 |
'label' => 'Fecha de la comunicación', |
| 405 |
'help' => 'Seleccione la fecha en el que se produjo la comunicación.', |
| 406 |
'default' => date('Y-m-d'), |
| 407 |
], |
| 408 |
], |
| 409 |
'params_submit_lbl' => 'Consulta lotes', |
| 410 |
], |
| 411 |
[ |
| 412 |
'id' => 'prepareCommunicationMessage', |
| 413 |
'name' => 'Prepare communication mesage', |
| 414 |
// flag to indicate that it's callable internally, but not graphically |
| 415 |
'hidden' => true, |
| 416 |
'scopes' => [ |
| 417 |
'web', |
| 418 |
], |
| 419 |
], |
| 420 |
]; |
| 421 |
|
| 422 |
// filter actions by scope |
| 423 |
if ($scope && (!strcasecmp($scope, 'cron') || !strcasecmp($scope, 'web'))) { |
| 424 |
$actions = array_filter($actions, function($action) use ($scope) { |
| 425 |
if (!($action['scopes'] ?? [])) { |
| 426 |
return true; |
| 427 |
} |
| 428 |
|
| 429 |
return in_array(strtolower($scope), $action['scopes']); |
| 430 |
}); |
| 431 |
} |
| 432 |
|
| 433 |
// filter by visibility |
| 434 |
if ($visible) { |
| 435 |
$actions = array_filter($actions, function($action) { |
| 436 |
return !($action['hidden'] ?? false); |
| 437 |
}); |
| 438 |
} |
| 439 |
|
| 440 |
return array_values($actions); |
| 441 |
} |
| 442 |
|
| 443 |
/** |
| 444 |
* Returns the filters of this report. |
| 445 |
* |
| 446 |
* @return array |
| 447 |
*/ |
| 448 |
public function getFilters() |
| 449 |
{ |
| 450 |
if ($this->reportFilters) { |
| 451 |
// do not run this method twice, as it could load JS and CSS files. |
| 452 |
return $this->reportFilters; |
| 453 |
} |
| 454 |
|
| 455 |
$app = JFactory::getApplication(); |
| 456 |
|
| 457 |
// get VBO Application Object |
| 458 |
$vbo_app = VikBooking::getVboApplication(); |
| 459 |
|
| 460 |
// get the possibly injected report options |
| 461 |
$options = $this->getReportOptions(); |
| 462 |
|
| 463 |
// load the jQuery UI Datepicker |
| 464 |
$this->loadDatePicker(); |
| 465 |
|
| 466 |
// custom export button |
| 467 |
$this->customExport = '<a href="JavaScript: void(0);" onclick="vboDownloadHospedajes();" class="vbcsvexport"><i class="'.VikBookingIcons::i('download').'"></i> <span>Download XML</span></a>'; |
| 468 |
|
| 469 |
// build the hidden values for the selection of various fields. |
| 470 |
$hidden_vals = '<div id="vbo-report-hospedajes-hidden" style="display: none;">'; |
| 471 |
|
| 472 |
// build params container HTML structure |
| 473 |
$hidden_vals .= '<div class="vbo-admin-container vbo-admin-container-full vbo-admin-container-compact">'; |
| 474 |
$hidden_vals .= ' <div class="vbo-params-wrap">'; |
| 475 |
$hidden_vals .= ' <div class="vbo-params-container">'; |
| 476 |
$hidden_vals .= ' <div class="vbo-params-block vbo-params-block-noborder">'; |
| 477 |
|
| 478 |
// tipos de pago |
| 479 |
$hidden_vals .= ' <div id="vbo-report-hospedajes-paytype" class="vbo-report-hospedajes-selcont vbo-param-container" style="display: none;">'; |
| 480 |
$hidden_vals .= ' <div class="vbo-param-label">Tipo de pago</div>'; |
| 481 |
$hidden_vals .= ' <div class="vbo-param-setting">'; |
| 482 |
$hidden_vals .= ' <select id="choose-paytype" onchange="vboReportChosenTipodepago(this);"><option value=""></option>'; |
| 483 |
foreach ($this->tipos_de_pago as $code => $pago) { |
| 484 |
$hidden_vals .= ' <option value="' . $code . '">' . $pago . '</option>' . "\n"; |
| 485 |
} |
| 486 |
$hidden_vals .= ' </select>'; |
| 487 |
$hidden_vals .= ' </div>'; |
| 488 |
$hidden_vals .= ' </div>'; |
| 489 |
|
| 490 |
// Nacionalidad |
| 491 |
$hidden_vals .= ' <div id="vbo-report-hospedajes-nazione" class="vbo-report-hospedajes-selcont vbo-param-container" style="display: none;">'; |
| 492 |
$hidden_vals .= ' <div class="vbo-param-label">Pais</div>'; |
| 493 |
$hidden_vals .= ' <div class="vbo-param-setting">'; |
| 494 |
$hidden_vals .= ' <select id="choose-nazione" onchange="vboReportChosenNacionalidad(this);"><option value=""></option>'; |
| 495 |
foreach (VikBooking::getCountriesArray() as $code => $country) { |
| 496 |
$hidden_vals .= ' <option value="' . $code . '">' . $country['country_name'] . '</option>'."\n"; |
| 497 |
} |
| 498 |
$hidden_vals .= ' </select>'; |
| 499 |
$hidden_vals .= ' </div>'; |
| 500 |
$hidden_vals .= ' </div>'; |
| 501 |
|
| 502 |
// tipos de documento |
| 503 |
$hidden_vals .= ' <div id="vbo-report-hospedajes-doctype" class="vbo-report-hospedajes-selcont vbo-param-container" style="display: none;">'; |
| 504 |
$hidden_vals .= ' <div class="vbo-param-label">Tipos de documento</div>'; |
| 505 |
$hidden_vals .= ' <div class="vbo-param-setting">'; |
| 506 |
$hidden_vals .= ' <select id="choose-documento" onchange="vboReportChosenDocumento(this);"><option value=""></option>'; |
| 507 |
foreach ($this->tipos_de_documento as $code => $documento) { |
| 508 |
$hidden_vals .= ' <option value="' . $code . '">' . $documento . '</option>' . "\n"; |
| 509 |
} |
| 510 |
$hidden_vals .= ' </select>'; |
| 511 |
$hidden_vals .= ' </div>'; |
| 512 |
$hidden_vals .= ' </div>'; |
| 513 |
|
| 514 |
// relacion de parentesco |
| 515 |
$hidden_vals .= ' <div id="vbo-report-hospedajes-parentesco" class="vbo-report-hospedajes-selcont vbo-param-container" style="display: none;">'; |
| 516 |
$hidden_vals .= ' <div class="vbo-param-label">Relacion de parentesco</div>'; |
| 517 |
$hidden_vals .= ' <div class="vbo-param-setting">'; |
| 518 |
$hidden_vals .= ' <select id="choose-parentesco" onchange="vboReportChosenParentesco(this);"><option value=""></option>'; |
| 519 |
foreach ($this->relacion_de_parentesco as $code => $val) { |
| 520 |
$hidden_vals .= ' <option value="' . $code . '">' . $val . '</option>' . "\n"; |
| 521 |
} |
| 522 |
$hidden_vals .= ' </select>'; |
| 523 |
$hidden_vals .= ' </div>'; |
| 524 |
$hidden_vals .= ' </div>'; |
| 525 |
|
| 526 |
// sexo |
| 527 |
$hidden_vals .= ' <div id="vbo-report-hospedajes-sesso" class="vbo-report-hospedajes-selcont vbo-param-container" style="display: none;">'; |
| 528 |
$hidden_vals .= ' <div class="vbo-param-label">Sexo</div>'; |
| 529 |
$hidden_vals .= ' <div class="vbo-param-setting">'; |
| 530 |
$hidden_vals .= ' <select id="choose-sesso" onchange="vboReportChosenSesso(this);"><option value=""></option>'; |
| 531 |
foreach ($this->sexo as $code => $ses) { |
| 532 |
$hidden_vals .= ' <option value="' . $code . '">' . $ses . '</option>' . "\n"; |
| 533 |
} |
| 534 |
$hidden_vals .= ' </select>'; |
| 535 |
$hidden_vals .= ' </div>'; |
| 536 |
$hidden_vals .= ' </div>'; |
| 537 |
|
| 538 |
// id number |
| 539 |
$hidden_vals .= ' <div id="vbo-report-hospedajes-docnum" class="vbo-report-hospedajes-selcont vbo-param-container" style="display: none;">'; |
| 540 |
$hidden_vals .= ' <div class="vbo-param-label">Número de documento</div>'; |
| 541 |
$hidden_vals .= ' <div class="vbo-param-setting">'; |
| 542 |
$hidden_vals .= ' <input type="text" size="40" id="choose-docnum" value="" />'; |
| 543 |
$hidden_vals .= ' </div>'; |
| 544 |
$hidden_vals .= ' </div>'; |
| 545 |
|
| 546 |
// número de soporte del documento |
| 547 |
$hidden_vals .= ' <div id="vbo-report-hospedajes-docsoporte" class="vbo-report-hospedajes-selcont vbo-param-container" style="display: none;">'; |
| 548 |
$hidden_vals .= ' <div class="vbo-param-label">Número de soporte del documento</div>'; |
| 549 |
$hidden_vals .= ' <div class="vbo-param-setting">'; |
| 550 |
$hidden_vals .= ' <input type="text" size="40" id="choose-docsoporte" value="" />'; |
| 551 |
$hidden_vals .= ' <span class="vbo-param-setting-comment">Obligatorio si el tipo de documento es NIF, NIE.</span>'; |
| 552 |
$hidden_vals .= ' </div>'; |
| 553 |
$hidden_vals .= ' </div>'; |
| 554 |
|
| 555 |
// address |
| 556 |
$hidden_vals .= ' <div id="vbo-report-hospedajes-address" class="vbo-report-hospedajes-selcont vbo-param-container" style="display: none;">'; |
| 557 |
$hidden_vals .= ' <div class="vbo-param-label">Direccion</div>'; |
| 558 |
$hidden_vals .= ' <div class="vbo-param-setting">'; |
| 559 |
$hidden_vals .= ' <input type="text" size="40" id="choose-address" value="" />'; |
| 560 |
$hidden_vals .= ' <span class="vbo-param-setting-comment">Calle, número, escalera, piso, puerta, y demás campos que indiquen la dirección.</span>'; |
| 561 |
$hidden_vals .= ' </div>'; |
| 562 |
$hidden_vals .= ' </div>'; |
| 563 |
|
| 564 |
// codigo municipio |
| 565 |
$hidden_vals .= ' <div id="vbo-report-hospedajes-municipio" class="vbo-report-hospedajes-selcont vbo-param-container" style="display: none;">'; |
| 566 |
$hidden_vals .= ' <div class="vbo-param-label">Código de municipio</div>'; |
| 567 |
$hidden_vals .= ' <div class="vbo-param-setting">'; |
| 568 |
$hidden_vals .= ' <select id="choose-municipio" onchange="vboReportChosenMunicipio(this);"><option value=""></option>'; |
| 569 |
foreach (VBOCheckinPaxfieldTypeSpainMunicipio::loadMunicipioCodes() as $code => $val) { |
| 570 |
$hidden_vals .= ' <option value="' . $code . '">' . $val . '</option>' . "\n"; |
| 571 |
} |
| 572 |
$hidden_vals .= ' </select>'; |
| 573 |
$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>'; |
| 574 |
$hidden_vals .= ' </div>'; |
| 575 |
$hidden_vals .= ' </div>'; |
| 576 |
|
| 577 |
// city |
| 578 |
$hidden_vals .= ' <div id="vbo-report-hospedajes-city" class="vbo-report-hospedajes-selcont vbo-param-container" style="display: none;">'; |
| 579 |
$hidden_vals .= ' <div class="vbo-param-label">Nombre del municipio</div>'; |
| 580 |
$hidden_vals .= ' <div class="vbo-param-setting">'; |
| 581 |
$hidden_vals .= ' <input type="text" size="40" id="choose-city" value="" />'; |
| 582 |
$hidden_vals .= ' <span class="vbo-param-setting-comment">Nombre del municipio, ciudad, estado, etc.. Obligatorio cuando el paÃs no es España.</span>'; |
| 583 |
$hidden_vals .= ' </div>'; |
| 584 |
$hidden_vals .= ' </div>'; |
| 585 |
|
| 586 |
// postal code |
| 587 |
$hidden_vals .= ' <div id="vbo-report-hospedajes-postalcode" class="vbo-report-hospedajes-selcont vbo-param-container" style="display: none;">'; |
| 588 |
$hidden_vals .= ' <div class="vbo-param-label">Código postal</div>'; |
| 589 |
$hidden_vals .= ' <div class="vbo-param-setting">'; |
| 590 |
$hidden_vals .= ' <input type="text" size="40" id="choose-postalcode" value="" />'; |
| 591 |
$hidden_vals .= ' </div>'; |
| 592 |
$hidden_vals .= ' </div>'; |
| 593 |
|
| 594 |
// phone |
| 595 |
$hidden_vals .= ' <div id="vbo-report-hospedajes-phone" class="vbo-report-hospedajes-selcont vbo-param-container" style="display: none;">'; |
| 596 |
$hidden_vals .= ' <div class="vbo-param-label">Teléfono</div>'; |
| 597 |
$hidden_vals .= ' <div class="vbo-param-setting">'; |
| 598 |
$hidden_vals .= ' <input type="tel" size="40" id="choose-phone" value="" />'; |
| 599 |
$hidden_vals .= ' </div>'; |
| 600 |
$hidden_vals .= ' </div>'; |
| 601 |
|
| 602 |
// email |
| 603 |
$hidden_vals .= ' <div id="vbo-report-hospedajes-email" class="vbo-report-hospedajes-selcont vbo-param-container" style="display: none;">'; |
| 604 |
$hidden_vals .= ' <div class="vbo-param-label">Dirección de correo electrónico</div>'; |
| 605 |
$hidden_vals .= ' <div class="vbo-param-setting">'; |
| 606 |
$hidden_vals .= ' <input type="email" size="40" id="choose-email" value="" />'; |
| 607 |
$hidden_vals .= ' </div>'; |
| 608 |
$hidden_vals .= ' </div>'; |
| 609 |
|
| 610 |
// birth date |
| 611 |
$hidden_vals .= ' <div id="vbo-report-hospedajes-dbirth" class="vbo-report-hospedajes-selcont vbo-param-container" style="display: none;">'; |
| 612 |
$hidden_vals .= ' <div class="vbo-param-label">Data di nascita</div>'; |
| 613 |
$hidden_vals .= ' <div class="vbo-param-setting">'; |
| 614 |
$hidden_vals .= ' <input type="text" size="40" id="choose-dbirth" value="" />'; |
| 615 |
$hidden_vals .= ' </div>'; |
| 616 |
$hidden_vals .= ' </div>'; |
| 617 |
|
| 618 |
// close params container HTML structure |
| 619 |
$hidden_vals .= ' </div>'; |
| 620 |
$hidden_vals .= ' </div>'; |
| 621 |
$hidden_vals .= ' </div>'; |
| 622 |
$hidden_vals .= '</div>'; |
| 623 |
|
| 624 |
// close hidden values container |
| 625 |
$hidden_vals .= '</div>'; |
| 626 |
|
| 627 |
// From Date Filter (with hidden values for the dropdown menus of Comuni, Province, Stati etc..) |
| 628 |
$filter_opt = array( |
| 629 |
'label' => '<label for="fromdate">' . JText::translate('VBOREPORTSDATEFROM') . '</label>', |
| 630 |
'html' => '<input type="text" id="fromdate" name="fromdate" value="" class="vbo-report-datepicker vbo-report-datepicker-from" />' . $hidden_vals, |
| 631 |
'type' => 'calendar', |
| 632 |
'name' => 'fromdate' |
| 633 |
); |
| 634 |
array_push($this->reportFilters, $filter_opt); |
| 635 |
|
| 636 |
// To Date Filter |
| 637 |
$filter_opt = array( |
| 638 |
'label' => '<label for="todate">' . JText::translate('VBOREPORTSDATETO') . '</label>', |
| 639 |
'html' => '<input type="text" id="todate" name="todate" value="" class="vbo-report-datepicker vbo-report-datepicker-to" />', |
| 640 |
'type' => 'calendar', |
| 641 |
'name' => 'todate' |
| 642 |
); |
| 643 |
array_push($this->reportFilters, $filter_opt); |
| 644 |
|
| 645 |
// Listings Filter |
| 646 |
$filter_opt = array( |
| 647 |
'label' => '<label for="listingsfilt">' . JText::translate('VBO_LISTINGS') . '</label>', |
| 648 |
'html' => '<span class="vbo-toolbar-multiselect-wrap">' . $vbo_app->renderElementsDropDown([ |
| 649 |
'id' => 'listingsfilt', |
| 650 |
'elements' => 'listings', |
| 651 |
'placeholder' => JText::translate('VBO_LISTINGS'), |
| 652 |
'allow_clear' => 1, |
| 653 |
'attributes' => [ |
| 654 |
'name' => 'listings[]', |
| 655 |
'multiple' => 'multiple', |
| 656 |
], |
| 657 |
'selected_values' => (array) ($app->input->get('listings', [], 'array') ?: $options->get('listings', [])), |
| 658 |
]) . '</span>', |
| 659 |
'type' => 'select', |
| 660 |
'multiple' => true, |
| 661 |
'name' => 'listings', |
| 662 |
); |
| 663 |
array_push($this->reportFilters, $filter_opt); |
| 664 |
|
| 665 |
// export type filter |
| 666 |
$types = [ |
| 667 |
'checkin' => sprintf('%s (%s)', JText::translate('VBPICKUPAT'), 'Partes de viajeros'), |
| 668 |
'reservation' => sprintf('%s (%s)', JText::translate('VBPCHOOSEBUSYORDATE'), 'Reservas de hospedaje'), |
| 669 |
]; |
| 670 |
$ptype = VikRequest::getString('type', 'checkin', 'request'); |
| 671 |
$types_sel_html = $vbo_app->getNiceSelect($types, $ptype, 'type', '', '', '', '', 'type'); |
| 672 |
$filter_opt = array( |
| 673 |
'label' => '<label for="type">' . JText::translate('VBPSHOWSEASONSTHREE') . '</label>', |
| 674 |
'html' => $types_sel_html, |
| 675 |
'type' => 'select', |
| 676 |
'name' => 'type' |
| 677 |
); |
| 678 |
array_push($this->reportFilters, $filter_opt); |
| 679 |
|
| 680 |
// append button to save the data when creating manual values |
| 681 |
$filter_opt = array( |
| 682 |
'label' => '<label class="vbo-report-hospedajes-manualsave" style="display: none;">Guests data</label>', |
| 683 |
'html' => '<button type="button" class="btn vbo-config-btn vbo-report-hospedajes-manualsave" style="display: none;" onclick="vboHospedajesSaveData();"><i class="' . VikBookingIcons::i('save') . '"></i> ' . JText::translate('VBSAVE') . '</button>', |
| 684 |
); |
| 685 |
array_push($this->reportFilters, $filter_opt); |
| 686 |
|
| 687 |
// datepicker calendars, select2 and triggers for the dropdown menus |
| 688 |
$pfromdate = VikRequest::getString('fromdate', '', 'request'); |
| 689 |
$ptodate = VikRequest::getString('todate', '', 'request'); |
| 690 |
|
| 691 |
$js = 'var reportActiveCell = null, reportObj = {}; |
| 692 |
var vbo_hospedajes_ajax_uri = "' . VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=invoke_report&report=' . $this->reportFile) . '"; |
| 693 |
var vbo_hospedajes_save_icn = "' . VikBookingIcons::i('save') . '"; |
| 694 |
var vbo_hospedajes_saving_icn = "' . VikBookingIcons::i('circle-notch', 'fa-spin fa-fw') . '"; |
| 695 |
var vbo_hospedajes_saved_icn = "' . VikBookingIcons::i('check-circle') . '"; |
| 696 |
jQuery(function() { |
| 697 |
//prepare main filters |
| 698 |
jQuery(".vbo-report-datepicker:input").datepicker({ |
| 699 |
maxDate: "+7 days", |
| 700 |
dateFormat: "'.$this->getDateFormat('jui').'", |
| 701 |
onSelect: vboReportCheckDates |
| 702 |
}); |
| 703 |
'.(!empty($pfromdate) ? 'jQuery(".vbo-report-datepicker-from").datepicker("setDate", "'.$pfromdate.'");' : '').' |
| 704 |
'.(!empty($ptodate) ? 'jQuery(".vbo-report-datepicker-to").datepicker("setDate", "'.$ptodate.'");' : '').' |
| 705 |
//prepare filler helpers |
| 706 |
jQuery("#vbo-report-hospedajes-hidden").children().detach().appendTo(".vbo-info-overlay-report"); |
| 707 |
jQuery("#choose-paytype").select2({placeholder: "- Tipo de pago -", width: "200px"}); |
| 708 |
jQuery("#choose-nazione").select2({placeholder: "- Seleccione un paÃs -", width: "200px"}); |
| 709 |
jQuery("#choose-documento").select2({placeholder: "- Seleccione un tipo de documento -", width: "200px"}); |
| 710 |
jQuery("#choose-parentesco").select2({placeholder: "----", width: "200px"}); |
| 711 |
jQuery("#choose-municipio").select2({placeholder: "----", width: "200px"}); |
| 712 |
jQuery("#choose-sesso").select2({placeholder: "- Seleccione sexo -", width: "200px"}); |
| 713 |
jQuery("#choose-dbirth").datepicker({ |
| 714 |
maxDate: 0, |
| 715 |
dateFormat: "dd/mm/yy", |
| 716 |
changeMonth: true, |
| 717 |
changeYear: true, |
| 718 |
yearRange: "'.(date('Y') - 100).':'.date('Y').'" |
| 719 |
}); |
| 720 |
//click events |
| 721 |
jQuery(".vbo-report-load-nazione, .vbo-report-load-nazione-stay, .vbo-report-load-cittadinanza , .vbo-report-load-countrystay").click(function() { |
| 722 |
reportActiveCell = this; |
| 723 |
jQuery(".vbo-report-hospedajes-selcont").hide(); |
| 724 |
jQuery("#vbo-report-hospedajes-nazione").show(); |
| 725 |
vboShowOverlay({ |
| 726 |
title: "Completa la información", |
| 727 |
extra_class: "vbo-modal-rounded vbo-modal-dialog vbo-modal-nofooter", |
| 728 |
}); |
| 729 |
}); |
| 730 |
jQuery(".vbo-report-load-doctype").click(function() { |
| 731 |
reportActiveCell = this; |
| 732 |
jQuery(".vbo-report-hospedajes-selcont").hide(); |
| 733 |
jQuery("#vbo-report-hospedajes-doctype").show(); |
| 734 |
vboShowOverlay({ |
| 735 |
title: "Completa la información", |
| 736 |
extra_class: "vbo-modal-rounded vbo-modal-dialog vbo-modal-nofooter", |
| 737 |
}); |
| 738 |
}); |
| 739 |
jQuery(".vbo-report-load-paytype").click(function() { |
| 740 |
reportActiveCell = this; |
| 741 |
jQuery(".vbo-report-hospedajes-selcont").hide(); |
| 742 |
jQuery("#vbo-report-hospedajes-paytype").show(); |
| 743 |
vboShowOverlay({ |
| 744 |
title: "Completa la información", |
| 745 |
extra_class: "vbo-modal-rounded vbo-modal-dialog vbo-modal-nofooter", |
| 746 |
}); |
| 747 |
}); |
| 748 |
jQuery(".vbo-report-load-sesso").click(function() { |
| 749 |
reportActiveCell = this; |
| 750 |
jQuery(".vbo-report-hospedajes-selcont").hide(); |
| 751 |
jQuery("#vbo-report-hospedajes-sesso").show(); |
| 752 |
vboShowOverlay({ |
| 753 |
title: "Completa la información", |
| 754 |
extra_class: "vbo-modal-rounded vbo-modal-dialog vbo-modal-nofooter", |
| 755 |
}); |
| 756 |
}); |
| 757 |
jQuery(".vbo-report-load-docnum").click(function() { |
| 758 |
reportActiveCell = this; |
| 759 |
jQuery(".vbo-report-hospedajes-selcont").hide(); |
| 760 |
jQuery("#vbo-report-hospedajes-docnum").show(); |
| 761 |
vboShowOverlay({ |
| 762 |
title: "Completa la información", |
| 763 |
extra_class: "vbo-modal-rounded vbo-modal-dialog", |
| 764 |
footer_right: "<button type=\"button\" class=\"btn btn-success\" onclick=\"vboReportChosenDocnum(document.getElementById(\'choose-docnum\').value);\">Guardar</button>", |
| 765 |
}); |
| 766 |
setTimeout(function(){jQuery("#choose-docnum").focus();}, 500); |
| 767 |
}); |
| 768 |
jQuery(".vbo-report-load-docsoporte").click(function() { |
| 769 |
reportActiveCell = this; |
| 770 |
jQuery(".vbo-report-hospedajes-selcont").hide(); |
| 771 |
jQuery("#vbo-report-hospedajes-docsoporte").show(); |
| 772 |
vboShowOverlay({ |
| 773 |
title: "Completa la información", |
| 774 |
extra_class: "vbo-modal-rounded vbo-modal-dialog", |
| 775 |
footer_right: "<button type=\"button\" class=\"btn btn-success\" onclick=\"vboReportChosenDocsoporte(document.getElementById(\'choose-docsoporte\').value);\">Guardar</button>", |
| 776 |
}); |
| 777 |
setTimeout(function(){jQuery("#choose-docsoporte").focus();}, 500); |
| 778 |
}); |
| 779 |
jQuery(".vbo-report-load-address").click(function() { |
| 780 |
reportActiveCell = this; |
| 781 |
jQuery(".vbo-report-hospedajes-selcont").hide(); |
| 782 |
jQuery("#vbo-report-hospedajes-address").show(); |
| 783 |
vboShowOverlay({ |
| 784 |
title: "Completa la información", |
| 785 |
extra_class: "vbo-modal-rounded vbo-modal-dialog", |
| 786 |
footer_right: "<button type=\"button\" class=\"btn btn-success\" onclick=\"vboReportChosenAddress(document.getElementById(\'choose-address\').value);\">Guardar</button>", |
| 787 |
}); |
| 788 |
setTimeout(function(){jQuery("#choose-address").focus();}, 500); |
| 789 |
}); |
| 790 |
jQuery(".vbo-report-load-parentesco").click(function() { |
| 791 |
reportActiveCell = this; |
| 792 |
jQuery(".vbo-report-hospedajes-selcont").hide(); |
| 793 |
jQuery("#vbo-report-hospedajes-parentesco").show(); |
| 794 |
vboShowOverlay({ |
| 795 |
title: "Completa la información", |
| 796 |
extra_class: "vbo-modal-rounded vbo-modal-dialog", |
| 797 |
footer_right: "<button type=\"button\" class=\"btn btn-success\" onclick=\"vboReportChosenParentesco(document.getElementById(\'choose-parentesco\').value);\">Guardar</button>", |
| 798 |
}); |
| 799 |
setTimeout(function(){jQuery("#choose-parentesco").focus();}, 500); |
| 800 |
}); |
| 801 |
jQuery(".vbo-report-load-municipio").click(function() { |
| 802 |
reportActiveCell = this; |
| 803 |
jQuery(".vbo-report-hospedajes-selcont").hide(); |
| 804 |
jQuery("#vbo-report-hospedajes-municipio").show(); |
| 805 |
vboShowOverlay({ |
| 806 |
title: "Completa la información", |
| 807 |
extra_class: "vbo-modal-rounded vbo-modal-dialog", |
| 808 |
footer_right: "<button type=\"button\" class=\"btn btn-success\" onclick=\"vboReportChosenMunicipio(document.getElementById(\'choose-municipio\').value);\">Guardar</button>", |
| 809 |
}); |
| 810 |
setTimeout(function(){jQuery("#choose-municipio").focus();}, 500); |
| 811 |
}); |
| 812 |
jQuery(".vbo-report-load-city").click(function() { |
| 813 |
reportActiveCell = this; |
| 814 |
jQuery(".vbo-report-hospedajes-selcont").hide(); |
| 815 |
jQuery("#vbo-report-hospedajes-city").show(); |
| 816 |
vboShowOverlay({ |
| 817 |
title: "Completa la información", |
| 818 |
extra_class: "vbo-modal-rounded vbo-modal-dialog", |
| 819 |
footer_right: "<button type=\"button\" class=\"btn btn-success\" onclick=\"vboReportChosenCity(document.getElementById(\'choose-city\').value);\">Guardar</button>", |
| 820 |
}); |
| 821 |
setTimeout(function(){jQuery("#choose-city").focus();}, 500); |
| 822 |
}); |
| 823 |
jQuery(".vbo-report-load-postalcode").click(function() { |
| 824 |
reportActiveCell = this; |
| 825 |
jQuery(".vbo-report-hospedajes-selcont").hide(); |
| 826 |
jQuery("#vbo-report-hospedajes-postalcode").show(); |
| 827 |
vboShowOverlay({ |
| 828 |
title: "Completa la información", |
| 829 |
extra_class: "vbo-modal-rounded vbo-modal-dialog", |
| 830 |
footer_right: "<button type=\"button\" class=\"btn btn-success\" onclick=\"vboReportChosenPostalcode(document.getElementById(\'choose-postalcode\').value);\">Guardar</button>", |
| 831 |
}); |
| 832 |
setTimeout(function(){jQuery("#choose-postalcode").focus();}, 500); |
| 833 |
}); |
| 834 |
jQuery(".vbo-report-load-phone").click(function() { |
| 835 |
reportActiveCell = this; |
| 836 |
jQuery(".vbo-report-hospedajes-selcont").hide(); |
| 837 |
jQuery("#vbo-report-hospedajes-phone").show(); |
| 838 |
vboShowOverlay({ |
| 839 |
title: "Completa la información", |
| 840 |
extra_class: "vbo-modal-rounded vbo-modal-dialog", |
| 841 |
footer_right: "<button type=\"button\" class=\"btn btn-success\" onclick=\"vboReportChosenPhone(document.getElementById(\'choose-phone\').value);\">Guardar</button>", |
| 842 |
}); |
| 843 |
setTimeout(function(){jQuery("#choose-phone").focus();}, 500); |
| 844 |
}); |
| 845 |
jQuery(".vbo-report-load-email").click(function() { |
| 846 |
reportActiveCell = this; |
| 847 |
jQuery(".vbo-report-hospedajes-selcont").hide(); |
| 848 |
jQuery("#vbo-report-hospedajes-email").show(); |
| 849 |
vboShowOverlay({ |
| 850 |
title: "Completa la información", |
| 851 |
extra_class: "vbo-modal-rounded vbo-modal-dialog", |
| 852 |
footer_right: "<button type=\"button\" class=\"btn btn-success\" onclick=\"vboReportChosenEmail(document.getElementById(\'choose-email\').value);\">Guardar</button>", |
| 853 |
}); |
| 854 |
setTimeout(function(){jQuery("#choose-email").focus();}, 500); |
| 855 |
}); |
| 856 |
jQuery(".vbo-report-load-dbirth").click(function() { |
| 857 |
reportActiveCell = this; |
| 858 |
jQuery(".vbo-report-hospedajes-selcont").hide(); |
| 859 |
jQuery("#vbo-report-hospedajes-dbirth").show(); |
| 860 |
vboShowOverlay({ |
| 861 |
title: "Completa la información", |
| 862 |
extra_class: "vbo-modal-rounded vbo-modal-dialog", |
| 863 |
footer_right: "<button type=\"button\" class=\"btn btn-success\" onclick=\"vboReportChosenDbirth(document.getElementById(\'choose-dbirth\').value);\">Guardar</button>", |
| 864 |
}); |
| 865 |
}); |
| 866 |
}); |
| 867 |
function vboReportCheckDates(selectedDate, inst) { |
| 868 |
if (selectedDate === null || inst === null) { |
| 869 |
return; |
| 870 |
} |
| 871 |
var cur_from_date = jQuery(this).val(); |
| 872 |
if (jQuery(this).hasClass("vbo-report-datepicker-from") && cur_from_date.length) { |
| 873 |
var nowstart = jQuery(this).datepicker("getDate"); |
| 874 |
var nowstartdate = new Date(nowstart.getTime()); |
| 875 |
jQuery(".vbo-report-datepicker-to").datepicker("option", {minDate: nowstartdate}); |
| 876 |
} |
| 877 |
} |
| 878 |
function vboReportChosenTipodepago(pago) { |
| 879 |
var c_code = pago.value; |
| 880 |
var c_val = pago.options[pago.selectedIndex].text; |
| 881 |
|
| 882 |
// apply the selected value to all guests of this booking |
| 883 |
if (reportActiveCell !== null) { |
| 884 |
var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr")); |
| 885 |
if (isNaN(nowindex) || parseInt(nowindex) < 0) { |
| 886 |
alert("Error, cannot find element to update."); |
| 887 |
return false; |
| 888 |
} |
| 889 |
var rep_act_cell = jQuery(reportActiveCell); |
| 890 |
var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid"); |
| 891 |
jQuery(\'[data-field="paytype"][data-fieldbid="\' + rep_guest_bid + \'"]\').each(function(k, v) { |
| 892 |
let nowcell = jQuery(v); |
| 893 |
nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(nowcell).closest("tr")); |
| 894 |
nowcell.addClass("vbo-report-load-elem-filled").find("span").text(c_val); |
| 895 |
if (!reportObj.hasOwnProperty(nowindex)) { |
| 896 |
reportObj[nowindex] = { |
| 897 |
bid: rep_guest_bid, |
| 898 |
bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr")) |
| 899 |
}; |
| 900 |
} |
| 901 |
reportObj[nowindex]["paytype"] = c_code; |
| 902 |
}); |
| 903 |
} |
| 904 |
|
| 905 |
reportActiveCell = null; |
| 906 |
vboHideOverlay(); |
| 907 |
jQuery("#choose-paytype").val("").select2("data", null, false); |
| 908 |
jQuery(".vbo-report-hospedajes-manualsave").show(); |
| 909 |
} |
| 910 |
function vboReportChosenNacionalidad(naz) { |
| 911 |
var c_code = naz.value; |
| 912 |
var c_val = naz.options[naz.selectedIndex].text; |
| 913 |
if (reportActiveCell !== null) { |
| 914 |
var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr")); |
| 915 |
if (isNaN(nowindex) || parseInt(nowindex) < 0) { |
| 916 |
alert("Error, cannot find element to update."); |
| 917 |
} else { |
| 918 |
var rep_act_cell = jQuery(reportActiveCell); |
| 919 |
rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val); |
| 920 |
var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid"); |
| 921 |
if (!reportObj.hasOwnProperty(nowindex)) { |
| 922 |
reportObj[nowindex] = { |
| 923 |
bid: rep_guest_bid, |
| 924 |
bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr")) |
| 925 |
}; |
| 926 |
} |
| 927 |
if (jQuery(reportActiveCell).hasClass("vbo-report-load-nazione")) { |
| 928 |
reportObj[nowindex]["country_b"] = c_code; |
| 929 |
} else if (jQuery(reportActiveCell).hasClass("vbo-report-load-nazione-stay")) { |
| 930 |
reportObj[nowindex]["country_s"] = c_code; |
| 931 |
} else if (jQuery(reportActiveCell).hasClass("vbo-report-load-docplace")) { |
| 932 |
reportObj[nowindex]["docplace"] = c_code; |
| 933 |
} else if (jQuery(reportActiveCell).hasClass("vbo-report-load-countrystay")) { |
| 934 |
reportObj[nowindex]["country_s"] = c_code; |
| 935 |
} else { |
| 936 |
reportObj[nowindex]["country_c"] = c_code; |
| 937 |
} |
| 938 |
} |
| 939 |
} |
| 940 |
reportActiveCell = null; |
| 941 |
vboHideOverlay(); |
| 942 |
jQuery("#choose-nazione").val("").select2("data", null, false); |
| 943 |
jQuery(".vbo-report-hospedajes-manualsave").show(); |
| 944 |
} |
| 945 |
function vboReportChosenDocumento(doctype) { |
| 946 |
var c_code = doctype.value; |
| 947 |
var c_val = doctype.options[doctype.selectedIndex].text; |
| 948 |
if (reportActiveCell !== null) { |
| 949 |
var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr")); |
| 950 |
if (isNaN(nowindex) || parseInt(nowindex) < 0) { |
| 951 |
alert("Error, cannot find element to update."); |
| 952 |
} else { |
| 953 |
var rep_act_cell = jQuery(reportActiveCell); |
| 954 |
rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val); |
| 955 |
var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid"); |
| 956 |
if (!reportObj.hasOwnProperty(nowindex)) { |
| 957 |
reportObj[nowindex] = { |
| 958 |
bid: rep_guest_bid, |
| 959 |
bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr")) |
| 960 |
}; |
| 961 |
} |
| 962 |
reportObj[nowindex]["doctype"] = c_code; |
| 963 |
} |
| 964 |
} |
| 965 |
reportActiveCell = null; |
| 966 |
vboHideOverlay(); |
| 967 |
jQuery("#choose-documento").val("").select2("data", null, false); |
| 968 |
jQuery(".vbo-report-hospedajes-manualsave").show(); |
| 969 |
} |
| 970 |
function vboReportChosenParentesco(parentesco) { |
| 971 |
var c_code = parentesco.value; |
| 972 |
var c_val = parentesco.options[parentesco.selectedIndex].text; |
| 973 |
if (reportActiveCell !== null) { |
| 974 |
var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr")); |
| 975 |
if (isNaN(nowindex) || parseInt(nowindex) < 0) { |
| 976 |
alert("Error, cannot find element to update."); |
| 977 |
} else { |
| 978 |
var rep_act_cell = jQuery(reportActiveCell); |
| 979 |
rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val); |
| 980 |
var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid"); |
| 981 |
if (!reportObj.hasOwnProperty(nowindex)) { |
| 982 |
reportObj[nowindex] = { |
| 983 |
bid: rep_guest_bid, |
| 984 |
bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr")) |
| 985 |
}; |
| 986 |
} |
| 987 |
reportObj[nowindex]["parentesco"] = c_code; |
| 988 |
} |
| 989 |
} |
| 990 |
reportActiveCell = null; |
| 991 |
vboHideOverlay(); |
| 992 |
jQuery("#choose-parentesco").val("").select2("data", null, false); |
| 993 |
jQuery(".vbo-report-hospedajes-manualsave").show(); |
| 994 |
} |
| 995 |
function vboReportChosenSesso(sesso) { |
| 996 |
var c_code = sesso.value; |
| 997 |
var c_val = sesso.options[sesso.selectedIndex].text; |
| 998 |
if (reportActiveCell !== null) { |
| 999 |
var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr")); |
| 1000 |
if (isNaN(nowindex) || parseInt(nowindex) < 0) { |
| 1001 |
alert("Error, cannot find element to update."); |
| 1002 |
} else { |
| 1003 |
var rep_act_cell = jQuery(reportActiveCell); |
| 1004 |
rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val); |
| 1005 |
var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid"); |
| 1006 |
if (!reportObj.hasOwnProperty(nowindex)) { |
| 1007 |
reportObj[nowindex] = { |
| 1008 |
bid: rep_guest_bid, |
| 1009 |
bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr")) |
| 1010 |
}; |
| 1011 |
} |
| 1012 |
reportObj[nowindex]["gender"] = c_code; |
| 1013 |
} |
| 1014 |
} |
| 1015 |
reportActiveCell = null; |
| 1016 |
vboHideOverlay(); |
| 1017 |
jQuery("#choose-sesso").val("").select2("data", null, false); |
| 1018 |
jQuery(".vbo-report-hospedajes-manualsave").show(); |
| 1019 |
} |
| 1020 |
function vboReportChosenDocnum(val) { |
| 1021 |
var c_code = val, c_val = val; |
| 1022 |
if (reportActiveCell !== null) { |
| 1023 |
var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr")); |
| 1024 |
if (isNaN(nowindex) || parseInt(nowindex) < 0) { |
| 1025 |
alert("Error, cannot find element to update."); |
| 1026 |
} else { |
| 1027 |
var rep_act_cell = jQuery(reportActiveCell); |
| 1028 |
rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val); |
| 1029 |
var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid"); |
| 1030 |
if (!reportObj.hasOwnProperty(nowindex)) { |
| 1031 |
reportObj[nowindex] = { |
| 1032 |
bid: rep_guest_bid, |
| 1033 |
bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr")) |
| 1034 |
}; |
| 1035 |
} |
| 1036 |
reportObj[nowindex]["docnum"] = c_code; |
| 1037 |
} |
| 1038 |
} |
| 1039 |
reportActiveCell = null; |
| 1040 |
vboHideOverlay(); |
| 1041 |
jQuery("#choose-docnum").val(""); |
| 1042 |
jQuery(".vbo-report-hospedajes-manualsave").show(); |
| 1043 |
} |
| 1044 |
function vboReportChosenDocsoporte(val) { |
| 1045 |
var c_code = val, c_val = val; |
| 1046 |
if (reportActiveCell !== null) { |
| 1047 |
var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr")); |
| 1048 |
if (isNaN(nowindex) || parseInt(nowindex) < 0) { |
| 1049 |
alert("Error, cannot find element to update."); |
| 1050 |
} else { |
| 1051 |
var rep_act_cell = jQuery(reportActiveCell); |
| 1052 |
rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val); |
| 1053 |
var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid"); |
| 1054 |
if (!reportObj.hasOwnProperty(nowindex)) { |
| 1055 |
reportObj[nowindex] = { |
| 1056 |
bid: rep_guest_bid, |
| 1057 |
bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr")) |
| 1058 |
}; |
| 1059 |
} |
| 1060 |
reportObj[nowindex]["docsoporte"] = c_code; |
| 1061 |
} |
| 1062 |
} |
| 1063 |
reportActiveCell = null; |
| 1064 |
vboHideOverlay(); |
| 1065 |
jQuery("#choose-docsoporte").val(""); |
| 1066 |
jQuery(".vbo-report-hospedajes-manualsave").show(); |
| 1067 |
} |
| 1068 |
function vboReportChosenAddress(val) { |
| 1069 |
var c_code = val, c_val = val; |
| 1070 |
if (reportActiveCell !== null) { |
| 1071 |
var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr")); |
| 1072 |
if (isNaN(nowindex) || parseInt(nowindex) < 0) { |
| 1073 |
alert("Error, cannot find element to update."); |
| 1074 |
} else { |
| 1075 |
var rep_act_cell = jQuery(reportActiveCell); |
| 1076 |
rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val); |
| 1077 |
var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid"); |
| 1078 |
if (!reportObj.hasOwnProperty(nowindex)) { |
| 1079 |
reportObj[nowindex] = { |
| 1080 |
bid: rep_guest_bid, |
| 1081 |
bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr")) |
| 1082 |
}; |
| 1083 |
} |
| 1084 |
reportObj[nowindex]["address"] = c_code; |
| 1085 |
} |
| 1086 |
} |
| 1087 |
reportActiveCell = null; |
| 1088 |
vboHideOverlay(); |
| 1089 |
jQuery("#choose-address").val(""); |
| 1090 |
jQuery(".vbo-report-hospedajes-manualsave").show(); |
| 1091 |
} |
| 1092 |
function vboReportChosenMunicipio(municipio) { |
| 1093 |
var c_code = municipio.value; |
| 1094 |
var c_val = municipio.options[municipio.selectedIndex].text; |
| 1095 |
if (reportActiveCell !== null) { |
| 1096 |
var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr")); |
| 1097 |
if (isNaN(nowindex) || parseInt(nowindex) < 0) { |
| 1098 |
alert("Error, cannot find element to update."); |
| 1099 |
} else { |
| 1100 |
var rep_act_cell = jQuery(reportActiveCell); |
| 1101 |
rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val); |
| 1102 |
var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid"); |
| 1103 |
if (!reportObj.hasOwnProperty(nowindex)) { |
| 1104 |
reportObj[nowindex] = { |
| 1105 |
bid: rep_guest_bid, |
| 1106 |
bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr")) |
| 1107 |
}; |
| 1108 |
} |
| 1109 |
reportObj[nowindex]["municipio"] = c_code; |
| 1110 |
} |
| 1111 |
} |
| 1112 |
reportActiveCell = null; |
| 1113 |
vboHideOverlay(); |
| 1114 |
jQuery("#choose-municipio").val("").select2("data", null, false); |
| 1115 |
jQuery(".vbo-report-hospedajes-manualsave").show(); |
| 1116 |
} |
| 1117 |
function vboReportChosenCity(val) { |
| 1118 |
var c_code = val, c_val = val; |
| 1119 |
if (reportActiveCell !== null) { |
| 1120 |
var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr")); |
| 1121 |
if (isNaN(nowindex) || parseInt(nowindex) < 0) { |
| 1122 |
alert("Error, cannot find element to update."); |
| 1123 |
} else { |
| 1124 |
var rep_act_cell = jQuery(reportActiveCell); |
| 1125 |
rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val); |
| 1126 |
var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid"); |
| 1127 |
if (!reportObj.hasOwnProperty(nowindex)) { |
| 1128 |
reportObj[nowindex] = { |
| 1129 |
bid: rep_guest_bid, |
| 1130 |
bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr")) |
| 1131 |
}; |
| 1132 |
} |
| 1133 |
reportObj[nowindex]["city"] = c_code; |
| 1134 |
} |
| 1135 |
} |
| 1136 |
reportActiveCell = null; |
| 1137 |
vboHideOverlay(); |
| 1138 |
jQuery("#choose-city").val(""); |
| 1139 |
jQuery(".vbo-report-hospedajes-manualsave").show(); |
| 1140 |
} |
| 1141 |
function vboReportChosenPostalcode(val) { |
| 1142 |
var c_code = val, c_val = val; |
| 1143 |
if (reportActiveCell !== null) { |
| 1144 |
var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr")); |
| 1145 |
if (isNaN(nowindex) || parseInt(nowindex) < 0) { |
| 1146 |
alert("Error, cannot find element to update."); |
| 1147 |
} else { |
| 1148 |
var rep_act_cell = jQuery(reportActiveCell); |
| 1149 |
rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val); |
| 1150 |
var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid"); |
| 1151 |
if (!reportObj.hasOwnProperty(nowindex)) { |
| 1152 |
reportObj[nowindex] = { |
| 1153 |
bid: rep_guest_bid, |
| 1154 |
bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr")) |
| 1155 |
}; |
| 1156 |
} |
| 1157 |
reportObj[nowindex]["postalcode"] = c_code; |
| 1158 |
} |
| 1159 |
} |
| 1160 |
reportActiveCell = null; |
| 1161 |
vboHideOverlay(); |
| 1162 |
jQuery("#choose-postalcode").val(""); |
| 1163 |
jQuery(".vbo-report-hospedajes-manualsave").show(); |
| 1164 |
} |
| 1165 |
function vboReportChosenPhone(val) { |
| 1166 |
var c_code = val, c_val = val; |
| 1167 |
if (reportActiveCell !== null) { |
| 1168 |
var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr")); |
| 1169 |
if (isNaN(nowindex) || parseInt(nowindex) < 0) { |
| 1170 |
alert("Error, cannot find element to update."); |
| 1171 |
} else { |
| 1172 |
var rep_act_cell = jQuery(reportActiveCell); |
| 1173 |
rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val); |
| 1174 |
var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid"); |
| 1175 |
if (!reportObj.hasOwnProperty(nowindex)) { |
| 1176 |
reportObj[nowindex] = { |
| 1177 |
bid: rep_guest_bid, |
| 1178 |
bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr")) |
| 1179 |
}; |
| 1180 |
} |
| 1181 |
reportObj[nowindex]["phone"] = c_code; |
| 1182 |
} |
| 1183 |
} |
| 1184 |
reportActiveCell = null; |
| 1185 |
vboHideOverlay(); |
| 1186 |
jQuery("#choose-phone").val(""); |
| 1187 |
jQuery(".vbo-report-hospedajes-manualsave").show(); |
| 1188 |
} |
| 1189 |
function vboReportChosenEmail(val) { |
| 1190 |
var c_code = val, c_val = val; |
| 1191 |
if (reportActiveCell !== null) { |
| 1192 |
var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr")); |
| 1193 |
if (isNaN(nowindex) || parseInt(nowindex) < 0) { |
| 1194 |
alert("Error, cannot find element to update."); |
| 1195 |
} else { |
| 1196 |
var rep_act_cell = jQuery(reportActiveCell); |
| 1197 |
rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val); |
| 1198 |
var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid"); |
| 1199 |
if (!reportObj.hasOwnProperty(nowindex)) { |
| 1200 |
reportObj[nowindex] = { |
| 1201 |
bid: rep_guest_bid, |
| 1202 |
bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr")) |
| 1203 |
}; |
| 1204 |
} |
| 1205 |
reportObj[nowindex]["email"] = c_code; |
| 1206 |
} |
| 1207 |
} |
| 1208 |
reportActiveCell = null; |
| 1209 |
vboHideOverlay(); |
| 1210 |
jQuery("#choose-email").val(""); |
| 1211 |
jQuery(".vbo-report-hospedajes-manualsave").show(); |
| 1212 |
} |
| 1213 |
function vboReportChosenDbirth(val) { |
| 1214 |
var c_code = val, c_val = val; |
| 1215 |
if (reportActiveCell !== null) { |
| 1216 |
var nowindex = jQuery(".vbo-reports-output table tbody tr").index(jQuery(reportActiveCell).closest("tr")); |
| 1217 |
if (isNaN(nowindex) || parseInt(nowindex) < 0) { |
| 1218 |
alert("Error, cannot find element to update."); |
| 1219 |
} else { |
| 1220 |
var rep_act_cell = jQuery(reportActiveCell); |
| 1221 |
rep_act_cell.addClass("vbo-report-load-elem-filled").find("span").text(c_val); |
| 1222 |
var rep_guest_bid = rep_act_cell.closest("tr").find("a[data-bid]").attr("data-bid"); |
| 1223 |
if (!reportObj.hasOwnProperty(nowindex)) { |
| 1224 |
reportObj[nowindex] = { |
| 1225 |
bid: rep_guest_bid, |
| 1226 |
bid_index: jQuery(".vbo-reports-output table tbody tr").index(jQuery("a[data-bid=\"" + rep_guest_bid + "\"]").first().closest("tr")) |
| 1227 |
}; |
| 1228 |
} |
| 1229 |
reportObj[nowindex]["date_birth"] = c_code; |
| 1230 |
} |
| 1231 |
} |
| 1232 |
reportActiveCell = null; |
| 1233 |
vboHideOverlay(); |
| 1234 |
jQuery("#choose-dbirth").val(""); |
| 1235 |
jQuery(".vbo-report-hospedajes-manualsave").show(); |
| 1236 |
} |
| 1237 |
//download function |
| 1238 |
function vboDownloadHospedajes(type, report_type) { |
| 1239 |
if (!confirm("¿Estás seguro de que quieres continuar?")) { |
| 1240 |
return false; |
| 1241 |
} |
| 1242 |
|
| 1243 |
let use_blank = true; |
| 1244 |
if (typeof type === "undefined") { |
| 1245 |
type = 1; |
| 1246 |
} else { |
| 1247 |
use_blank = false; |
| 1248 |
} |
| 1249 |
|
| 1250 |
if (typeof report_type !== "undefined") { |
| 1251 |
jQuery(\'#adminForm\').find(\'select[name="type"]\').val(report_type).trigger(\'change\'); |
| 1252 |
} |
| 1253 |
|
| 1254 |
if (use_blank) { |
| 1255 |
document.adminForm.target = "_blank"; |
| 1256 |
document.adminForm.action += "&tmpl=component"; |
| 1257 |
} |
| 1258 |
|
| 1259 |
vboSetFilters({exportreport: type, filler: JSON.stringify(reportObj)}, true); |
| 1260 |
|
| 1261 |
setTimeout(function() { |
| 1262 |
document.adminForm.target = ""; |
| 1263 |
document.adminForm.action = document.adminForm.action.replace("&tmpl=component", ""); |
| 1264 |
vboSetFilters({exportreport: "0", filler: ""}, false); |
| 1265 |
}, 1000); |
| 1266 |
} |
| 1267 |
// save data function |
| 1268 |
function vboHospedajesSaveData() { |
| 1269 |
jQuery("button.vbo-report-hospedajes-manualsave").find("i").attr("class", vbo_hospedajes_saving_icn); |
| 1270 |
VBOCore.doAjax( |
| 1271 |
vbo_hospedajes_ajax_uri, |
| 1272 |
{ |
| 1273 |
call: "updatePaxData", |
| 1274 |
params: reportObj, |
| 1275 |
tmpl: "component" |
| 1276 |
}, |
| 1277 |
function(response) { |
| 1278 |
if (!response || !response[0]) { |
| 1279 |
alert("An error occurred."); |
| 1280 |
return false; |
| 1281 |
} |
| 1282 |
jQuery("button.vbo-report-hospedajes-manualsave").addClass("btn-success").find("i").attr("class", vbo_hospedajes_saved_icn); |
| 1283 |
}, |
| 1284 |
function(error) { |
| 1285 |
alert(error.responseText); |
| 1286 |
jQuery("button.vbo-report-hospedajes-manualsave").removeClass("btn-success").find("i").attr("class", vbo_hospedajes_save_icn); |
| 1287 |
} |
| 1288 |
); |
| 1289 |
} |
| 1290 |
'; |
| 1291 |
$this->setScript($js); |
| 1292 |
|
| 1293 |
return $this->reportFilters; |
| 1294 |
} |
| 1295 |
|
| 1296 |
/** |
| 1297 |
* Loads the report data from the DB. |
| 1298 |
* Returns true in case of success, false otherwise. |
| 1299 |
* Sets the columns and rows for the report to be displayed. |
| 1300 |
* |
| 1301 |
* @return boolean |
| 1302 |
*/ |
| 1303 |
public function getReportData() |
| 1304 |
{ |
| 1305 |
if ($this->getError()) { |
| 1306 |
// export functions may set errors rather than exiting the process, and |
| 1307 |
// the View may continue the execution to attempt to render the report. |
| 1308 |
return false; |
| 1309 |
} |
| 1310 |
|
| 1311 |
if ($this->rows) { |
| 1312 |
// method must have run already |
| 1313 |
return true; |
| 1314 |
} |
| 1315 |
|
| 1316 |
// get the possibly injected report options |
| 1317 |
$options = $this->getReportOptions(); |
| 1318 |
|
| 1319 |
// injected options will replace request variables, if any |
| 1320 |
$opt_fromdate = $options->get('fromdate', ''); |
| 1321 |
$opt_todate = $options->get('todate', ''); |
| 1322 |
$opt_type = $options->get('type', ''); |
| 1323 |
|
| 1324 |
// input fields and other vars |
| 1325 |
$pfromdate = $opt_fromdate ?: VikRequest::getString('fromdate', '', 'request'); |
| 1326 |
$ptodate = $opt_todate ?: VikRequest::getString('todate', '', 'request'); |
| 1327 |
$ptype = $opt_type ?: VikRequest::getString('type', 'checkin', 'request'); |
| 1328 |
|
| 1329 |
$pkrsort = VikRequest::getString('krsort', $this->defaultKeySort, 'request'); |
| 1330 |
$pkrsort = empty($pkrsort) ? $this->defaultKeySort : $pkrsort; |
| 1331 |
$pkrorder = VikRequest::getString('krorder', $this->defaultKeyOrder, 'request'); |
| 1332 |
$pkrorder = empty($pkrorder) ? $this->defaultKeyOrder : $pkrorder; |
| 1333 |
$pkrorder = $pkrorder == 'DESC' ? 'DESC' : 'ASC'; |
| 1334 |
$plistings = ((array) VikRequest::getVar('listings', array())) ?: ((array) $options->get('listings', [])); |
| 1335 |
$plistings = array_filter(array_map('intval', $plistings)); |
| 1336 |
|
| 1337 |
$currency_symb = VikBooking::getCurrencySymb(); |
| 1338 |
$df = $this->getDateFormat(); |
| 1339 |
$datesep = VikBooking::getDateSeparator(); |
| 1340 |
|
| 1341 |
if (empty($ptodate)) { |
| 1342 |
$ptodate = $pfromdate; |
| 1343 |
} |
| 1344 |
|
| 1345 |
// get date timestamps |
| 1346 |
$from_ts = VikBooking::getDateTimestamp($pfromdate, 0, 0); |
| 1347 |
$to_ts = VikBooking::getDateTimestamp($ptodate, 23, 59, 59); |
| 1348 |
if (empty($pfromdate) || empty($from_ts) || empty($to_ts)) { |
| 1349 |
$this->setError(JText::translate('VBOREPORTSERRNODATES')); |
| 1350 |
return false; |
| 1351 |
} |
| 1352 |
|
| 1353 |
// set the dates being exported |
| 1354 |
$this->exported_checkin_dates = [ |
| 1355 |
date('Y-m-d', $from_ts), |
| 1356 |
date('Y-m-d', $to_ts), |
| 1357 |
]; |
| 1358 |
|
| 1359 |
// query to obtain the records (all check-ins or reservations created within the dates filter) |
| 1360 |
$q = $this->dbo->getQuery(true) |
| 1361 |
->select([ |
| 1362 |
$this->dbo->qn('o.id'), |
| 1363 |
$this->dbo->qn('o.custdata'), |
| 1364 |
$this->dbo->qn('o.ts'), |
| 1365 |
$this->dbo->qn('o.days'), |
| 1366 |
$this->dbo->qn('o.checkin'), |
| 1367 |
$this->dbo->qn('o.checkout'), |
| 1368 |
$this->dbo->qn('o.totpaid'), |
| 1369 |
$this->dbo->qn('o.roomsnum'), |
| 1370 |
$this->dbo->qn('o.total'), |
| 1371 |
$this->dbo->qn('o.idorderota'), |
| 1372 |
$this->dbo->qn('o.channel'), |
| 1373 |
$this->dbo->qn('o.country'), |
| 1374 |
$this->dbo->qn('o.custmail'), |
| 1375 |
$this->dbo->qn('o.phone'), |
| 1376 |
$this->dbo->qn('or.idorder'), |
| 1377 |
$this->dbo->qn('or.idroom'), |
| 1378 |
$this->dbo->qn('or.adults'), |
| 1379 |
$this->dbo->qn('or.children'), |
| 1380 |
$this->dbo->qn('or.t_first_name'), |
| 1381 |
$this->dbo->qn('or.t_last_name'), |
| 1382 |
$this->dbo->qn('or.cust_cost'), |
| 1383 |
$this->dbo->qn('or.cust_idiva'), |
| 1384 |
$this->dbo->qn('or.extracosts'), |
| 1385 |
$this->dbo->qn('or.room_cost'), |
| 1386 |
$this->dbo->qn('co.idcustomer'), |
| 1387 |
$this->dbo->qn('co.pax_data'), |
| 1388 |
$this->dbo->qn('c.first_name'), |
| 1389 |
$this->dbo->qn('c.last_name'), |
| 1390 |
$this->dbo->qn('c.country', 'customer_country'), |
| 1391 |
$this->dbo->qn('c.address'), |
| 1392 |
$this->dbo->qn('c.doctype'), |
| 1393 |
$this->dbo->qn('c.docnum'), |
| 1394 |
$this->dbo->qn('c.gender'), |
| 1395 |
$this->dbo->qn('c.bdate'), |
| 1396 |
$this->dbo->qn('c.pbirth'), |
| 1397 |
]) |
| 1398 |
->from($this->dbo->qn('#__vikbooking_orders', 'o')) |
| 1399 |
->leftJoin($this->dbo->qn('#__vikbooking_ordersrooms', 'or') . ' ON ' . $this->dbo->qn('or.idorder') . ' = ' . $this->dbo->qn('o.id')) |
| 1400 |
->leftJoin($this->dbo->qn('#__vikbooking_customers_orders', 'co') . ' ON ' . $this->dbo->qn('co.idorder') . ' = ' . $this->dbo->qn('o.id')) |
| 1401 |
->leftJoin($this->dbo->qn('#__vikbooking_customers', 'c') . ' ON ' . $this->dbo->qn('c.id') . ' = ' . $this->dbo->qn('co.idcustomer')) |
| 1402 |
->where($this->dbo->qn('o.status') . ' = ' . $this->dbo->q('confirmed')) |
| 1403 |
->where($this->dbo->qn('o.closure') . ' = 0') |
| 1404 |
->order($this->dbo->qn('o.checkin') . ' ASC') |
| 1405 |
->order($this->dbo->qn('o.id') . ' ASC') |
| 1406 |
->order($this->dbo->qn('or.id') . ' ASC'); |
| 1407 |
|
| 1408 |
if ($plistings) { |
| 1409 |
$q->where($this->dbo->qn('or.idroom') . ' IN (' . implode(', ', $plistings) . ')'); |
| 1410 |
} |
| 1411 |
|
| 1412 |
if ($ptype === 'reservation') { |
| 1413 |
$q->where($this->dbo->qn('o.ts') . ' >= ' . $from_ts); |
| 1414 |
$q->where($this->dbo->qn('o.ts') . ' <= ' . $to_ts); |
| 1415 |
} else { |
| 1416 |
$q->where($this->dbo->qn('o.checkin') . ' >= ' . $from_ts); |
| 1417 |
$q->where($this->dbo->qn('o.checkin') . ' <= ' . $to_ts); |
| 1418 |
} |
| 1419 |
|
| 1420 |
$this->dbo->setQuery($q); |
| 1421 |
$records = $this->dbo->loadAssocList(); |
| 1422 |
|
| 1423 |
if (!$records) { |
| 1424 |
$this->setError(JText::translate('VBOREPORTSERRNORESERV')); |
| 1425 |
$this->setError('No hay reservas con los filtros seleccionados.'); |
| 1426 |
return false; |
| 1427 |
} |
| 1428 |
|
| 1429 |
// nest records with multiple rooms booked inside sub-array |
| 1430 |
$bookings = []; |
| 1431 |
foreach ($records as $v) { |
| 1432 |
if (!isset($bookings[$v['id']])) { |
| 1433 |
$bookings[$v['id']] = []; |
| 1434 |
} |
| 1435 |
array_push($bookings[$v['id']], $v); |
| 1436 |
} |
| 1437 |
|
| 1438 |
// free some memory up |
| 1439 |
unset($records); |
| 1440 |
|
| 1441 |
// define the columns of the report |
| 1442 |
$this->cols = array( |
| 1443 |
// guest type (rol) |
| 1444 |
array( |
| 1445 |
'key' => 'guest_type', |
| 1446 |
'label' => 'Rol', |
| 1447 |
), |
| 1448 |
// first name |
| 1449 |
array( |
| 1450 |
'key' => 'first_name', |
| 1451 |
'label' => JText::translate('VBTRAVELERNAME'), |
| 1452 |
), |
| 1453 |
// last name |
| 1454 |
array( |
| 1455 |
'key' => 'last_name', |
| 1456 |
'label' => JText::translate('VBTRAVELERLNAME'), |
| 1457 |
), |
| 1458 |
// reservation date |
| 1459 |
array( |
| 1460 |
'key' => 'resdate', |
| 1461 |
'attr' => array( |
| 1462 |
'class="center"' |
| 1463 |
), |
| 1464 |
'label' => JText::translate('VBPCHOOSEBUSYORDATE'), |
| 1465 |
'ignore_view' => 1, |
| 1466 |
), |
| 1467 |
// number of guests |
| 1468 |
array( |
| 1469 |
'key' => 'numguests', |
| 1470 |
'attr' => array( |
| 1471 |
'class="center"' |
| 1472 |
), |
| 1473 |
'label' => JText::translate('VBPVIEWORDERSPEOPLE'), |
| 1474 |
'ignore_view' => 1, |
| 1475 |
), |
| 1476 |
// sexo |
| 1477 |
array( |
| 1478 |
'key' => 'gender', |
| 1479 |
'attr' => array( |
| 1480 |
'class="center"' |
| 1481 |
), |
| 1482 |
'label' => JText::translate('VBCUSTOMERGENDER'), |
| 1483 |
), |
| 1484 |
// id type |
| 1485 |
array( |
| 1486 |
'key' => 'doctype', |
| 1487 |
'attr' => array( |
| 1488 |
'class="center"' |
| 1489 |
), |
| 1490 |
'label' => JText::translate('VBCUSTOMERDOCTYPE'), |
| 1491 |
), |
| 1492 |
// id number |
| 1493 |
array( |
| 1494 |
'key' => 'docnum', |
| 1495 |
'attr' => array( |
| 1496 |
'class="center"' |
| 1497 |
), |
| 1498 |
'label' => JText::translate('VBCUSTOMERDOCNUM'), |
| 1499 |
), |
| 1500 |
// número de soporte del documento |
| 1501 |
array( |
| 1502 |
'key' => 'docsoporte', |
| 1503 |
'attr' => array( |
| 1504 |
'class="center"' |
| 1505 |
), |
| 1506 |
'label' => 'Número de soporte', |
| 1507 |
'tip' => 'Número de soporte del documento. Obligatorio si el tipo de documento es NIF, NIE.', |
| 1508 |
), |
| 1509 |
// birth date |
| 1510 |
array( |
| 1511 |
'key' => 'date_birth', |
| 1512 |
'attr' => array( |
| 1513 |
'class="center"' |
| 1514 |
), |
| 1515 |
'label' => JText::translate('VBCUSTOMERBDATE'), |
| 1516 |
), |
| 1517 |
// parentesco |
| 1518 |
array( |
| 1519 |
'key' => 'parentesco', |
| 1520 |
'label' => 'Parentesco', |
| 1521 |
'attr' => array( |
| 1522 |
'class="center"' |
| 1523 |
), |
| 1524 |
'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.', |
| 1525 |
), |
| 1526 |
// address |
| 1527 |
array( |
| 1528 |
'key' => 'address', |
| 1529 |
'attr' => array( |
| 1530 |
'class="center"' |
| 1531 |
), |
| 1532 |
'label' => JText::translate('ORDER_ADDRESS'), |
| 1533 |
), |
| 1534 |
// codigo municipio |
| 1535 |
array( |
| 1536 |
'key' => 'municipio', |
| 1537 |
'label' => 'Municipio', |
| 1538 |
'attr' => array( |
| 1539 |
'class="center"' |
| 1540 |
), |
| 1541 |
'tip' => 'Código de municipio del INE (5 dÃgitos). Obligatorio cuando el paÃs es España.', |
| 1542 |
), |
| 1543 |
// city |
| 1544 |
array( |
| 1545 |
'key' => 'city', |
| 1546 |
'label' => JText::translate('ORDER_CITY'), |
| 1547 |
), |
| 1548 |
// postal code |
| 1549 |
array( |
| 1550 |
'key' => 'postalcode', |
| 1551 |
'attr' => array( |
| 1552 |
'class="center"' |
| 1553 |
), |
| 1554 |
'label' => JText::translate('ORDER_ZIP'), |
| 1555 |
), |
| 1556 |
// country of stay |
| 1557 |
array( |
| 1558 |
'key' => 'country_s', |
| 1559 |
'attr' => array( |
| 1560 |
'class="center"' |
| 1561 |
), |
| 1562 |
'label' => JText::translate('ORDER_STATE'), |
| 1563 |
), |
| 1564 |
// citizenship |
| 1565 |
array( |
| 1566 |
'key' => 'country_c', |
| 1567 |
'attr' => array( |
| 1568 |
'class="center"' |
| 1569 |
), |
| 1570 |
'label' => JText::translate('VBCUSTOMERNATION'), |
| 1571 |
), |
| 1572 |
// phone |
| 1573 |
array( |
| 1574 |
'key' => 'phone', |
| 1575 |
'attr' => array( |
| 1576 |
'class="center"' |
| 1577 |
), |
| 1578 |
'label' => JText::translate('ORDER_PHONE'), |
| 1579 |
), |
| 1580 |
// email |
| 1581 |
array( |
| 1582 |
'key' => 'email', |
| 1583 |
'attr' => array( |
| 1584 |
'class="center"' |
| 1585 |
), |
| 1586 |
'label' => JText::translate('ORDER_EMAIL'), |
| 1587 |
), |
| 1588 |
// payment type |
| 1589 |
array( |
| 1590 |
'key' => 'paytype', |
| 1591 |
'attr' => array( |
| 1592 |
'class="center"' |
| 1593 |
), |
| 1594 |
'label' => JText::translate('VBLIBPAYNAME'), |
| 1595 |
), |
| 1596 |
// check-in |
| 1597 |
array( |
| 1598 |
'key' => 'checkin', |
| 1599 |
'attr' => array( |
| 1600 |
'class="center"' |
| 1601 |
), |
| 1602 |
'label' => JText::translate('VBPICKUPAT'), |
| 1603 |
), |
| 1604 |
// check-out |
| 1605 |
array( |
| 1606 |
'key' => 'checkout', |
| 1607 |
'attr' => array( |
| 1608 |
'class="center"' |
| 1609 |
), |
| 1610 |
'label' => JText::translate('VBRELEASEAT'), |
| 1611 |
), |
| 1612 |
// id booking |
| 1613 |
array( |
| 1614 |
'key' => 'idbooking', |
| 1615 |
'attr' => array( |
| 1616 |
'class="center"' |
| 1617 |
), |
| 1618 |
'label' => 'ID', |
| 1619 |
), |
| 1620 |
); |
| 1621 |
|
| 1622 |
// codigo municipio list |
| 1623 |
$municipio_codes_list = VBOCheckinPaxfieldTypeSpainMunicipio::loadMunicipioCodes(); |
| 1624 |
|
| 1625 |
// loop over the bookings to build the rows of the report |
| 1626 |
$from_info = getdate($from_ts); |
| 1627 |
foreach ($bookings as $gbook) { |
| 1628 |
// count the total number of guests for all rooms of this booking |
| 1629 |
$tot_booking_guests = 0; |
| 1630 |
$tot_booking_adults = 0; |
| 1631 |
$tot_booking_children = 0; |
| 1632 |
$room_guests = []; |
| 1633 |
foreach ($gbook as $rbook) { |
| 1634 |
$tot_booking_guests += ($rbook['adults'] + $rbook['children']); |
| 1635 |
$tot_booking_adults += $rbook['adults']; |
| 1636 |
$tot_booking_children += $rbook['children']; |
| 1637 |
$room_guests[] = ($rbook['adults'] + $rbook['children']); |
| 1638 |
} |
| 1639 |
|
| 1640 |
// make sure to decode the current pax data |
| 1641 |
if (!empty($gbook[0]['pax_data'])) { |
| 1642 |
$gbook[0]['pax_data'] = (array) json_decode($gbook[0]['pax_data'], true); |
| 1643 |
} |
| 1644 |
|
| 1645 |
// push a copy of the booking for each guest (adults and children) |
| 1646 |
$guests_rows = []; |
| 1647 |
for ($i = 1; $i <= $tot_booking_guests; $i++) { |
| 1648 |
array_push($guests_rows, $gbook[0]); |
| 1649 |
} |
| 1650 |
|
| 1651 |
// create one row for each guest |
| 1652 |
$guest_ind = 1; |
| 1653 |
foreach ($guests_rows as $ind => $guests) { |
| 1654 |
// prepare row record for this room-guest |
| 1655 |
$insert_row = []; |
| 1656 |
|
| 1657 |
// find the actual guest-room-index |
| 1658 |
$guest_room_ind = $this->calcGuestRoomIndex($room_guests, $guest_ind); |
| 1659 |
|
| 1660 |
// guest type (rol) |
| 1661 |
$pax_guesttype = $ptype === 'reservation' && $guest_room_ind < 2 ? 'TI' : 'VI'; |
| 1662 |
|
| 1663 |
array_push($insert_row, array( |
| 1664 |
'key' => 'guest_type', |
| 1665 |
'callback' => function($val) { |
| 1666 |
return $this->guest_types[$val] ?? $val; |
| 1667 |
}, |
| 1668 |
'no_export_callback' => 1, |
| 1669 |
'value' => $pax_guesttype, |
| 1670 |
)); |
| 1671 |
|
| 1672 |
// name |
| 1673 |
$nome = !empty($guests['t_first_name']) ? $guests['t_first_name'] : $guests['first_name']; |
| 1674 |
$pax_nome = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'first_name'); |
| 1675 |
$nome = !empty($pax_nome) ? $pax_nome : $nome; |
| 1676 |
array_push($insert_row, array( |
| 1677 |
'key' => 'first_name', |
| 1678 |
'value' => $nome, |
| 1679 |
)); |
| 1680 |
|
| 1681 |
// last name |
| 1682 |
$cognome = !empty($guests['t_last_name']) ? $guests['t_last_name'] : $guests['last_name']; |
| 1683 |
$pax_cognome = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'last_name'); |
| 1684 |
$cognome = !empty($pax_cognome) ? $pax_cognome : $cognome; |
| 1685 |
array_push($insert_row, array( |
| 1686 |
'key' => 'last_name', |
| 1687 |
'value' => $cognome, |
| 1688 |
)); |
| 1689 |
|
| 1690 |
// reservation date |
| 1691 |
array_push($insert_row, array( |
| 1692 |
'key' => 'resdate', |
| 1693 |
'attr' => array( |
| 1694 |
'class="center"' |
| 1695 |
), |
| 1696 |
'callback' => function($val) { |
| 1697 |
return date('Y-m-d', $val); |
| 1698 |
}, |
| 1699 |
'value' => $guests['ts'], |
| 1700 |
'ignore_view' => 1, |
| 1701 |
)); |
| 1702 |
|
| 1703 |
// number of guests |
| 1704 |
array_push($insert_row, array( |
| 1705 |
'key' => 'numguests', |
| 1706 |
'attr' => array( |
| 1707 |
'class="center"' |
| 1708 |
), |
| 1709 |
'value' => $tot_booking_guests, |
| 1710 |
'ignore_view' => 1, |
| 1711 |
)); |
| 1712 |
|
| 1713 |
// Sexo |
| 1714 |
$gender = !empty($guests['gender']) && $guest_ind < 2 ? strtoupper($guests['gender']) : ''; |
| 1715 |
$pax_gender = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'gender'); |
| 1716 |
$gender = !empty($pax_gender) ? $pax_gender : $gender; |
| 1717 |
|
| 1718 |
/** |
| 1719 |
* We make sure the gender will be compatible with both back-end and front-end |
| 1720 |
* check-in/registration data collection driver and processes. |
| 1721 |
*/ |
| 1722 |
if (is_numeric($gender)) { |
| 1723 |
$gender = (int) $gender; |
| 1724 |
} elseif (!strcasecmp($gender, 'H')) { |
| 1725 |
$gender = 1; |
| 1726 |
} elseif (!strcasecmp($gender, 'F') || !strcasecmp($gender, 'M')) { |
| 1727 |
$gender = 2; |
| 1728 |
} elseif (!strcasecmp($gender, 'O')) { |
| 1729 |
$gender = -1; |
| 1730 |
} |
| 1731 |
|
| 1732 |
// normalize value to hospedajes codes |
| 1733 |
switch ($gender) { |
| 1734 |
case 2: |
| 1735 |
// mujer |
| 1736 |
$spain_gender = 'M'; |
| 1737 |
break; |
| 1738 |
|
| 1739 |
case 1: |
| 1740 |
// hombre |
| 1741 |
$spain_gender = 'H'; |
| 1742 |
break; |
| 1743 |
|
| 1744 |
default: |
| 1745 |
// otro |
| 1746 |
$spain_gender = 'O'; |
| 1747 |
break; |
| 1748 |
} |
| 1749 |
|
| 1750 |
$sexo_elem_class = ''; |
| 1751 |
if (empty($gender)) { |
| 1752 |
// optional selection style |
| 1753 |
$sexo_elem_class = ' vbo-report-load-sesso vbo-report-load-field-optional'; |
| 1754 |
} else { |
| 1755 |
// rectify selection style |
| 1756 |
$sexo_elem_class = ' vbo-report-load-sesso vbo-report-load-elem-filled'; |
| 1757 |
} |
| 1758 |
|
| 1759 |
array_push($insert_row, array( |
| 1760 |
'key' => 'gender', |
| 1761 |
'attr' => array( |
| 1762 |
'class="center' . $sexo_elem_class . '"' |
| 1763 |
), |
| 1764 |
'callback' => function($val) { |
| 1765 |
return $this->sexo[$val] ?? 'O'; |
| 1766 |
}, |
| 1767 |
'no_export_callback' => 1, |
| 1768 |
'value' => $spain_gender, |
| 1769 |
)); |
| 1770 |
|
| 1771 |
// document type |
| 1772 |
$pax_doctype = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'doctype'); |
| 1773 |
|
| 1774 |
$doctype = $pax_doctype ?: ''; |
| 1775 |
|
| 1776 |
if (strlen((string) $doctype) === 1) { |
| 1777 |
// try to normalize the doc-type value from pre-checkin |
| 1778 |
switch ($doctype) { |
| 1779 |
case 'D': |
| 1780 |
case 'C': |
| 1781 |
case 'I': |
| 1782 |
$doctype = 'NIF'; |
| 1783 |
break; |
| 1784 |
|
| 1785 |
case 'N': |
| 1786 |
case 'X': |
| 1787 |
$doctype = 'NIE'; |
| 1788 |
break; |
| 1789 |
|
| 1790 |
case 'P': |
| 1791 |
$doctype = 'PAS'; |
| 1792 |
break; |
| 1793 |
|
| 1794 |
default: |
| 1795 |
$doctype = $doctype; |
| 1796 |
break; |
| 1797 |
} |
| 1798 |
} |
| 1799 |
|
| 1800 |
$doctype_elem_class = ''; |
| 1801 |
if (empty($doctype)) { |
| 1802 |
// optional selection style |
| 1803 |
$doctype_elem_class = ' vbo-report-load-doctype vbo-report-load-field-optional'; |
| 1804 |
} else { |
| 1805 |
// rectify selection style |
| 1806 |
$doctype_elem_class = ' vbo-report-load-doctype vbo-report-load-elem-filled'; |
| 1807 |
} |
| 1808 |
|
| 1809 |
array_push($insert_row, array( |
| 1810 |
'key' => 'doctype', |
| 1811 |
'attr' => array( |
| 1812 |
'class="center' . $doctype_elem_class . '"' |
| 1813 |
), |
| 1814 |
'callback' => function($val) { |
| 1815 |
return empty($val) ? '?' : $val; |
| 1816 |
}, |
| 1817 |
'no_export_callback' => 1, |
| 1818 |
'value' => $doctype, |
| 1819 |
)); |
| 1820 |
|
| 1821 |
// document number |
| 1822 |
$pax_docnum = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'docnum'); |
| 1823 |
|
| 1824 |
$docnum = $pax_docnum ?: ''; |
| 1825 |
|
| 1826 |
$docnum_elem_class = ''; |
| 1827 |
if (empty($docnum)) { |
| 1828 |
// optional selection style |
| 1829 |
$docnum_elem_class = ' vbo-report-load-docnum vbo-report-load-field-optional'; |
| 1830 |
} else { |
| 1831 |
// rectify selection style |
| 1832 |
$docnum_elem_class = ' vbo-report-load-docnum vbo-report-load-elem-filled'; |
| 1833 |
} |
| 1834 |
|
| 1835 |
array_push($insert_row, array( |
| 1836 |
'key' => 'docnum', |
| 1837 |
'attr' => array( |
| 1838 |
'class="center' . $docnum_elem_class . '"' |
| 1839 |
), |
| 1840 |
'callback' => function($val) { |
| 1841 |
return empty($val) ? '?' : $val; |
| 1842 |
}, |
| 1843 |
'no_export_callback' => 1, |
| 1844 |
'value' => $docnum, |
| 1845 |
)); |
| 1846 |
|
| 1847 |
// número de soporte del documento |
| 1848 |
$pax_docsoporte = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'docsoporte'); |
| 1849 |
|
| 1850 |
$docsoporte = $pax_docsoporte ?: ''; |
| 1851 |
|
| 1852 |
$docsoporte_elem_class = ''; |
| 1853 |
if (empty($docsoporte)) { |
| 1854 |
// optional selection style |
| 1855 |
$docsoporte_elem_class = ' vbo-report-load-docsoporte vbo-report-load-field-optional'; |
| 1856 |
} else { |
| 1857 |
// rectify selection style |
| 1858 |
$docsoporte_elem_class = ' vbo-report-load-docsoporte vbo-report-load-elem-filled'; |
| 1859 |
} |
| 1860 |
|
| 1861 |
array_push($insert_row, array( |
| 1862 |
'key' => 'docsoporte', |
| 1863 |
'attr' => array( |
| 1864 |
'class="center' . $docsoporte_elem_class . '"' |
| 1865 |
), |
| 1866 |
'callback' => function($val) { |
| 1867 |
return empty($val) ? '?' : $val; |
| 1868 |
}, |
| 1869 |
'no_export_callback' => 1, |
| 1870 |
'value' => $docsoporte, |
| 1871 |
)); |
| 1872 |
|
| 1873 |
// birth date (attempt to convert it into a timestamp to support any date format) |
| 1874 |
$dbirth = !empty($guests['bdate']) && $guest_ind < 2 ? VikBooking::getDateTimestamp($guests['bdate'], 0, 0) : ''; |
| 1875 |
$pax_dbirth = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'date_birth'); |
| 1876 |
$dbirth = $pax_dbirth ?: $dbirth; |
| 1877 |
$dbirth = !is_numeric($dbirth) ? VikBooking::getDateTimestamp($dbirth) : $dbirth; |
| 1878 |
|
| 1879 |
$dbirth_elem_class = ''; |
| 1880 |
if (empty($dbirth)) { |
| 1881 |
// optional selection style |
| 1882 |
$dbirth_elem_class = ' vbo-report-load-dbirth vbo-report-load-field-optional'; |
| 1883 |
} else { |
| 1884 |
// rectify selection style |
| 1885 |
$dbirth_elem_class = ' vbo-report-load-dbirth vbo-report-load-elem-filled'; |
| 1886 |
} |
| 1887 |
|
| 1888 |
array_push($insert_row, array( |
| 1889 |
'key' => 'date_birth', |
| 1890 |
'attr' => array( |
| 1891 |
'class="center' . $dbirth_elem_class . '"' |
| 1892 |
), |
| 1893 |
'callback' => function($val) { |
| 1894 |
if (!empty($val) && is_numeric($val)) { |
| 1895 |
return date('Y-m-d', $val); |
| 1896 |
} |
| 1897 |
return $val ?: '?'; |
| 1898 |
}, |
| 1899 |
'value' => $dbirth, |
| 1900 |
)); |
| 1901 |
|
| 1902 |
// parentesco |
| 1903 |
$pax_parentesco = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'parentesco'); |
| 1904 |
|
| 1905 |
$parentesco = $pax_parentesco ?: ''; |
| 1906 |
|
| 1907 |
$parentesco_elem_class = ''; |
| 1908 |
if (empty($parentesco)) { |
| 1909 |
// optional selection style |
| 1910 |
$parentesco_elem_class = ' vbo-report-load-parentesco vbo-report-load-field vbo-report-load-field-optional'; |
| 1911 |
} else { |
| 1912 |
// rectify selection style |
| 1913 |
$parentesco_elem_class = ' vbo-report-load-parentesco vbo-report-load-field vbo-report-load-elem-filled'; |
| 1914 |
} |
| 1915 |
|
| 1916 |
array_push($insert_row, array( |
| 1917 |
'key' => 'parentesco', |
| 1918 |
'attr' => array( |
| 1919 |
'class="center' . $parentesco_elem_class . '"' |
| 1920 |
), |
| 1921 |
'callback' => function($val) use ($tot_booking_children) { |
| 1922 |
if (!$tot_booking_children) { |
| 1923 |
return ''; |
| 1924 |
} |
| 1925 |
return empty($val) ? '?' : ($this->relacion_de_parentesco[$val] ?? $val); |
| 1926 |
}, |
| 1927 |
'no_export_callback' => 1, |
| 1928 |
'value' => $parentesco, |
| 1929 |
)); |
| 1930 |
|
| 1931 |
// address |
| 1932 |
$pax_address = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'address'); |
| 1933 |
|
| 1934 |
$address = $pax_address ?: ''; |
| 1935 |
|
| 1936 |
$address_elem_class = ''; |
| 1937 |
if (empty($address)) { |
| 1938 |
// optional selection style |
| 1939 |
$address_elem_class = ' vbo-report-load-address vbo-report-load-field vbo-report-load-field-optional'; |
| 1940 |
} else { |
| 1941 |
// rectify selection style |
| 1942 |
$address_elem_class = ' vbo-report-load-address vbo-report-load-field vbo-report-load-elem-filled'; |
| 1943 |
} |
| 1944 |
|
| 1945 |
array_push($insert_row, array( |
| 1946 |
'key' => 'address', |
| 1947 |
'attr' => array( |
| 1948 |
'class="center' . $address_elem_class . '"' |
| 1949 |
), |
| 1950 |
'callback' => function($val) { |
| 1951 |
return empty($val) ? '?' : $val; |
| 1952 |
}, |
| 1953 |
'no_export_callback' => 1, |
| 1954 |
'value' => $address, |
| 1955 |
)); |
| 1956 |
|
| 1957 |
// codigo municipio |
| 1958 |
$pax_municipio = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'municipio'); |
| 1959 |
|
| 1960 |
$municipio = $pax_municipio ?: ''; |
| 1961 |
|
| 1962 |
$municipio_elem_class = ''; |
| 1963 |
if (empty($municipio)) { |
| 1964 |
// optional selection style |
| 1965 |
$municipio_elem_class = ' vbo-report-load-municipio vbo-report-load-field vbo-report-load-field-optional'; |
| 1966 |
} else { |
| 1967 |
// rectify selection style |
| 1968 |
$municipio_elem_class = ' vbo-report-load-municipio vbo-report-load-field vbo-report-load-elem-filled'; |
| 1969 |
} |
| 1970 |
|
| 1971 |
array_push($insert_row, array( |
| 1972 |
'key' => 'municipio', |
| 1973 |
'attr' => array( |
| 1974 |
'class="center' . $municipio_elem_class . '"' |
| 1975 |
), |
| 1976 |
'callback' => function($val) use ($municipio_codes_list) { |
| 1977 |
return empty($val) ? '?' : ($municipio_codes_list[$val] ?? $val); |
| 1978 |
}, |
| 1979 |
'no_export_callback' => 1, |
| 1980 |
'value' => $municipio, |
| 1981 |
)); |
| 1982 |
|
| 1983 |
// city |
| 1984 |
$pax_city = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'city'); |
| 1985 |
|
| 1986 |
$city = $pax_city ?: ''; |
| 1987 |
|
| 1988 |
$city_elem_class = ''; |
| 1989 |
if (empty($city)) { |
| 1990 |
// optional selection style |
| 1991 |
$city_elem_class = ' vbo-report-load-city vbo-report-load-field vbo-report-load-field-optional'; |
| 1992 |
} else { |
| 1993 |
// rectify selection style |
| 1994 |
$city_elem_class = ' vbo-report-load-city vbo-report-load-field vbo-report-load-elem-filled'; |
| 1995 |
} |
| 1996 |
|
| 1997 |
array_push($insert_row, array( |
| 1998 |
'key' => 'city', |
| 1999 |
'attr' => array( |
| 2000 |
'class="center' . $city_elem_class . '"' |
| 2001 |
), |
| 2002 |
'callback' => function($val) { |
| 2003 |
return empty($val) ? '?' : $val; |
| 2004 |
}, |
| 2005 |
'no_export_callback' => 1, |
| 2006 |
'value' => $city, |
| 2007 |
)); |
| 2008 |
|
| 2009 |
// postal code |
| 2010 |
$pax_postalcode = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'postalcode'); |
| 2011 |
|
| 2012 |
$postalcode = $pax_postalcode ?: ''; |
| 2013 |
|
| 2014 |
$postalcode_elem_class = ''; |
| 2015 |
if (empty($postalcode)) { |
| 2016 |
// optional selection style |
| 2017 |
$postalcode_elem_class = ' vbo-report-load-postalcode vbo-report-load-field vbo-report-load-field-optional'; |
| 2018 |
} else { |
| 2019 |
// rectify selection style |
| 2020 |
$postalcode_elem_class = ' vbo-report-load-postalcode vbo-report-load-field vbo-report-load-elem-filled'; |
| 2021 |
} |
| 2022 |
|
| 2023 |
array_push($insert_row, array( |
| 2024 |
'key' => 'postalcode', |
| 2025 |
'attr' => array( |
| 2026 |
'class="center' . $postalcode_elem_class . '"' |
| 2027 |
), |
| 2028 |
'callback' => function($val) { |
| 2029 |
return empty($val) ? '?' : $val; |
| 2030 |
}, |
| 2031 |
'no_export_callback' => 1, |
| 2032 |
'value' => $postalcode, |
| 2033 |
)); |
| 2034 |
|
| 2035 |
// country of stay |
| 2036 |
$pax_country_s = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'country_s'); |
| 2037 |
|
| 2038 |
// check country field from pre-checkin |
| 2039 |
$pax_citizen = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'country'); |
| 2040 |
|
| 2041 |
$countrystay = !empty($guests['country']) ? $guests['country'] : ''; |
| 2042 |
$countrystay = $pax_citizen ?: $countrystay; |
| 2043 |
$countrystay = $pax_country_s ?: $countrystay; |
| 2044 |
|
| 2045 |
$country_elem_class = ''; |
| 2046 |
if (empty($countrystay)) { |
| 2047 |
// optional selection style |
| 2048 |
$country_elem_class = ' vbo-report-load-countrystay vbo-report-load-field-optional'; |
| 2049 |
} else { |
| 2050 |
// rectify selection style |
| 2051 |
$country_elem_class = ' vbo-report-load-countrystay vbo-report-load-elem-filled'; |
| 2052 |
} |
| 2053 |
|
| 2054 |
array_push($insert_row, array( |
| 2055 |
'key' => 'country_s', |
| 2056 |
'attr' => array( |
| 2057 |
'class="center' . $country_elem_class . '"' |
| 2058 |
), |
| 2059 |
'callback' => function($val) { |
| 2060 |
return $val ?: '---'; |
| 2061 |
}, |
| 2062 |
'no_export_callback' => 1, |
| 2063 |
'value' => $countrystay, |
| 2064 |
)); |
| 2065 |
|
| 2066 |
// citizenship |
| 2067 |
$pax_country_c = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'country_c'); |
| 2068 |
|
| 2069 |
// check country field from pre-checkin |
| 2070 |
$pax_citizen = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'country'); |
| 2071 |
|
| 2072 |
$citizen = !empty($guests['country']) ? $guests['country'] : ''; |
| 2073 |
$citizen = $pax_citizen ?: $citizen; |
| 2074 |
$citizen = $pax_country_c ?: $citizen; |
| 2075 |
|
| 2076 |
$country_elem_class = ''; |
| 2077 |
if (empty($citizen)) { |
| 2078 |
// optional selection style |
| 2079 |
$country_elem_class = ' vbo-report-load-cittadinanza vbo-report-load-field-optional'; |
| 2080 |
} else { |
| 2081 |
// rectify selection style |
| 2082 |
$country_elem_class = ' vbo-report-load-cittadinanza vbo-report-load-elem-filled'; |
| 2083 |
} |
| 2084 |
|
| 2085 |
array_push($insert_row, array( |
| 2086 |
'key' => 'country_c', |
| 2087 |
'attr' => array( |
| 2088 |
'class="center' . $country_elem_class . '"' |
| 2089 |
), |
| 2090 |
'callback' => function($val) { |
| 2091 |
return $val ?: '---'; |
| 2092 |
}, |
| 2093 |
'no_export_callback' => 1, |
| 2094 |
'value' => $citizen, |
| 2095 |
)); |
| 2096 |
|
| 2097 |
// direccion (phone number or email address from pre-checkin fields) |
| 2098 |
$pax_direccion = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'direccion'); |
| 2099 |
|
| 2100 |
$direccion_phone = preg_match("/^[0-9\+\s]+$/", (string) $pax_direccion) ? $pax_direccion : ''; |
| 2101 |
|
| 2102 |
// phone number |
| 2103 |
$pax_phone = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'phone'); |
| 2104 |
|
| 2105 |
$phone = $direccion_phone; |
| 2106 |
$phone = empty($phone) && !empty($guests['phone']) ? $guests['phone'] : $phone; |
| 2107 |
$phone = $pax_phone ?: $phone; |
| 2108 |
|
| 2109 |
$phone_elem_class = ''; |
| 2110 |
if (empty($phone)) { |
| 2111 |
// optional selection style |
| 2112 |
$phone_elem_class = ' vbo-report-load-phone vbo-report-load-field vbo-report-load-field-optional'; |
| 2113 |
} else { |
| 2114 |
// rectify selection style |
| 2115 |
$phone_elem_class = ' vbo-report-load-phone vbo-report-load-field vbo-report-load-elem-filled'; |
| 2116 |
} |
| 2117 |
|
| 2118 |
array_push($insert_row, array( |
| 2119 |
'key' => 'phone', |
| 2120 |
'attr' => array( |
| 2121 |
'class="center' . $phone_elem_class . '"' |
| 2122 |
), |
| 2123 |
'callback' => function($val) { |
| 2124 |
return $val ?: '---'; |
| 2125 |
}, |
| 2126 |
'no_export_callback' => 1, |
| 2127 |
'value' => $phone, |
| 2128 |
)); |
| 2129 |
|
| 2130 |
// direccion (phone number or email address from pre-checkin fields) |
| 2131 |
$pax_direccion = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'direccion'); |
| 2132 |
|
| 2133 |
$direccion_email = preg_match("/^.+@.+\..+$/", (string) $pax_direccion) ? $pax_direccion : ''; |
| 2134 |
|
| 2135 |
// email |
| 2136 |
$pax_email = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'email'); |
| 2137 |
|
| 2138 |
$email = $direccion_email; |
| 2139 |
$email = empty($email) && !empty($guests['custmail']) ? $guests['custmail'] : $email; |
| 2140 |
$email = $pax_email ?: $email; |
| 2141 |
|
| 2142 |
$email_elem_class = ''; |
| 2143 |
if (empty($email)) { |
| 2144 |
// optional selection style |
| 2145 |
$email_elem_class = ' vbo-report-load-email vbo-report-load-field vbo-report-load-field-optional'; |
| 2146 |
} else { |
| 2147 |
// rectify selection style |
| 2148 |
$email_elem_class = ' vbo-report-load-email vbo-report-load-field vbo-report-load-elem-filled'; |
| 2149 |
} |
| 2150 |
|
| 2151 |
array_push($insert_row, array( |
| 2152 |
'key' => 'email', |
| 2153 |
'attr' => array( |
| 2154 |
'class="center' . $email_elem_class . '"' |
| 2155 |
), |
| 2156 |
'callback' => function($val) { |
| 2157 |
return $val ?: '---'; |
| 2158 |
}, |
| 2159 |
'no_export_callback' => 1, |
| 2160 |
'value' => $email, |
| 2161 |
)); |
| 2162 |
|
| 2163 |
// payment type |
| 2164 |
$pax_paytype = $this->getGuestPaxDataValue($guests['pax_data'], $room_guests, $guest_ind, 'paytype') ?: 'TARJT'; |
| 2165 |
|
| 2166 |
$paytype_elem_class = ''; |
| 2167 |
if ($guest_room_ind < 2 && empty($pax_paytype)) { |
| 2168 |
// mandatory selection style |
| 2169 |
$paytype_elem_class = ' vbo-report-load-paytype vbo-report-load-field'; |
| 2170 |
} elseif (empty($pax_paytype)) { |
| 2171 |
// optional selection style |
| 2172 |
$paytype_elem_class = ' vbo-report-load-paytype vbo-report-load-field vbo-report-load-field-optional'; |
| 2173 |
} elseif (!empty($pax_paytype)) { |
| 2174 |
// rectify selection style |
| 2175 |
$paytype_elem_class = ' vbo-report-load-paytype vbo-report-load-field vbo-report-load-elem-filled'; |
| 2176 |
} |
| 2177 |
|
| 2178 |
array_push($insert_row, array( |
| 2179 |
'key' => 'paytype', |
| 2180 |
'attr' => array( |
| 2181 |
'class="center' . $paytype_elem_class . '"', |
| 2182 |
'data-field="paytype"', |
| 2183 |
'data-fieldbid="' . $guests['id'] . '"', |
| 2184 |
), |
| 2185 |
'callback' => function($val) { |
| 2186 |
return $this->tipos_de_pago[$val] ?? $val; |
| 2187 |
}, |
| 2188 |
'no_export_callback' => 1, |
| 2189 |
'value' => $pax_paytype, |
| 2190 |
)); |
| 2191 |
|
| 2192 |
// check-in |
| 2193 |
array_push($insert_row, array( |
| 2194 |
'key' => 'checkin', |
| 2195 |
'attr' => array( |
| 2196 |
'class="center"' |
| 2197 |
), |
| 2198 |
'callback' => function($val) { |
| 2199 |
return date('Y-m-d\TH:i:s', $val); |
| 2200 |
}, |
| 2201 |
'value' => $guests['checkin'], |
| 2202 |
)); |
| 2203 |
|
| 2204 |
// check-out |
| 2205 |
array_push($insert_row, array( |
| 2206 |
'key' => 'checkout', |
| 2207 |
'attr' => array( |
| 2208 |
'class="center"' |
| 2209 |
), |
| 2210 |
'callback' => function($val) { |
| 2211 |
return date('Y-m-d\TH:i:s', $val); |
| 2212 |
}, |
| 2213 |
'value' => $guests['checkout'], |
| 2214 |
)); |
| 2215 |
|
| 2216 |
// id booking |
| 2217 |
array_push($insert_row, array( |
| 2218 |
'key' => 'idbooking', |
| 2219 |
'attr' => array( |
| 2220 |
'class="center"' |
| 2221 |
), |
| 2222 |
'callback' => function($val) { |
| 2223 |
// make sure to keep the data-bid attribute as it's used by JS to identify the booking ID |
| 2224 |
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>'; |
| 2225 |
}, |
| 2226 |
'no_export_callback' => 1, |
| 2227 |
'value' => $guests['id'], |
| 2228 |
)); |
| 2229 |
|
| 2230 |
// push fields in the rows array as a new row |
| 2231 |
array_push($this->rows, $insert_row); |
| 2232 |
|
| 2233 |
// increment guest index |
| 2234 |
$guest_ind++; |
| 2235 |
} |
| 2236 |
} |
| 2237 |
|
| 2238 |
// do not sort the rows for this report because the lines of the guests of the same booking must be consecutive |
| 2239 |
// $this->sortRows($pkrsort, $pkrorder); |
| 2240 |
|
| 2241 |
// the footer row will just print the amount of records to export |
| 2242 |
array_push($this->footerRow, array( |
| 2243 |
array( |
| 2244 |
'attr' => array( |
| 2245 |
'class="vbo-report-total"', |
| 2246 |
), |
| 2247 |
'value' => '<h3>' . JText::translate('VBOREPORTSTOTALROW') . '</h3>', |
| 2248 |
), |
| 2249 |
array( |
| 2250 |
'attr' => array( |
| 2251 |
'colspan="' . (count($this->cols) - 1) . '"', |
| 2252 |
), |
| 2253 |
'value' => count($this->rows), |
| 2254 |
) |
| 2255 |
)); |
| 2256 |
|
| 2257 |
return true; |
| 2258 |
} |
| 2259 |
|
| 2260 |
/** |
| 2261 |
* Generates the authority file, then sends it to output for download. |
| 2262 |
* In case of errors, the process is not terminated (exit) to let the View display the |
| 2263 |
* error message(s). The export type argument can eventually determine an action to run. |
| 2264 |
* |
| 2265 |
* @param string $export_type Differentiates the type of export requested. |
| 2266 |
* |
| 2267 |
* @return void|bool Void in case of script termination, boolean otherwise. |
| 2268 |
*/ |
| 2269 |
public function customExport($export_type = null) |
| 2270 |
{ |
| 2271 |
// build the XML file |
| 2272 |
$xml = $this->buildXMLFile(); |
| 2273 |
|
| 2274 |
// build report action data, if needed |
| 2275 |
$action_data = array_merge($this->getActionData($registry = false), ['xml' => $xml]); |
| 2276 |
|
| 2277 |
/** |
| 2278 |
* Custom export method can run a custom action. |
| 2279 |
*/ |
| 2280 |
if ($export_type && !is_numeric($export_type)) { |
| 2281 |
try { |
| 2282 |
// ensure the type of export is a callable scoped action, hidden or visible |
| 2283 |
$actions = $this->getScopedActions($this->getScope(), $visible = false); |
| 2284 |
$action_ids = array_column($actions, 'id'); |
| 2285 |
$action_names = array_column($actions, 'name'); |
| 2286 |
if (!in_array($export_type, $action_ids)) { |
| 2287 |
throw new Exception(sprintf('Cannot invoke the requested type of export [%s].', $export_type), 403); |
| 2288 |
} |
| 2289 |
|
| 2290 |
// get the requested action readable name |
| 2291 |
$action_name = $action_names[array_search($export_type, $action_ids)]; |
| 2292 |
|
| 2293 |
if ($this->getScope() === 'web') { |
| 2294 |
// run the action and output the HTML response string |
| 2295 |
$html_result = $this->_callActionReturn($export_type, 'html', $this->getScope(), $action_data); |
| 2296 |
|
| 2297 |
// build the action result data object |
| 2298 |
$js_result = json_encode([ |
| 2299 |
'actionName' => $action_name, |
| 2300 |
'actionHtml' => $html_result, |
| 2301 |
]); |
| 2302 |
|
| 2303 |
// render modal script with the action result |
| 2304 |
JFactory::getDocument()->addScriptDeclaration( |
| 2305 |
<<<JS |
| 2306 |
;(function($) { |
| 2307 |
$(function() { |
| 2308 |
let result = $js_result; |
| 2309 |
VBOCore.displayModal({ |
| 2310 |
suffix: 'report-custom-scopedaction-result', |
| 2311 |
extra_class: 'vbo-modal-rounded vbo-modal-tall vbo-modal-nofooter', |
| 2312 |
title: result.actionName, |
| 2313 |
body: result.actionHtml, |
| 2314 |
}); |
| 2315 |
}); |
| 2316 |
})(jQuery); |
| 2317 |
JS |
| 2318 |
); |
| 2319 |
|
| 2320 |
// abort and let the View render the result within a modal |
| 2321 |
return; |
| 2322 |
} |
| 2323 |
|
| 2324 |
// let the report custom action run and return a boolean value if invoked by a cron |
| 2325 |
return (bool) $this->_callActionReturn($export_type, 'success', $this->getScope(), $action_data); |
| 2326 |
|
| 2327 |
} catch (Exception $e) { |
| 2328 |
// silently catch the error and set it |
| 2329 |
$this->setError(sprintf('(%s) %s', $e->getCode(), $e->getMessage())); |
| 2330 |
|
| 2331 |
// abort |
| 2332 |
return false; |
| 2333 |
} |
| 2334 |
} |
| 2335 |
|
| 2336 |
// proceed with the regular export function (write on file through cron or download file through web) |
| 2337 |
|
| 2338 |
if (!$xml) { |
| 2339 |
// abort |
| 2340 |
return false; |
| 2341 |
} |
| 2342 |
|
| 2343 |
// update history for all bookings affected before exporting |
| 2344 |
foreach ($this->export_booking_ids as $bid) { |
| 2345 |
VikBooking::getBookingHistoryInstance($bid)->store('RP', $this->reportName . ' - Export'); |
| 2346 |
} |
| 2347 |
|
| 2348 |
// custom export method supports a custom export handler, if previously set. |
| 2349 |
if ($this->hasExportHandler()) { |
| 2350 |
// write data onto the custom file handler |
| 2351 |
$fp = $this->getExportCSVHandler(); |
| 2352 |
fwrite($fp, $xml); |
| 2353 |
fclose($fp); |
| 2354 |
|
| 2355 |
// return true as data was written |
| 2356 |
return true; |
| 2357 |
} |
| 2358 |
|
| 2359 |
// force text file download in case of regular export |
| 2360 |
header("Content-type: text/xml"); |
| 2361 |
header("Cache-Control: no-store, no-cache"); |
| 2362 |
header('Content-Disposition: attachment; filename="' . $this->getExportCSVFileName() . '"'); |
| 2363 |
echo $xml; |
| 2364 |
|
| 2365 |
exit; |
| 2366 |
} |
| 2367 |
|
| 2368 |
/** |
| 2369 |
* Helper method invoked via AJAX by the controller. |
| 2370 |
* Needed to save the manual entries for the pax data. |
| 2371 |
* |
| 2372 |
* @param array $manual_data the object representation of the manual entries. |
| 2373 |
* |
| 2374 |
* @return array one boolean value array with the operation result. |
| 2375 |
*/ |
| 2376 |
public function updatePaxData($manual_data = []) |
| 2377 |
{ |
| 2378 |
if (!is_array($manual_data) || !$manual_data) { |
| 2379 |
VBOHttpDocument::getInstance()->close(400, 'Nothing to save!'); |
| 2380 |
} |
| 2381 |
|
| 2382 |
// re-build manual entries object representation |
| 2383 |
$bids_guests = []; |
| 2384 |
foreach ($manual_data as $guest_ind => $guest_data) { |
| 2385 |
if (!is_numeric($guest_ind) || !is_array($guest_data) || empty($guest_data['bid']) || !isset($guest_data['bid_index']) || count($guest_data) < 2) { |
| 2386 |
// empty or invalid manual entries array |
| 2387 |
continue; |
| 2388 |
} |
| 2389 |
// the guest index in the reportObj starts from 0 |
| 2390 |
$use_guest_ind = ($guest_ind + 1 - (int)$guest_data['bid_index']); |
| 2391 |
if (!isset($bids_guests[$guest_data['bid']])) { |
| 2392 |
$bids_guests[$guest_data['bid']] = []; |
| 2393 |
} |
| 2394 |
// set manual entries for this guest number |
| 2395 |
$bids_guests[$guest_data['bid']][$use_guest_ind] = $guest_data; |
| 2396 |
// remove the "bid" and "bid_index" keys |
| 2397 |
unset($bids_guests[$guest_data['bid']][$use_guest_ind]['bid'], $bids_guests[$guest_data['bid']][$use_guest_ind]['bid_index']); |
| 2398 |
} |
| 2399 |
|
| 2400 |
if (!$bids_guests) { |
| 2401 |
VBOHttpDocument::getInstance()->close(400, 'No manual entries to save found'); |
| 2402 |
} |
| 2403 |
|
| 2404 |
// loop through all bookings to update the data for the various rooms and guests |
| 2405 |
$bids_updated = 0; |
| 2406 |
foreach ($bids_guests as $bid => $entries) { |
| 2407 |
$b_rooms = VikBooking::loadOrdersRoomsData($bid); |
| 2408 |
if (empty($b_rooms)) { |
| 2409 |
continue; |
| 2410 |
} |
| 2411 |
// count guests per room (adults + children) |
| 2412 |
$room_guests = []; |
| 2413 |
foreach ($b_rooms as $b_room) { |
| 2414 |
$room_guests[] = $b_room['adults'] + $b_room['children']; |
| 2415 |
} |
| 2416 |
// get current booking pax data |
| 2417 |
$pax_data = VBOCheckinPax::getBookingPaxData($bid); |
| 2418 |
$pax_data = empty($pax_data) ? [] : $pax_data; |
| 2419 |
foreach ($entries as $guest_ind => $guest_data) { |
| 2420 |
// find room index for this guest |
| 2421 |
$room_num = 0; |
| 2422 |
$use_guest_ind = $guest_ind; |
| 2423 |
foreach ($room_guests as $room_index => $tot_guests) { |
| 2424 |
// find the proper guest index for the room to which this belongs |
| 2425 |
if ($use_guest_ind <= $tot_guests) { |
| 2426 |
// proper room index found for this guest |
| 2427 |
$room_num = $room_index; |
| 2428 |
break; |
| 2429 |
} else { |
| 2430 |
// it's probably in a next room |
| 2431 |
$use_guest_ind -= $tot_guests; |
| 2432 |
} |
| 2433 |
} |
| 2434 |
// push new pax data for this room and guest |
| 2435 |
if (!isset($pax_data[$room_num])) { |
| 2436 |
$pax_data[$room_num] = []; |
| 2437 |
} |
| 2438 |
if (!isset($pax_data[$room_num][$use_guest_ind])) { |
| 2439 |
$pax_data[$room_num][$use_guest_ind] = $guest_data; |
| 2440 |
} else { |
| 2441 |
$pax_data[$room_num][$use_guest_ind] = array_merge($pax_data[$room_num][$use_guest_ind], $guest_data); |
| 2442 |
} |
| 2443 |
} |
| 2444 |
// update booking pax data |
| 2445 |
if (VBOCheckinPax::setBookingPaxData($bid, $pax_data)) { |
| 2446 |
$bids_updated++; |
| 2447 |
} |
| 2448 |
} |
| 2449 |
|
| 2450 |
return $bids_updated ? [true] : [false]; |
| 2451 |
} |
| 2452 |
|
| 2453 |
/** |
| 2454 |
* Builds the XML file for export or transmission. |
| 2455 |
* |
| 2456 |
* @param string $type The XML export type (checkin or reservation). |
| 2457 |
* |
| 2458 |
* @return string Empty string in case of errors, XML otherwise. |
| 2459 |
*/ |
| 2460 |
protected function buildXMLFile($type = '') |
| 2461 |
{ |
| 2462 |
if (!$this->getReportData()) { |
| 2463 |
return ''; |
| 2464 |
} |
| 2465 |
|
| 2466 |
// load report settings |
| 2467 |
$settings = $this->loadSettings(); |
| 2468 |
|
| 2469 |
// get the possibly injected report options |
| 2470 |
$options = $this->getReportOptions(); |
| 2471 |
|
| 2472 |
// injected options will substitute request variables, if any |
| 2473 |
$export_type = $type ?: VikRequest::getString('type', $options->get('type', 'checkin'), 'request'); |
| 2474 |
|
| 2475 |
// access manually filled values, if any |
| 2476 |
$pfiller = VikRequest::getString('filler', '', 'request', VIKREQUEST_ALLOWRAW); |
| 2477 |
$pfiller = !empty($pfiller) ? (array) json_decode($pfiller, true) : []; |
| 2478 |
|
| 2479 |
// determine the XML namespace to use |
| 2480 |
if ($export_type === 'checkin') { |
| 2481 |
$xmlns = 'http://www.neg.hospedajes.mir.es/altaParteHospedaje'; |
| 2482 |
} else { |
| 2483 |
$xmlns = 'http://www.neg.hospedajes.mir.es/altaReservaHospedaje'; |
| 2484 |
} |
| 2485 |
|
| 2486 |
// start building the XML |
| 2487 |
$xml = $this->loadXmlSoap('<alt:peticion xmlns:alt="' . $xmlns . '"></alt:peticion>'); |
| 2488 |
|
| 2489 |
// add main child common node (no value, empty namespace) |
| 2490 |
$solicitud = $xml->addChild('solicitud', null, ''); |
| 2491 |
|
| 2492 |
if ($export_type === 'checkin') { |
| 2493 |
// partes de viajeros (check-in report) |
| 2494 |
$solicitud->addChild('codigoEstablecimiento', htmlspecialchars($settings['codigo'] ?? '')); |
| 2495 |
} |
| 2496 |
|
| 2497 |
// group all rows by booking id |
| 2498 |
$booking_rows = []; |
| 2499 |
foreach ($this->rows as $ind => $row) { |
| 2500 |
$bid = 0; |
| 2501 |
foreach ($row as $row_ind => $field) { |
| 2502 |
if ($field['key'] == 'idbooking') { |
| 2503 |
// set booking ID |
| 2504 |
$bid = (int) $field['value']; |
| 2505 |
|
| 2506 |
if (!isset($booking_rows[$bid])) { |
| 2507 |
// start booking rows container |
| 2508 |
$booking_rows[$bid] = []; |
| 2509 |
} |
| 2510 |
|
| 2511 |
// check for manual report value |
| 2512 |
if (strlen((string) ($pfiller[$ind][$field['key']] ?? ''))) { |
| 2513 |
$row[$row_ind]['value'] = $pfiller[$ind][$field['key']]; |
| 2514 |
} |
| 2515 |
|
| 2516 |
// break this one loop |
| 2517 |
break; |
| 2518 |
} |
| 2519 |
} |
| 2520 |
// push booking row |
| 2521 |
$booking_rows[$bid][] = $row; |
| 2522 |
} |
| 2523 |
|
| 2524 |
// scan all booking rows |
| 2525 |
foreach ($booking_rows as $bid => $rows) { |
| 2526 |
// add <comunicacion> node for this reservation |
| 2527 |
$comunicacion = $solicitud->addChild('comunicacion'); |
| 2528 |
|
| 2529 |
// check if <establecimiento> node is needed |
| 2530 |
if ($export_type !== 'checkin') { |
| 2531 |
// reservas de hospedaje (reservation report) |
| 2532 |
$establecimiento = $comunicacion->addChild('establecimiento'); |
| 2533 |
if (!empty($settings['codigo'])) { |
| 2534 |
// property code, if known |
| 2535 |
$establecimiento->addChild('codigo', htmlspecialchars($settings['codigo'])); |
| 2536 |
} else { |
| 2537 |
// property details otherwise |
| 2538 |
$datos = $establecimiento->addChild('datosEstablecimiento'); |
| 2539 |
$datos->addChild('tipo', htmlspecialchars($settings['tipo_establecimiento'] ?? '')); |
| 2540 |
$datos->addChild('nombre', htmlspecialchars($settings['nombre_establecimiento'] ?? '')); |
| 2541 |
$direccion = $datos->addChild('direccion'); |
| 2542 |
$direccion->addChild('direccion', htmlspecialchars($settings['direccion'] ?? '')); |
| 2543 |
$direccion->addChild('codigoMunicipio', htmlspecialchars($settings['codigo_municipio'] ?? '')); |
| 2544 |
$direccion->addChild('nombreMunicipio', htmlspecialchars($settings['nombre_municipio'] ?? '')); |
| 2545 |
$direccion->addChild('codigoPostal', htmlspecialchars($settings['codigo_postal'] ?? '')); |
| 2546 |
$direccion->addChild('pais', htmlspecialchars($settings['pais'] ?? '')); |
| 2547 |
} |
| 2548 |
} |
| 2549 |
|
| 2550 |
// build an associative list of data for the first guest row of this booking |
| 2551 |
$main_res_data = $this->getAssocRowData($rows[0]); |
| 2552 |
|
| 2553 |
// add <contrato> node |
| 2554 |
$contrato = $comunicacion->addChild('contrato'); |
| 2555 |
$contrato->addChild('referencia', $main_res_data['idbooking']); |
| 2556 |
$contrato->addChild('fechaContrato', htmlspecialchars($main_res_data['resdate'])); |
| 2557 |
$contrato->addChild('fechaEntrada', htmlspecialchars($main_res_data['checkin'])); |
| 2558 |
$contrato->addChild('fechaSalida', htmlspecialchars($main_res_data['checkout'])); |
| 2559 |
$contrato->addChild('numPersonas', htmlspecialchars($main_res_data['numguests'])); |
| 2560 |
$pago = $contrato->addChild('pago'); |
| 2561 |
$pago->addChild('tipoPago', htmlspecialchars($main_res_data['paytype'])); |
| 2562 |
|
| 2563 |
// scan all guest rows for this reservation to build the various <persona> nodes |
| 2564 |
foreach ($rows as $row) { |
| 2565 |
// get the associative list of guest data from the current row |
| 2566 |
$row_data = $this->getAssocRowData($row); |
| 2567 |
|
| 2568 |
// add <persona> node for this guest |
| 2569 |
$persona = $comunicacion->addChild('persona'); |
| 2570 |
|
| 2571 |
// last name parts |
| 2572 |
$last_name_parts = explode(' ', (string) $row_data['last_name']); |
| 2573 |
if (count($last_name_parts) === 1) { |
| 2574 |
$last_name_one = $last_name_parts[0]; |
| 2575 |
$last_name_two = $last_name_parts[0]; |
| 2576 |
} else { |
| 2577 |
$last_name_two = $last_name_parts[count($last_name_parts) - 1]; |
| 2578 |
unset($last_name_parts[count($last_name_parts) - 1]); |
| 2579 |
$last_name_one = implode(' ', $last_name_parts); |
| 2580 |
} |
| 2581 |
|
| 2582 |
// set persona details |
| 2583 |
$persona->addChild('rol', htmlspecialchars($row_data['guest_type'])); |
| 2584 |
$persona->addChild('nombre', htmlspecialchars($row_data['first_name'])); |
| 2585 |
$persona->addChild('apellido1', htmlspecialchars($last_name_one)); |
| 2586 |
if ($last_name_one != $last_name_two || (!empty($row_data['doctype']) && !strcasecmp($row_data['doctype'], 'NIF'))) { |
| 2587 |
// apellido2 is mandatory in this case |
| 2588 |
$persona->addChild('apellido2', htmlspecialchars($last_name_two)); |
| 2589 |
} |
| 2590 |
if (!empty($row_data['doctype'])) { |
| 2591 |
$persona->addChild('tipoDocumento', htmlspecialchars($row_data['doctype'])); |
| 2592 |
} |
| 2593 |
if (!empty($row_data['docnum'])) { |
| 2594 |
$persona->addChild('numeroDocumento', htmlspecialchars($row_data['docnum'])); |
| 2595 |
} |
| 2596 |
if (!empty($row_data['docsoporte']) && $export_type == 'checkin') { |
| 2597 |
$persona->addChild('soporteDocumento', htmlspecialchars($row_data['docsoporte'])); |
| 2598 |
} |
| 2599 |
$persona->addChild('fechaNacimiento', htmlspecialchars($row_data['date_birth'])); |
| 2600 |
$persona->addChild('nacionalidad', htmlspecialchars(($row_data['country_c'] ?: $row_data['country_s']))); |
| 2601 |
$persona->addChild('sexo', htmlspecialchars($row_data['gender'])); |
| 2602 |
|
| 2603 |
// direccion |
| 2604 |
$direccion = $persona->addChild('direccion'); |
| 2605 |
if ($row_data['address']) { |
| 2606 |
$direccion->addChild('direccion', htmlspecialchars($row_data['address'])); |
| 2607 |
} |
| 2608 |
if ($row_data['municipio']) { |
| 2609 |
$direccion->addChild('codigoMunicipio', htmlspecialchars($row_data['municipio'])); |
| 2610 |
} |
| 2611 |
if ($row_data['city']) { |
| 2612 |
$direccion->addChild('nombreMunicipio', htmlspecialchars($row_data['city'])); |
| 2613 |
} |
| 2614 |
if ($row_data['postalcode']) { |
| 2615 |
$direccion->addChild('codigoPostal', htmlspecialchars($row_data['postalcode'])); |
| 2616 |
} |
| 2617 |
if ($row_data['country_s'] || $row_data['country_c']) { |
| 2618 |
$direccion->addChild('pais', htmlspecialchars(($row_data['country_s'] ?: $row_data['country_c']))); |
| 2619 |
} |
| 2620 |
|
| 2621 |
if (!empty($row_data['phone'])) { |
| 2622 |
$persona->addChild('telefono', htmlspecialchars($row_data['phone'])); |
| 2623 |
} |
| 2624 |
if (!empty($row_data['email'])) { |
| 2625 |
$persona->addChild('correo', htmlspecialchars($row_data['email'])); |
| 2626 |
} |
| 2627 |
if ($export_type === 'checkin' && !empty($row_data['parentesco'])) { |
| 2628 |
$persona->addChild('parentesco', htmlspecialchars($row_data['parentesco'])); |
| 2629 |
} |
| 2630 |
} |
| 2631 |
} |
| 2632 |
|
| 2633 |
// set pool of booking IDs to update their history |
| 2634 |
$this->export_booking_ids = array_keys($booking_rows); |
| 2635 |
|
| 2636 |
// get the formatted XML file string |
| 2637 |
$formatted_xml = $xml->formatXml(); |
| 2638 |
|
| 2639 |
// make sure to get rid of empty namespace attributes |
| 2640 |
$formatted_xml = str_replace(' xmlns=""', '', $formatted_xml); |
| 2641 |
|
| 2642 |
// return the final XML file string |
| 2643 |
return $formatted_xml; |
| 2644 |
} |
| 2645 |
|
| 2646 |
/** |
| 2647 |
* Custom scoped action to transmit the registration of the traveler parts (Alta de partes de viajeros). |
| 2648 |
* Accepted scopes are "web" and "cron", so the "success" property must be returned. |
| 2649 |
* |
| 2650 |
* @param string $scope Optional scope identifier (cron, web, etc..). |
| 2651 |
* @param array $data Optional associative list of data to process. |
| 2652 |
* |
| 2653 |
* @return array The execution result properties. |
| 2654 |
* |
| 2655 |
* @throws Exception |
| 2656 |
*/ |
| 2657 |
protected function registerTravelerParts($scope = null, array $data = []) |
| 2658 |
{ |
| 2659 |
if (!($data['xml'] ?? '') && $scope === 'web') { |
| 2660 |
// start the process through the interface by submitting the current data |
| 2661 |
return [ |
| 2662 |
'html' => '<script type="text/javascript">vboDownloadHospedajes(\'registerTravelerParts\', \'checkin\');</script>', |
| 2663 |
]; |
| 2664 |
} |
| 2665 |
|
| 2666 |
if (!($data['xml'] ?? '')) { |
| 2667 |
// attempt to build the XML file if not set |
| 2668 |
$data['xml'] = $this->buildXMLFile(); |
| 2669 |
} |
| 2670 |
|
| 2671 |
if (!$data['xml']) { |
| 2672 |
throw new Exception('Missing XML request message.', 500); |
| 2673 |
} |
| 2674 |
|
| 2675 |
// load report settings |
| 2676 |
$settings = $this->loadSettings(); |
| 2677 |
|
| 2678 |
if (!$settings || empty($settings['service_username']) || empty($settings['service_password']) || empty($settings['service_arrendador'])) { |
| 2679 |
throw new Exception(sprintf('[%s] error: missing service settings.', __METHOD__), 500); |
| 2680 |
} |
| 2681 |
|
| 2682 |
// set the type of transmission |
| 2683 |
$tn_type = 'PV'; |
| 2684 |
|
| 2685 |
// prepare the communication message data |
| 2686 |
$message_data = array_merge($data, [ |
| 2687 |
'operation_type' => 'A', |
| 2688 |
'report_type' => $tn_type, |
| 2689 |
]); |
| 2690 |
|
| 2691 |
// get the communication message |
| 2692 |
$message = $this->_callActionReturn('prepareCommunicationMessage', 'message', $scope, $message_data); |
| 2693 |
|
| 2694 |
try { |
| 2695 |
// post the message to the electronic service and get the Soap XML response message |
| 2696 |
$response = $this->postMessage($message, $settings); |
| 2697 |
|
| 2698 |
// parse the response message and get the main node across multiple namespaces |
| 2699 |
$xmlBody = $this->loadXmlSoap($response)->getSoapRecursiveNsElement([ |
| 2700 |
[ |
| 2701 |
'SOAP-ENV', |
| 2702 |
true, |
| 2703 |
'Body', |
| 2704 |
], |
| 2705 |
[ |
| 2706 |
'http://www.soap.servicios.hospedajes.mir.es/comunicacion', |
| 2707 |
false, |
| 2708 |
'respuesta', |
| 2709 |
], |
| 2710 |
]); |
| 2711 |
|
| 2712 |
// access the desired XML element |
| 2713 |
$xmlBody = $xmlBody->respuesta ?? $xmlBody; |
| 2714 |
|
| 2715 |
// access the result code |
| 2716 |
$result_code = $xmlBody->codigoRetorno ?? $xmlBody->codigo ?? null; |
| 2717 |
|
| 2718 |
if (is_null($result_code)) { |
| 2719 |
// unexpected response |
| 2720 |
throw new UnexpectedValueException(sprintf('Unexpected response [%s]', htmlspecialchars($xmlBody->formatXml() ?: $response)), 500); |
| 2721 |
} |
| 2722 |
|
| 2723 |
// validate the response |
| 2724 |
$is_error = (int) $result_code !== 0; |
| 2725 |
|
| 2726 |
if ($is_error || !($xmlBody->lote ?? '')) { |
| 2727 |
$error_code = (string) ($result_code ?? '500'); |
| 2728 |
$error_dets = (string) ($xmlBody->descripcion ?? 'Unknown'); |
| 2729 |
// terminate the execution in case of errors or empty result |
| 2730 |
throw new Exception(sprintf("[%s] Response error:\n%s", $error_code, $error_dets), 500); |
| 2731 |
} |
| 2732 |
|
| 2733 |
// the batch value obtained with the transmission |
| 2734 |
$batch_value = (string) $xmlBody->lote; |
| 2735 |
|
| 2736 |
// store the batch value on the DB for later fetching |
| 2737 |
$this->storeBatchData([ |
| 2738 |
'batch' => $batch_value, |
| 2739 |
'op_date' => date('Y-m-d H:i:s'), |
| 2740 |
'from_dt' => $this->exported_checkin_dates[0] ?? date('Y-m-d'), |
| 2741 |
'to_dt' => $this->exported_checkin_dates[1] ?? date('Y-m-d'), |
| 2742 |
'op_type' => 'A', |
| 2743 |
'rp_type' => $tn_type, |
| 2744 |
], 'hospedajes_batches_' . date('Yn')); |
| 2745 |
|
| 2746 |
// build HTML response string |
| 2747 |
$html = ''; |
| 2748 |
$html .= '<p class="successmade">Lote: ' . $batch_value . '</p>'; |
| 2749 |
|
| 2750 |
} catch (Exception $e) { |
| 2751 |
// propagate the error caught |
| 2752 |
throw new Exception(sprintf('[%s] error: %s', __METHOD__, $e->getMessage()), $e->getCode() ?: 500); |
| 2753 |
} |
| 2754 |
|
| 2755 |
// when executed through a cron, store an event in the Notifications Center |
| 2756 |
if ($scope === 'cron') { |
| 2757 |
// build the notification record |
| 2758 |
$notification = [ |
| 2759 |
'sender' => 'reports', |
| 2760 |
'type' => 'pmsreport.travelparts.ok', |
| 2761 |
'title' => 'Hospedajes - Alta de partes de viajeros', |
| 2762 |
'summary' => sprintf( |
| 2763 |
'Las partes de viajeros se han registrado correctamente para las fechas de check-in del %s al %s. Número de lote obtenido: %s.', |
| 2764 |
$this->exported_checkin_dates[0] ?? '', |
| 2765 |
$this->exported_checkin_dates[1] ?? '', |
| 2766 |
$batch_value |
| 2767 |
), |
| 2768 |
]; |
| 2769 |
|
| 2770 |
try { |
| 2771 |
// store the notification record |
| 2772 |
VBOFactory::getNotificationCenter()->store([$notification]); |
| 2773 |
} catch (Exception $e) { |
| 2774 |
// silently catch the error without doing anything |
| 2775 |
} |
| 2776 |
} |
| 2777 |
|
| 2778 |
return [ |
| 2779 |
'html' => $html, |
| 2780 |
'success' => !empty($batch_value), |
| 2781 |
'batch' => $batch_value, |
| 2782 |
]; |
| 2783 |
} |
| 2784 |
|
| 2785 |
/** |
| 2786 |
* Custom scoped action to transmit the registration of the accommodation reservation (Alta de reservas de hospedaje). |
| 2787 |
* Accepted scopes are "web" and "cron", so the "success" property must be returned. |
| 2788 |
* |
| 2789 |
* @param string $scope Optional scope identifier (cron, web, etc..). |
| 2790 |
* @param array $data Optional associative list of data to process. |
| 2791 |
* |
| 2792 |
* @return array The execution result properties. |
| 2793 |
* |
| 2794 |
* @throws Exception |
| 2795 |
*/ |
| 2796 |
protected function registerAccommodationReservations($scope = null, array $data = []) |
| 2797 |
{ |
| 2798 |
if (!($data['xml'] ?? '') && $scope === 'web') { |
| 2799 |
// start the process through the interface by submitting the current data |
| 2800 |
return [ |
| 2801 |
'html' => '<script type="text/javascript">vboDownloadHospedajes(\'registerAccommodationReservations\', \'reservation\');</script>', |
| 2802 |
]; |
| 2803 |
} |
| 2804 |
|
| 2805 |
if (!($data['xml'] ?? '')) { |
| 2806 |
// attempt to build the XML file if not set |
| 2807 |
$data['xml'] = $this->buildXMLFile(); |
| 2808 |
} |
| 2809 |
|
| 2810 |
if (!$data['xml']) { |
| 2811 |
throw new Exception('Missing XML request message.', 500); |
| 2812 |
} |
| 2813 |
|
| 2814 |
// load report settings |
| 2815 |
$settings = $this->loadSettings(); |
| 2816 |
|
| 2817 |
if (!$settings || empty($settings['service_username']) || empty($settings['service_password']) || empty($settings['service_arrendador'])) { |
| 2818 |
throw new Exception(sprintf('[%s] error: missing service settings.', __METHOD__), 500); |
| 2819 |
} |
| 2820 |
|
| 2821 |
// set the type of transmission |
| 2822 |
$tn_type = 'RH'; |
| 2823 |
|
| 2824 |
// prepare the communication message data |
| 2825 |
$message_data = array_merge($data, [ |
| 2826 |
'operation_type' => 'A', |
| 2827 |
'report_type' => $tn_type, |
| 2828 |
]); |
| 2829 |
|
| 2830 |
// get the communication message |
| 2831 |
$message = $this->_callActionReturn('prepareCommunicationMessage', 'message', $scope, $message_data); |
| 2832 |
|
| 2833 |
try { |
| 2834 |
// post the message to the electronic service and get the Soap XML response message |
| 2835 |
$response = $this->postMessage($message, $settings); |
| 2836 |
|
| 2837 |
// parse the response message and get the main node across multiple namespaces |
| 2838 |
$xmlBody = $this->loadXmlSoap($response)->getSoapRecursiveNsElement([ |
| 2839 |
[ |
| 2840 |
'SOAP-ENV', |
| 2841 |
true, |
| 2842 |
'Body', |
| 2843 |
], |
| 2844 |
[ |
| 2845 |
'http://www.soap.servicios.hospedajes.mir.es/comunicacion', |
| 2846 |
false, |
| 2847 |
'respuesta', |
| 2848 |
], |
| 2849 |
]); |
| 2850 |
|
| 2851 |
// access the desired XML element |
| 2852 |
$xmlBody = $xmlBody->respuesta ?? $xmlBody; |
| 2853 |
|
| 2854 |
// access the result code (should be "codigo") |
| 2855 |
$result_code = $xmlBody->codigo ?? $xmlBody->codigoRetorno ?? null; |
| 2856 |
|
| 2857 |
if (is_null($result_code)) { |
| 2858 |
// unexpected response |
| 2859 |
throw new UnexpectedValueException(sprintf('Unexpected response [%s]', htmlspecialchars($xmlBody->formatXml() ?: $response)), 500); |
| 2860 |
} |
| 2861 |
|
| 2862 |
// validate the response |
| 2863 |
$is_error = (int) $result_code !== 0; |
| 2864 |
|
| 2865 |
if ($is_error || !($xmlBody->lote ?? '')) { |
| 2866 |
$error_code = (string) ($result_code ?? '500'); |
| 2867 |
$error_dets = (string) ($xmlBody->descripcion ?? 'Unknown'); |
| 2868 |
// terminate the execution in case of errors or empty result |
| 2869 |
throw new Exception(sprintf("[%s] Response error:\n%s", $error_code, $error_dets), 500); |
| 2870 |
} |
| 2871 |
|
| 2872 |
// the batch value obtained with the transmission |
| 2873 |
$batch_value = (string) $xmlBody->lote; |
| 2874 |
|
| 2875 |
// store the batch value on the DB for later fetching |
| 2876 |
$this->storeBatchData([ |
| 2877 |
'batch' => $batch_value, |
| 2878 |
'op_date' => date('Y-m-d H:i:s'), |
| 2879 |
'from_dt' => $this->exported_checkin_dates[0] ?? date('Y-m-d'), |
| 2880 |
'to_dt' => $this->exported_checkin_dates[1] ?? date('Y-m-d'), |
| 2881 |
'op_type' => 'A', |
| 2882 |
'rp_type' => $tn_type, |
| 2883 |
], 'hospedajes_batches_' . date('Yn')); |
| 2884 |
|
| 2885 |
// build HTML response string |
| 2886 |
$html = ''; |
| 2887 |
$html .= '<p class="successmade">Lote: ' . $batch_value . '</p>'; |
| 2888 |
|
| 2889 |
} catch (Exception $e) { |
| 2890 |
// propagate the error caught |
| 2891 |
throw new Exception(sprintf('[%s] error: %s', __METHOD__, $e->getMessage()), $e->getCode() ?: 500); |
| 2892 |
} |
| 2893 |
|
| 2894 |
// when executed through a cron, store an event in the Notifications Center |
| 2895 |
if ($scope === 'cron') { |
| 2896 |
// build the notification record |
| 2897 |
$notification = [ |
| 2898 |
'sender' => 'reports', |
| 2899 |
'type' => 'pmsreport.reshospedaje.ok', |
| 2900 |
'title' => 'Hospedajes - Alta de reservas de hospedaje', |
| 2901 |
'summary' => sprintf( |
| 2902 |
'Las reservas de hospedaje se han registrado correctamente para las fechas del %s al %s. Número de lote obtenido: %s.', |
| 2903 |
$this->exported_checkin_dates[0] ?? '', |
| 2904 |
$this->exported_checkin_dates[1] ?? '', |
| 2905 |
$batch_value |
| 2906 |
), |
| 2907 |
]; |
| 2908 |
|
| 2909 |
try { |
| 2910 |
// store the notification record |
| 2911 |
VBOFactory::getNotificationCenter()->store([$notification]); |
| 2912 |
} catch (Exception $e) { |
| 2913 |
// silently catch the error without doing anything |
| 2914 |
} |
| 2915 |
} |
| 2916 |
|
| 2917 |
return [ |
| 2918 |
'html' => $html, |
| 2919 |
'success' => !empty($batch_value), |
| 2920 |
'batch' => $batch_value, |
| 2921 |
]; |
| 2922 |
} |
| 2923 |
|
| 2924 |
/** |
| 2925 |
* Custom scoped action to list all the previously obtained batches. |
| 2926 |
* |
| 2927 |
* @param string $scope Optional scope identifier (cron, web, etc..). |
| 2928 |
* @param array $data Optional associative list of data to process. |
| 2929 |
* |
| 2930 |
* @return array The execution result properties. |
| 2931 |
* |
| 2932 |
* @throws Exception |
| 2933 |
*/ |
| 2934 |
protected function batchArchive($scope = null, array $data = []) |
| 2935 |
{ |
| 2936 |
// response properties |
| 2937 |
$html = ''; |
| 2938 |
|
| 2939 |
// optional filter by exact date |
| 2940 |
$date_filter = ''; |
| 2941 |
|
| 2942 |
// optional filter by report type |
| 2943 |
$rptype_filter = $data['rp_type'] ?? ''; |
| 2944 |
|
| 2945 |
// read exact or current period (4-digit year + month without leading zero) |
| 2946 |
$read_period = $data['yearmon'] ?? date('Yn'); |
| 2947 |
|
| 2948 |
if (!empty($data['op_month'])) { |
| 2949 |
// date in Y-m-d format to be converted into year+mon for reading a specific month |
| 2950 |
$read_period = date('Yn', strtotime($data['op_month'])); |
| 2951 |
} |
| 2952 |
|
| 2953 |
if (!empty($data['op_date'])) { |
| 2954 |
// full date in Y-m-d format for reading the operations of a specific date |
| 2955 |
$date_filter = $data['op_date']; |
| 2956 |
// set the month to read from the database |
| 2957 |
$read_period = date('Yn', strtotime($data['op_date'])); |
| 2958 |
} |
| 2959 |
|
| 2960 |
// read batches for the requested period |
| 2961 |
$batches = $this->readBatchData('hospedajes_batches_' . $read_period); |
| 2962 |
|
| 2963 |
if ($date_filter) { |
| 2964 |
// filter batches by exact date |
| 2965 |
$batches = $this->filterBatchData($batches, $date_filter); |
| 2966 |
} |
| 2967 |
|
| 2968 |
if (strlen((string) $rptype_filter) === 2) { |
| 2969 |
// filter batches by report type |
| 2970 |
$batches = $this->filterBatchData($batches, '', $rptype_filter); |
| 2971 |
} |
| 2972 |
|
| 2973 |
if (!$batches) { |
| 2974 |
$html .= '<p class="warn">No se encontraron lotes para el perÃodo solicitado.</p>'; |
| 2975 |
} else { |
| 2976 |
$html .= '<div class="vbo-admin-container vbo-admin-container-full vbo-admin-container-compact">'; |
| 2977 |
$html .= ' <div class="vbo-params-wrap">'; |
| 2978 |
$html .= ' <div class="vbo-params-container">'; |
| 2979 |
$html .= ' <div class="vbo-params-block">'; |
| 2980 |
|
| 2981 |
foreach ($batches as $batch) { |
| 2982 |
$report_type = $batch['rp_type'] === 'PV' ? 'Partes de viajeros' : 'Reservas de hospedaje'; |
| 2983 |
|
| 2984 |
$html .= ' <div class="vbo-param-container">'; |
| 2985 |
$html .= ' <div class="vbo-param-label">' . $report_type . '<br/>' . $batch['op_date'] . '</div>'; |
| 2986 |
$html .= ' <div class="vbo-param-setting">'; |
| 2987 |
$html .= ' <span>' . $batch['batch'] . '</span>'; |
| 2988 |
$html .= ' <span class="vbo-param-setting-comment">' . sprintf('(%s) %s - %s', $batch['op_type'], $batch['from_dt'], $batch['to_dt']) . '</span>'; |
| 2989 |
$html .= ' </div>'; |
| 2990 |
$html .= ' </div>'; |
| 2991 |
} |
| 2992 |
|
| 2993 |
$html .= ' </div>'; |
| 2994 |
$html .= ' </div>'; |
| 2995 |
$html .= ' </div>'; |
| 2996 |
$html .= '</div>'; |
| 2997 |
} |
| 2998 |
|
| 2999 |
return [ |
| 3000 |
'html' => $html, |
| 3001 |
'total' => count($batches), |
| 3002 |
'batches' => $batches, |
| 3003 |
'period' => $read_period, |
| 3004 |
'date' => $date_filter, |
| 3005 |
]; |
| 3006 |
} |
| 3007 |
|
| 3008 |
/** |
| 3009 |
* Custom scoped action to check the status of batches obtained from previous transmissions. |
| 3010 |
* Accepted scopes are "web" and "cron", so the "success" property must be returned. |
| 3011 |
* |
| 3012 |
* @param string $scope Optional scope identifier (cron, web, etc..). |
| 3013 |
* @param array $data Optional associative list of data to process. |
| 3014 |
* |
| 3015 |
* @return array The execution result properties. |
| 3016 |
* |
| 3017 |
* @throws Exception |
| 3018 |
*/ |
| 3019 |
protected function checkBatchStatus($scope = null, array $data = []) |
| 3020 |
{ |
| 3021 |
// response properties |
| 3022 |
$html = ''; |
| 3023 |
$communication_ok = 0; |
| 3024 |
$communication_err = 0; |
| 3025 |
|
| 3026 |
// list of batch strings (sequences) to consult |
| 3027 |
$batches = []; |
| 3028 |
|
| 3029 |
if ($data['batch_sequence'] ?? '') { |
| 3030 |
// push a single batch to check |
| 3031 |
$batches[] = $data['batch_sequence']; |
| 3032 |
} elseif ($data['op_date'] ?? '') { |
| 3033 |
// get the batches from a specific date |
| 3034 |
$list = $this->_callActionReturn('batchArchive', 'batches', $scope, ['op_date' => $data['op_date']]); |
| 3035 |
$batches = array_column($list, 'batch'); |
| 3036 |
} |
| 3037 |
|
| 3038 |
if (!$batches) { |
| 3039 |
throw new Exception(sprintf('[%s] error: %s', __METHOD__, 'No batch values to check according to filters.'), 404); |
| 3040 |
} |
| 3041 |
|
| 3042 |
// build the communication XML string |
| 3043 |
$batch_nodes = implode("\n", array_map(function($batch) { |
| 3044 |
return "\t" . '<con:lote>' . $batch . '</con:lote>'; |
| 3045 |
}, $batches)); |
| 3046 |
|
| 3047 |
$xml_comunication = <<<XML |
| 3048 |
<con:lotes xmlns:con="http://www.neg.hospedajes.mir.es/consultarComunicacion"> |
| 3049 |
$batch_nodes |
| 3050 |
</con:lotes> |
| 3051 |
XML; |
| 3052 |
|
| 3053 |
// prepare the communication message data |
| 3054 |
$message_data = [ |
| 3055 |
'xml' => $xml_comunication, |
| 3056 |
'operation_type' => 'C', |
| 3057 |
]; |
| 3058 |
|
| 3059 |
// get the communication message |
| 3060 |
$message = $this->_callActionReturn('prepareCommunicationMessage', 'message', $scope, $message_data); |
| 3061 |
|
| 3062 |
try { |
| 3063 |
// post the message to the electronic service and get the Soap XML response message |
| 3064 |
$response = $this->postMessage($message, $settings); |
| 3065 |
|
| 3066 |
// parse the response message and get the main node across multiple namespaces |
| 3067 |
$xmlResponseNode = $this->loadXmlSoap($response)->getSoapRecursiveNsElement([ |
| 3068 |
[ |
| 3069 |
'SOAP-ENV', |
| 3070 |
true, |
| 3071 |
'Body', |
| 3072 |
], |
| 3073 |
[ |
| 3074 |
'http://www.soap.servicios.hospedajes.mir.es/comunicacion', |
| 3075 |
false, |
| 3076 |
'respuesta', |
| 3077 |
], |
| 3078 |
]); |
| 3079 |
|
| 3080 |
// access the "response" node for validation |
| 3081 |
$xmlResponseNode = $xmlResponseNode->respuesta ?? $xmlResponseNode; |
| 3082 |
|
| 3083 |
if (!isset($xmlResponseNode->codigo)) { |
| 3084 |
// unexpected response |
| 3085 |
throw new UnexpectedValueException(sprintf('Unexpected response [%s]', $xmlResponseNode->formatXml() ?: $response), 500); |
| 3086 |
} |
| 3087 |
|
| 3088 |
// validate the response |
| 3089 |
$is_error = (int) $xmlResponseNode->codigo !== 0; |
| 3090 |
|
| 3091 |
if ($is_error) { |
| 3092 |
$error_code = (string) ($xmlBody->codigo ?? '500'); |
| 3093 |
$error_dets = (string) ($xmlBody->descripcion ?? 'Unknown'); |
| 3094 |
// terminate the execution in case of errors or empty result |
| 3095 |
throw new Exception(sprintf("[%s] Response error:\n%s", $error_code, $error_dets), 500); |
| 3096 |
} |
| 3097 |
|
| 3098 |
// now access the "result" node across multiple namespaces |
| 3099 |
$xmlResultNode = $this->loadXmlSoap($response)->getSoapRecursiveNsElement([ |
| 3100 |
[ |
| 3101 |
'SOAP-ENV', |
| 3102 |
true, |
| 3103 |
'Body', |
| 3104 |
], |
| 3105 |
[ |
| 3106 |
'http://www.soap.servicios.hospedajes.mir.es/comunicacion', |
| 3107 |
false, |
| 3108 |
'resultado', |
| 3109 |
], |
| 3110 |
]); |
| 3111 |
|
| 3112 |
// access the "result" node for validation |
| 3113 |
$xmlResultNode = $xmlResultNode->resultado ?? $xmlResultNode; |
| 3114 |
|
| 3115 |
if (!isset($xmlResultNode->resultadoComunicaciones->resultadoComunicacion)) { |
| 3116 |
// unexpected response |
| 3117 |
throw new UnexpectedValueException(sprintf('Unexpected response with no results [%s]', $xmlResultNode->formatXml() ?: $response), 500); |
| 3118 |
} |
| 3119 |
|
| 3120 |
// build HTML response string |
| 3121 |
$html .= '<div class="vbo-admin-container vbo-admin-container-full vbo-admin-container-compact">'; |
| 3122 |
$html .= ' <div class="vbo-params-wrap">'; |
| 3123 |
$html .= ' <div class="vbo-params-container">'; |
| 3124 |
$html .= ' <div class="vbo-params-block">'; |
| 3125 |
|
| 3126 |
$html .= ' <div class="vbo-param-container">'; |
| 3127 |
$html .= ' <div class="vbo-param-label">Lote</div>'; |
| 3128 |
$html .= ' <div class="vbo-param-setting">'; |
| 3129 |
$html .= ' <span>' . (string) $xmlResultNode->lote . '</span>'; |
| 3130 |
$html .= ' </div>'; |
| 3131 |
$html .= ' </div>'; |
| 3132 |
|
| 3133 |
$html .= ' <div class="vbo-param-container">'; |
| 3134 |
$html .= ' <div class="vbo-param-label">Tipo de comunicaciones enviadas</div>'; |
| 3135 |
$html .= ' <div class="vbo-param-setting">'; |
| 3136 |
$html .= ' <span>' . (string) $xmlResultNode->tipoComunicacion . ' - ' . (string) ($xmlResultNode->tipoOperacion ?? '') . '</span>'; |
| 3137 |
$html .= ' </div>'; |
| 3138 |
$html .= ' </div>'; |
| 3139 |
|
| 3140 |
$html .= ' <div class="vbo-param-container">'; |
| 3141 |
$html .= ' <div class="vbo-param-label">Fecha Peticion</div>'; |
| 3142 |
$html .= ' <div class="vbo-param-setting">'; |
| 3143 |
$html .= ' <span>' . (string) $xmlResultNode->fechaPeticion . '</span>'; |
| 3144 |
$html .= ' <span class="vbo-param-setting-comment">Fecha Procesamiento ' . (string) ($xmlResultNode->fechaProcesamiento ?? '') . '</span>'; |
| 3145 |
$html .= ' </div>'; |
| 3146 |
$html .= ' </div>'; |
| 3147 |
|
| 3148 |
$html .= ' <div class="vbo-param-container">'; |
| 3149 |
$html .= ' <div class="vbo-param-label">Estado</div>'; |
| 3150 |
$html .= ' <div class="vbo-param-setting">'; |
| 3151 |
$html .= ' <span>(' . (string) $xmlResultNode->codigoEstado . ') ' . (string) $xmlResultNode->descEstado . '</span>'; |
| 3152 |
$html .= ' </div>'; |
| 3153 |
$html .= ' </div>'; |
| 3154 |
|
| 3155 |
// scan all results and increase success/error counters |
| 3156 |
foreach ($xmlResultNode->resultadoComunicaciones->resultadoComunicacion as $rescom) { |
| 3157 |
$html .= ' <div class="vbo-param-container">'; |
| 3158 |
$html .= ' <div class="vbo-param-label">Resultado #' . (string) $rescom->orden . '</div>'; |
| 3159 |
$html .= ' <div class="vbo-param-setting">'; |
| 3160 |
if ((string) ($rescom->codigoComunicacion ?? '')) { |
| 3161 |
// expected communication code (success) |
| 3162 |
$html .= ' <span>' . (string) $rescom->codigoComunicacion . '</span>'; |
| 3163 |
$html .= ' <span class="vbo-param-setting-comment">Codigo comunicacion.</span>'; |
| 3164 |
// increase counter |
| 3165 |
$communication_ok++; |
| 3166 |
} else { |
| 3167 |
// expected error details |
| 3168 |
$html .= ' <span>' . (string) ($rescom->tipoError ?? '') . '</span>'; |
| 3169 |
$html .= ' <span class="vbo-param-setting-comment">' . (string) ($rescom->error ?? '') . '</span>'; |
| 3170 |
// increase counter |
| 3171 |
$communication_err++; |
| 3172 |
} |
| 3173 |
$html .= ' </div>'; |
| 3174 |
$html .= ' </div>'; |
| 3175 |
} |
| 3176 |
|
| 3177 |
$html .= ' </div>'; |
| 3178 |
$html .= ' </div>'; |
| 3179 |
$html .= ' </div>'; |
| 3180 |
$html .= '</div>'; |
| 3181 |
} catch (Exception $e) { |
| 3182 |
// propagate the error caught |
| 3183 |
throw new Exception(sprintf('[%s] error: %s', __METHOD__, $e->getMessage()), $e->getCode() ?: 500); |
| 3184 |
} |
| 3185 |
|
| 3186 |
// when executed through a cron, store an event in the Notifications Center |
| 3187 |
if ($scope === 'cron') { |
| 3188 |
// build the notification record |
| 3189 |
$notification = [ |
| 3190 |
'sender' => 'reports', |
| 3191 |
'type' => 'pmsreport.checkbatchstatus.' . ($communication_err ? 'error' : 'ok'), |
| 3192 |
'title' => 'Hospedajes - Consulta de lotes', |
| 3193 |
'summary' => sprintf( |
| 3194 |
'Consulta de lotes finalizados. Resultados totales: %d. Éxito: %d. Error: %d.', |
| 3195 |
($communication_ok + $communication_err), |
| 3196 |
$communication_ok, |
| 3197 |
$communication_err |
| 3198 |
), |
| 3199 |
]; |
| 3200 |
|
| 3201 |
try { |
| 3202 |
// store the notification record |
| 3203 |
VBOFactory::getNotificationCenter()->store([$notification]); |
| 3204 |
} catch (Exception $e) { |
| 3205 |
// silently catch the error without doing anything |
| 3206 |
} |
| 3207 |
} |
| 3208 |
|
| 3209 |
return [ |
| 3210 |
'html' => $html, |
| 3211 |
'success' => true, |
| 3212 |
'count_ok' => $communication_ok, |
| 3213 |
'count_err' => $communication_err, |
| 3214 |
]; |
| 3215 |
} |
| 3216 |
|
| 3217 |
/** |
| 3218 |
* Custom scoped action to prepare a communication request towards the Electronic Service. |
| 3219 |
* |
| 3220 |
* @param string $scope Optional scope identifier (cron, web, etc..). |
| 3221 |
* @param array $data Optional associative list of data to process. |
| 3222 |
* |
| 3223 |
* @return array The execution result properties. |
| 3224 |
* |
| 3225 |
* @throws Exception |
| 3226 |
*/ |
| 3227 |
protected function prepareCommunicationMessage($scope = null, array $data = []) |
| 3228 |
{ |
| 3229 |
// load report settings |
| 3230 |
$settings = $this->loadSettings(); |
| 3231 |
|
| 3232 |
if (empty($data['operation_type'])) { |
| 3233 |
throw new Exception('Missing mandatory Operation Type.', 500); |
| 3234 |
} |
| 3235 |
|
| 3236 |
// ensure the operation type is upper-case (A, C or B) |
| 3237 |
$data['operation_type'] = strtoupper($data['operation_type']); |
| 3238 |
|
| 3239 |
if ($data['operation_type'] === 'A' && empty($data['report_type'])) { |
| 3240 |
// either "PV" (checkin) or "HR" (reservation) is mandatory |
| 3241 |
throw new Exception('Missing mandatory Report Type.', 500); |
| 3242 |
} |
| 3243 |
|
| 3244 |
// ensure the report type is upper-case ("PV" or "HR") |
| 3245 |
$data['report_type'] = strtoupper($data['report_type'] ?? ''); |
| 3246 |
|
| 3247 |
if (!($data['xml'] ?? '')) { |
| 3248 |
// attempt to build the XML file if not set |
| 3249 |
$data['xml'] = $this->buildXMLFile(); |
| 3250 |
} |
| 3251 |
|
| 3252 |
if (!$data['xml']) { |
| 3253 |
throw new Exception('Missing XML request (solicitud).', 500); |
| 3254 |
} |
| 3255 |
|
| 3256 |
// first off, clean up the report temporary directory to ensure we've got no other files |
| 3257 |
JFolder::delete($this->report_tmp_path); |
| 3258 |
|
| 3259 |
// build the temporary XML file name |
| 3260 |
$xml_fname = uniqid('hospedajes_') . '.xml'; |
| 3261 |
|
| 3262 |
// store the XML file internally |
| 3263 |
$xml_stored = JFile::write($this->report_tmp_path . DIRECTORY_SEPARATOR . $xml_fname, $data['xml']); |
| 3264 |
|
| 3265 |
if (!$xml_stored) { |
| 3266 |
throw new Exception('Could not store the XML file internally for the data transmission.', 500); |
| 3267 |
} |
| 3268 |
|
| 3269 |
// build the zip file destination path |
| 3270 |
$zip_destination = $this->report_tmp_path . DIRECTORY_SEPARATOR . preg_replace("/\.xml$/", '.zip', $xml_fname); |
| 3271 |
|
| 3272 |
// compress the folder (should contain a single XML file) into an archive |
| 3273 |
$xml_compressed = VBOArchiveFactory::compress($this->report_tmp_path, $zip_destination); |
| 3274 |
|
| 3275 |
if (!$xml_compressed) { |
| 3276 |
throw new Exception('Could not compress the XML file in zip format for the data transmission.', 500); |
| 3277 |
} |
| 3278 |
|
| 3279 |
// read the archive into a base64-encoded string |
| 3280 |
$base64_request = base64_encode(file_get_contents($zip_destination)); |
| 3281 |
|
| 3282 |
if (!$base64_request) { |
| 3283 |
throw new Exception('Could not read the zip archive containing the XML file into a base64-encoded string for the data transmission.', 500); |
| 3284 |
} |
| 3285 |
|
| 3286 |
// build SOAP message values |
| 3287 |
$codigo_arrendador = $settings['service_arrendador'] ?? ''; |
| 3288 |
$application_name = $this->software_application_name; |
| 3289 |
$operation_type_code = $data['operation_type']; |
| 3290 |
$communication_type_node = ''; |
| 3291 |
if ($data['operation_type'] === 'A') { |
| 3292 |
// communication type node is mandatory |
| 3293 |
$communication_type_node = '<tipoComunicacion>' . $data['report_type'] . '</tipoComunicacion>'; |
| 3294 |
} |
| 3295 |
|
| 3296 |
// build SOAP XML message |
| 3297 |
$soap_xml = <<<XML |
| 3298 |
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:com="http://www.soap.servicios.hospedajes.mir.es/comunicacion"> |
| 3299 |
<soapenv:Header/> |
| 3300 |
<soapenv:Body> |
| 3301 |
<com:comunicacionRequest> |
| 3302 |
<peticion> |
| 3303 |
<cabecera> |
| 3304 |
<codigoArrendador>$codigo_arrendador</codigoArrendador> |
| 3305 |
<aplicacion>$application_name</aplicacion> |
| 3306 |
<tipoOperacion>$operation_type_code</tipoOperacion> |
| 3307 |
$communication_type_node |
| 3308 |
</cabecera> |
| 3309 |
<solicitud>$base64_request</solicitud> |
| 3310 |
</peticion> |
| 3311 |
</com:comunicacionRequest> |
| 3312 |
</soapenv:Body> |
| 3313 |
</soapenv:Envelope> |
| 3314 |
XML; |
| 3315 |
|
| 3316 |
return [ |
| 3317 |
'message' => $soap_xml, |
| 3318 |
'solicitud' => $data['xml'], |
| 3319 |
]; |
| 3320 |
} |
| 3321 |
|
| 3322 |
/** |
| 3323 |
* Parses a report row into an associative list of key-value pairs. |
| 3324 |
* |
| 3325 |
* @param array $row The report row to parse. |
| 3326 |
* |
| 3327 |
* @return array |
| 3328 |
*/ |
| 3329 |
protected function getAssocRowData(array $row) |
| 3330 |
{ |
| 3331 |
$row_data = []; |
| 3332 |
|
| 3333 |
foreach ($row as $field) { |
| 3334 |
$field_val = $field['value']; |
| 3335 |
if (!($field['no_export_callback'] ?? 0) && is_callable($field['callback'] ?? null)) { |
| 3336 |
$field_val = $field['callback']($field_val); |
| 3337 |
} |
| 3338 |
$row_data[$field['key']] = $field_val; |
| 3339 |
} |
| 3340 |
|
| 3341 |
return $row_data; |
| 3342 |
} |
| 3343 |
|
| 3344 |
/** |
| 3345 |
* Makes a POST request towards the electronic service by posting a SOAP XML message. |
| 3346 |
* |
| 3347 |
* @param string $message The SOAP XML message to post. |
| 3348 |
* @param array $settings The report settings. |
| 3349 |
* |
| 3350 |
* @return string The response obtained. |
| 3351 |
* |
| 3352 |
* @throws Exception |
| 3353 |
*/ |
| 3354 |
protected function postMessage($message, array $settings = []) |
| 3355 |
{ |
| 3356 |
if (!$settings) { |
| 3357 |
// load report settings |
| 3358 |
$settings = $this->loadSettings(); |
| 3359 |
} |
| 3360 |
|
| 3361 |
/** |
| 3362 |
* @todo start debug responses |
| 3363 |
*/ |
| 3364 |
/* |
| 3365 |
$ok = '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> |
| 3366 |
<SOAP-ENV:Header/> |
| 3367 |
<SOAP-ENV:Body> |
| 3368 |
<ns3:comunicacionResponse xmlns:ns3="http://www.soap.servicios.hospedajes.mir.es/comunicacion"> |
| 3369 |
<respuesta> |
| 3370 |
<codigoRetorno>0</codigoRetorno> |
| 3371 |
<descripcion>Ok</descripcion> |
| 3372 |
<lote>00000000-1234-5678-0000-00000000' . rand(1000, 9999) . '</lote> |
| 3373 |
</respuesta> |
| 3374 |
</ns3:comunicacionResponse> |
| 3375 |
</SOAP-ENV:Body> |
| 3376 |
</SOAP-ENV:Envelope>'; |
| 3377 |
|
| 3378 |
$nok = '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> |
| 3379 |
<SOAP-ENV:Header/> |
| 3380 |
<SOAP-ENV:Body> |
| 3381 |
<ns3:comunicacionResponse xmlns:ns3="http://www.soap.servicios.hospedajes.mir.es/comunicacion"> |
| 3382 |
<respuesta> |
| 3383 |
<codigoRetorno>109</codigoRetorno> |
| 3384 |
<descripcion>Formato de solicitud incorrecto. Ha de ir comprimido (zip) y codificado en Base64.</descripcion> |
| 3385 |
</respuesta> |
| 3386 |
</ns3:comunicacionResponse> |
| 3387 |
</SOAP-ENV:Body> |
| 3388 |
</SOAP-ENV:Envelope>'; |
| 3389 |
|
| 3390 |
$okc = '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> |
| 3391 |
<SOAP-ENV:Header/> |
| 3392 |
<SOAP-ENV:Body> |
| 3393 |
<ns3:comunicacionResponse xmlns:ns3="http://www.soap.servicios.hospedajes.mir.es/comunicacion"> |
| 3394 |
<respuesta> |
| 3395 |
<codigo>0</codigo> |
| 3396 |
<descripcion>Ok</descripcion> |
| 3397 |
</respuesta> |
| 3398 |
<resultado> |
| 3399 |
<lote>00000000-0000-0000-0000-000000000000</lote> |
| 3400 |
<tipoComunicacion>PV</tipoComunicacion> |
| 3401 |
<tipoOperacion>A</tipoOperacion> |
| 3402 |
<fechaPeticion>2023-02-23T11:37:13.000+01:00</fechaPeticion> |
| 3403 |
<fechaProcesamiento>2023-02-23T11:37:33.000+01:00</fechaProcesamiento> |
| 3404 |
<codigoEstado>6</codigoEstado> |
| 3405 |
<descEstado>Se ha ejecutado pero hay errores en algunas comunicaciones</descEstado> |
| 3406 |
<identificadorUsuario>B00000000</identificadorUsuario> |
| 3407 |
<nombreUsuario>Prueba</nombreUsuario> |
| 3408 |
<codigoArrendador>0000000001</codigoArrendador> |
| 3409 |
<aplicacion>Sistema de pruebas</aplicacion> |
| 3410 |
<resultadoComunicaciones> |
| 3411 |
<resultadoComunicacion> |
| 3412 |
<orden>1</orden> |
| 3413 |
<codigoComunicacion>12345678-4321-3210-6789-210987654321</codigoComunicacion> |
| 3414 |
</resultadoComunicacion> |
| 3415 |
</resultadoComunicaciones> |
| 3416 |
</resultado> |
| 3417 |
</ns3:comunicacionResponse> |
| 3418 |
</SOAP-ENV:Body> |
| 3419 |
</SOAP-ENV:Envelope>'; |
| 3420 |
|
| 3421 |
$nokc = '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> |
| 3422 |
<SOAP-ENV:Header/> |
| 3423 |
<SOAP-ENV:Body> |
| 3424 |
<ns3:comunicacionResponse xmlns:ns3="http://www.soap.servicios.hospedajes.mir.es/comunicacion"> |
| 3425 |
<respuesta> |
| 3426 |
<codigo>0</codigo> |
| 3427 |
<descripcion>Ok</descripcion> |
| 3428 |
</respuesta> |
| 3429 |
<resultado> |
| 3430 |
<lote>00000000-0000-0000-0000-000000000000</lote> |
| 3431 |
<tipoComunicacion>PV</tipoComunicacion> |
| 3432 |
<tipoOperacion>A</tipoOperacion> |
| 3433 |
<fechaPeticion>2023-02-23T11:37:13.000+01:00</fechaPeticion> |
| 3434 |
<fechaProcesamiento>2023-02-23T11:37:33.000+01:00</fechaProcesamiento> |
| 3435 |
<codigoEstado>6</codigoEstado> |
| 3436 |
<descEstado>Se ha ejecutado pero hay errores en algunas comunicaciones</descEstado> |
| 3437 |
<identificadorUsuario>B00000000</identificadorUsuario> |
| 3438 |
<nombreUsuario>Prueba</nombreUsuario> |
| 3439 |
<codigoArrendador>0000000001</codigoArrendador> |
| 3440 |
<aplicacion>Sistema de pruebas</aplicacion> |
| 3441 |
<resultadoComunicaciones> |
| 3442 |
<resultadoComunicacion> |
| 3443 |
<orden>1</orden> |
| 3444 |
<tipoError>Error validación de datos</tipoError> |
| 3445 |
<error>Error de validación en la comunicación [1]: [No existe un establecimiento para ese código. codigoEstablecimiento: [1234567890]]</error> |
| 3446 |
</resultadoComunicacion> |
| 3447 |
</resultadoComunicaciones> |
| 3448 |
</resultado> |
| 3449 |
</ns3:comunicacionResponse> |
| 3450 |
</SOAP-ENV:Body> |
| 3451 |
</SOAP-ENV:Envelope>'; |
| 3452 |
|
| 3453 |
if (strpos($message, '<tipoOperacion>C</tipoOperacion>')) { |
| 3454 |
// consulta de lotes response simulation |
| 3455 |
return rand(0, 1) ? $okc : $nokc; |
| 3456 |
} |
| 3457 |
|
| 3458 |
return rand(0, 1) ? $ok : $nok; |
| 3459 |
*/ |
| 3460 |
// end debug responses |
| 3461 |
|
| 3462 |
|
| 3463 |
// build endpoint URL |
| 3464 |
if ($settings['service_test_mode'] ?? 1) { |
| 3465 |
$endpoint = $this->endpoint_test; |
| 3466 |
} else { |
| 3467 |
$endpoint = $this->endpoint_production; |
| 3468 |
} |
| 3469 |
|
| 3470 |
// build basic-auth value |
| 3471 |
$basic_auth = base64_encode(($settings['service_username'] ?? '') . ':' . ($settings['service_password'] ?? '')); |
| 3472 |
|
| 3473 |
// start HTTP transporter |
| 3474 |
$http = new JHttp(); |
| 3475 |
|
| 3476 |
// build connection request headers |
| 3477 |
$headers = [ |
| 3478 |
'Authorization' => 'Basic ' . $basic_auth, |
| 3479 |
'Content-Type' => 'text/xml', |
| 3480 |
]; |
| 3481 |
|
| 3482 |
// check SSL request header settings |
| 3483 |
if (is_file(dirname(__FILE__) . DIRECTORY_SEPARATOR . '_.ses.mir.es_1.crt')) { |
| 3484 |
// register custom SSL certificate path |
| 3485 |
$headers['sslcertificates'] = dirname(__FILE__) . DIRECTORY_SEPARATOR . '_.ses.mir.es_1.crt'; |
| 3486 |
} elseif (is_file(dirname(__FILE__) . DIRECTORY_SEPARATOR . '_.ses.mir.es.crt')) { |
| 3487 |
// register custom SSL certificate path |
| 3488 |
$headers['sslcertificates'] = dirname(__FILE__) . DIRECTORY_SEPARATOR . '_.ses.mir.es.crt'; |
| 3489 |
} else { |
| 3490 |
// disable SSL peer validation for using an unsecure connection |
| 3491 |
$headers['sslverify'] = false; |
| 3492 |
} |
| 3493 |
|
| 3494 |
// make POST request to the specified URL |
| 3495 |
$response = $http->post($endpoint, $message, $headers); |
| 3496 |
|
| 3497 |
if ($response->code != 200) { |
| 3498 |
// invalid response, throw an exception |
| 3499 |
throw new Exception(strip_tags((string) $response->body), $response->code); |
| 3500 |
} |
| 3501 |
|
| 3502 |
return $response->body; |
| 3503 |
} |
| 3504 |
|
| 3505 |
/** |
| 3506 |
* Stores batch data under the given batch field name. |
| 3507 |
* |
| 3508 |
* @param array $data The batch data to store. |
| 3509 |
* @param string $field The batch field name. |
| 3510 |
* |
| 3511 |
* @return void |
| 3512 |
*/ |
| 3513 |
protected function storeBatchData(array $data, $field = '') |
| 3514 |
{ |
| 3515 |
// the configuration field name |
| 3516 |
$field = $field ?: 'hospedajes_batches_' . date('Yn'); |
| 3517 |
|
| 3518 |
// access batches from the current field |
| 3519 |
$current_batches = VBOFactory::getConfig()->getArray($field, []); |
| 3520 |
|
| 3521 |
// prepend new batch data |
| 3522 |
array_unshift($current_batches, $data); |
| 3523 |
|
| 3524 |
// save new batches |
| 3525 |
VBOFactory::getConfig()->set($field, $current_batches); |
| 3526 |
} |
| 3527 |
|
| 3528 |
/** |
| 3529 |
* Reads batch data under the given batch field name. |
| 3530 |
* |
| 3531 |
* @param string $field The batch field name. |
| 3532 |
* |
| 3533 |
* @return array |
| 3534 |
*/ |
| 3535 |
protected function readBatchData($field = '') |
| 3536 |
{ |
| 3537 |
// the configuration field name |
| 3538 |
$field = $field ?: 'hospedajes_batches_' . date('Yn'); |
| 3539 |
|
| 3540 |
// return batches from the current field |
| 3541 |
return VBOFactory::getConfig()->getArray($field, []); |
| 3542 |
} |
| 3543 |
|
| 3544 |
/** |
| 3545 |
* Filters the given list of batch data by date and/or type. |
| 3546 |
* |
| 3547 |
* @param string $date The exact date to filter for. |
| 3548 |
* @param string $type Filter by report type ("PV", "HR"). |
| 3549 |
* |
| 3550 |
* @return array |
| 3551 |
*/ |
| 3552 |
protected function filterBatchData(array $data, $date = '', $type = '') |
| 3553 |
{ |
| 3554 |
// return the filtered batches, if any |
| 3555 |
return array_filter($data, function($batch) use ($date, $type) { |
| 3556 |
$date_valid = true; |
| 3557 |
$type_valid = true; |
| 3558 |
|
| 3559 |
if ($date) { |
| 3560 |
$date_valid = (bool) preg_match("/^" . preg_quote($date) . "/", $batch['op_date'] ?? ''); |
| 3561 |
} |
| 3562 |
|
| 3563 |
if ($type) { |
| 3564 |
$type_valid = !strcasecmp($type, $batch['rp_type'] ?? ''); |
| 3565 |
} |
| 3566 |
|
| 3567 |
return $date_valid && $type_valid; |
| 3568 |
}); |
| 3569 |
} |
| 3570 |
|
| 3571 |
/** |
| 3572 |
* Parses a SOAP XML message into a VBOXmlSoap object. |
| 3573 |
* |
| 3574 |
* @param string $xmlMessage The SOAP XML message to load. |
| 3575 |
* |
| 3576 |
* @return VBOXmlSoap |
| 3577 |
* |
| 3578 |
* @throws Exception |
| 3579 |
*/ |
| 3580 |
protected function loadXmlSoap($xmlMessage) |
| 3581 |
{ |
| 3582 |
if (empty($xmlMessage)) { |
| 3583 |
throw new Exception('Empty Soap XML message.', 500); |
| 3584 |
} |
| 3585 |
|
| 3586 |
// suppress warning messages |
| 3587 |
libxml_use_internal_errors(true); |
| 3588 |
|
| 3589 |
// parse the Soap XML message |
| 3590 |
return simplexml_load_string($xmlMessage, VBOXmlSoap::class); |
| 3591 |
} |
| 3592 |
|
| 3593 |
/** |
| 3594 |
* Registers the name to give to the file being exported. |
| 3595 |
* |
| 3596 |
* @return void |
| 3597 |
*/ |
| 3598 |
protected function registerExportFileName() |
| 3599 |
{ |
| 3600 |
$pfromdate = VikRequest::getString('fromdate', '', 'request'); |
| 3601 |
$ptodate = VikRequest::getString('todate', '', 'request'); |
| 3602 |
$ptype = VikRequest::getString('type', '', 'request'); |
| 3603 |
|
| 3604 |
// build report type name |
| 3605 |
if ($ptype === 'checkin') { |
| 3606 |
$export_name = 'Partes_de_viajeros'; |
| 3607 |
} else { |
| 3608 |
$export_name = 'Reservas_de_hospedaje'; |
| 3609 |
} |
| 3610 |
|
| 3611 |
$this->setExportCSVFileName($export_name . '-' . $this->reportName . '-' . str_replace('/', '_', $pfromdate) . '-' . str_replace('/', '_', $ptodate) . '.xml'); |
| 3612 |
} |
| 3613 |
|
| 3614 |
/** |
| 3615 |
* Helper method to quickly get a pax_data property for the guest. |
| 3616 |
* |
| 3617 |
* @param array $pax_data the current pax_data stored. |
| 3618 |
* @param array $guests list of total guests per room. |
| 3619 |
* @param int $guest_ind the guest index. |
| 3620 |
* @param string $key the pax_data key to look for. |
| 3621 |
* |
| 3622 |
* @return mixed null on failure or value fetched. |
| 3623 |
*/ |
| 3624 |
protected function getGuestPaxDataValue($pax_data, $guests, $guest_ind, $key) |
| 3625 |
{ |
| 3626 |
if (!is_array($pax_data) || !$pax_data || empty($key)) { |
| 3627 |
return null; |
| 3628 |
} |
| 3629 |
|
| 3630 |
// find room index for this guest number |
| 3631 |
$room_num = 0; |
| 3632 |
$use_guest_ind = $guest_ind; |
| 3633 |
foreach ($guests as $room_index => $room_tot_guests) { |
| 3634 |
// find the proper guest index for the room to which this belongs |
| 3635 |
if ($use_guest_ind <= $room_tot_guests) { |
| 3636 |
// proper room index found for this guest |
| 3637 |
$room_num = $room_index; |
| 3638 |
break; |
| 3639 |
} else { |
| 3640 |
// it's probably in a next room |
| 3641 |
$use_guest_ind -= $room_tot_guests; |
| 3642 |
} |
| 3643 |
} |
| 3644 |
|
| 3645 |
// check if a value exists for the requested key in the found room and guest indexes |
| 3646 |
if (isset($pax_data[$room_num]) && isset($pax_data[$room_num][$use_guest_ind])) { |
| 3647 |
if (isset($pax_data[$room_num][$use_guest_ind][$key])) { |
| 3648 |
// we've got a value previously stored |
| 3649 |
return $pax_data[$room_num][$use_guest_ind][$key]; |
| 3650 |
} |
| 3651 |
} |
| 3652 |
|
| 3653 |
// nothing was found |
| 3654 |
return null; |
| 3655 |
} |
| 3656 |
|
| 3657 |
/** |
| 3658 |
* Helper method to determine the exact number for this guest in the room booked. |
| 3659 |
* |
| 3660 |
* @param array $guests list of total guests per room. |
| 3661 |
* @param int $guest_ind the guest index. |
| 3662 |
* |
| 3663 |
* @return int the actual guest room index starting from 1. |
| 3664 |
*/ |
| 3665 |
protected function calcGuestRoomIndex($guests, $guest_ind) |
| 3666 |
{ |
| 3667 |
// find room index for this guest number |
| 3668 |
$room_num = 0; |
| 3669 |
$use_guest_ind = $guest_ind; |
| 3670 |
foreach ($guests as $room_index => $room_tot_guests) { |
| 3671 |
// find the proper guest index for the room to which this belongs |
| 3672 |
if ($use_guest_ind <= $room_tot_guests) { |
| 3673 |
// proper room index found for this guest |
| 3674 |
$room_num = $room_index; |
| 3675 |
break; |
| 3676 |
} else { |
| 3677 |
// it's probably in a next room |
| 3678 |
$use_guest_ind -= $room_tot_guests; |
| 3679 |
} |
| 3680 |
} |
| 3681 |
|
| 3682 |
return $use_guest_ind; |
| 3683 |
} |
| 3684 |
} |
| 3685 |
|