[IMP] pms: add model to save log of sending files to institutions

This commit is contained in:
miguelpadin
2021-06-18 19:08:25 +02:00
parent 01d09c9c47
commit 4cfe6e9022
9 changed files with 131 additions and 96 deletions

View File

@@ -24,9 +24,9 @@
], ],
}, },
"data": [ "data": [
# "data/cron_jobs.xml", "data/cron_jobs.xml",
# "data/queue_data.xml", "data/queue_data.xml",
# "data/queue_job_function_data.xml", "data/queue_job_function_data.xml",
"security/ir.model.access.csv", "security/ir.model.access.csv",
"views/pms_checkin_partner_views.xml", "views/pms_checkin_partner_views.xml",
"views/pms_property_views.xml", "views/pms_property_views.xml",

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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

View File

@@ -9,10 +9,14 @@ class PmsLogInstitutionTravellerReport(models.Model):
string="Date and time", string="Date and time",
default=fields.Datetime.now, default=fields.Datetime.now,
) )
txtIncidenciesFromInstitution = fields.Text( error_sending_data = fields.Boolean(
string="Error sending data",
required=True,
)
txt_incidencies_from_institution = fields.Text(
string="Detailed message", string="Detailed message",
) )
fileIncidenciesFromInstitution = fields.Binary( file_incidencies_from_institution = fields.Binary(
string="Detailed file", string="Detailed file",
) )
txt_filename = fields.Text() txt_filename = fields.Text()

View File

@@ -8,10 +8,11 @@
<sheet> <sheet>
<group> <group>
<field name="txt_filename" invisible="1" /> <field name="txt_filename" invisible="1" />
<field name="error_sending_data" />
<field name="date" /> <field name="date" />
<field name="txtIncidenciesFromInstitution" select="1" /> <field name="txt_incidencies_from_institution" select="1" />
<field <field
name="fileIncidenciesFromInstitution" name="file_incidencies_from_institution"
filename="txt_filename" filename="txt_filename"
readonly="1" readonly="1"
/> />
@@ -24,12 +25,17 @@
<field name="name">pms.log.institution.traveller.report.tree</field> <field name="name">pms.log.institution.traveller.report.tree</field>
<field name="model">pms.log.institution.traveller.report</field> <field name="model">pms.log.institution.traveller.report</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string=" Property Ubications" create="false"> <tree
string="Property Ubications"
create="false"
decoration-danger="error_sending_data"
>
<field name="date" /> <field name="date" />
<field name="txtIncidenciesFromInstitution" /> <field name="error_sending_data" />
<field name="txt_incidencies_from_institution" />
<field name="txt_filename" string="File" /> <field name="txt_filename" string="File" />
<field <field
name="fileIncidenciesFromInstitution" name="file_incidencies_from_institution"
filename="txt_filename" filename="txt_filename"
readonly="1" readonly="1"
string="Size" string="Size"

View File

