[IMP] pms_l10n_es: spanish police travellers report sending

This commit is contained in:
miguelpadin
2021-06-11 19:19:42 +02:00
parent 3c1ac33bd8
commit 01d09c9c47
9 changed files with 394 additions and 53 deletions

View File

@@ -24,13 +24,14 @@
],
},
"data": [
"data/cron_jobs.xml",
"data/queue_data.xml",
"data/queue_job_function_data.xml",
# "data/cron_jobs.xml",
# "data/queue_data.xml",
# "data/queue_job_function_data.xml",
"security/ir.model.access.csv",
"views/pms_checkin_partner_views.xml",
"views/pms_property_views.xml",
"views/res_partner_views.xml",
"views/pms_log_institution_traveller_report_views.xml",
"wizards/traveller_report.xml",
],
"installable": True,

View File

@@ -1,3 +1,4 @@
from . import res_partner
from . import pms_checkin_partner
from . import pms_property
from . import pms_log_institution_traveller_report

View File

@@ -0,0 +1,18 @@
from odoo import fields, models
class PmsLogInstitutionTravellerReport(models.Model):
_name = "pms.log.institution.traveller.report"
_description = "Report of daily sending files of travellers to institutions."
date = fields.Datetime(
string="Date and time",
default=fields.Datetime.now,
)
txtIncidenciesFromInstitution = fields.Text(
string="Detailed message",
)
fileIncidenciesFromInstitution = fields.Binary(
string="Detailed file",
)
txt_filename = fields.Text()

View File

