From d5302160e65cac675efff2e3251139f1e1a58019 Mon Sep 17 00:00:00 2001 From: braisab Date: Wed, 13 Oct 2021 20:46:49 +0200 Subject: [PATCH] [IMP]: improvements in precheckin portal --- pms/controllers/pms_portal.py | 168 +-- pms/models/pms_checkin_partner.py | 78 +- pms/models/pms_reservation.py | 1 + pms/security/ir.model.access.csv | 1 - pms/security/pms_security.xml | 2 +- pms/views/pms_reservation_views.xml | 2 +- pms/views/precheckin_portal_templates.xml | 1295 +++++++++++++-------- 7 files changed, 949 insertions(+), 598 deletions(-) diff --git a/pms/controllers/pms_portal.py b/pms/controllers/pms_portal.py index 1164e6dd6..29d7efc25 100644 --- a/pms/controllers/pms_portal.py +++ b/pms/controllers/pms_portal.py @@ -128,8 +128,8 @@ class PortalFolio(CustomerPortal): return request.redirect("/my") values.update(self._folio_get_page_view_values(folio_sudo, access_token, **kw)) values.update({"no_breadcrumbs": True, "error": {}}) - country_ids = request.env['res.country'].search([]) - state_ids = request.env['res.country.state'].search([]) + country_ids = request.env["res.country"].search([]) + state_ids = request.env["res.country.state"].search([]) doc_type_ids = request.env["res.partner.id_category"].sudo().search([]) values.update( { @@ -175,9 +175,7 @@ class PortalReservation(CustomerPortal): auth="user", website=True, ) - def portal_my_reservations( - self, page=1, date_begin=None, date_end=None, sortby=None, filterby=None, **kw - ): + def portal_my_reservations(self, page=1, date_begin=None, date_end=None): partner = request.env.user.partner_id values = self._prepare_portal_layout_values() Reservation = request.env["pms.reservation"] @@ -239,8 +237,6 @@ class PortalReservation(CustomerPortal): ) except (AccessError, MissingError): return request.redirect("/my") - # for attachment in reservation_sudo.attachment_ids: - # attachment.generate_access_token() values = self._reservation_get_page_view_values( reservation_sudo, access_token, **kw ) @@ -252,9 +248,7 @@ class PortalReservation(CustomerPortal): auth="user", website=True, ) - def portal_my_reservation_precheckin( - self, reservation_id, access_token=None, report_type=None, download=False, **kw - ): + def portal_my_reservation_precheckin(self, reservation_id, access_token=None, **kw): try: reservation_sudo = self._document_check_access( "pms.reservation", @@ -298,26 +292,24 @@ class PortalPrecheckin(CustomerPortal): except (AccessError, MissingError): return request.redirect("/my") values = self._precheckin_get_page_view_values(checkin_sudo, access_token, **kw) - country_ids = request.env['res.country'].search([]) - state_ids = request.env['res.country.state'].search([]) - doc_type_ids = request.env['res.partner.id_category'].sudo().search([]) + country_ids = request.env["res.country"].search([]) + state_ids = request.env["res.country.state"].search([]) + doc_type_ids = request.env["res.partner.id_category"].sudo().search([]) values.update( { "doc_type_ids": doc_type_ids, "country_ids": country_ids, "state_ids": state_ids, "no_breadcrumbs": True, - "error": {} + "error": {}, } ) return request.render("pms.portal_my_precheckin_detail", values) @http.route(["/my/precheckin"], type="http", auth="user", website=True, csrf=False) - def portal_precheckin_submit(self, access_token=None, **kw): + def portal_precheckin_submit(self, **kw): values = dict() - checkin_partner = request.env["pms.checkin.partner"].browse( - int(kw.get("id")) - ) + checkin_partner = request.env["pms.checkin.partner"].browse(int(kw.get("id"))) values.update( { "checkin_partner": checkin_partner, @@ -325,8 +317,8 @@ class PortalPrecheckin(CustomerPortal): "error_message": {}, } ) - country_ids = request.env['res.country'].search([]) - state_ids = request.env['res.country.state'].search([]) + country_ids = request.env["res.country"].search([]) + state_ids = request.env["res.country.state"].search([]) doc_type_ids = request.env["res.partner.id_category"].sudo().search([]) if kw: error, error_message = self.form_validate(kw, None) @@ -341,35 +333,34 @@ class PortalPrecheckin(CustomerPortal): } ) if error: - return request.render("pms.portal_my_precheckin_detail", values) else: try: values = kw if values.get("document_type"): - doc_type = request.env["res.partner.id_category"].sudo().search([("name", "=", values.get("document_type"))]) + doc_type = ( + request.env["res.partner.id_category"] + .sudo() + .search([("name", "=", values.get("document_type"))]) + ) values.update( { "document_type": doc_type, } ) - request.env["pms.checkin.partner"].sudo()._save_data_from_portal(values) - doc_type_ids = request.env['res.partner.id_category'].sudo().search([]) + request.env["pms.checkin.partner"].sudo()._save_data_from_portal( + values + ) + doc_type_ids = ( + request.env["res.partner.id_category"].sudo().search([]) + ) values.update( { "doc_type_ids": doc_type_ids, } ) - # if values.get("document_type"): - # doc_type_id = values.get("document_type") - # doc_type = request.env["res.partner.id_category"].sudo().search([("id", "=", doc_type_id)]) - # values.update( - # { - # "document_type": doc_type, - # } - # ) - country_ids = request.env['res.country'].search([]) - state_ids = request.env['res.country.state'].search([]) + country_ids = request.env["res.country"].search([]) + state_ids = request.env["res.country.state"].search([]) values.update( { "country_ids": country_ids, @@ -409,40 +400,36 @@ class PortalPrecheckin(CustomerPortal): int(kw.get("reservation_id")) ) checkin_partners = reservation.checkin_partner_ids - country_ids = request.env['res.country'].search([]) - state_ids = request.env['res.country.state'].search([]) - doc_type_ids = request.env["res.partner.id_category"].sudo().search([]) - values = { - "no_breadcrumbs": True, - "country_ids": country_ids, - "state_ids": state_ids, - "doc_type_ids": doc_type_ids, - } for checkin in checkin_partners: - values.update( - { - "id": kw.get("id-" + str(counter)), - "firstname": kw.get("firstname-" + str(counter)), - "lastname": kw.get("lastname-" + str(counter)), - "lastname2": kw.get("lastname2-" + str(counter)), - "gender": kw.get("gender-" + str(counter)), - "birthdate_date": kw.get("birthdate_date-" + str(counter)) - if kw.get("birthdate_date-" + str(counter)) - else False, - "document_type": kw.get("document_type-" + str(counter)), - "document_number": kw.get("document_number-" + str(counter)), - "document_expedition_date": kw.get( - "document_expedition_date-" + str(counter) - ) - if kw.get("document_expedition_date-" + str(counter)) - else False, - "mobile": kw.get("mobile-" + str(counter)), - "email": kw.get("email-" + str(counter)), - } - ) + values = { + "id": kw.get("id-" + str(counter)), + "firstname": kw.get("firstname-" + str(counter)), + "lastname": kw.get("lastname-" + str(counter)), + "lastname2": kw.get("lastname2-" + str(counter)), + "gender": kw.get("gender-" + str(counter)), + "birthdate_date": kw.get("birthdate_date-" + str(counter)) + if kw.get("birthdate_date-" + str(counter)) + else False, + "document_type": kw.get("document_type-" + str(counter)), + "document_number": kw.get("document_number-" + str(counter)), + "document_expedition_date": kw.get( + "document_expedition_date-" + str(counter) + ) + if kw.get("document_expedition_date-" + str(counter)) + else False, + "mobile": kw.get("mobile-" + str(counter)), + "email": kw.get("email-" + str(counter)), + "nationality_id": kw.get("nationality_id-" + str(counter)), + "state": kw.get("state-" + str(counter)), + } + if values.get("document_type"): doc_type_code = values.get("document_type") - doc_type = request.env["res.partner.id_category"].sudo().search([("code", "=", doc_type_code)]) + doc_type = ( + request.env["res.partner.id_category"] + .sudo() + .search([("name", "=", doc_type_code)]) + ) values.update( { "document_type": doc_type, @@ -450,19 +437,30 @@ class PortalPrecheckin(CustomerPortal): ) error, error_message = self.form_validate(kw, counter) errors.update(error) + e_messages.update(error_message) if error_message: has_error = True else: checkin.sudo()._save_data_from_portal(values) counter = counter + 1 values = {"no_breadcrumbs": True} - + doc_type_ids = request.env["res.partner.id_category"].sudo().search([]) + country_ids = request.env["res.country"].search([]) + state_ids = request.env["res.country.state"].search([]) + values.update( + { + "doc_type_ids": doc_type_ids, + "country_ids": country_ids, + "state_ids": state_ids, + } + ) if has_error: - filtered_dict = {k: v for k, v in errors.items() if v} - values.update({"error": filtered_dict}) + filtered_dict_error = {k: v for k, v in errors.items() if v} + filtered_dict_error_messages = {k: v for k, v in e_messages.items() if v} values.update( { - "error_message": e_messages, + "error": filtered_dict_error, + "error_message": filtered_dict_error_messages, } ) else: @@ -539,11 +537,13 @@ class PortalPrecheckin(CustomerPortal): ) if data[document_expedition_date] and not data[document_number]: error[document_expedition_date] = "error" - error_message[document_expedition_date] = "Document Number not entered and Document Type is not selected" + error_message[ + document_expedition_date + ] = "Document Number not entered and Document Type is not selected" if data[document_number]: if not data[document_type]: error[document_type] = "error" - error_message[document_type] ="Document Type is not selected" + error_message[document_type] = "Document Type is not selected" if data[document_type] == "D": if len(data[document_number]) == 9 or len(data[document_number]) == 10: if not re.match(r"^\d{8}[ -]?[a-zA-Z]$", data[document_number]): @@ -576,8 +576,8 @@ class PortalPrecheckin(CustomerPortal): } dni_number = data[document_number][0:8] dni_letter = data[document_number][ - len(data[document_number]) - 1 : len(data[document_number]) - ] + len(data[document_number]) - 1 : len(data[document_number]) + ] if letters.get(int(dni_number) % 23) != dni_letter.upper(): error[document_number] = "error" error_message[document_number] = "DNI format is invalid" @@ -593,27 +593,33 @@ class PortalPrecheckin(CustomerPortal): r"^[X|Y]{1}[ -]?\d{7,8}[ -]?[a-zA-Z]$", data[document_number] ): error[document_number] = "error" - error_message[document_number] = "The Spanish Residence Permit format is wrong" + error_message[ + document_number + ] = "The Spanish Residence Permit format is wrong" if data[document_type] == "X" and not re.match( r"^[X|Y]{1}[ -]?\d{7,8}[ -]?[a-zA-Z]$", data[document_number] ): error[document_number] = "error" - error_message[document_number] = "The European Residence Permit format is wrong" + error_message[ + document_number + ] = "The European Residence Permit format is wrong" elif data[document_type]: error[document_number] = "error" error_message[document_number] = "Document Number not entered" return error, error_message - @http.route( ["/my/precheckin/send_invitation"], auth="user", + type="json", website=True, csrf=False, ) def portal_precheckin_folio_send_invitation(self, **kw): - print(kw) - # checkin_partner_id = kw.get("checkin_partner_id") - # checkin_partner = request.env["pms.checkin.partner"].search([("id", "=", checkin_partner_id)]) - # print(checkin_partner) - return request.redirect("/my") + checkin_partner = request.env["pms.checkin.partner"].browse( + int(kw["checkin_partner_id"]) + ) + url = kw.get("url_access_token") + firstname = kw["firstname"] + email = kw["email"] + checkin_partner.send_portal_invitation_email(url, firstname, email) diff --git a/pms/models/pms_checkin_partner.py b/pms/models/pms_checkin_partner.py index 5ffecca6e..cf6944285 100644 --- a/pms/models/pms_checkin_partner.py +++ b/pms/models/pms_checkin_partner.py @@ -3,13 +3,14 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import json +from datetime import datetime + +from dateutil.relativedelta import relativedelta from odoo import _, api, fields, models from odoo.exceptions import UserError, ValidationError -from odoo.tools.safe_eval import safe_eval -from datetime import datetime -from dateutil.relativedelta import relativedelta from odoo.tools import DEFAULT_SERVER_DATE_FORMAT +from odoo.tools.safe_eval import safe_eval class PmsCheckinPartner(models.Model): @@ -468,20 +469,6 @@ class PmsCheckinPartner(models.Model): for checkin in self: checkin.access_url = "/my/precheckin/%s" % (checkin.id) - @api.model - def _checkin_mandatory_fields(self, depends=False): - # api.depends need "reservation_id.state" in the lambda function - if depends: - return ["reservation_id.state", "name"] - return ["name"] - - @api.model - def _checkin_partner_fields(self): - # api.depends need "reservation_id.state" in the lambda function - checkin_fields = self._checkin_mandatory_fields() - checkin_fields.extend(["mobile", "email"]) - return checkin_fields - # Constraints and onchanges @api.constrains("departure", "arrival") @@ -674,21 +661,23 @@ class PmsCheckinPartner(models.Model): checkin.write(checkin_vals) @api.model - def calculate_doc_type_expedition_date_from_validity_date(self, doc_type, doc_date, birthdate): + def calculate_doc_type_expedition_date_from_validity_date( + self, doc_type, doc_date, birthdate + ): today = fields.datetime.today() datetime_doc_date = datetime.strptime(doc_date, DEFAULT_SERVER_DATE_FORMAT) if datetime_doc_date < today: return datetime_doc_date datetime_birthdate = datetime.strptime(birthdate, DEFAULT_SERVER_DATE_FORMAT) age = today.year - datetime_birthdate.year - document_type = self.env["res.partner.id_category"].search([("id", "=", doc_type)]) + # document_type = self.env["res.partner.id_category"].search([("id", "=", doc_type)]) document_expedition_date = False - if document_type.code == "D" or document_type.code == "P": + if doc_type.code == "D" or doc_type.code == "P": if age < 30: document_expedition_date = datetime_doc_date - relativedelta(years=5) else: document_expedition_date = datetime_doc_date - relativedelta(years=10) - if document_type.code == "C": + if doc_type.code == "C": if age < 70: document_expedition_date = datetime_doc_date - relativedelta(years=10) return document_expedition_date @@ -748,31 +737,56 @@ class PmsCheckinPartner(models.Model): "type": "ir.actions.act_window", "context": ctx, } + def _save_data_from_portal(self, values): checkin_partner = self.env["pms.checkin.partner"].browse(int(values.get("id"))) if values.get("nationality_id"): - nationality_id = self.env['res.country'].search([("id", "=", values.get("nationality_id"))]) + nationality_id = self.env["res.country"].search( + [("id", "=", values.get("nationality_id"))] + ) values.update({"nationality_id": nationality_id.id}) else: values.update({"nationality_id": False}) if not values.get("document_type"): values.update({"document_type": False}) - # else: - # doc_type_id = values.get("document_type") - # document_type = self.env["res.partner.id_category"].search([("id", "=", doc_type_id)]) - # values.update({"document_type": document_type.id}) if values.get("state"): - state_id = self.env["res.country.state"].search([("id", "=", values.get("state"))]) - values.update( - { - "state_id": state_id - } + state_id = self.env["res.country.state"].search( + [("id", "=", values.get("state"))] ) + values.update({"state_id": state_id}) values.pop("state") if values.get("document_expedition_date"): doc_type = values.get("document_type") doc_date = values.get("document_expedition_date") birthdate = values.get("birthdate_date") - document_expedition_date = self.calculate_doc_type_expedition_date_from_validity_date(doc_type, doc_date, birthdate) + document_expedition_date = ( + self.calculate_doc_type_expedition_date_from_validity_date( + doc_type, doc_date, birthdate + ) + ) values.update({"document_expedition_date": document_expedition_date}) checkin_partner.sudo().write(values) + + def send_portal_invitation_email(self, url, firstname=None, email=None): + subject = ( + "Hi " + + firstname + + ", do your check-in now in " + + self.sudo().pms_property_id.name + ) + template = self.sudo().env.ref( + "pms.precheckin_invitation_email", raise_if_not_found=False + ) + invitation_mail = ( + self.env["mail.mail"] + .sudo() + .create( + { + "subject": subject, + "body_html": template.body_html, + "email_from": self.pms_property_id.partner_id.email, + "email_to": email, + } + ) + ) + invitation_mail.send() diff --git a/pms/models/pms_reservation.py b/pms/models/pms_reservation.py index e9cd685b8..afeefcf4e 100644 --- a/pms/models/pms_reservation.py +++ b/pms/models/pms_reservation.py @@ -1134,6 +1134,7 @@ class PmsReservation(models.Model): record.checkout = False # date checking record.check_in_out_dates() + def _compute_precheckin_url(self): super(PmsReservation, self)._compute_access_url() for reservation in self: diff --git a/pms/security/ir.model.access.csv b/pms/security/ir.model.access.csv index a587d4c21..0cf1b3a73 100644 --- a/pms/security/ir.model.access.csv +++ b/pms/security/ir.model.access.csv @@ -62,6 +62,5 @@ user_access_pms_folio_portal,user_access_pms_folio_portal,model_pms_folio,base.g user_access_pms_reservation_portal,user_access_pms_reservation_portal,model_pms_reservation,base.group_portal,1,0,0,0 user_access_pms_automated_mails,user_access_pms_automated_mails,model_pms_automated_mails,pms.group_pms_user,1,1,1,1 access_pms_several_partners_wizard,access_pms_several_partners_wizard,model_pms_several_partners_wizard,base.group_user,1,1,1,1 -user_access_pms_precheckin_portal,user_access_pms_precheckin_portal,model_pms_checkin_partner,base.group_portal,1,0,0,0 user_access_res_partner_portal,user_access_res_partner_portal,model_res_partner,base.group_portal,1,1,1,1 user_access_pms_precheckin_portal,user_access_pms_precheckin_portal,model_pms_checkin_partner,base.group_portal,1,1,1,1 diff --git a/pms/security/pms_security.xml b/pms/security/pms_security.xml index a47fff764..7ab889e8c 100644 --- a/pms/security/pms_security.xml +++ b/pms/security/pms_security.xml @@ -256,7 +256,7 @@ [] - + diff --git a/pms/views/pms_reservation_views.xml b/pms/views/pms_reservation_views.xml index 21680490c..53216b050 100644 --- a/pms/views/pms_reservation_views.xml +++ b/pms/views/pms_reservation_views.xml @@ -360,7 +360,7 @@ string="General Info" name="contact_details" > - + Contact Details
- - - @@ -34,7 +31,10 @@ t-att-value="firstname or checkin_partner.firstname" /> - +
@@ -66,19 +66,25 @@ class="col-form-label" for="document_type" >Doc. Type - - +
@@ -93,7 +99,10 @@ t-att-value="doc_number or checkin_partner.document_number" /> - +
@@ -105,7 +114,7 @@ class="fa fa-question-circle fa-lg" data-toggle="tooltip" title="If you enter the validity date of the document, the expedition date will be automatically calculated and entered depending on the document type." - style = "margin-left: 70px;" + style="margin-left: 70px;" /> - +
@@ -129,7 +141,10 @@ t-att-value="birth_date or checkin_partner.birthdate_date" /> - +
@@ -144,7 +159,10 @@ t-att-value="mobile or checkin_partner.mobile" /> - +
@@ -156,7 +174,10 @@ t-att-value="email or checkin_partner.email" /> - +
@@ -165,8 +186,8 @@ for="gender" >Gender

+ t-esc="checkin_partner.gender" + />

+ @@ -218,7 +243,11 @@ + +
+ + +
+
+ + +
+
-
- - + Send Invitation
-
- - -
-
- - -
-
- - -
-
- -

- -
-
- - -

- -
-
- - -
-
- - -
-
- - -
-
- - -
-
+ + + + + + + + + + +
+
+
+
- + +
+
+
+
+ + + + + +
+
+ + +
+
+ + +
+
+ + + + + +
+
+ + + + + +
+
+ + + + + + +
+
+ + + + + +
+
+ + + + + +
+
+ + + + + +
+
+ +

+ +
+
+ + +
+
+ + +
+
+
-
- - + + +
@@ -601,7 +804,9 @@ - PreCheckin in Folio + PreCheckin in @@ -610,28 +815,38 @@ - - - + + + + + + + + + + + + + + - Reservation: + Room Type: - + @@ -652,8 +867,9 @@ - + Host @@ -669,9 +885,21 @@ />