[IMP]pms_l10n_es: Traveller report flow

This commit is contained in:
Darío Lodeiros
2022-12-15 20:07:32 +01:00
parent e9d4bd784e
commit bc21bba4dd
6 changed files with 566 additions and 426 deletions

View File

@@ -712,9 +712,6 @@ class PmsCheckinPartner(models.Model):
lambda c: c.state == "dummy" lambda c: c.state == "dummy"
) )
if len(reservation.checkin_partner_ids) < reservation.adults: 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) return super(PmsCheckinPartner, self).create(vals)
if len(dummy_checkins) > 0: if len(dummy_checkins) > 0:
dummy_checkins[0].write(vals) dummy_checkins[0].write(vals)
@@ -844,6 +841,7 @@ class PmsCheckinPartner(models.Model):
} }
record.update(vals) record.update(vals)
record.reservation_id.state = "onboard" record.reservation_id.state = "onboard"
record.identifier = record.pms_property_id.checkin_sequence_id._next_do()
def action_done(self): def action_done(self):
for record in self.filtered(lambda c: c.state == "onboard"): for record in self.filtered(lambda c: c.state == "onboard"):

View File

@@ -33,6 +33,7 @@
"data/pms_data.xml", "data/pms_data.xml",
"data/queue_data.xml", "data/queue_data.xml",
"data/queue_job_function_data.xml", "data/queue_job_function_data.xml",
"data/pms_traveler_report_notification_email_template.xml",
"security/ir.model.access.csv", "security/ir.model.access.csv",
"views/pms_property_views.xml", "views/pms_property_views.xml",
"views/pms_room_views.xml", "views/pms_room_views.xml",

View File

@@ -1,21 +1,23 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<odoo> <odoo>
<data noupdate="1"> <data noupdate="1">
<record model="ir.cron" id="autosend_traveller_report">
<field name="name">Automatic Send Traveller Report</field> <record model="ir.cron" id="autosend_traveller_report">
<field name="active" eval="False" /> <field name="name">Automatic Send Traveller Report</field>
<field name="interval_number">1</field> <field name="active" eval="False" />
<field name="user_id" ref="base.user_root" /> <field name="interval_number">1</field>
<field name="interval_type">days</field> <field name="user_id" ref="base.user_root" />
<field name="numbercall">-1</field> <field name="interval_type">days</field>
<field name="doall" eval="False" /> <field name="numbercall">-1</field>
<field name="state">code</field> <field name="doall" eval="False" />
<field name="model_id" ref="model_traveller_report_wizard" /> <field name="state">code</field>
<field <field name="model_id" ref="model_traveller_report_wizard" />
<field
name="nextcall" name="nextcall"
eval="datetime.now(pytz.timezone('UTC')).strftime('%Y-%m-%d 16:57:00')" eval="datetime.now(pytz.timezone('UTC')).strftime('%Y-%m-%d 16:57:00')"
/> />
<field name="code">model.send_file_institution_async()</field> <field name="code">model.send_file_institution_async()</field>
</record> </record>
</data> </data>
</odoo> </odoo>

View File

@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data>
<record id="notification_send_error_travel_report_email" model="mail.template">
<field name="name">Travel Report Send</field>
<field
name="model_id"
ref="pms_l10n_es.model_pms_log_institution_traveller_report"
/>
<field
name="subject"
>Error: ${object.pms_property_id.name}, ${object.target_date} Error sending the Traveler report</field>
<field
name="email_from"
>${object.pms_property_id.company_id.partner_id.email | safe}</field>
<field
name="email_to"
>${object.pms_property_id.partner_id.email | safe}</field>
<field name="body_html" type="html">
<div>
There was an error sending the traveler report
</div>
</field>
</record>
</data>
<data>
<record
id="notification_send_success_travel_report_email"
model="mail.template"
>
<field name="name">Travel Report Send</field>
<field
name="model_id"
ref="pms_l10n_es.model_pms_log_institution_traveller_report"
/>
<field
name="subject"
>Succes: ${object.pms_property_id.name}, ${object.target_date} Traveler report sent successfully</field>
<field
name="email_from"
>${object.pms_property_id.company_id.partner_id.email | safe}</field>
<field
name="email_to"
>${object.pms_property_id.partner_id.email | safe}</field>
<field name="body_html" type="html">
<div>
Traveler report sent successfully
</div>
</field>
</record>
</data>
</odoo>

View File