@@ -14,7 +14,7 @@ class PmsProperty(models.Model):
institution = fields.Selection(
[
("guardia_civil", "Guardia Civil"),
("policia_nacional", "Policía Nacional (soon)"),
("policia_nacional", "Policía Nacional"),
("ertxaintxa", "Ertxaintxa (soon)"),
("mossos", "Mossos_d'esquadra (soon)"),
],
@@ -24,7 +24,6 @@ class PmsProperty(models.Model):
)
institution_property_id = fields.Char(
string="Institution property id",
size=10,
help="Id provided by institution to send data from property.",
)
institution_user = fields.Char(
@@ -35,30 +34,27 @@ class PmsProperty(models.Model):
help="Password provided by institution to send the data.",
)
def test_gc_connection(self):
for pms_property in self:
def test_connection(self):
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",
}
for record in self:
if (
pms_property.institution == "guardia_civil"
and pms_property.institution_property_id
and pms_property.institution_user
and pms_property.institution_password
record.institution == "guardia_civil"
and record.institution_property_id
and record.institution_user
and record.institution_password
):
url = "https://hospederias.guardiacivil.es/"
login_route = "/hospederias/login.do"
logout_route = "/hospederias/logout.do"
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,
"usuario": record.institution_user,
"pswd": record.institution_password,
}
# login
response_login = session.post(
url + login_route,
@@ -66,7 +62,7 @@ class PmsProperty(models.Model):
data=login_payload,
verify=get_module_resource("pms_l10n_es", "static", "cert.pem"),
)
time.sleep(1)
time.sleep(0.1)
# logout
session.get(
url + logout_route,
@@ -96,3 +92,62 @@ class PmsProperty(models.Model):
return message
else:
raise ValidationError(_("Connection could not be established"))
elif (
record.institution == "policia_nacional"
and record.institution_property_id
and record.institution_user
and record.institution_password
):
url = "https://webpol.policia.es/e-hotel"
pre_login_route = "/login"
login_route = "/execute_login"
home_route = "/inicio"
logout_route = "/execute_logout"
session = requests.session()
response_pre_login = session.post(
url + pre_login_route,
headers=headers,
verify=False,
)
soup = bs(response_pre_login.text, "html.parser")
token = soup.select("input[name='_csrf']")[0]["value"]
time.sleep(0.1)
login_payload = {
"username": record.institution_user,
"password": record.institution_password,
"_csrf": token,
}
session.post(
url + login_route,
headers=headers,
data=login_payload,
verify=False,
)
time.sleep(0.1)
response_home = session.get(
url + home_route,
headers=headers,
verify=False,
)
soup = bs(response_home.text, "html.parser")
login_correct = soup.select("#datosUsuarioBanner")
if login_correct:
session.post(
url + logout_route,
headers=headers,
verify=False,
data={"_csrf": token},
)
message = {
"type": "ir.actions.client",
"tag": "display_notification",
"params": {
"title": _("Connection Established!"),
"message": _("Connection established succesfully"),
"sticky": False,
},
}
return message
else:
raise ValidationError(_("Connection could not be established"))

View File

@@ -1,2 +1,3 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
user_access_traveller_report_wizard,user_access_traveller_report_wizard,model_traveller_report_wizard,pms.group_pms_user,1,1,1,1
user_access_traveller_report_logs,user_access_traveller_report_logs,model_pms_log_institution_traveller_report,pms.group_pms_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 user_access_traveller_report_wizard user_access_traveller_report_wizard model_traveller_report_wizard pms.group_pms_user 1 1 1 1
3 user_access_traveller_report_logs user_access_traveller_report_logs model_pms_log_institution_traveller_report pms.group_pms_user 1 1 1 1

View File

@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record model="ir.ui.view" id="pms_log_institution_traveller_report_view_form">
<field name="name">pms.log.institution.traveller.report.form</field>
<field name="model">pms.log.institution.traveller.report</field>
<field name="arch" type="xml">
<form string="Log institution traveller report detail">
<sheet>
<group>
<field name="txt_filename" invisible="1" />
<field name="date" />
<field name="txtIncidenciesFromInstitution" select="1" />
<field
name="fileIncidenciesFromInstitution"
filename="txt_filename"
readonly="1"
/>
</group>
</sheet>
</form>
</field>
</record>
<record model="ir.ui.view" id="pms_log_institution_traveller_report_view_tree">
<field name="name">pms.log.institution.traveller.report.tree</field>
<field name="model">pms.log.institution.traveller.report</field>
<field name="arch" type="xml">
<tree string=" Property Ubications" create="false">
<field name="date" />
<field name="txtIncidenciesFromInstitution" />
<field name="txt_filename" string="File" />
<field
name="fileIncidenciesFromInstitution"
filename="txt_filename"
readonly="1"
string="Size"
/>
</tree>
</field>
</record>
<record
model="ir.actions.act_window"
id="open_pms_log_institution_traveller_report_form_tree"
>
<field name="name">Log of sending files to institutions</field>
<field name="res_model">pms.log.institution.traveller.report</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem
name="Log institution traveller report"
id="menu_open_pms_log_institution_traveller_report_form_tree"
action="open_pms_log_institution_traveller_report_form_tree"
parent="pms.menu_reservations"
sequence="28"
/>
</odoo>

View File

@@ -27,7 +27,7 @@
<field name="institution_password" password="True" />
</group>
<button
name="test_gc_connection"
name="test_connection"
class="btn btn-primary btn-sm"
type="object"
string="Test user/password"

View File

@@ -1,5 +1,6 @@
import base64
import datetime
import json
import time
from datetime import date
@@ -62,7 +63,6 @@ class TravellerReport(models.TransientModel):
[
("state", "=", "onboard"),
("arrival", ">=", str(date.today()) + " 0:00:00"),
("arrival", "<=", str(date.today()) + " 23:59:59"),
]
):
@@ -131,32 +131,13 @@ class TravellerReport(models.TransientModel):
return content
def send_file_gc(self, pms_property=False):
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"
called_from_user = False
if not pms_property:
called_from_user = True
# get the active property
pms_property = self.env["pms.property"].search(
[("id", "=", self.env.user.get_active_property_ids()[0])]
)
if not (
pms_property
and pms_property.institution_property_id
and pms_property.institution_user
and pms_property.institution_password
):
raise ValidationError(
_("The guest information sending settings is not complete.")
)
content = self.generate_checkin_list(pms_property.id)
if content:
if file_content:
headers = {
"User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 "
"Build/MRA58N) AppleWebKit/537.36 (KHTML, like "
@@ -167,14 +148,13 @@ class TravellerReport(models.TransientModel):
"usuario": pms_property.institution_user,
"pswd": pms_property.institution_password,
}
# login
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.1)
# check if authentication was successful / unsuccessful or the
# resource cannot be accessed
@@ -189,8 +169,7 @@ class TravellerReport(models.TransientModel):
raise ValidationError(_("Connection could not be established"))
# build the file to send
files = {"fichero": (pms_property.institution_user + ".999", content)}
time.sleep(1)
files = {"fichero": (pms_property.institution_user + ".999", file_content)}
# send file
response_file_sent = session.post(
@@ -199,8 +178,8 @@ class TravellerReport(models.TransientModel):
files=files,
verify=get_module_resource("pms_l10n_es", "static", "cert.pem"),
)
time.sleep(0.1)
time.sleep(1)
# logout & close connection
session.get(
url + logout_route,
@@ -217,8 +196,18 @@ class TravellerReport(models.TransientModel):
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(
{
"txt_message": msg,
}
)
raise ValidationError(msg)
else:
self.env["pms.log.institution.traveller.report"].create(
{
"txt_message": "Successful file sending",
}
)
if called_from_user:
message = {
"type": "ir.actions.client",
@@ -231,6 +220,227 @@ class TravellerReport(models.TransientModel):
}
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"
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"]
# 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
# send file
session.post(
base_url + upload_file_route,
headers=headers,
verify=False,
data={
"jsonHiddenComunes": "",
"ficheroJ": "",
"_csrf": token,
},
files={"fichero": (file_name, file_content)},
)
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,
},
)
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, 5):
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(0.5)
if not file_data:
raise ValidationError(_("Could not send file"))
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,
},
)
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,
)
time.sleep(0.1)
self.env["pms.log.institution.traveller.report"].create(
{
"fileIncidenciesFromInstitution": 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()
# file creation
txt_binary = self.env["traveller.report.wizard"].create(
{
"txt_filename": pms_property.institution_property_id + ".999",
"txt_binary": base64.b64encode(response_last_file_errors_route.content),
"txt_message": "download pdf report",
}
)
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 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.env.user.get_active_property_ids()[0])]
)
if not (
pms_property
and pms_property.institution_property_id
and pms_property.institution_user
and pms_property.institution_password
):
raise ValidationError(
_("The guest information sending settings is not complete.")
)
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":
self.send_file_gc(file_content, called_from_user, pms_property)
@api.model
def send_file_gc_async(self):
for prop in self.env["pms.property"].search([]):

View File

@@ -32,7 +32,7 @@
</div>
<div class="col-3">
<button
name="send_file_gc"
name="send_file_institution"
class="btn btn-primary btn-sm"
type="object"
string="Send file"
@@ -55,8 +55,8 @@
<menuitem
id="menu_traveller_report"
name="Traveller Report"
sequence="30"
parent="pms.pms_configuration_menu"
sequence="27"
parent="pms.menu_reservations"
action="action_traveller_report"
/>
</odoo>