From d28ab6aacd227526cc2b5f2c5d9488fe729f9286 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dar=C3=ADo=20Lodeiros?= Date: Sun, 15 Dec 2024 18:48:38 +0100 Subject: [PATCH] [IMP]pms_l10n_es: allow traveler report account by room --- pms_l10n_es/models/pms_reservation.py | 22 +- pms_l10n_es/models/pms_room.py | 35 +++ pms_l10n_es/models/pms_ses_communication.py | 8 + pms_l10n_es/views/pms_room_views.xml | 16 ++ pms_l10n_es/wizards/traveller_report.py | 235 ++++++++++++++------ 5 files changed, 239 insertions(+), 77 deletions(-) diff --git a/pms_l10n_es/models/pms_reservation.py b/pms_l10n_es/models/pms_reservation.py index eb6492f553..69e5e341f6 100644 --- a/pms_l10n_es/models/pms_reservation.py +++ b/pms_l10n_es/models/pms_reservation.py @@ -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: - record.is_ses = record.pms_property_id.institution == "ses" + if ( + record.preferred_room_id + and record.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 @@ def _compute_ses_status_reservation(self): 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 @@ def _compute_ses_status_traveller_report(self): @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 @@ def create_communication_after_update_reservation(self, reservation, vals): 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) diff --git a/pms_l10n_es/models/pms_room.py b/pms_l10n_es/models/pms_room.py index 76dbc5efd3..5efc348b69 100644 --- a/pms_l10n_es/models/pms_room.py +++ b/pms_l10n_es/models/pms_room.py @@ -3,8 +3,43 @@ 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.", + ) diff --git a/pms_l10n_es/models/pms_ses_communication.py b/pms_l10n_es/models/pms_ses_communication.py index 41056c62b6..1931b1893d 100644 --- a/pms_l10n_es/models/pms_ses_communication.py +++ b/pms_l10n_es/models/pms_ses_communication.py @@ -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, diff --git a/pms_l10n_es/views/pms_room_views.xml b/pms_l10n_es/views/pms_room_views.xml index 820fceaa94..7bccd886b7 100644 --- a/pms_l10n_es/views/pms_room_views.xml +++ b/pms_l10n_es/views/pms_room_views.xml @@ -7,6 +7,22 @@ + + + + + + + + + + + + + diff --git a/pms_l10n_es/wizards/traveller_report.py b/pms_l10n_es/wizards/traveller_report.py index b90bf10295..de3c6138d1 100644 --- a/pms_l10n_es/wizards/traveller_report.py +++ b/pms_l10n_es/wizards/traveller_report.py @@ -310,8 +310,15 @@ def _ses_xml_person_elements(comunicacion, checkin_partner): def _get_auth_headers(communication): - user = communication.reservation_id.pms_property_id.institution_user - password = communication.reservation_id.pms_property_id.institution_password + 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 user_and_password_base64 = "Basic " + base64.b64encode( bytes(user + ":" + password, "utf-8") @@ -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,31 +447,50 @@ 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: - record.is_ses = record.pms_property_id.institution == "ses" + 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)] ) - # 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 set up.") - ) + room = self.room_id + if not room: + # 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 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 @@ def generate_file_from_user_action(self): 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 @@ def generate_file_from_user_action(self): 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 @@ def generate_file_from_user_action(self): } 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 @@ def generate_checkin_list(self, pms_property_id, date_target=False): 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 @@ def generate_checkin_list(self, pms_property_id, date_target=False): 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 @@ def send_file_gc(self, file_content, called_from_user, pms_property): ) 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 @@ def send_file_pn(self, file_content, called_from_user, pms_property): ) def send_file_institution(self, pms_property=False, offset=0, date_target=False): + # DEPRECATED called_from_user = False log = False try: @@ -898,33 +945,44 @@ def send_file_institution(self, pms_property=False, offset=0, date_target=False) @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( - [ - ("pms_property_id", "=", pms_property_id), - ("state", "!=", "cancel"), - ("reservation_type", "!=", "out"), - "|", - ("date_order", ">=", date_from), - ("date_order", "<=", date_to), - ] - ) - .mapped("id") - ) + 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"), + "|", + ("date_order", ">=", date_from), + ("date_order", "<=", date_to), + ] + 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 @@ def generate_xml_reservation(self, solicitud, reservation_id): 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 @@ def generate_xml_reservations(self, reservation_ids): 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( - [ - ("pms_property_id", "=", pms_property_id), - ("checkin", "=", date_target), - ] - ) - .mapped("id") - ) + def generate_ses_travellers_list(self, pms_property_id, date_target, room_id=False): + domain = [ + ("pms_property_id", "=", pms_property_id), + ("checkin", "=", date_target), + ] + 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 @@ def generate_xml_reservations_travellers_report( ): 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: - raise ValidationError( - _("The property does not have an 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 @@ def ses_send_communications(self, entity, pms_ses_communication_id=False): 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 @@ def ses_send_communications(self, entity, pms_ses_communication_id=False): 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 @@ def ses_send_communications(self, entity, pms_ses_communication_id=False): 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 @@ def ses_send_incomplete_traveller_reports( ] ): 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 @@ def ses_send_incomplete_traveller_reports( 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 @@ def ses_send_incomplete_traveller_reports( 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 @@ def ses_process_communications(self): ] ): 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""" @@ -1233,7 +1334,7 @@ def ses_process_communications(self): 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 @@ def ses_process_communications(self): 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"),