@@ -1,14 +1,16 @@
import base64 import base64
import datetime import datetime
import io
import json 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
@@ -20,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",
@@ -68,42 +73,27 @@ class TravellerReport(models.TransientModel):
# 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
@@ -198,14 +188,16 @@ class TravellerReport(models.TransientModel):
msg += e.select("a")[2].text + "\n" msg += e.select("a")[2].text + "\n"
self.env["pms.log.institution.traveller.report"].create( self.env["pms.log.institution.traveller.report"].create(
{ {
"txt_message": msg, "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( self.env["pms.log.institution.traveller.report"].create(
{ {
"txt_message": "Successful file sending", "error_sending_data": False,
"txt_message": _("Successful file sending"),
} }
) )
if called_from_user: if called_from_user:
@@ -250,6 +242,10 @@ class TravellerReport(models.TransientModel):
token = bs(response_pre_login.text, "html.parser").select( token = bs(response_pre_login.text, "html.parser").select(
"input[name='_csrf']" "input[name='_csrf']"
)[0]["value"] )[0]["value"]
if not token:
raise MissingError(_("Could not get token login."))
# do login # do login
session.post( session.post(
base_url + login_route, base_url + login_route,
@@ -272,8 +268,12 @@ class TravellerReport(models.TransientModel):
time.sleep(0.1) time.sleep(0.1)
soup = bs(response_name_file_route.text, "html.parser") soup = bs(response_name_file_route.text, "html.parser")
file_name = soup.select("#msjNombreFichero > b > u")[0].text 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
session.post( upload_result = session.post(
base_url + upload_file_route, base_url + upload_file_route,
headers=headers, headers=headers,
verify=False, verify=False,
@@ -284,7 +284,12 @@ class TravellerReport(models.TransientModel):
}, },
files={"fichero": (file_name, file_content)}, files={"fichero": (file_name, file_content)},
) )
if upload_result.status_code != 200:
raise MissingError(_("Could not upload file."))
time.sleep(0.1) time.sleep(0.1)
# retrieve property data # retrieve property data
response_pre_files_sent_list_route = session.post( response_pre_files_sent_list_route = session.post(
base_url + pre_get_list_files_sent_route, base_url + pre_get_list_files_sent_route,
@@ -296,7 +301,11 @@ class TravellerReport(models.TransientModel):
"_csrf": token, "_csrf": token,
}, },
) )
if response_pre_files_sent_list_route.status_code != 200:
raise MissingError(_("Could not get property_info."))
time.sleep(0.1) time.sleep(0.1)
soup = bs(response_pre_files_sent_list_route.text, "html.parser") soup = bs(response_pre_files_sent_list_route.text, "html.parser")
property_specific_data = { property_specific_data = {
"codigoHospederia": soup.select("#codigoHospederia")[0]["value"], "codigoHospederia": soup.select("#codigoHospederia")[0]["value"],
@@ -321,7 +330,7 @@ class TravellerReport(models.TransientModel):
} }
# retrieve list of sent files # retrieve list of sent files
file_data = dict() file_data = dict()
for _attempt in range(1, 5): for _attempt in range(1, 10):
response_files_sent_list_route = session.post( response_files_sent_list_route = session.post(
base_url + files_sent_list_route, base_url + files_sent_list_route,
headers=headers, headers=headers,
@@ -343,10 +352,10 @@ class TravellerReport(models.TransientModel):
file_data = file_data[0] file_data = file_data[0]
break break
else: else:
time.sleep(0.5) time.sleep(1)
if not file_data: if not file_data:
raise ValidationError(_("Could not send file")) raise ValidationError(_("Could not get last file sent"))
else: else:
response_last_file_errors_route = session.post( response_last_file_errors_route = session.post(
base_url + last_file_errors_route, base_url + last_file_errors_route,
@@ -373,6 +382,9 @@ class TravellerReport(models.TransientModel):
}, },
) )
if response_last_file_errors_route.status_code != 200:
raise ValidationError(_("Could last files sent"))
time.sleep(0.1) time.sleep(0.1)
soup = bs(response_last_file_errors_route.text, "html.parser") soup = bs(response_last_file_errors_route.text, "html.parser")
# get file sent pdf report # get file sent pdf report
@@ -381,10 +393,30 @@ class TravellerReport(models.TransientModel):
headers=headers, headers=headers,
verify=False, verify=False,
) )
if response_last_file_errors_route.status_code != 200:
raise ValidationError(_("Could last files sent"))
time.sleep(0.1) 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( self.env["pms.log.institution.traveller.report"].create(
{ {
"fileIncidenciesFromInstitution": base64.b64encode( "error_sending_data": error,
"txt_incidencies_from_institution": message,
"file_incidencies_from_institution": base64.b64encode(
response_last_file_errors_route.content response_last_file_errors_route.content
), ),
"txt_filename": file_name + ".pdf", "txt_filename": file_name + ".pdf",
@@ -400,24 +432,17 @@ class TravellerReport(models.TransientModel):
) )
session.close() session.close()
# file creation if called_from_user:
txt_binary = self.env["traveller.report.wizard"].create( message = {
{ "type": "ir.actions.client",
"txt_filename": pms_property.institution_property_id + ".999", "tag": "display_notification",
"txt_binary": base64.b64encode(response_last_file_errors_route.content), "params": {
"txt_message": "download pdf report", "title": _("Sent succesfully!"),
"message": _("Successful file sending"),
"sticky": False,
},
} }
) return message
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): def send_file_institution(self, pms_property=False):
called_from_user = False called_from_user = False
@@ -426,11 +451,11 @@ class TravellerReport(models.TransientModel):
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])]
) )
if not ( if (
pms_property not pms_property
and pms_property.institution_property_id or not pms_property.institution_property_id
and pms_property.institution_user or not pms_property.institution_user
and pms_property.institution_password or not pms_property.institution_password
): ):
raise ValidationError( raise ValidationError(
_("The guest information sending settings is not complete.") _("The guest information sending settings is not complete.")
@@ -439,9 +464,9 @@ class TravellerReport(models.TransientModel):
if pms_property.institution == "policia_nacional": if pms_property.institution == "policia_nacional":
return self.send_file_pn(file_content, called_from_user, pms_property) return self.send_file_pn(file_content, called_from_user, pms_property)
elif pms_property.institution == "guardia_civil": elif pms_property.institution == "guardia_civil":
self.send_file_gc(file_content, called_from_user, pms_property) 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)

View File

@@ -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"