[IMP]pms_l10n_es: allow traveler report account by room

This commit is contained in:
Darío Lodeiros
2024-12-15 18:48:38 +01:00
parent f54b8a6763
commit 704fc48220
5 changed files with 239 additions and 77 deletions

View File

@@ -30,7 +30,6 @@ class PmsReservation(models.Model):
("processed", "Processed"),
],
compute="_compute_ses_status_reservation",
store=True,
)
ses_status_traveller_report = fields.Selection(
string="SES Status traveller",
@@ -46,15 +45,20 @@ class PmsReservation(models.Model):
("processed", "Processed"),
],
compute="_compute_ses_status_traveller_report",
store=True,
)
@api.depends("pms_property_id")
@api.depends("pms_property_id", "preferred_room_id")
def _compute_is_ses(self):
for record in self:
if (
record.preferred_room_id
and record.preferred_room_id.institution_independent_account
and record.preferred_room_id.institution == "ses"
):
record.is_ses = True
else:
record.is_ses = record.pms_property_id.institution == "ses"
@api.depends("ses_communication_ids", "ses_communication_ids.state")
def _compute_ses_status_reservation(self):
for record in self:
if record.pms_property_id.institution != "ses":
@@ -70,7 +74,6 @@ class PmsReservation(models.Model):
communication.state if communication else "error_create"
)
@api.depends("ses_communication_ids", "ses_communication_ids.state")
def _compute_ses_status_traveller_report(self):
for record in self:
if record.pms_property_id.institution != "ses":
@@ -88,11 +91,13 @@ class PmsReservation(models.Model):
@api.model
def create_communication(self, reservation_id, operation, entity):
reservation = self.env["pms.reservation"].browse(reservation_id)
self.env["pms.ses.communication"].create(
{
"reservation_id": reservation_id,
"operation": operation,
"entity": entity,
"room_id": reservation.preferred_room_id.id,
}
)
@@ -164,9 +169,6 @@ class PmsReservation(models.Model):
def write(self, vals):
for record in self:
if (
record.pms_property_id.institution == "ses"
and record.reservation_type != "out"
):
if record.is_ses and record.reservation_type != "out":
self.create_communication_after_update_reservation(record, vals)
return super(PmsReservation, self).write(vals)

View File

@@ -3,8 +3,43 @@ from odoo import fields, models
class PmsRoom(models.Model):
_inherit = "pms.room"
in_ine = fields.Boolean(
string="In INE",
help="Take it into account to generate INE statistics",
default=True,
)
institution_independent_account = fields.Boolean(
string="Independent account for institution (travel reports)",
help="This room has an independent account",
default=False,
)
institution = fields.Selection(
[
("ses", "SES"),
("ertxaintxa", "Ertxaintxa (soon)"),
("mossos", "Mossos_d'esquadra (soon)"),
],
string="Institution",
help="Institution to send daily guest data.",
required=False,
)
institution_property_id = fields.Char(
string="Institution property id",
help="Id provided by institution to send data from property.",
)
ses_url = fields.Char(
string="SES URL",
help="URL to send the data to SES",
)
institution_user = fields.Char(
string="Institution user", help="User provided by institution to send the data."
)
institution_password = fields.Char(
string="Institution password",
help="Password provided by institution to send the data.",
)
institution_lessor_id = fields.Char(
string="Institution lessor id",
help="Id provided by institution to send data from lessor.",
)

View File