@@ -7,7 +7,7 @@ CODE_SPAIN = "ES"
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
class PmsCheckinParnert(models.Model): class PmsCheckinPartner(models.Model):
_inherit = "pms.checkin.partner" _inherit = "pms.checkin.partner"
support_number = fields.Char( support_number = fields.Char(
@@ -35,7 +35,7 @@ class PmsCheckinParnert(models.Model):
@api.model @api.model
def _checkin_mandatory_fields(self, country=False, depends=False): 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 depends
) )
mandatory_fields.extend( mandatory_fields.extend(
@@ -60,6 +60,6 @@ class PmsCheckinParnert(models.Model):
@api.model @api.model
def _checkin_manual_fields(self, country=False, depends=False): 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"]) manual_fields.extend(["support_number"])
return manual_fields return manual_fields

View File

@@ -2,17 +2,21 @@ import base64
import datetime import datetime
import io import io
import json import json
import logging
import re import re
import time import time
import PyPDF2 import PyPDF2
import requests import requests
from bs4 import BeautifulSoup as bs from bs4 import BeautifulSoup as bs
from dateutil.relativedelta import relativedelta
from odoo import _, api, fields, models from odoo import _, api, fields, models
from odoo.exceptions import MissingError, ValidationError from odoo.exceptions import MissingError, ValidationError
from odoo.modules.module import get_module_resource from odoo.modules.module import get_module_resource
_logger = logging.getLogger(__name__)
class TravellerReport(models.TransientModel): class TravellerReport(models.TransientModel):
_name = "traveller.report.wizard" _name = "traveller.report.wizard"
@@ -48,448 +52,529 @@ class TravellerReport(models.TransientModel):
# build content # build content
content = self.generate_checkin_list( content = self.generate_checkin_list(
property_id=pms_property.id, pms_property_id=pms_property.id,
date_target=self.date_target, date_target=self.date_target,
) )
if content: if content:
txt_binary = self.env["traveller.report.wizard"].create( self.txt_filename = pms_property.institution_property_id + ".999"
{ self.txt_binary = base64.b64encode(str.encode(content))
"txt_filename": pms_property.institution_property_id + ".999", self.txt_message = content
"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",
}
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]") 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 # 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"]), ("state", "in", ["onboard", "done"]),
("arrival", ">=", str(date_target) + " 0:00:00"), ("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),
] ]
): else:
pms_property = ( domain = [
self.env["pms.property"] ("id", "in", checkin_ids),
.with_context(lang="es_ES") ]
.search([("id", "=", property_id)]) pms_property = (
) self.env["pms.property"]
# get checkin partners info to send .with_context(lang="es_ES")
lines = self.env["pms.checkin.partner"].search( .search([("id", "=", pms_property_id)])
[ )
("state", "in", ["onboard", "done"]), # get checkin partners info to send
("arrival", ">=", str(date_target) + " 0:00:00"), lines = self.env["pms.checkin.partner"].search(domain)
("arrival", "<=", str(date_target) + " 23:59:59"), # build the property info record
("pms_property_id", "=", property_id), # 1 | property id | property name | date | nº of checkin partners
] content = (
) "1|"
# build the property info record + pms_property.institution_property_id.upper()
# 1 | property id | property name | date | nº of checkin partners + "|"
content = ( + regex.sub(" ", pms_property.name.upper())
"1|" + "|"
+ pms_property.institution_property_id.upper() + datetime.datetime.now().strftime("%Y%m%d|%H%M")
+ "|" + "|"
+ regex.sub(" ", pms_property.name.upper()) + str(len(lines))
+ "|" + "\n"
+ datetime.datetime.now().strftime("%Y%m%d|%H%M") )
+ "|" # build each checkin partner line's record
+ str(len(lines)) # 2|DNI nº|Doc.number|doc.type|exp.date|lastname|lastname2|name|...
+ "\n" # ...gender|birthdate|nation.|checkin
) lines = lines.with_context(lang="es_ES")
# build each checkin partner line's record for line in lines:
# 2|DNI nº|Doc.number|doc.type|exp.date|lastname|lastname2|name|... content += "2"
# ...gender|birthdate|nation.|checkin # [P|N|..]
lines = lines.with_context(lang="es_ES") if line.document_type.code not in ["D", "C"]:
for line in lines: content += "||" + regex.sub("", line.document_number.upper()) + "|"
content += "2" else:
# [P|N|..] content += "|" + regex.sub("", line.document_number.upper()) + "||"
if line.document_type.code not in ["D", "C"]: content += line.document_type.code + "|"
content += "||" + regex.sub("", line.document_number.upper()) + "|" content += line.document_expedition_date.strftime("%Y%m%d") + "|"
else: content += regex.sub(" ", line.lastname.upper()) + "|"
content += "|" + regex.sub("", line.document_number.upper()) + "||" if line.lastname2:
content += line.document_type.code + "|" content += regex.sub(" ", line.lastname2.upper())
content += line.document_expedition_date.strftime("%Y%m%d") + "|" content += "|" + regex.sub(" ", line.firstname.upper()) + "|"
content += regex.sub(" ", line.lastname.upper()) + "|" if line.gender == "female":
if line.lastname2: content += "F|"
content += regex.sub(" ", line.lastname2.upper()) else:
content += "|" + regex.sub(" ", line.firstname.upper()) + "|" content += "M|"
if line.gender == "female": content += line.birthdate_date.strftime("%Y%m%d") + "|"
content += "F|" content += line.nationality_id.name.upper() + "|"
else: content += line.arrival.strftime("%Y%m%d") + "\n"
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): def send_file_gc(self, file_content, called_from_user, pms_property):
url = "https://hospederias.guardiacivil.es/" try:
login_route = "/hospederias/login.do" _logger.info(
upload_file_route = "/hospederias/cargaFichero.do" "Sending file to Guardia Civil, Property %s, date: %s"
logout_route = "/hospederias/logout.do" % (pms_property.name, self.date_target)
target_date = self.date_target or fields.date.today() )
if file_content: 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 = { headers = {
"User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 " "User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 "
"Build/MRA58N) AppleWebKit/537.36 (KHTML, like " "Build/MRA58N) AppleWebKit/537.36 (KHTML, like "
"Gecko) Chrome/90.0.4430.93 Mobile Safari/537.36", "Gecko) Chrome/90.0.4430.93 Mobile Safari/537.36",
} }
session = requests.session() pre_login_route = "/e-hotel/login"
login_payload = { login_route = "/e-hotel/execute_login"
"usuario": pms_property.institution_user, next_file_name_route = "/e-hotel/hospederia/ficheros/vista/envioFicheros"
"pswd": pms_property.institution_password, upload_file_route = "/e-hotel/hospederia/ficheros/subirFichero"
} pre_get_list_files_sent_route = (
response_login = session.post( "/e-hotel/hospederia/vista/seguimientoHospederia"
url + login_route,
headers=headers,
data=login_payload,
verify=get_module_resource("pms_l10n_es", "static", "cert.pem"),
) )
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 if not token:
# resource cannot be accessed raise MissingError(_("Could not get token login."))
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 # do login
files = {"fichero": (pms_property.institution_user + ".999", file_content)} 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 # send file
response_file_sent = session.post( upload_result = session.post(
url + upload_file_route, base_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,
headers=headers, 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() session.close()
return log
# check if the file send has been correct except Exception as e:
soup = bs(response_file_sent.text, "html.parser") return self.env["pms.log.institution.traveller.report"].create(
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(
{ {
"error_sending_data": error, "error_sending_data": True,
"txt_incidencies_from_institution": message, "txt_message": str(e),
"file_incidencies_from_institution": base64.b64encode(
response_last_file_errors_route.content
),
"txt_filename": file_name + ".pdf",
"pms_property_id": pms_property.id, "pms_property_id": pms_property.id,
"target_date": target_date, "target_date": target_date,
} }
) )
# do logout def send_file_institution(
session.post( self, pms_property=False, checkin_ids=False, offset=0, date_target=False
base_url + logout_route, ):
headers=headers, try:
verify=False, called_from_user = False
data={"_csrf": token}, if not pms_property:
) called_from_user = True
pms_property = self.env["pms.property"].search(
session.close() [("id", "=", self.pms_property_id.id)]
if called_from_user: )
message = { if (
"type": "ir.actions.client", not pms_property
"tag": "display_notification", or not pms_property.institution_property_id
"params": { or not pms_property.institution_user
"title": _("Sent succesfully!"), or not pms_property.institution_password
"message": _("Successful file sending"), ):
"sticky": False, raise ValidationError(
}, _("The guest information sending settings is not complete.")
} )
return message if not date_target:
date_target = fields.Date.today()
def send_file_institution(self, pms_property=False): date_target = date_target - relativedelta(days=offset)
called_from_user = False file_content = self.generate_checkin_list(
if not pms_property: pms_property_id=pms_property.id,
called_from_user = True date_target=date_target,
pms_property = self.env["pms.property"].search( checkin_ids=checkin_ids,
[("id", "=", self.pms_property_id.id)]
) )
if ( if pms_property.institution == "policia_nacional":
not pms_property log = self.send_file_pn(file_content, called_from_user, pms_property)
or not pms_property.institution_property_id elif pms_property.institution == "guardia_civil":
or not pms_property.institution_user log = self.send_file_gc(file_content, called_from_user, pms_property)
or not pms_property.institution_password if log.error_sending_data:
): _logger.warning(
raise ValidationError( """
_("The guest information sending settings is not complete.") 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 called_from_user:
if pms_property.institution == "policia_nacional": message = {
return self.send_file_pn(file_content, called_from_user, pms_property) "type": "ir.actions.client",
elif pms_property.institution == "guardia_civil": "tag": "display_notification",
return self.send_file_gc(file_content, called_from_user, pms_property) "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 @api.model
def send_file_institution_async(self): def send_file_institution_async(self, offset=0):
for prop in self.env["pms.property"].search([]): for prop in self.env["pms.property"].search([]):
if prop.institution: if prop.institution:
self.with_delay().send_file_institution(prop) self.send_file_institution(prop, offset)
time.sleep(0.5)