diff --git a/pms/models/pms_checkin_partner.py b/pms/models/pms_checkin_partner.py index 0f945912c..d20d299b3 100644 --- a/pms/models/pms_checkin_partner.py +++ b/pms/models/pms_checkin_partner.py @@ -712,9 +712,6 @@ class PmsCheckinPartner(models.Model): lambda c: c.state == "dummy" ) if len(reservation.checkin_partner_ids) < reservation.adults: - if vals.get("identifier", _("New")) == _("New") or "identifier" not in vals: - pms_property = reservation.pms_property_id - vals["identifier"] = pms_property.checkin_sequence_id._next_do() return super(PmsCheckinPartner, self).create(vals) if len(dummy_checkins) > 0: dummy_checkins[0].write(vals) @@ -844,6 +841,7 @@ class PmsCheckinPartner(models.Model): } record.update(vals) record.reservation_id.state = "onboard" + record.identifier = record.pms_property_id.checkin_sequence_id._next_do() def action_done(self): for record in self.filtered(lambda c: c.state == "onboard"): diff --git a/pms_l10n_es/__manifest__.py b/pms_l10n_es/__manifest__.py index d3daeda9a..ca968f52f 100644 --- a/pms_l10n_es/__manifest__.py +++ b/pms_l10n_es/__manifest__.py @@ -33,6 +33,7 @@ "data/pms_data.xml", "data/queue_data.xml", "data/queue_job_function_data.xml", + "data/pms_traveler_report_notification_email_template.xml", "security/ir.model.access.csv", "views/pms_property_views.xml", "views/pms_room_views.xml", diff --git a/pms_l10n_es/data/cron_jobs.xml b/pms_l10n_es/data/cron_jobs.xml index 1da4809b1..1a7bf2009 100644 --- a/pms_l10n_es/data/cron_jobs.xml +++ b/pms_l10n_es/data/cron_jobs.xml @@ -1,21 +1,23 @@ - - Automatic Send Traveller Report - - 1 - - days - -1 - - code - - + Automatic Send Traveller Report + + 1 + + days + -1 + + code + + - model.send_file_institution_async() - + model.send_file_institution_async() + + diff --git a/pms_l10n_es/data/pms_traveler_report_notification_email_template.xml b/pms_l10n_es/data/pms_traveler_report_notification_email_template.xml new file mode 100644 index 000000000..661a1ba2b --- /dev/null +++ b/pms_l10n_es/data/pms_traveler_report_notification_email_template.xml @@ -0,0 +1,54 @@ + + + + + Travel Report Send + + Error: ${object.pms_property_id.name}, ${object.target_date} Error sending the Traveler report + ${object.pms_property_id.company_id.partner_id.email | safe} + ${object.pms_property_id.partner_id.email | safe} + + + There was an error sending the traveler report + + + + + + + + Travel Report Send + + Succes: ${object.pms_property_id.name}, ${object.target_date} Traveler report sent successfully + ${object.pms_property_id.company_id.partner_id.email | safe} + ${object.pms_property_id.partner_id.email | safe} + + + Traveler report sent successfully + + + + + + diff --git a/pms_l10n_es/models/pms_checkin_partner.py b/pms_l10n_es/models/pms_checkin_partner.py index 7086da9cf..0119f7faa 100644 --- a/pms_l10n_es/models/pms_checkin_partner.py +++ b/pms_l10n_es/models/pms_checkin_partner.py @@ -7,7 +7,7 @@ CODE_SPAIN = "ES" _logger = logging.getLogger(__name__) -class PmsCheckinParnert(models.Model): +class PmsCheckinPartner(models.Model): _inherit = "pms.checkin.partner" support_number = fields.Char( @@ -35,7 +35,7 @@ class PmsCheckinParnert(models.Model): @api.model def _checkin_mandatory_fields(self, country=False, depends=False): - mandatory_fields = super(PmsCheckinParnert, self)._checkin_mandatory_fields( + mandatory_fields = super(PmsCheckinPartner, self)._checkin_mandatory_fields( depends ) mandatory_fields.extend( @@ -60,6 +60,6 @@ class PmsCheckinParnert(models.Model): @api.model def _checkin_manual_fields(self, country=False, depends=False): - manual_fields = super(PmsCheckinParnert, self)._checkin_manual_fields(depends) + manual_fields = super(PmsCheckinPartner, self)._checkin_manual_fields(depends) manual_fields.extend(["support_number"]) return manual_fields diff --git a/pms_l10n_es/wizards/traveller_report.py b/pms_l10n_es/wizards/traveller_report.py index 6a1468620..895cc43aa 100644 --- a/pms_l10n_es/wizards/traveller_report.py +++ b/pms_l10n_es/wizards/traveller_report.py @@ -2,17 +2,21 @@ import base64 import datetime import io import json +import logging import re import time import PyPDF2 import requests from bs4 import BeautifulSoup as bs +from dateutil.relativedelta import relativedelta from odoo import _, api, fields, models from odoo.exceptions import MissingError, ValidationError from odoo.modules.module import get_module_resource +_logger = logging.getLogger(__name__) + class TravellerReport(models.TransientModel): _name = "traveller.report.wizard" @@ -48,448 +52,529 @@ class TravellerReport(models.TransientModel): # build content content = self.generate_checkin_list( - property_id=pms_property.id, + pms_property_id=pms_property.id, date_target=self.date_target, ) if content: - txt_binary = self.env["traveller.report.wizard"].create( - { - "txt_filename": pms_property.institution_property_id + ".999", - "txt_binary": base64.b64encode(str.encode(content)), - "txt_message": content, - } - ) - return { - "name": _("Traveller Report"), - "res_id": txt_binary.id, - "res_model": "traveller.report.wizard", - "target": "new", - "type": "ir.actions.act_window", - "view_id": self.env.ref("pms_l10n_es.traveller_report_wizard").id, - "view_mode": "form", - "view_type": "form", - } + self.txt_filename = pms_property.institution_property_id + ".999" + self.txt_binary = base64.b64encode(str.encode(content)) + self.txt_message = content - def generate_checkin_list(self, property_id, date_target=False): + return { + "name": _("Traveller Report"), + "res_id": self.id, + "res_model": "traveller.report.wizard", + "target": "new", + "type": "ir.actions.act_window", + "view_id": self.env.ref("pms_l10n_es.traveller_report_wizard").id, + "view_mode": "form", + } + + def generate_checkin_list( + self, pms_property_id, date_target=False, checkin_ids=False + ): regex = re.compile("[^a-zA-Z0-9]") - if not date_target: - date_target = fields.date.today() + # check if there's guests info pending to send - if self.env["pms.checkin.partner"].search_count( - [ + if not checkin_ids: + if not date_target: + date_target = fields.date.today() + domain = [ ("state", "in", ["onboard", "done"]), ("arrival", ">=", str(date_target) + " 0:00:00"), - ("pms_property_id", "=", property_id), + ("arrival", "<=", str(date_target) + " 23:59:59"), + ("pms_property_id", "=", pms_property_id), ] - ): - pms_property = ( - self.env["pms.property"] - .with_context(lang="es_ES") - .search([("id", "=", property_id)]) - ) - # get checkin partners info to send - lines = self.env["pms.checkin.partner"].search( - [ - ("state", "in", ["onboard", "done"]), - ("arrival", ">=", str(date_target) + " 0:00:00"), - ("arrival", "<=", str(date_target) + " 23:59:59"), - ("pms_property_id", "=", property_id), - ] - ) - # build the property info record - # 1 | property id | property name | date | nº of checkin partners - content = ( - "1|" - + pms_property.institution_property_id.upper() - + "|" - + regex.sub(" ", pms_property.name.upper()) - + "|" - + datetime.datetime.now().strftime("%Y%m%d|%H%M") - + "|" - + str(len(lines)) - + "\n" - ) - # build each checkin partner line's record - # 2|DNI nº|Doc.number|doc.type|exp.date|lastname|lastname2|name|... - # ...gender|birthdate|nation.|checkin - lines = lines.with_context(lang="es_ES") - for line in lines: - content += "2" - # [P|N|..] - if line.document_type.code not in ["D", "C"]: - content += "||" + regex.sub("", line.document_number.upper()) + "|" - else: - content += "|" + regex.sub("", line.document_number.upper()) + "||" - content += line.document_type.code + "|" - content += line.document_expedition_date.strftime("%Y%m%d") + "|" - content += regex.sub(" ", line.lastname.upper()) + "|" - if line.lastname2: - content += regex.sub(" ", line.lastname2.upper()) - content += "|" + regex.sub(" ", line.firstname.upper()) + "|" - if line.gender == "female": - content += "F|" - else: - content += "M|" - content += line.birthdate_date.strftime("%Y%m%d") + "|" - content += line.nationality_id.name.upper() + "|" - content += line.arrival.strftime("%Y%m%d") + "\n" + else: + domain = [ + ("id", "in", checkin_ids), + ] + pms_property = ( + self.env["pms.property"] + .with_context(lang="es_ES") + .search([("id", "=", pms_property_id)]) + ) + # get checkin partners info to send + lines = self.env["pms.checkin.partner"].search(domain) + # build the property info record + # 1 | property id | property name | date | nº of checkin partners + content = ( + "1|" + + pms_property.institution_property_id.upper() + + "|" + + regex.sub(" ", pms_property.name.upper()) + + "|" + + datetime.datetime.now().strftime("%Y%m%d|%H%M") + + "|" + + str(len(lines)) + + "\n" + ) + # build each checkin partner line's record + # 2|DNI nº|Doc.number|doc.type|exp.date|lastname|lastname2|name|... + # ...gender|birthdate|nation.|checkin + lines = lines.with_context(lang="es_ES") + for line in lines: + content += "2" + # [P|N|..] + if line.document_type.code not in ["D", "C"]: + content += "||" + regex.sub("", line.document_number.upper()) + "|" + else: + content += "|" + regex.sub("", line.document_number.upper()) + "||" + content += line.document_type.code + "|" + content += line.document_expedition_date.strftime("%Y%m%d") + "|" + content += regex.sub(" ", line.lastname.upper()) + "|" + if line.lastname2: + content += regex.sub(" ", line.lastname2.upper()) + content += "|" + regex.sub(" ", line.firstname.upper()) + "|" + if line.gender == "female": + content += "F|" + else: + content += "M|" + content += line.birthdate_date.strftime("%Y%m%d") + "|" + content += line.nationality_id.name.upper() + "|" + content += line.arrival.strftime("%Y%m%d") + "\n" - return content + return content def send_file_gc(self, file_content, called_from_user, pms_property): - url = "https://hospederias.guardiacivil.es/" - login_route = "/hospederias/login.do" - upload_file_route = "/hospederias/cargaFichero.do" - logout_route = "/hospederias/logout.do" - target_date = self.date_target or fields.date.today() - if file_content: + try: + _logger.info( + "Sending file to Guardia Civil, Property %s, date: %s" + % (pms_property.name, self.date_target) + ) + url = "https://hospederias.guardiacivil.es/" + login_route = "/hospederias/login.do" + upload_file_route = "/hospederias/cargaFichero.do" + logout_route = "/hospederias/logout.do" + target_date = self.date_target or fields.date.today() + if file_content: + headers = { + "User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 " + "Build/MRA58N) AppleWebKit/537.36 (KHTML, like " + "Gecko) Chrome/90.0.4430.93 Mobile Safari/537.36", + } + session = requests.session() + login_payload = { + "usuario": pms_property.institution_user, + "pswd": pms_property.institution_password, + } + response_login = session.post( + url + login_route, + headers=headers, + data=login_payload, + verify=get_module_resource("pms_l10n_es", "static", "cert.pem"), + ) + time.sleep(0.4) + + # check if authentication was successful / unsuccessful or the + # resource cannot be accessed + soup = bs(response_login.text, "html.parser") + errors_login = soup.select("#txterror > ul > li") + if errors_login: + raise ValidationError(errors_login[0].text) + else: + login_correct = soup.select(".cabecera2") + if not login_correct: + session.close() + raise ValidationError(_("Connection could not be established")) + + # build the file to send + files = { + "fichero": (pms_property.institution_user + ".999", file_content) + } + + # send file + response_file_sent = session.post( + url + upload_file_route, + data={"autoSeq": "on"}, + files=files, + verify=get_module_resource("pms_l10n_es", "static", "cert.pem"), + ) + time.sleep(0.4) + + # logout & close connection + session.get( + url + logout_route, + headers=headers, + verify=get_module_resource("pms_l10n_es", "static", "cert.pem"), + ) + session.close() + + # check if the file send has been correct + soup = bs(response_file_sent.text, "html.parser") + errors = soup.select("#errores > tbody > tr") + if errors: + msg = "Errores en el fichero:\n" + for e in errors: + msg += "Error en línea " + e.select("a")[0].text + ": " + msg += e.select("a")[2].text + "\n" + return self.env["pms.log.institution.traveller.report"].create( + { + "error_sending_data": True, + "pms_property_id": pms_property.id, + "target_date": target_date, + "txt_message": _("Error in file sended"), + "txt_incidencies_from_institution": msg, + } + ) + else: + return self.env["pms.log.institution.traveller.report"].create( + { + "error_sending_data": False, + "pms_property_id": pms_property.id, + "target_date": target_date, + "txt_message": _("Successful file sending"), + } + ) + except Exception as e: + return self.env["pms.log.institution.traveller.report"].create( + { + "error_sending_data": True, + "pms_property_id": pms_property.id, + "target_date": target_date, + "txt_message": str(e), + } + ) + + def send_file_pn(self, file_content, called_from_user, pms_property): + try: + base_url = "https://webpol.policia.es" headers = { "User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 " "Build/MRA58N) AppleWebKit/537.36 (KHTML, like " "Gecko) Chrome/90.0.4430.93 Mobile Safari/537.36", } - session = requests.session() - login_payload = { - "usuario": pms_property.institution_user, - "pswd": pms_property.institution_password, - } - response_login = session.post( - url + login_route, - headers=headers, - data=login_payload, - verify=get_module_resource("pms_l10n_es", "static", "cert.pem"), + pre_login_route = "/e-hotel/login" + login_route = "/e-hotel/execute_login" + next_file_name_route = "/e-hotel/hospederia/ficheros/vista/envioFicheros" + upload_file_route = "/e-hotel/hospederia/ficheros/subirFichero" + pre_get_list_files_sent_route = ( + "/e-hotel/hospederia/vista/seguimientoHospederia" ) - time.sleep(0.1) + files_sent_list_route = "/e-hotel/hospederia/listar/ficherosHospederia" + last_file_errors_route = ( + "/e-hotel/hospederia/report/erroresFicheroHospederia" + ) + logout_route = "/e-hotel/execute_logout" + target_date = self.date_target or fields.date.today() + session = requests.session() + # retrieve token + response_pre_login = session.post( + base_url + pre_login_route, + headers=headers, + verify=False, + ) + time.sleep(0.3) + token = bs(response_pre_login.text, "html.parser").select( + "input[name='_csrf']" + )[0]["value"] - # check if authentication was successful / unsuccessful or the - # resource cannot be accessed - soup = bs(response_login.text, "html.parser") - errors_login = soup.select("#txterror > ul > li") - if errors_login: - raise ValidationError(errors_login[0].text) - else: - login_correct = soup.select(".cabecera2") - if not login_correct: - session.close() - raise ValidationError(_("Connection could not be established")) + if not token: + raise MissingError(_("Could not get token login.")) - # build the file to send - files = {"fichero": (pms_property.institution_user + ".999", file_content)} + # do login + session.post( + base_url + login_route, + headers=headers, + data={ + "username": pms_property.institution_user, + "password": pms_property.institution_password, + "_csrf": token, + }, + verify=False, + ) + time.sleep(0.3) + headers["x-csrf-token"] = token + # retrieve file name to send + response_name_file_route = session.post( + base_url + next_file_name_route, + headers=headers, + verify=False, + ) + time.sleep(0.2) + soup = bs(response_name_file_route.text, "html.parser") + file_name = soup.select("#msjNombreFichero > b > u")[0].text + + if not file_name: + raise MissingError(_("Could not get next file name to send.")) # send file - response_file_sent = session.post( - url + upload_file_route, - data={"autoSeq": "on"}, - files=files, - verify=get_module_resource("pms_l10n_es", "static", "cert.pem"), - ) - time.sleep(0.1) - - # logout & close connection - session.get( - url + logout_route, + upload_result = session.post( + base_url + upload_file_route, headers=headers, - verify=get_module_resource("pms_l10n_es", "static", "cert.pem"), + verify=False, + data={ + "jsonHiddenComunes": "", + "ficheroJ": "", + "_csrf": token, + }, + files={"fichero": (file_name, file_content)}, + ) + + if upload_result.status_code != 200: + raise MissingError(_("Could not upload file.")) + + time.sleep(0.2) + + # retrieve property data + response_pre_files_sent_list_route = session.post( + base_url + pre_get_list_files_sent_route, + headers=headers, + verify=False, + data={ + "jsonHiddenComunes": "", + "ficheroJ": "", + "_csrf": token, + }, + ) + if response_pre_files_sent_list_route.status_code != 200: + raise MissingError(_("Could not get property_info.")) + + time.sleep(0.2) + + soup = bs(response_pre_files_sent_list_route.text, "html.parser") + property_specific_data = { + "codigoHospederia": soup.select("#codigoHospederia")[0]["value"], + "nombreHospederia": soup.select("#nombreHospederia")[0]["value"], + "direccionCompleta": soup.select("#direccionCompleta")[0]["value"], + "telefono": soup.select("#telefono")[0]["value"], + "tieneAgrup": soup.select("#tieneAgrup")[0]["value"], + } + common_file_data = { + "jsonHiddenComunes": "", + "fechaDesde": ( + datetime.date.today() + datetime.timedelta(days=-1) + ).strftime("%d/%m/%Y"), + "fechaHasta": datetime.date.today().strftime("%d/%m/%Y"), + "_csrf": token, + "_search": False, + "nd": str(int(time.time() * 1000)), + "rows": 10, + "page": 1, + "sidx": "", + "sord": "dat_fich.fecha_alta desc", + } + # retrieve list of sent files + file_data = dict() + for _attempt in range(1, 10): + response_files_sent_list_route = session.post( + base_url + files_sent_list_route, + headers=headers, + verify=False, + data={ + **property_specific_data, + **common_file_data, + "primeraConsulta": True, + }, + ) + file_list = json.loads( + str(bs(response_files_sent_list_route.text, "html.parser")) + )["rows"] + + file_data = list( + filter(lambda x: x["nombreFichero"] == file_name, file_list) + ) + if file_data: + file_data = file_data[0] + break + else: + time.sleep(1) + + if not file_data: + raise ValidationError(_("Could not get last file sent")) + else: + response_last_file_errors_route = session.post( + base_url + last_file_errors_route, + headers=headers, + verify=False, + data={ + "idFichero": file_data["idFichero"], + "numErroresHuespedes": file_data["numErroresHuespedes"], + "numAvisosHuespedes": file_data["numAvisosHuespedes"], + "nombreFichero": file_data["nombreFichero"], + "fechaAlta": file_data["fechaAlta"], + "envioDesdeAgrupacion": file_data["envioDesdeAgrupacion"], + "envioDesdeAgrupacionImg": "", + "estadoProceso": file_data["estadoProceso"], + "numTotalErrores": file_data["numTotalErrores"], + "numTotalAvisos": file_data["numTotalAvisos"], + "separadorTabla": "", + "numHuespedesInformados": file_data["numHuespedesInformados"], + "numHuespedes": file_data["numHuespedes"], + "primeraConsulta": False, + **property_specific_data, + **common_file_data, + "datosServidor": False, + }, + ) + + if response_last_file_errors_route.status_code != 200: + raise ValidationError(_("Could last files sent")) + + time.sleep(0.4) + soup = bs(response_last_file_errors_route.text, "html.parser") + # get file sent pdf report + response_last_file_errors_route = session.get( + base_url + soup.select("#iframePdf")[0].attrs["src"], + headers=headers, + verify=False, + ) + + if response_last_file_errors_route.status_code != 200: + raise ValidationError(_("Could last files sent")) + + time.sleep(0.4) + pdfReader = PyPDF2.PdfFileReader( + io.BytesIO(response_last_file_errors_route.content) + ) + + if ( + pdfReader.getPage(0) + .extractText() + .find("ERRORES Y AVISOS HUESPEDES") + == -1 + ): + message = _("Successful file sending") + error = False + log = self.env["pms.log.institution.traveller.report"].create( + { + "error_sending_data": False, + "pms_property_id": pms_property.id, + "target_date": target_date, + "txt_message": _("Successful file sending"), + } + ) + else: + message = _("Errors (check the pdf file).") + error = True + log = self.env["pms.log.institution.traveller.report"].create( + { + "error_sending_data": error, + "txt_message": message, + "pms_property_id": pms_property.id, + "target_date": target_date, + "file_incidencies_from_institution": base64.b64encode( + response_last_file_errors_route.content + ), + "txt_filename": file_name + ".pdf", + } + ) + # do logout + session.post( + base_url + logout_route, + headers=headers, + verify=False, + data={"_csrf": token}, ) session.close() - - # check if the file send has been correct - soup = bs(response_file_sent.text, "html.parser") - errors = soup.select("#errores > tbody > tr") - if errors: - msg = "Errores en el fichero:\n" - for e in errors: - msg += "Error en línea " + e.select("a")[0].text + ": " - msg += e.select("a")[2].text + "\n" - self.env["pms.log.institution.traveller.report"].create( - { - "error_sending_data": True, - "txt_incidencies_from_institution": msg, - "pms_property_id": pms_property.id, - "target_date": target_date, - } - ) - raise ValidationError(msg) - else: - self.env["pms.log.institution.traveller.report"].create( - { - "error_sending_data": False, - "txt_message": _("Successful file sending"), - } - ) - if called_from_user: - message = { - "type": "ir.actions.client", - "tag": "display_notification", - "params": { - "title": _("Sent succesfully!"), - "message": _("Successful file sending"), - "sticky": False, - }, - "pms_property_id": pms_property.id, - "target_date": target_date, - } - return message - - def send_file_pn(self, file_content, called_from_user, pms_property): - base_url = "https://webpol.policia.es" - headers = { - "User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 " - "Build/MRA58N) AppleWebKit/537.36 (KHTML, like " - "Gecko) Chrome/90.0.4430.93 Mobile Safari/537.36", - } - pre_login_route = "/e-hotel/login" - login_route = "/e-hotel/execute_login" - next_file_name_route = "/e-hotel/hospederia/ficheros/vista/envioFicheros" - upload_file_route = "/e-hotel/hospederia/ficheros/subirFichero" - pre_get_list_files_sent_route = ( - "/e-hotel/hospederia/vista/seguimientoHospederia" - ) - files_sent_list_route = "/e-hotel/hospederia/listar/ficherosHospederia" - last_file_errors_route = "/e-hotel/hospederia/report/erroresFicheroHospederia" - logout_route = "/e-hotel/execute_logout" - target_date = self.date_target or fields.date.today() - session = requests.session() - - # retrieve token - response_pre_login = session.post( - base_url + pre_login_route, - headers=headers, - verify=False, - ) - time.sleep(0.1) - token = bs(response_pre_login.text, "html.parser").select( - "input[name='_csrf']" - )[0]["value"] - - if not token: - raise MissingError(_("Could not get token login.")) - - # do login - session.post( - base_url + login_route, - headers=headers, - data={ - "username": pms_property.institution_user, - "password": pms_property.institution_password, - "_csrf": token, - }, - verify=False, - ) - time.sleep(0.1) - headers["x-csrf-token"] = token - # retrieve file name to send - response_name_file_route = session.post( - base_url + next_file_name_route, - headers=headers, - verify=False, - ) - time.sleep(0.1) - soup = bs(response_name_file_route.text, "html.parser") - file_name = soup.select("#msjNombreFichero > b > u")[0].text - - if not file_name: - raise MissingError(_("Could not get next file name to send.")) - - # send file - upload_result = session.post( - base_url + upload_file_route, - headers=headers, - verify=False, - data={ - "jsonHiddenComunes": "", - "ficheroJ": "", - "_csrf": token, - }, - files={"fichero": (file_name, file_content)}, - ) - - if upload_result.status_code != 200: - raise MissingError(_("Could not upload file.")) - - time.sleep(0.1) - - # retrieve property data - response_pre_files_sent_list_route = session.post( - base_url + pre_get_list_files_sent_route, - headers=headers, - verify=False, - data={ - "jsonHiddenComunes": "", - "ficheroJ": "", - "_csrf": token, - }, - ) - if response_pre_files_sent_list_route.status_code != 200: - raise MissingError(_("Could not get property_info.")) - - time.sleep(0.1) - - soup = bs(response_pre_files_sent_list_route.text, "html.parser") - property_specific_data = { - "codigoHospederia": soup.select("#codigoHospederia")[0]["value"], - "nombreHospederia": soup.select("#nombreHospederia")[0]["value"], - "direccionCompleta": soup.select("#direccionCompleta")[0]["value"], - "telefono": soup.select("#telefono")[0]["value"], - "tieneAgrup": soup.select("#tieneAgrup")[0]["value"], - } - common_file_data = { - "jsonHiddenComunes": "", - "fechaDesde": ( - datetime.date.today() + datetime.timedelta(days=-1) - ).strftime("%d/%m/%Y"), - "fechaHasta": datetime.date.today().strftime("%d/%m/%Y"), - "_csrf": token, - "_search": False, - "nd": str(int(time.time() * 1000)), - "rows": 10, - "page": 1, - "sidx": "", - "sord": "dat_fich.fecha_alta desc", - } - # retrieve list of sent files - file_data = dict() - for _attempt in range(1, 10): - response_files_sent_list_route = session.post( - base_url + files_sent_list_route, - headers=headers, - verify=False, - data={ - **property_specific_data, - **common_file_data, - "primeraConsulta": True, - }, - ) - file_list = json.loads( - str(bs(response_files_sent_list_route.text, "html.parser")) - )["rows"] - - file_data = list( - filter(lambda x: x["nombreFichero"] == file_name, file_list) - ) - if file_data: - file_data = file_data[0] - break - else: - time.sleep(1) - - if not file_data: - raise ValidationError(_("Could not get last file sent")) - else: - response_last_file_errors_route = session.post( - base_url + last_file_errors_route, - headers=headers, - verify=False, - data={ - "idFichero": file_data["idFichero"], - "numErroresHuespedes": file_data["numErroresHuespedes"], - "numAvisosHuespedes": file_data["numAvisosHuespedes"], - "nombreFichero": file_data["nombreFichero"], - "fechaAlta": file_data["fechaAlta"], - "envioDesdeAgrupacion": file_data["envioDesdeAgrupacion"], - "envioDesdeAgrupacionImg": "", - "estadoProceso": file_data["estadoProceso"], - "numTotalErrores": file_data["numTotalErrores"], - "numTotalAvisos": file_data["numTotalAvisos"], - "separadorTabla": "", - "numHuespedesInformados": file_data["numHuespedesInformados"], - "numHuespedes": file_data["numHuespedes"], - "primeraConsulta": False, - **property_specific_data, - **common_file_data, - "datosServidor": False, - }, - ) - - if response_last_file_errors_route.status_code != 200: - raise ValidationError(_("Could last files sent")) - - time.sleep(0.1) - soup = bs(response_last_file_errors_route.text, "html.parser") - # get file sent pdf report - response_last_file_errors_route = session.get( - base_url + soup.select("#iframePdf")[0].attrs["src"], - headers=headers, - verify=False, - ) - - if response_last_file_errors_route.status_code != 200: - raise ValidationError(_("Could last files sent")) - - time.sleep(0.1) - pdfReader = PyPDF2.PdfFileReader( - io.BytesIO(response_last_file_errors_route.content) - ) - - if ( - pdfReader.getPage(0).extractText().find("ERRORES Y AVISOS HUESPEDES") - == -1 - ): - message = _("Successful file sending") - error = False - else: - message = _("Errors (check the pdf file).") - error = True - - self.env["pms.log.institution.traveller.report"].create( + return log + except Exception as e: + return self.env["pms.log.institution.traveller.report"].create( { - "error_sending_data": error, - "txt_incidencies_from_institution": message, - "file_incidencies_from_institution": base64.b64encode( - response_last_file_errors_route.content - ), - "txt_filename": file_name + ".pdf", + "error_sending_data": True, + "txt_message": str(e), "pms_property_id": pms_property.id, "target_date": target_date, } ) - # do logout - session.post( - base_url + logout_route, - headers=headers, - verify=False, - data={"_csrf": token}, - ) - - session.close() - if called_from_user: - message = { - "type": "ir.actions.client", - "tag": "display_notification", - "params": { - "title": _("Sent succesfully!"), - "message": _("Successful file sending"), - "sticky": False, - }, - } - return message - - def send_file_institution(self, pms_property=False): - called_from_user = False - if not pms_property: - called_from_user = True - pms_property = self.env["pms.property"].search( - [("id", "=", self.pms_property_id.id)] + def send_file_institution( + self, pms_property=False, checkin_ids=False, offset=0, date_target=False + ): + try: + called_from_user = False + if not pms_property: + called_from_user = True + pms_property = self.env["pms.property"].search( + [("id", "=", self.pms_property_id.id)] + ) + if ( + not pms_property + or not pms_property.institution_property_id + or not pms_property.institution_user + or not pms_property.institution_password + ): + raise ValidationError( + _("The guest information sending settings is not complete.") + ) + if not date_target: + date_target = fields.Date.today() + date_target = date_target - relativedelta(days=offset) + file_content = self.generate_checkin_list( + pms_property_id=pms_property.id, + date_target=date_target, + checkin_ids=checkin_ids, ) - if ( - not pms_property - or not pms_property.institution_property_id - or not pms_property.institution_user - or not pms_property.institution_password - ): - raise ValidationError( - _("The guest information sending settings is not complete.") + if pms_property.institution == "policia_nacional": + log = self.send_file_pn(file_content, called_from_user, pms_property) + elif pms_property.institution == "guardia_civil": + log = self.send_file_gc(file_content, called_from_user, pms_property) + if log.error_sending_data: + _logger.warning( + """ + Error sending file, Property %s, date: %s, message: %s + """ + % (pms_property.name, self.date_target, log.txt_message) + ) + raise ValidationError(log.txt_incidencies_from_institution) + _logger.info( + """ + Successful file sending, sending confirmation mail, + Property %s, date: %s" % (pms_property.name, self.date_target) + """ ) - file_content = self.generate_checkin_list(pms_property.id) - if pms_property.institution == "policia_nacional": - return self.send_file_pn(file_content, called_from_user, pms_property) - elif pms_property.institution == "guardia_civil": - return self.send_file_gc(file_content, called_from_user, pms_property) + if called_from_user: + message = { + "type": "ir.actions.client", + "tag": "display_notification", + "params": { + "title": _("Sent succesfully!"), + "message": _("Successful file sending"), + "sticky": False, + }, + } + return message + else: + template = self.env.ref( + "pms_l10n_es.notification_send_success_travel_report_email" + ) + template.send_mail(log.id, force_send=True) + except Exception as e: + _logger.warning( + """ + Error sending file, Property %s, date: %s, message: %s + """ + % (pms_property.name, self.date_target, str(e)) + ) + if called_from_user: + message = { + "type": "ir.actions.client", + "tag": "display_notification", + "params": { + "title": _("Error!"), + "message": _("Error sending file: %s" % e), + "sticky": False, + }, + } + return message + else: + log = self.env["pms.log.institution.traveller.report"].create( + { + "error_sending_data": True, + "txt_incidencies_from_institution": str(e), + "pms_property_id": pms_property.id, + "target_date": date_target, + } + ) + template = self.env.ref( + "pms_l10n_es.notification_send_error_travel_report_email" + ) + template.send_mail(log.id, force_send=True) @api.model - def send_file_institution_async(self): + def send_file_institution_async(self, offset=0): for prop in self.env["pms.property"].search([]): if prop.institution: - self.with_delay().send_file_institution(prop) + self.send_file_institution(prop, offset) + time.sleep(0.5)