@@ -22,6 +22,14 @@ class PmsSesCommunication(models.Model):
index=True,
store=True,
)
room_id = fields.Many2one(
comodel_name="pms.room",
string="Room",
help="Room related to this communication",
related="reservation_id.preferred_room_id",
index=True,
store=True,
)
batch_id = fields.Char(
string="Batch ID",
default=False,

View File

@@ -7,6 +7,22 @@
<field name="arch" type="xml">
<xpath expr="//field[@name='sequence']" position="after">
<field name="in_ine" />
<field name="institution_independent_account" />
</xpath>
<xpath expr="//notebook" position="inside">
<page
string="Travel record institution"
attrs="{'invisible': [('institution_independent_account', '=', False)]}"
>
<group>
<field name="institution" />
<field name="institution_property_id" />
<field name="institution_lessor_id" />
<field name="ses_url" />
<field name="institution_user" />
<field name="institution_password" />
</group>
</page>
</xpath>
</field>
</record>

View File

@@ -310,6 +310,13 @@ def _ses_xml_person_elements(comunicacion, checkin_partner):
def _get_auth_headers(communication):
if (
communication.reservation_id.preferred_room_id
and communication.reservation_id.preferred_room_id.institution_independent_account
):
user = communication.reservation_id.preferred_room_id.institution_user
password = communication.reservation_id.preferred_room_id.institution_password
else:
user = communication.reservation_id.pms_property_id.institution_user
password = communication.reservation_id.pms_property_id.institution_password
@@ -412,13 +419,22 @@ class TravellerReport(models.TransientModel):
required=True,
default=lambda self: self.env.user.get_active_property_ids()[0],
)
room_id = fields.Many2one(
comodel_name="pms.room",
string="Room",
domain="""
[
('pms_property_id', '=', pms_property_id),
('institution_independent_account, '=', True),
('institution', '=', 'ses')
]
""",
)
is_ses = fields.Boolean(
string="Is SES",
readonly=True,
compute="_compute_is_ses",
)
report_type = fields.Selection(
string="Report Type",
required=True,
@@ -431,21 +447,31 @@ class TravellerReport(models.TransientModel):
)
@api.depends(
"pms_property_id", "date_target", "date_from", "date_to", "report_type"
"pms_property_id",
"date_target",
"date_from",
"date_to",
"report_type",
"room_id",
)
def _compute_txt_message(self):
for record in self:
record.txt_message = False
@api.depends("pms_property_id.institution")
@api.depends("pms_property_id.institution", "room_id.institution")
def _compute_is_ses(self):
for record in self:
if record.room_id:
record.is_ses = record.room_id.institution == "ses"
else:
record.is_ses = record.pms_property_id.institution == "ses"
def generate_file_from_user_action(self):
pms_property = self.env["pms.property"].search(
[("id", "=", self.pms_property_id.id)]
)
room = self.room_id
if not room:
# check if there's institution settings properly established
if (
not pms_property
@@ -456,6 +482,15 @@ class TravellerReport(models.TransientModel):
raise ValidationError(
_("The guest information sending settings is not property set up.")
)
else:
if (
not room.institution_property_id
or not room.institution_user
or not room.institution_password
):
raise ValidationError(
_("The guest information sending settings is not property set up.")
)
content = False
# build content
@@ -464,12 +499,14 @@ class TravellerReport(models.TransientModel):
content = self.generate_ses_travellers_list(
pms_property_id=pms_property.id,
date_target=self.date_target,
room_id=room.id if room else False,
)
elif self.report_type == "reservations":
content = self.generate_ses_reservation_list(
pms_property_id=pms_property.id,
date_from=self.date_from,
date_to=self.date_to,
room_id=room.id if room else False,
)
else:
content = self.generate_checkin_list(
@@ -479,22 +516,26 @@ class TravellerReport(models.TransientModel):
if content:
if self.is_ses:
institution_property_id = (
room.institution_property_id
if room
else pms_property.institution_property_id
)
if self.report_type == "travellers":
self.txt_filename = (
pms_property.institution_property_id
institution_property_id
+ "-"
+ self.date_target.strftime("%Y%m%d")
)
else:
self.txt_filename = (
pms_property.institution_property_id
institution_property_id
+ "-"
+ self.date_from.strftime("%Y%m%d")
+ "-"
+ self.date_to.strftime("%Y%m%d")
)
self.txt_filename = self.txt_filename + ".xml"
else:
self.txt_filename = (
pms_property.institution_property_id
@@ -521,6 +562,7 @@ class TravellerReport(models.TransientModel):
}
def generate_checkin_list(self, pms_property_id, date_target=False):
# DEPRECATED
regex = re.compile("[^a-zA-Z0-9]")
# check if there's guests info pending to send
@@ -541,11 +583,13 @@ class TravellerReport(models.TransientModel):
lines = self.env["pms.checkin.partner"].search(domain)
# build the property info record
# 1 | property id | property name | date | nº of checkin partners
institution_property_id = pms_property.institution_property_id
name = pms_property.name
content = (
"1|"
+ pms_property.institution_property_id.upper()
+ institution_property_id.upper()
+ "|"
+ regex.sub(" ", pms_property.name.upper())
+ regex.sub(" ", name.upper())
+ "|"
+ datetime.datetime.now().strftime("%Y%m%d|%H%M")
+ "|"
@@ -580,6 +624,7 @@ class TravellerReport(models.TransientModel):
return content
def send_file_gc(self, file_content, called_from_user, pms_property):
# DEPRECATED
try:
_logger.info(
"Sending file to Guardia Civil, Property %s, date: %s"
@@ -680,6 +725,7 @@ class TravellerReport(models.TransientModel):
)
def send_file_pn(self, file_content, called_from_user, pms_property):
# DEPRECATED
try:
base_url = "https://webpol.policia.es"
headers = {
@@ -805,6 +851,7 @@ class TravellerReport(models.TransientModel):
)
def send_file_institution(self, pms_property=False, offset=0, date_target=False):
# DEPRECATED
called_from_user = False
log = False
try:
@@ -898,17 +945,17 @@ class TravellerReport(models.TransientModel):
@api.model
def send_file_institution_async(self, offset=0):
# DEPRECATED
for prop in self.env["pms.property"].search([]):
if prop.institution:
self.send_file_institution(pms_property=prop, offset=offset)
time.sleep(0.5)
# SES RESERVATIONS
def generate_ses_reservation_list(self, pms_property_id, date_from, date_to):
reservation_ids = (
self.env["pms.reservation"]
.search(
[
def generate_ses_reservation_list(
self, pms_property_id, date_from, date_to, room_id=False
):
domain = [
("pms_property_id", "=", pms_property_id),
("state", "!=", "cancel"),
("reservation_type", "!=", "out"),
@@ -916,15 +963,26 @@ class TravellerReport(models.TransientModel):
("date_order", ">=", date_from),
("date_order", "<=", date_to),
]
)
.mapped("id")
)
if room_id:
domain.append(("preferred_room_id.room_id", "=", room_id))
reservation_ids = self.env["pms.reservation"].search(domain).mapped("id")
return self.generate_xml_reservations(reservation_ids)
def generate_xml_reservation(self, solicitud, reservation_id):
reservation = self.env["pms.reservation"].browse(reservation_id)
if not reservation.pms_property_id.institution_property_id:
institution_property_id = False
if (
reservation.preferred_room_id
and reservation.preferred_room_id.institution_independent_account
):
institution_property_id = (
reservation.preferred_room_id.institution_property_id
)
else:
institution_property_id = (
reservation.pms_property_id.institution_property_id
)
if not institution_property_id:
raise ValidationError(
_("The property does not have an institution property id.")
)
@@ -936,9 +994,7 @@ class TravellerReport(models.TransientModel):
establecimiento = ET.SubElement(comunicacion, "establecimiento")
# SOLICITUD > COMUNICACION > ESTABLECIMIENTO > CODIGO
ET.SubElement(
establecimiento, "codigo"
).text = reservation.pms_property_id.institution_property_id
ET.SubElement(establecimiento, "codigo").text = institution_property_id
# SOLICITUD > COMUNICACION > CONTRATO
_ses_xml_contract_elements(comunicacion, reservation)
@@ -974,17 +1030,14 @@ class TravellerReport(models.TransientModel):
return xml_str
# SES RESERVATIONS TRAVELLER REPORT
def generate_ses_travellers_list(self, pms_property_id, date_target):
reservation_ids = (
self.env["pms.reservation"]
.search(
[
def generate_ses_travellers_list(self, pms_property_id, date_target, room_id=False):
domain = [
("pms_property_id", "=", pms_property_id),
("checkin", "=", date_target),
]
)
.mapped("id")
)
if room_id:
domain.append(("preferred_room_id.room_id", "=", room_id))
reservation_ids = self.env["pms.reservation"].search(domain).mapped("id")
return self.generate_xml_reservations_travellers_report(reservation_ids)
def generate_xml_reservation_travellers_report(
@@ -1029,19 +1082,34 @@ class TravellerReport(models.TransientModel):
):
raise ValidationError(_("There are some guests not onboard."))
else:
# SOLICITUD
solicitud = ET.Element("solicitud")
pms_property = (
self.env["pms.reservation"].browse(reservation_ids[0]).pms_property_id
reservations = self.env["pms.reservation"].browse(reservation_ids)
independent_accounts = reservations.filtered(
lambda r: r.preferred_room_id.institution_independent_account
)
if not pms_property.institution_property_id:
if independent_accounts:
institution_property_ids = independent_accounts.mapped(
"preferred_room_id.institution_property_id"
)
if len(institution_property_ids) != 1:
raise ValidationError(
_(
"All reservation rooms must have the same institution property id."
)
)
institution_property_id = institution_property_ids[0]
else:
pms_property = reservations[0].pms_property_id
institution_property_id = pms_property.institution_property_id
if not institution_property_id:
raise ValidationError(
_("The property does not have an institution property id.")
)
# SOLICITUD
solicitud = ET.Element("solicitud")
# SOLICITUD -> CODIGO ESTABLECIMIENTO
ET.SubElement(
solicitud, "codigoEstablecimiento"
).text = pms_property.institution_property_id
).text = institution_property_id
for reservation_id in reservation_ids:
if ignore_some_not_onboard:
num_people_on_board = len(
@@ -1084,6 +1152,17 @@ class TravellerReport(models.TransientModel):
for communication in self.env["pms.ses.communication"].search(domain):
data = False
try:
if (
communication.room_id
and communication.room_id.institution_independent_account
):
institution_lessor_id = communication.room_id.institution_lessor_id
ses_url = communication.room_id.ses_url
else:
institution_lessor_id = (
communication.reservation_id.pms_property_id.institution_lessor_id
)
ses_url = communication.reservation_id.pms_property_id.ses_url
if communication.operation == DELETE_OPERATION_CODE:
communication_to_cancel = self.env["pms.ses.communication"].search(
[
@@ -1115,7 +1194,7 @@ class TravellerReport(models.TransientModel):
communication.communication_xml = data
data = _string_to_zip_to_base64(data)
payload = _generate_payload(
communication.reservation_id.pms_property_id.institution_lessor_id,
institution_lessor_id,
communication.operation,
communication.entity,
data,
@@ -1125,7 +1204,7 @@ class TravellerReport(models.TransientModel):
soap_response = requests.request(
"POST",
communication.reservation_id.pms_property_id.ses_url,
ses_url,
headers=_get_auth_headers(communication),
data=payload,
verify=get_module_resource("pms_l10n_es", "static", "cert.pem"),
@@ -1162,6 +1241,17 @@ class TravellerReport(models.TransientModel):
]
):
try:
if (
communication.room_id
and communication.room_id.institution_independent_account
):
institution_lessor_id = communication.room_id.institution_lessor_id
ses_url = communication.room_id.ses_url
else:
institution_lessor_id = (
communication.reservation_id.pms_property_id.institution_lessor_id
)
ses_url = communication.reservation_id.pms_property_id.ses_url
time_difference = fields.Datetime.now() - communication.create_date
hours_difference = (
time_difference.days * 24 + time_difference.seconds // 3600
@@ -1181,7 +1271,7 @@ class TravellerReport(models.TransientModel):
communication.communication_xml = data
data = _string_to_zip_to_base64(data)
payload = _generate_payload(
communication.reservation_id.pms_property_id.institution_lessor_id,
institution_lessor_id,
communication.operation,
communication.entity,
data,
@@ -1191,7 +1281,7 @@ class TravellerReport(models.TransientModel):
soap_response = requests.request(
"POST",
communication.reservation_id.pms_property_id.ses_url,
ses_url,
headers=_get_auth_headers(communication),
data=payload,
verify=get_module_resource("pms_l10n_es", "static", "cert.pem"),
@@ -1224,6 +1314,17 @@ class TravellerReport(models.TransientModel):
]
):
try:
if (
communication.room_id
and communication.room_id.institution_independent_account
):
institution_lessor_id = communication.room_id.institution_lessor_id
ses_url = communication.room_id.ses_url
else:
institution_lessor_id = (
communication.reservation_id.pms_property_id.institution_lessor_id
)
ses_url = communication.reservation_id.pms_property_id.ses_url
var_xml_get_batch = f"""
<con:lotes
xmlns:con="http://www.neg.hospedajes.mir.es/consultarComunicacion">
@@ -1233,7 +1334,7 @@ class TravellerReport(models.TransientModel):
communication.query_status_xml = var_xml_get_batch
data = _string_to_zip_to_base64(var_xml_get_batch)
payload = _generate_payload(
communication.reservation_id.pms_property_id.institution_lessor_id,
institution_lessor_id,
"C",
False,
data,
@@ -1243,7 +1344,7 @@ class TravellerReport(models.TransientModel):
soap_response = requests.request(
"POST",
communication.reservation_id.pms_property_id.ses_url,
ses_url,
headers=_get_auth_headers(communication),
data=payload,
verify=get_module_resource("pms_l10n_es", "static", "cert.pem"),