[16.0][IMP] pms_l10n_es: INE occupancy surveys for IRIA: fix hotel XML and add tourist apartments (EOAP) - #233
[16.0][IMP] pms_l10n_es: INE occupancy surveys for IRIA: fix hotel XML and add tourist apartments (EOAP)#233davidpachecop wants to merge 11 commits into
Conversation
… tourist apartments (EOAP) The INE replaced the ARCE platform with IRIA. IRIA questionnaire schemas are namespace-qualified, so the XML files generated so far are rejected at upload time (XSD error on line 1: cannot find the declaration of the root element). IRIA also removed the in-portal editing that ARCE allowed, so the generated file must be exact. Hotel survey (EOH) fixes: - Qualify the root element with the IRIA namespace, configurable through the ir.config_parameter pms_l10n_es.ine_xml_namespace_hotel. - Declare and encode the file as UTF-8 (it declared ISO-8859-1 while encoding UTF-8 bytes). - Print DIAS_ABIERTO_MES_REFERENCIA zero-padded to 2 digits and omit the URL element when the property has no website (both rejected by the IRIA schema). - Emit every decimal with exactly 2 digits and normalize the occupancy percentages in integer hundredths so the printed values add up to exactly 100.00: float artifacts have been a recurrent source of files rejected by the INE content validations. - New INE province literal on res.country.state: the survey header expects the province literal of the INE specification (max. 25 chars) and several Odoo state names exceed it. New tourist apartments survey (EOAP): - New survey_type on the INE categories and seed data for the tourist apartments categories (0-4 keys). The wizard picks the questionnaire format from the property INE category. - New apartment typology on rooms (studio / 2-4 pax / 4-6 pax / other), inferred from the room capacity when not set. - New informant fields on the property (required block in EOAP). - New XML builder with the EOAP blocks (CABECERA_APARTAMENTOS, INFORMANTE, CAPACIDAD, OCUPACION and PRECIOS per typology), sharing the guest movements and staff blocks with the hotel survey. The whole occupancy of each typology is reported under the normal rate with its ADR, which satisfies the INE content validations and has been accepted by the INE in a real submission. Tests validate both generated files against the current IRIA schemas and the exactness of the printed decimals and percentage sums.
…nexes The INE publishes the survey annexes as XML files. Checking the seed data against them: - The province literal expected for province 48 is VIZCAKAIA (as published in the province annex), not VIZCAYA. - The hotel type/category table includes one pair that was missing.
Actualización: respuesta del INE (5-ago) y datos oficialesEl INE (equipo de IRIA) ha contestado a nuestras consultas y ha publicado los enlaces permanentes de los esquemas y anexos de cada encuesta. Resumen de lo que confirma y de lo que ha cambiado en la rama: Confirmado por el INE:
Cambios en la rama a partir de sus anexos oficiales (commit "align INE reference data with the published INE annexes"):
Matiz importante sobre el espacio de nombres (decisión 1): el INE indica que "el esquema es exactamente igual que el de ARCE". Estructuralmente es cierto (mismos 65 elementos en el mismo orden), pero hay dos variantes del esquema y se excluyen mutuamente:
Comprobado: el fichero que el INE nos aceptó y registró lleva espacio de nombres y no valida contra el esquema publicado; y ese mismo fichero sin espacio de nombres no valida contra el del cuestionario. Es decir, la carga por el portal valida contra el esquema versionado (con espacio de nombres), que es lo que hace esta rama. Además, la documentación del servicio web apunta al esquema publicado (sin espacio de nombres), así que puede haber divergencia entre canales: otro motivo para mantener el espacio de nombres como parámetro configurable en lugar de fijarlo en el código. Pendiente de que el INE confirme ambos puntos (preguntado). |
The INE confirmed that the reference schema of each survey is the one they publish, which declares no target namespace, and not the one the IRIA application generates for the questionnaire. Both variants have been accepted on upload so far (hotel files without namespace, an apartments file with it), so the files are built after the published schema and the qualified variant can be enabled per survey with a config parameter for the questionnaires that need it. This keeps the hotel file byte-compatible with what the establishments have been uploading successfully.
Corrección importante: el fichero hotelero NO estaba rotoEn el comentario anterior daba por probable que los ficheros hoteleros estuvieran siendo rechazados en IRIA por no declarar el espacio de nombres. Era una inferencia y es incorrecta. Lo aclaran dos cosas de hoy:
El rechazo que originó todo esto se explica entonces solo por el guión equivocado: se subía el fichero de hoteles a un cuestionario de apartamentos, y ahí Cambio aplicado (commit "build the INE files after the published schema"): el espacio de nombres pasa a estar vacío por defecto en las dos encuestas, de modo que el fichero hotelero queda idéntico al que la flota sube con éxito, y la variante cualificada se puede activar por encuesta con un parámetro si algún cuestionario la exigiera. Los tests cubren ahora las dos variantes: por defecto validan contra los esquemas publicados por el INE y, con el parámetro puesto, contra los versionados que entrega IRIA. 27 tests, 0 fallos. Otras confirmaciones del INE
|
The INE questionnaire is also downloaded from the guest app through the REST API, so the validation messages reach end users: translate the new error messages, field labels and selections.
Traducciones al castellano de los mensajes nuevosEl cuestionario también se descarga desde la app a través de la API REST ( Nota para el revisor: el Sobre el lado de la app: propuesta de no tocar nadaEl flag
Es un estado transitorio que solo aparece si se marca una propiedad como apartamentos sin completar el informante, así que encaja mejor en el checklist de configuración que en el gate. |
Generating the file of every property with an INE category in the fleet and checking it against the schema published by the INE and its official content validations (XML_0..XML_17 of the web service documentation) surfaced three cases that build a file the INE rejects: - Properties whose phone has less than 9 digits: the schema requires between 9 and 13 characters in TELEFONO_1. - Periods without guest movements: the schema requires at least one RESIDENCIA under ALOJAMIENTO, so an empty block cannot be uploaded. - A client type reporting a rate with a zero percentage, or the other way around: the INE requires both to be consistent, on top of the percentages adding up to 100. The first two now raise a message explaining what to fix instead of building an invalid file, and the percentages are normalized keeping their consistency with the rates. The file must also carry the whole reference month even though the questionnaire asks for a single week (hotels) or fortnight (apartments), so a partial period is rejected up front.
Prueba de la flota completa contra las validaciones oficiales, sin gastar clavesEl INE nos ha dado claves ficticias de prueba, pero el código de control es de un solo uso (así lo dice la documentación del servicio web: "Sólo es válido para una vez, pues corresponde a un único cuestionario"). Antes de gastar ninguna, hemos hecho la comprobación en frío con datos reales:
Lo que ha salidoRechazos de esquema reales, hoy, en producción:
Los otros dos son ficheros que hoy se generan sin protestar y que el INE rechazaría, así que esta rama los convierte en un mensaje claro en lugar de un fichero inválido. Sobre los porcentajes, conviene matizar lo que decía el primer comentario: con el código actual la suma sale exactamente 100.00 en los 21 ficheros que se generan, así que el arreglo de 2024-2025 funciona. Lo de esta rama es endurecerlo (normalización en centésimas enteras, exacta por construcción) y añadir la coherencia entre tarifa y porcentaje por tipo de cliente, que es otra validación oficial (XML_15 y XML_16) y que la normalización podía romper al redondear un grupo pequeño a cero. Y una regla que no estábamos cumpliendo por diseño: el fichero debe llevar el mes completo aunque el cuestionario pida una sola semana (hoteles) o quincena (apartamentos). El asistente aceptaba cualquier rango, así que quien elegía la semana que le pedía la carta del INE se llevaba un fichero incompleto. Ahora se rechaza el periodo parcial indicando qué fechas seleccionar. Configuración pendiente en 8 propiedades (no es código): 3 con huéspedes españoles sin provincia, 2 con huéspedes sin país de residencia y 3 con las plazas del INE mal configuradas (una a cero). Hoy ya no pueden generar el fichero; queda como tarea de soporte. 31 tests, 0 fallos. |
The order number identifies the establishment in the INE questionnaire and is fixed, so it is stored in the property and prefilled in the INE wizard, where it can also be filled in for the first time. The control code is deliberately not stored: it belongs to a single questionnaire and is single use.
The establishment used to find out about a rejected file days later, on the INE portal, with a message naming an XML element. Two changes move that feedback to the moment the file is generated. The reference period is now expanded to the natural month of the start date instead of being rejected when it is not the whole month. A range reaching into the next month was the worst case: it repeats day numbers inside a place of residence, and the day is a key in the survey schema, so the INE answered with a duplicate key error that says nothing to a receptionist who only picked the wrong end date. The content validations the INE runs after the schema are now applied to the built file, and a failure names the day and the figures involved instead of the XML element. Checked against 97 files generated from two real fleets: the only two files reported are the two the INE would reject, both for overnight stays exceeding the seats declared in the property. The empty month error now points at the check-in data, which is where the survey is built from: several establishments with real occupancy and no completed check-ins would otherwise report an empty month.
Actualizacion 07/08: el fichero se valida antes de entregarloDario, resumen de lo que anade el commit Por queHoy ha entrado un ticket urgente de Beratxa (TR1365131) con dos fallos seguidos del INE en el mismo dia. El segundo es el interesante y ha cambiado una decision de diseno de la PR. El hotel selecciono del 1 de julio al 1 de agosto, que es la forma natural de "marcar julio" en un selector de rango. El fichero salio con el dia
El PMS le dejo pedir ese rango y no dijo nada. El hotel se entera por el portal del INE, con un mensaje que nombra un elemento XML. Que cambia1. El periodo se expande al mes natural de la fecha inicial. Antes esta rama daba error si el rango no era el mes completo; ahora lo normaliza y punto. Motivos: la app manda 2. Las validaciones de contenido del INE se aplican al fichero construido (
3. El error de mes vacio apunta a los check-ins. El informe se construye desde los check-ins, no desde las reservas. En la flota hay establecimientos con ocupacion real y cero check-ins completados que declararian un mes vacio (Route 42: 100 reservas y 193 noches vendidas en julio; Alda Borox: 18 reservas; y tres hoteles de Alda igual). Ahora el mensaje lo dice. Verificacion
Pendiente por mi parte en esta rama
Duda para ti, no la decido yo
|
The configuration checks move from the wizard to the property, as ine_configuration_problems(), and report every missing field at once instead of only the first one. Two computed fields expose the result, ine_ready and ine_blocking_reasons, so the interface can list what to fix instead of offering a download that fails. The seats check joins them: it used to live in the middle of the file generation, and it is the most frequent blocker in the fleet, where establishments have the seats unset while their rooms already offer capacity. Spanish translations for the new messages are included, since the app shows them to the end user through the API. The help texts are left to Weblate.
The INE settings page now lists what is missing before the occupancy survey can be built, instead of leaving the operator to find it out when the download fails.
Estado final de la rama y lo que queda fuera de ellaDario, con Lo que anaden estos dos commitsLas comprobaciones de configuracion pasan del asistente a la propiedad, como Dos campos calculados lo exponen: La comprobacion de plazas se une al checklist. Estaba en medio de Traducciones al espanol de los 17 mensajes nuevos, porque son los que ve el usuario final a traves de la API. Los 26 tests de Lo que NO entra en esta rama, a propositoEl gate de la app. Esto revierte la decision que registre el 05/08 de no tocar El envio por servicio web. IRIA no exige alta: la credencial es el par que viene impreso en la carta del cuestionario, Numero de Orden (11 car., fijo por establecimiento, ya lo guardamos) + Codigo de Control (8 car., de un solo uso, cambia cada cuestionario). Eso pide, como minimo:
Va en PR aparte. Tenemos 4 claves de prueba del INE sin gastar (2 EOH + 2 EOAP). Las subidas de validacion en el portal no consumen el codigo: solo lo consume el envio. El plan es gastar el envio del cartucho #1 de cada encuesta cuando el cliente del WS este escrito y probado contra un fichero ya validado, y dejar el #2 de cada una en recamara. Y la duda de siempre, que sigue siendo tuya
|
The INE counts as an extra bed every bed without a fixed character that is not among the declared places, cots included (survey methodology, 5.10), and it counts every guest who stays the night as a traveller, with no exception by age. The file, however, only reported the extra beds sold as a service, and hardly any establishment of the fleet has an extra bed product configured: a baby in a cot was counted as a traveller while the bed they slept in was not, and the survey was rejected as soon as the guests of a night exceeded the declared seats. Extra beds are now also derived from the guests registered in a room beyond the places it offers, and the larger of the two sources wins, so establishments that do sell the service keep reporting it. The declared seats are already required to be at least the capacity of the rooms reported to the INE, which makes the derived figure enough for the overnight stays to never exceed the seats plus the extra beds. Since a room whose capacity is set too low would then report an extra bed every single night, the wizard lists the nights it reported one.
Camas supletorias: añadido
|
The survey carries the country of residence in ID_PAIS, taken from the ISO 3166-1 alpha-3 code, but the INE publishes its own country list next to the survey schemas and it does not match ISO everywhere. Kosovo has no alpha-3 in ISO, so Odoo leaves it empty and the file came out with an empty ID_PAIS, rejected by the schema with nothing pointing at the guest who caused it. The INE codes it as KOS. The code of the country of residence now goes through the INE list, and a country left without one is reported by name instead of producing a file the establishment can only see rejected days later, on the portal. The exception lives in the code because the countries of the base module carry noupdate and a data row over them is silently ignored. The new ine_country_code field is there for whatever the INE changes later without waiting for a release. Checked against the whole fleet, 226 countries of residence in use over 50 databases: Kosovo is the only one missing a code, and Spain the only one outside the INE list, which is correct because Spanish residents travel in ID_PROVINCIA_ISLA.
Códigos de país: añadido
|
Países de Odoo sin code_alpha3 |
1 — Kosovo (XK) |
| Alpha-3 de Odoo que el INE no reconoce | 1 — ESP, y es correcto: los residentes en España viajan en ID_PROVINCIA_ISLA, no en ID_PAIS, por eso el INE no los lista |
| Códigos del INE sin país equivalente en Odoo | 1 — KOS, el mismo caso |
O sea que la correspondencia es 1 a 1 salvo Kosovo. No hay más agujeros hoy, ni entre los países usados ni entre los que podrían usarse mañana.
Cómo queda cubierto para el futuro
Dos capas, porque la lista del INE puede cambiar y la de Odoo también:
res.country.ine_get_country_code()resuelve en este orden: campoine_country_codede la ficha del país → tabla de excepciones del módulo →code_alpha3. Así, si el INE añade otro código propio, se arregla desde la ficha del país sin esperar a una release.- Y sobre todo: si un país se queda sin código, el asistente lo dice por su nombre en vez de emitir un
ID_PAISvacío. Antes el establecimiento se enteraba días después, en el portal del INE, con un error de esquema que no menciona ningún país. Ahora no llega a generarse el fichero y el mensaje nombra el país que falta.
Un detalle de implementación que merece explicación
La excepción está en el código y no en un fichero de datos a propósito: los países del módulo base llevan noupdate, así que una fila CSV sobre base.xk se ignora en silencio. Lo probé primero por ahí y el dato no llegaba a escribirse sin dar ningún error, que es justo el tipo de fallo que no queremos. El campo ine_country_code se queda para las excepciones futuras, que sí se pueden poner a mano.
Verificación
32 tests en verde. Tres nuevos: que un país normal se resuelve por su alpha-3, que Kosovo se resuelve como KOS pese a no tener alpha-3, y que un país sin ningún código se reporta con un error que lo nombra.
Con esto van cuatro motivos distintos de rechazo cubiertos en la rama, los cuatro salidos de tickets reales de este mes: provincia de residencia sin rellenar, periodo que no es el mes natural (por exceso y por defecto), camas supletorias sin declarar y códigos de país fuera de la lista del INE.
Contexto (resumen para revisión)
El INE apagó ARCE y la subida de cuestionarios XML pasó a IRIA. Un cliente de apartamentos no conseguía subir su fichero: el portal lo rechazaba en la línea 1 ("Cannot find the declaration of element 'ENCUESTA'"). El motivo es que su establecimiento tiene asignada la encuesta de apartamentos turísticos (EOAP), un cuestionario distinto del hotelero, que Roomdoo no generaba: le estábamos dando el guión de hoteles.
Con las claves IRIA que nos facilitó el cliente generamos su cuestionario EOAP de julio con el enfoque de esta PR y el INE lo aceptó y registró (acuse de recibo). Después consultamos al equipo de IRIA del INE por correo y nos han confirmado por escrito los criterios que aplica esta rama (detalle en los comentarios de la PR).
Qué hace esta PR
1. Nueva encuesta de apartamentos turísticos (EOAP)
survey_typeenpms.ine.tourism.type.category(+ semilla de las categorías de apartamentos, 0–4 llaves). El wizard elige el guión según la categoría INE de la propiedad: sin configuración extra ni campos nuevos que decidir.pms.room(estudio / 2-4 pax / 4-6 pax / otros), con inferencia por capacidad si no se establece.pms.property(bloqueINFORMANTE, obligatorio en EOAP).CABECERAreducida,CABECERA_APARTAMENTOS(llaves),INFORMANTE,ALOJAMIENTO(bloque compartido con la encuesta hotelera, refactorizado a helper común),CAPACIDADyOCUPACIONpor tipología,PRECIOSpor tipología yPERSONAL_OCUPADO.PCTN_TARIFA_NORMAL= 100). Cumple las validaciones de contenido del INE y está aceptada en un envío real.2. Correcciones en la encuesta hotelera (EOH)
Sin cambiar el formato que los establecimientos ya suben con éxito:
res.country.state.ine_tourism_province_name, con semilla para las 52 provincias tomada del anexo oficial): la cabecera espera el literal de la especificación (máx. 25 caracteres) y varios nombres de provincia de Odoo lo superan, por ejemplo "Illes Balears (Islas Baleares)" (30) → "BALEARES".DIAS_ABIERTO_MES_REFERENCIAcon dos dígitos yURLomitida cuando la propiedad no tiene web.3. Espacio de nombres: configurable, sin cambiar el comportamiento actual
Existen dos variantes de cada esquema: la que publica el INE, sin espacio de nombres, y la que la aplicación de IRIA genera para el cuestionario, con espacio de nombres. El INE nos ha confirmado que la de referencia es la publicada y que a la generada por la aplicación "no debería hacérsele caso".
Los ficheros se generan por tanto según el esquema publicado, es decir igual que hasta ahora, y el espacio de nombres puede activarse por encuesta con un parámetro de configuración (
pms_l10n_es.ine_xml_namespace_hotel/_apartments) para el cuestionario que exija la variante cualificada. Así el fichero hotelero queda idéntico al que la flota sube correctamente, y conservamos la vía rápida si algún cuestionario pide la otra variante.4. Tests (27 en total, 9 nuevos)
tests/fixtures/).Notas de despliegue
-u pms_l10n_es(campos nuevos y datos CSV).Fuera del alcance, ya resuelto
iriaEngine/v2_0_0/SolicitudEncuestaWS) y el INE confirma que no hace falta alta previa, que las claves del cuestionario son el permiso. Sería una fase posterior: presentar el cuestionario desde el propio PMS en lugar de descargar el fichero.