diff --git a/pms/data/cron_jobs.xml b/pms/data/cron_jobs.xml index 2cd3c2029..ec067d944 100644 --- a/pms/data/cron_jobs.xml +++ b/pms/data/cron_jobs.xml @@ -61,5 +61,45 @@ /> model.update_daily_priority_reservation() + + + Send Confirmation Email + 5 + + minutes + + -1 + + code + + + model.send_confirmation_mail() + + + Send Modification Email + 5 + + minutes + + -1 + + code + + + model.send_modification_mail() + + + Send Cancellation Email + 5 + + + minutes + -1 + + code + + + model.send_cancelation_mail() + diff --git a/pms/models/mail_compose_message.py b/pms/models/mail_compose_message.py index e76de0ec6..0e74c8757 100644 --- a/pms/models/mail_compose_message.py +++ b/pms/models/mail_compose_message.py @@ -36,8 +36,10 @@ class MailComposeMessage(models.TransientModel): # folio.reservation_ids = cmds res = super(MailComposeMessage, self).send_mail(auto_commit=auto_commit) if self._context.get("record_id"): - reservation = self.env["pms.reservation"].search( + folio = self.env["pms.folio"].search( [("id", "=", self._context.get("record_id"))] ) - reservation.is_mail_send = True + reservations = folio.reservation_ids + for reservation in reservations: + reservation.is_mail_send = True return res diff --git a/pms/models/pms_folio.py b/pms/models/pms_folio.py index 68c8e769e..811d0bf90 100644 --- a/pms/models/pms_folio.py +++ b/pms/models/pms_folio.py @@ -499,6 +499,20 @@ class PmsFolio(models.Model): inverse_name="folio_possible_customer_id", ) + first_checkin = fields.Date( + string="First Folio Checkin", + readonly=False, + store=True, + compute="_compute_first_checkin", + ) + + last_checkout = fields.Date( + string="Last Folio Checkout", + readonly=False, + store=True, + compute="_compute_last_checkout", + ) + def name_get(self): result = [] for folio in self: @@ -1060,6 +1074,20 @@ class PmsFolio(models.Model): else: record.possible_existing_customer_ids = False + @api.depends("reservation_ids", "reservation_ids.checkin") + def _compute_first_checkin(self): + for record in self: + if record.reservation_ids: + checkins = record.reservation_ids.mapped("checkin") + record.first_checkin = min(checkins) + + @api.depends("reservation_ids", "reservation_ids.checkout") + def _compute_last_checkout(self): + for record in self: + if record.reservation_ids: + checkouts = record.reservation_ids.mapped("checkout") + record.last_checkout = max(checkouts) + def _search_invoice_ids(self, operator, value): if operator == "in" and value: self.env.cr.execute( @@ -1251,18 +1279,162 @@ class PmsFolio(models.Model): if self.env.context.get("confirm_all_reservations"): self.reservation_ids.confirm() - # if self.env.context.get('send_email'): - # self.force_quotation_send() - - # create an analytic account if at least an expense product - # if any([expense_policy != 'no' for expense_policy in - # self.sale_line_ids.mapped('product_id.expense_policy')]): - # if not self.analytic_account_id: - # self._create_analytic_account() return True # CHECKIN/OUT PROCESS + @api.model + def send_confirmation_mail(self): + folios = self.env["pms.folio"].search([]) + if folios and all( + is_confirmed_auto_mail + for is_confirmed_auto_mail in folios.pms_property_id.mapped( + "is_confirmed_auto_mail" + ) + ): + for folio in folios: + create_date = folio.create_date.date() + if ( + folio.state in "confirm" + and create_date == fields.Date.today() + and all( + not mail_send + for mail_send in folio.reservation_ids.mapped("is_mail_send") + ) + and all( + not is_modified_reservation + for is_modified_reservation in folio.reservation_ids.mapped( + "is_modified_reservation" + ) + ) + ): + template = folio.pms_property_id.property_confirmed_template + subject = template._render_field( + "subject", + [6, 0, folio.id], + compute_lang=True, + post_process=True, + )[folio.id] + body = template._render_field( + "body_html", + [6, 0, folio.id], + compute_lang=True, + post_process=True, + )[folio.id] + invitation_mail = ( + folio.env["mail.mail"] + .sudo() + .create( + { + "subject": subject, + "body_html": body, + "email_from": folio.pms_property_id.partner_id.email, + "email_to": folio.email, + } + ) + ) + invitation_mail.send() + for reservation in folio.reservation_ids: + reservation.is_mail_send = True + + @api.model + def send_modification_mail(self): + folios = self.env["pms.folio"].search([]) + if folios and all( + is_modified_auto_mail + for is_modified_auto_mail in folios.pms_property_id.mapped( + "is_modified_auto_mail" + ) + ): + for folio in folios: + if ( + folio.state in ("confirm", "onboard") + and any( + not mail_send + for mail_send in folio.reservation_ids.mapped("is_mail_send") + ) + and any( + is_modified_reservation + for is_modified_reservation in folio.reservation_ids.mapped( + "is_modified_reservation" + ) + ) + ): + template = folio.pms_property_id.property_modified_template + subject = template._render_field( + "subject", + [6, 0, folio.id], + compute_lang=True, + post_process=True, + )[folio.id] + body = template._render_field( + "body_html", + [6, 0, folio.id], + compute_lang=True, + post_process=True, + )[folio.id] + invitation_mail = ( + folio.env["mail.mail"] + .sudo() + .create( + { + "subject": subject, + "body_html": body, + "email_from": folio.pms_property_id.partner_id.email, + "email_to": folio.email, + } + ) + ) + invitation_mail.send() + for reservation in folio.reservation_ids: + reservation.is_mail_send = True + + @api.model + def send_cancelation_mail(self): + folios = self.env["pms.folio"].search([]) + if folios and all( + is_canceled_auto_mail + for is_canceled_auto_mail in folios.pms_property_id.mapped( + "is_canceled_auto_mail" + ) + ): + for folio in folios: + reservations = folio.reservation_ids.filtered( + lambda r: r.state in "cancel" + ) + for reservation in reservations: + if not reservation.is_mail_send: + template = ( + reservation.pms_property_id.property_canceled_template + ) + subject = template._render_field( + "subject", + [6, 0, reservation.id], + compute_lang=True, + post_process=True, + )[reservation.id] + body = template._render_field( + "body_html", + [6, 0, reservation.id], + compute_lang=True, + post_process=True, + )[reservation.id] + invitation_mail = ( + folio.env["mail.mail"] + .sudo() + .create( + { + "subject": subject, + "body_html": body, + "email_from": folio.pms_property_id.partner_id.email, + "email_to": folio.email, + } + ) + ) + invitation_mail.send() + for reservation in folio.reservation_ids: + reservation.is_mail_send = True + def action_view_invoice(self): invoices = self.mapped("move_ids") action = self.env["ir.actions.actions"]._for_xml_id( diff --git a/pms/models/pms_property.py b/pms/models/pms_property.py index 16d9209b2..7f2be5011 100644 --- a/pms/models/pms_property.py +++ b/pms/models/pms_property.py @@ -122,32 +122,27 @@ class PmsProperty(models.Model): privacy_policy = fields.Html(string="Privacy Policy", help="Mail privacy policy ") property_confirmed_template = fields.Many2one( - string="Confirmation Template", + string="Confirmation Email", help="Confirmation email template", comodel_name="mail.template", - default=lambda self: self.env["mail.template"] - .search([("name", "=", "Confirmed Reservation")]) - .id, ) property_modified_template = fields.Many2one( - string="Modification Template", + string="Modification Email", help="Modification email template", comodel_name="mail.template", - default=lambda self: self.env["mail.template"] - .search([("name", "=", "Modified Reservation")]) - .id, ) property_canceled_template = fields.Many2one( - string="Cancellation Template", + string="Cancellation Email", help="Cancellation email template", comodel_name="mail.template", - default=lambda self: self.env["mail.template"] - .search([("name", "=", "Cancelled Reservation")]) - .id, ) + is_confirmed_auto_mail = fields.Boolean(string="Auto Send Confirmation Mail") + is_modified_auto_mail = fields.Boolean(string="Auto Send Modification Mail") + is_canceled_auto_mail = fields.Boolean(string="Auto Send Cancellation Mail") + @api.depends_context( "checkin", "checkout", diff --git a/pms/models/pms_reservation.py b/pms/models/pms_reservation.py index b4132fcfd..a215ecf82 100644 --- a/pms/models/pms_reservation.py +++ b/pms/models/pms_reservation.py @@ -1727,38 +1727,36 @@ class PmsReservation(models.Model): def action_open_mail_composer(self): self.ensure_one() template = False + pms_property = self.pms_property_id if ( not self.is_mail_send and not self.is_modified_reservation and self.state not in "cancel" ): - template = self.env.ref( - "pms.confirmed_reservation_email", raise_if_not_found=False - ) + if pms_property.property_confirmed_template: + template = pms_property.property_confirmed_template elif ( not self.is_mail_send and self.is_modified_reservation and self.state not in "cancel" ): - template = self.env.ref( - "pms.modified_reservation_email", raise_if_not_found=False - ) + if pms_property.property_modified_template: + template = pms_property.property_modified_template elif not self.is_mail_send and self.state in "cancel": - template = self.env.ref( - "pms.cancelled_reservation_email", raise_if_not_found=False - ) + if pms_property.property_canceled_template: + template = pms_property.property_canceled_template compose_form = self.env.ref( "mail.email_compose_message_wizard_form", raise_if_not_found=False ) ctx = dict( - model="pms.reservation", - default_res_model="pms.reservation", - default_res_id=self.id, + model="pms.folio", + default_res_model="pms.folio", + default_res_id=self.folio_id.id, template_id=template and template.id or False, composition_mode="comment", partner_ids=[self.partner_id.id], force_email=True, - record_id=self.id, + record_id=self.folio_id.id, ) return { "name": _("Send Confirmed Reservation Mail "), diff --git a/pms/views/pms_property_views.xml b/pms/views/pms_property_views.xml index b89e4c6d0..f1ba521dc 100644 --- a/pms/views/pms_property_views.xml +++ b/pms/views/pms_property_views.xml @@ -86,10 +86,44 @@ - - - - + +
+
+ + + + + +
+
+ + + + + +
+