mirror of
https://github.com/OCA/pms.git
synced 2025-01-29 00:17:45 +02:00
@@ -31,6 +31,7 @@
|
|||||||
"views/pms_checkin_partner_views.xml",
|
"views/pms_checkin_partner_views.xml",
|
||||||
"views/pms_property_views.xml",
|
"views/pms_property_views.xml",
|
||||||
"views/res_partner_views.xml",
|
"views/res_partner_views.xml",
|
||||||
|
"views/pms_log_institution_traveller_report_views.xml",
|
||||||
"wizards/traveller_report.xml",
|
"wizards/traveller_report.xml",
|
||||||
],
|
],
|
||||||
"installable": True,
|
"installable": True,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<data noupdate="0">
|
<data noupdate="0">
|
||||||
<record model="ir.cron" id="autosend_traveller_report">
|
<record model="ir.cron" id="autosend_traveller_report">
|
||||||
<field name="name">Automatic Send Traveller Report</field>
|
<field name="name">Automatic Send Traveller Report</field>
|
||||||
<field name="active" eval="True" />
|
<field name="active" eval="False" />
|
||||||
<field name="interval_number">1</field>
|
<field name="interval_number">1</field>
|
||||||
<field name="user_id" ref="base.user_root" />
|
<field name="user_id" ref="base.user_root" />
|
||||||
<field name="interval_type">days</field>
|
<field name="interval_type">days</field>
|
||||||
@@ -13,9 +13,9 @@
|
|||||||
<field name="model_id" ref="model_traveller_report_wizard" />
|
<field name="model_id" ref="model_traveller_report_wizard" />
|
||||||
<field
|
<field
|
||||||
name="nextcall"
|
name="nextcall"
|
||||||
eval="datetime.now(pytz.timezone('UTC')).strftime('%Y-%m-%d 03:00:00')"
|
eval="datetime.now(pytz.timezone('UTC')).strftime('%Y-%m-%d 16:57:00')"
|
||||||
/>
|
/>
|
||||||
<field name="code">model.send_file_gc_async()</field>
|
<field name="code">model.send_file_institution_async()</field>
|
||||||
</record>
|
</record>
|
||||||
</data>
|
</data>
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<odoo>
|
<odoo>
|
||||||
<data noupdate="1">
|
<data noupdate="1">
|
||||||
<record id="channel_gc_file_send" model="queue.job.channel">
|
<record id="channel_institution_file_send" model="queue.job.channel">
|
||||||
<field name="name">gc_file_send</field>
|
<field name="name">institution_file_send</field>
|
||||||
<field name="parent_id" ref="queue_job.channel_root" />
|
<field name="parent_id" ref="queue_job.channel_root" />
|
||||||
</record>
|
</record>
|
||||||
</data>
|
</data>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
>
|
>
|
||||||
<field name="model_id" ref="pms_l10n_es.model_traveller_report_wizard" />
|
<field name="model_id" ref="pms_l10n_es.model_traveller_report_wizard" />
|
||||||
<field name="method">send_file_async</field>
|
<field name="method">send_file_async</field>
|
||||||
<field name="channel_id" ref="pms_l10n_es.channel_gc_file_send" />
|
<field name="channel_id" ref="pms_l10n_es.channel_institution_file_send" />
|
||||||
<field name="retry_pattern" eval="{1: 10, 5: 30, 10: 60, 15: 300}" />
|
<field name="retry_pattern" eval="{1: 10, 5: 30, 10: 60, 15: 300}" />
|
||||||
</record>
|
</record>
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ msgstr ""
|
|||||||
#. module: pms_l10n_es
|
#. module: pms_l10n_es
|
||||||
#: code:addons/pms_l10n_es/wizards/traveller_report.py:0
|
#: code:addons/pms_l10n_es/wizards/traveller_report.py:0
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Check the GC configuration to send the guests info"
|
msgid "Check the institution configuration to send the guests info"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. module: pms_l10n_es
|
#. module: pms_l10n_es
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
from . import res_partner
|
from . import res_partner
|
||||||
from . import pms_checkin_partner
|
from . import pms_checkin_partner
|
||||||
from . import pms_property
|
from . import pms_property
|
||||||
|
from . import pms_log_institution_traveller_report
|
||||||
|
|||||||
22
pms_l10n_es/models/pms_log_institution_traveller_report.py
Normal file
22
pms_l10n_es/models/pms_log_institution_traveller_report.py
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
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,
|
||||||
|
)
|
||||||
|
error_sending_data = fields.Boolean(
|
||||||
|
string="Error sending data",
|
||||||
|
required=True,
|
||||||
|
)
|
||||||
|
txt_incidencies_from_institution = fields.Text(
|
||||||
|
string="Detailed message",
|
||||||
|
)
|
||||||
|
file_incidencies_from_institution = fields.Binary(
|
||||||
|
string="Detailed file",
|
||||||
|
)
|
||||||
|
txt_filename = fields.Text()
|
||||||
@@ -14,7 +14,7 @@ class PmsProperty(models.Model):
|
|||||||
institution = fields.Selection(
|
institution = fields.Selection(
|
||||||
[
|
[
|
||||||
("guardia_civil", "Guardia Civil"),
|
("guardia_civil", "Guardia Civil"),
|
||||||
("policia_nacional", "Policía Nacional (soon)"),
|
("policia_nacional", "Policía Nacional"),
|
||||||
("ertxaintxa", "Ertxaintxa (soon)"),
|
("ertxaintxa", "Ertxaintxa (soon)"),
|
||||||
("mossos", "Mossos_d'esquadra (soon)"),
|
("mossos", "Mossos_d'esquadra (soon)"),
|
||||||
],
|
],
|
||||||
@@ -24,7 +24,6 @@ class PmsProperty(models.Model):
|
|||||||
)
|
)
|
||||||
institution_property_id = fields.Char(
|
institution_property_id = fields.Char(
|
||||||
string="Institution property id",
|
string="Institution property id",
|
||||||
size=10,
|
|
||||||
help="Id provided by institution to send data from property.",
|
help="Id provided by institution to send data from property.",
|
||||||
)
|
)
|
||||||
institution_user = fields.Char(
|
institution_user = fields.Char(
|
||||||
@@ -35,30 +34,27 @@ class PmsProperty(models.Model):
|
|||||||
help="Password provided by institution to send the data.",
|
help="Password provided by institution to send the data.",
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_gc_connection(self):
|
def test_connection(self):
|
||||||
for pms_property in 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 (
|
if (
|
||||||
pms_property.institution == "guardia_civil"
|
record.institution == "guardia_civil"
|
||||||
and pms_property.institution_property_id
|
and record.institution_property_id
|
||||||
and pms_property.institution_user
|
and record.institution_user
|
||||||
and pms_property.institution_password
|
and record.institution_password
|
||||||
):
|
):
|
||||||
|
|
||||||
url = "https://hospederias.guardiacivil.es/"
|
url = "https://hospederias.guardiacivil.es/"
|
||||||
login_route = "/hospederias/login.do"
|
login_route = "/hospederias/login.do"
|
||||||
logout_route = "/hospederias/logout.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()
|
session = requests.session()
|
||||||
login_payload = {
|
login_payload = {
|
||||||
"usuario": pms_property.institution_user,
|
"usuario": record.institution_user,
|
||||||
"pswd": pms_property.institution_password,
|
"pswd": record.institution_password,
|
||||||
}
|
}
|
||||||
|
|
||||||
# login
|
# login
|
||||||
response_login = session.post(
|
response_login = session.post(
|
||||||
url + login_route,
|
url + login_route,
|
||||||
@@ -66,7 +62,7 @@ class PmsProperty(models.Model):
|
|||||||
data=login_payload,
|
data=login_payload,
|
||||||
verify=get_module_resource("pms_l10n_es", "static", "cert.pem"),
|
verify=get_module_resource("pms_l10n_es", "static", "cert.pem"),
|
||||||
)
|
)
|
||||||
time.sleep(1)
|
time.sleep(0.1)
|
||||||
# logout
|
# logout
|
||||||
session.get(
|
session.get(
|
||||||
url + logout_route,
|
url + logout_route,
|
||||||
@@ -96,3 +92,62 @@ class PmsProperty(models.Model):
|
|||||||
return message
|
return message
|
||||||
else:
|
else:
|
||||||
raise ValidationError(_("Connection could not be established"))
|
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"))
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
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_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
|
||||||
|
|||||||
|
@@ -0,0 +1,61 @@
|
|||||||
|
<?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="error_sending_data" />
|
||||||
|
<field name="date" />
|
||||||
|
<field name="txt_incidencies_from_institution" select="1" />
|
||||||
|
<field
|
||||||
|
name="file_incidencies_from_institution"
|
||||||
|
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"
|
||||||
|
decoration-danger="error_sending_data"
|
||||||
|
>
|
||||||
|
<field name="date" />
|
||||||
|
<field name="error_sending_data" />
|
||||||
|
<field name="txt_incidencies_from_institution" />
|
||||||
|
<field name="txt_filename" string="File" />
|
||||||
|
<field
|
||||||
|
name="file_incidencies_from_institution"
|
||||||
|
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>
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
<field name="institution_password" password="True" />
|
<field name="institution_password" password="True" />
|
||||||
</group>
|
</group>
|
||||||
<button
|
<button
|
||||||
name="test_gc_connection"
|
name="test_connection"
|
||||||
class="btn btn-primary btn-sm"
|
class="btn btn-primary btn-sm"
|
||||||
type="object"
|
type="object"
|
||||||
string="Test user/password"
|
string="Test user/password"
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
import base64
|
import base64
|
||||||
import datetime
|
import datetime
|
||||||
|
import io
|
||||||
|
import json
|
||||||
import time
|
import time
|
||||||
from datetime import date
|
from datetime import date
|
||||||
|
|
||||||
|
import PyPDF2
|
||||||
import requests
|
import requests
|
||||||
from bs4 import BeautifulSoup as bs
|
from bs4 import BeautifulSoup as bs
|
||||||
|
|
||||||
from odoo import _, api, fields, models
|
from odoo import _, api, fields, models
|
||||||
from odoo.exceptions import ValidationError
|
from odoo.exceptions import MissingError, ValidationError
|
||||||
from odoo.modules.module import get_module_resource
|
from odoo.modules.module import get_module_resource
|
||||||
|
|
||||||
|
|
||||||
@@ -19,24 +22,27 @@ class TravellerReport(models.TransientModel):
|
|||||||
txt_binary = fields.Binary(string="File Download")
|
txt_binary = fields.Binary(string="File Download")
|
||||||
txt_message = fields.Char(string="File Preview")
|
txt_message = fields.Char(string="File Preview")
|
||||||
|
|
||||||
def generate_file(self):
|
def generate_file_from_user_action(self):
|
||||||
|
|
||||||
# get the active property
|
# get the active property
|
||||||
pms_property = self.env["pms.property"].search(
|
pms_property = self.env["pms.property"].search(
|
||||||
[("id", "=", self.env.user.get_active_property_ids()[0])]
|
[("id", "=", self.env.user.get_active_property_ids()[0])]
|
||||||
)
|
)
|
||||||
|
# check if there's institution settings properly established
|
||||||
|
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 property updated.")
|
||||||
|
)
|
||||||
|
|
||||||
# build content
|
# build content
|
||||||
content = self.generate_checkin_list(pms_property.id)
|
content = self.generate_checkin_list(pms_property.id)
|
||||||
|
|
||||||
if not pms_property.institution_property_id:
|
if content:
|
||||||
raise ValidationError(
|
|
||||||
_("The guest information sending settings is not property updated.")
|
|
||||||
)
|
|
||||||
elif not content:
|
|
||||||
raise ValidationError(_("There is no guest information to send."))
|
|
||||||
else:
|
|
||||||
# file creation
|
|
||||||
txt_binary = self.env["traveller.report.wizard"].create(
|
txt_binary = self.env["traveller.report.wizard"].create(
|
||||||
{
|
{
|
||||||
"txt_filename": pms_property.institution_property_id + ".999",
|
"txt_filename": pms_property.institution_property_id + ".999",
|
||||||
@@ -62,48 +68,32 @@ class TravellerReport(models.TransientModel):
|
|||||||
[
|
[
|
||||||
("state", "=", "onboard"),
|
("state", "=", "onboard"),
|
||||||
("arrival", ">=", str(date.today()) + " 0:00:00"),
|
("arrival", ">=", str(date.today()) + " 0:00:00"),
|
||||||
("arrival", "<=", str(date.today()) + " 23:59:59"),
|
|
||||||
]
|
]
|
||||||
):
|
):
|
||||||
|
|
||||||
# get the active property
|
# get the active property
|
||||||
pms_property = self.env["pms.property"].search([("id", "=", property_id)])
|
pms_property = self.env["pms.property"].search([("id", "=", property_id)])
|
||||||
|
# get checkin partners info to send
|
||||||
# check if the GC configuration info is properly set
|
lines = self.env["pms.checkin.partner"].search(
|
||||||
if not (
|
[
|
||||||
pms_property.name
|
("state", "=", "onboard"),
|
||||||
and pms_property.institution_property_id
|
("arrival", ">=", str(date.today()) + " 0:00:00"),
|
||||||
and pms_property.institution_user
|
("arrival", "<=", str(date.today()) + " 23:59:59"),
|
||||||
and pms_property.institution_password
|
]
|
||||||
):
|
)
|
||||||
raise ValidationError(
|
# build the property info record
|
||||||
_("Check the GC configuration to send the guests info")
|
# 1 | property id | property name | date | nº of checkin partners
|
||||||
)
|
content = (
|
||||||
else:
|
"1|"
|
||||||
# get checkin partners info to send
|
+ pms_property.institution_property_id.upper()
|
||||||
lines = self.env["pms.checkin.partner"].search(
|
+ "|"
|
||||||
[
|
+ pms_property.name.upper()
|
||||||
("state", "=", "onboard"),
|
+ "|"
|
||||||
("arrival", ">=", str(date.today()) + " 0:00:00"),
|
+ datetime.datetime.now().strftime("%Y%m%d|%H%M")
|
||||||
("arrival", "<=", str(date.today()) + " 23:59:59"),
|
+ "|"
|
||||||
]
|
+ str(len(lines))
|
||||||
)
|
+ "\n"
|
||||||
|
)
|
||||||
# build the property info record
|
|
||||||
# 1 | property id | property name | date | nº of checkin partners
|
|
||||||
|
|
||||||
content = (
|
|
||||||
"1|"
|
|
||||||
+ pms_property.institution_property_id.upper()
|
|
||||||
+ "|"
|
|
||||||
+ pms_property.name.upper()
|
|
||||||
+ "|"
|
|
||||||
+ datetime.datetime.now().strftime("%Y%m%d|%H%M")
|
|
||||||
+ "|"
|
|
||||||
+ str(len(lines))
|
|
||||||
+ "\n"
|
|
||||||
)
|
|
||||||
|
|
||||||
# build each checkin partner line's record
|
# build each checkin partner line's record
|
||||||
# 2|DNI nº|Doc.number|doc.type|exp.date|lastname|lastname2|name|...
|
# 2|DNI nº|Doc.number|doc.type|exp.date|lastname|lastname2|name|...
|
||||||
# ...gender|birthdate|nation.|checkin
|
# ...gender|birthdate|nation.|checkin
|
||||||
@@ -131,32 +121,13 @@ class TravellerReport(models.TransientModel):
|
|||||||
|
|
||||||
return content
|
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/"
|
url = "https://hospederias.guardiacivil.es/"
|
||||||
login_route = "/hospederias/login.do"
|
login_route = "/hospederias/login.do"
|
||||||
upload_file_route = "/hospederias/cargaFichero.do"
|
upload_file_route = "/hospederias/cargaFichero.do"
|
||||||
logout_route = "/hospederias/logout.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 (
|
if file_content:
|
||||||
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:
|
|
||||||
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 "
|
||||||
@@ -167,14 +138,13 @@ class TravellerReport(models.TransientModel):
|
|||||||
"usuario": pms_property.institution_user,
|
"usuario": pms_property.institution_user,
|
||||||
"pswd": pms_property.institution_password,
|
"pswd": pms_property.institution_password,
|
||||||
}
|
}
|
||||||
|
|
||||||
# login
|
|
||||||
response_login = session.post(
|
response_login = session.post(
|
||||||
url + login_route,
|
url + login_route,
|
||||||
headers=headers,
|
headers=headers,
|
||||||
data=login_payload,
|
data=login_payload,
|
||||||
verify=get_module_resource("pms_l10n_es", "static", "cert.pem"),
|
verify=get_module_resource("pms_l10n_es", "static", "cert.pem"),
|
||||||
)
|
)
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
# check if authentication was successful / unsuccessful or the
|
# check if authentication was successful / unsuccessful or the
|
||||||
# resource cannot be accessed
|
# resource cannot be accessed
|
||||||
@@ -189,8 +159,7 @@ class TravellerReport(models.TransientModel):
|
|||||||
raise ValidationError(_("Connection could not be established"))
|
raise ValidationError(_("Connection could not be established"))
|
||||||
|
|
||||||
# build the file to send
|
# build the file to send
|
||||||
files = {"fichero": (pms_property.institution_user + ".999", content)}
|
files = {"fichero": (pms_property.institution_user + ".999", file_content)}
|
||||||
time.sleep(1)
|
|
||||||
|
|
||||||
# send file
|
# send file
|
||||||
response_file_sent = session.post(
|
response_file_sent = session.post(
|
||||||
@@ -199,8 +168,8 @@ class TravellerReport(models.TransientModel):
|
|||||||
files=files,
|
files=files,
|
||||||
verify=get_module_resource("pms_l10n_es", "static", "cert.pem"),
|
verify=get_module_resource("pms_l10n_es", "static", "cert.pem"),
|
||||||
)
|
)
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
time.sleep(1)
|
|
||||||
# logout & close connection
|
# logout & close connection
|
||||||
session.get(
|
session.get(
|
||||||
url + logout_route,
|
url + logout_route,
|
||||||
@@ -217,8 +186,20 @@ class TravellerReport(models.TransientModel):
|
|||||||
for e in errors:
|
for e in errors:
|
||||||
msg += "Error en línea " + e.select("a")[0].text + ": "
|
msg += "Error en línea " + e.select("a")[0].text + ": "
|
||||||
msg += e.select("a")[2].text + "\n"
|
msg += e.select("a")[2].text + "\n"
|
||||||
|
self.env["pms.log.institution.traveller.report"].create(
|
||||||
|
{
|
||||||
|
"error_sending_data": True,
|
||||||
|
"txt_incidencies_from_institution": msg,
|
||||||
|
}
|
||||||
|
)
|
||||||
raise ValidationError(msg)
|
raise ValidationError(msg)
|
||||||
else:
|
else:
|
||||||
|
self.env["pms.log.institution.traveller.report"].create(
|
||||||
|
{
|
||||||
|
"error_sending_data": False,
|
||||||
|
"txt_message": _("Successful file sending"),
|
||||||
|
}
|
||||||
|
)
|
||||||
if called_from_user:
|
if called_from_user:
|
||||||
message = {
|
message = {
|
||||||
"type": "ir.actions.client",
|
"type": "ir.actions.client",
|
||||||
@@ -231,7 +212,261 @@ class TravellerReport(models.TransientModel):
|
|||||||
}
|
}
|
||||||
return message
|
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"]
|
||||||
|
|
||||||
|
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,
|
||||||
|
"txt_incidencies_from_institution": message,
|
||||||
|
"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()
|
||||||
|
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.env.user.get_active_property_ids()[0])]
|
||||||
|
)
|
||||||
|
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.")
|
||||||
|
)
|
||||||
|
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)
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def send_file_gc_async(self):
|
def send_file_institution_async(self):
|
||||||
for prop in self.env["pms.property"].search([]):
|
for prop in self.env["pms.property"].search([]):
|
||||||
self.with_delay().send_file_gc(prop)
|
self.with_delay().send_file_institution(prop)
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
<div class="row ">
|
<div class="row ">
|
||||||
<div class="col-3">
|
<div class="col-3">
|
||||||
<button
|
<button
|
||||||
name="generate_file"
|
name="generate_file_from_user_action"
|
||||||
class="btn btn-primary btn-sm"
|
class="btn btn-primary btn-sm"
|
||||||
type="object"
|
type="object"
|
||||||
string="Preview file"
|
string="Preview file"
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-3">
|
<div class="col-3">
|
||||||
<button
|
<button
|
||||||
name="send_file_gc"
|
name="send_file_institution"
|
||||||
class="btn btn-primary btn-sm"
|
class="btn btn-primary btn-sm"
|
||||||
type="object"
|
type="object"
|
||||||
string="Send file"
|
string="Send file"
|
||||||
@@ -55,8 +55,8 @@
|
|||||||
<menuitem
|
<menuitem
|
||||||
id="menu_traveller_report"
|
id="menu_traveller_report"
|
||||||
name="Traveller Report"
|
name="Traveller Report"
|
||||||
sequence="30"
|
sequence="27"
|
||||||
parent="pms.pms_configuration_menu"
|
parent="pms.menu_reservations"
|
||||||
action="action_traveller_report"
|
action="action_traveller_report"
|
||||||
/>
|
/>
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
Reference in New Issue
Block a user