Merge PR #7 into 14.0

Signed-off-by DarioLodeiros
This commit is contained in:
OCA-git-bot
2021-09-15 09:37:14 +00:00
17 changed files with 2081 additions and 18 deletions

View File

@@ -14,6 +14,7 @@
"installable": True,
"depends": [
"base",
"base_automation",
"mail",
# "account_payment_return",
# "email_template_qweb",
@@ -32,6 +33,9 @@
"security/ir.model.access.csv",
"data/cron_jobs.xml",
"data/pms_sequence.xml",
"data/pms_confirmed_reservation_email_template.xml",
"data/pms_modified_reservation_email_template.xml",
"data/pms_cancelled_reservation_email_template.xml",
"data/pms_data.xml",
"data/traveller_report_paperformat.xml",
"report/pms_folio.xml",
@@ -77,6 +81,7 @@
"views/res_company_views.xml",
"views/traveller_report_template.xml",
"wizards/wizard_split_join_swap_reservation.xml",
"views/pms_automated_mails_views.xml",
"wizards/wizard_massive_changes.xml",
"wizards/wizard_advanced_filters.xml",
],

View File

@@ -0,0 +1,160 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data>
<record id="cancelled_reservation_email" model="mail.template">
<field name="name">Cancelled Reservation</field>
<field name="model_id" ref="pms.model_pms_reservation" />
<field
name="subject"
>Your reservation in ${object.pms_property_id.name} has been cancelled</field>
<field
name="email_from"
>${object.pms_property_id.partner_id.email | safe}</field>
<field
name="email_to"
>${(object.email and '"%s" &lt;%s&gt;' % (object.name, object.email) or object.partner_id.email_formatted or '') | safe}</field>
<field name="body_html" type="html">
<table
border="0"
cellpadding="0"
cellspacing="0"
style="padding-top: 16px; background-color: #F1F1F1; font-family:Verdana, Arial,sans-serif; color: #454748; width: 100%; border-collapse:separate;"
><tr><td align="center">
<table
border="0"
cellpadding="0"
cellspacing="0"
width="590"
style="padding: 16px; background-color: white; color: #454748; border-collapse:separate;"
>
<tbody>
<!-- HEADER -->
<!-- PROPERTY DESCRIPTION -->
<tr>
<td align="center" style="min-width: 590px;">
<table
width="590"
border="0"
cellpadding="0"
cellspacing="0"
style="min-width: 590px; background-color: white; padding: 0px 0px 0px 0px; border-collapse:separate;"
>
<tr><td align="right">
<div class="col-sm-4">
% if object.pms_property_id.partner_id.street
<p
>${object.pms_property_id.partner_id.street}</p>
% endif
% if object.pms_property_id.partner_id.street2
<p
>${object.pms_property_id.partner_id.street2}</p>
% endif
<p
>${object.pms_property_id.partner_id.zip}</p>
<p
>${object.pms_property_id.partner_id.city}</p>
<p
>${object.pms_property_id.partner_id.country_id.name}</p>
</div>
</td></tr>
<tr><td valign="top" style="font-size: 14px;">
<hr
width="100%"
style="background-color:rgb(204,204,204);border:medium none;clear:both;display:block;font-size:0px;min-height:1px;line-height:0; margin: 16px 0px 16px 0px;"
/>
<div>
Hello ${object.partner_id.name or ''},<br
/>
Your reservation at ${object.pms_property_id.name} has been successfully canceled.
</div>
</td></tr>
</table>
</td>
</tr>
<!-- DETAILS -->
<tr>
<td align="center" style="min-width: 590px;">
<table
width="590"
border="0"
cellpadding="0"
cellspacing="0"
style="min-width: 590px; background-color: white; padding: 0px 8px 0px 8px; border-collapse:separate;"
>
<tr><td valign="top" style="font-size: 14px;">
<hr
width="100%"
style="background-color:rgb(204,204,204);border:medium none;clear:both;display:block;font-size:0px;min-height:1px;line-height:0; margin: 16px 0px 16px 0px;"
/>
<!-- CONTACT -->
<div>
<div
>If you have questions please contact with us:</div>
<ul>
<li
>${object.pms_property_id.name}</li>
% if object.pms_property_id.partner_id.email
<li>Mail: <a
href="mailto:${object.pms_property_id.partner_id.email}"
style="text-decoration:none;color:#875A7B;"
>${object.pms_property_id.partner_id.email}</a></li>
% endif
% if object.pms_property_id.partner_id.phone
<li
>Phone: ${object.pms_property_id.partner_id.phone}</li>
% endif
% if object.pms_property_id.partner_id.mobile
<li
>Mobile: ${object.pms_property_id.partner_id.mobile}</li>
% endif
</ul>
</div>
</td></tr>
</table>
</td>
</tr>
</tbody>
</table>
</td></tr>
<!-- FOOTER -->
<tr><td align="center" style="min-width: 590px;">
% if object.pms_property_id.privacy_policy
<table
width="590"
border="0"
cellpadding="0"
cellspacing="0"
style="min-width: 590px; background-color: #F1F1F1; color: #454748; padding: 8px; border-collapse:separate;"
>
<tr><td style="font-size: 10px;">
${object.pms_property_id.privacy_policy}
</td></tr>
</table>
% endif
</td></tr>
<tr><td align="center" style="min-width: 590px;">
% if object.company_id
<table
width="590"
border="0"
cellpadding="0"
cellspacing="0"
style="min-width: 590px; background-color: #F1F1F1; color: #454748; padding: 8px; border-collapse:separate;"
>
<tr><td style="text-align: center; font-size: 10px;">
Sent by <a
target="_blank"
href="${object.company_id.website}"
style="color: #875A7B;"
>${object.company_id.name}</a>
<br />
</td></tr>
</table>
% endif
</td></tr>
</table>
</field>
<field name="lang">${object.partner_id.lang}</field>
</record>
</data>
</odoo>

View File

@@ -0,0 +1,260 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data>
<record id="confirmed_reservation_email" model="mail.template">
<field name="name">Confirmed Reservation</field>
<field name="model_id" ref="pms.model_pms_reservation" />
<field
name="subject"
>${object.company_id.name} has confirmed your reservation in ${object.pms_property_id.name}</field>
<field
name="email_from"
>${object.pms_property_id.partner_id.email | safe}</field>
<field
name="email_to"
>${(object.email and '"%s" &lt;%s&gt;' % (object.name, object.email) or object.partner_id.email_formatted or '') | safe}</field>
<field name="body_html" type="html">
<table
border="0"
cellpadding="0"
cellspacing="0"
style="padding-top: 16px; background-color: #F1F1F1; font-family:Verdana, Arial,sans-serif; color: #454748; width: 100%; border-collapse:separate;"
><tr><td align="center">
<table
border="0"
cellpadding="0"
cellspacing="0"
width="590"
style="padding: 16px; background-color: white; color: #454748; border-collapse:separate;"
>
<head>
<link
rel="stylesheet"
href="https://use.fontawesome.com/releases/v5.8.1/css/all.css"
integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf"
crossorigin="anonymous"
/>
</head>
<tbody>
<!-- PROPERTY DESCRIPTION -->
<tr>
<td align="center" style="min-width: 590px;">
<table
width="590"
border="0"
cellpadding="0"
cellspacing="0"
style="min-width: 590px; background-color: white; padding: 0px 0px 0px 0px; border-collapse:separate;"
>
<tr><td align="right">
<div class="col-sm-4">
% if object.pms_property_id.partner_id.street
<p
>${object.pms_property_id.partner_id.street}</p>
% endif
% if object.pms_property_id.partner_id.street2
<p
>${object.pms_property_id.partner_id.street2}</p>
% endif
<p
>${object.pms_property_id.partner_id.zip}</p>
<p
>${object.pms_property_id.partner_id.city}</p>
<p
>${object.pms_property_id.partner_id.country_id.name}</p>
</div>
</td></tr>
<tr><td valign="top" style="font-size: 14px;">
<hr
width="100%"
style="background-color:rgb(204,204,204);border:medium none;clear:both;display:block;font-size:0px;min-height:1px;line-height:0; margin: 16px 0px 16px 0px;"
/>
<div>
Hello ${object.partner_id.name or ''},<br
/>
We are happy to confirm your reservation in ${object.pms_property_id.name}
</div>
<div>
See you soon,<br />
<span style="color: #454748;">
<br />
${object.company_id.name}
</span>
</div>
</td></tr>
</table>
</td>
</tr>
<!-- DETAILS -->
<tr>
<td align="center" style="min-width: 590px;">
<hr
width="100%"
style="background-color:rgb(204,204,204);border:medium none;clear:both;display:block;font-size:0px;min-height:1px;line-height:0; margin: 16px 0px 16px 0px;"
/>
<div
align="left"
style="margin: 16px 0px 16px 0px;"
><strong>Reservation Details</strong></div>
<table
width="590"
border="0"
cellpadding="0"
cellspacing="0"
style="min-width: 590px; background-color: white; padding: 0px 8px 0px 8px; border-collapse:separate;"
>
<tr><td valign="top" style="font-size: 14px;">
<table style="width:50%;">
<tr>
<td>
<div
class="far fa-calendar-alt fa-2x"
style="margin: 0px 16px 0px 0px;"
/>
</td>
<td
style="margin: 16px 0px 16px 0px; font-size: 14px;"
>
<div><strong
>From</strong> ${object.checkin} <strong
>At</strong> ${object.arrival_hour}</div>
<div><strong
>To</strong> ${object.checkout} <strong
>At</strong> ${object.departure_hour}</div>
<div
style="font-size:12px;color:#9e9e9e"
><i><strong
>TZ</strong> ${object.pms_property_id.tz}</i></div>
</td>
</tr>
<tr>
<td
style="margin: 16px 0px 16px 0px;"
>
<br />
<div
class="fas fa-bed fa-2x"
style="margin: 0px 16px 0px 0px;"
/>
</td>
<td style="vertical-align:top;">
<br />
<div><strong
>Room: </strong> ${object.room_type_id.name}</div>
</td>
</tr>
<tr>
<td
style="margin: 16px 0px 16px 0px;"
>
<br />
<div
class="fas fa-coins fa-2x"
style="margin: 0px 16px 0px 0px;"
/>
</td>
<td
style="margin: 16px 0px 16px 0px; font-size: 14px;"
>
<br />
<div><strong
>Price: </strong> ${object.price_room_services_set} ${object.pms_property_id.country_id.currency_id.symbol}</div>
</td>
</tr>
</table>
</td></tr>
<tr><td valign="top" style="font-size: 14px;">
<div>
% if object.pms_property_id.mail_information
<hr
width="100%"
style="background-color:rgb(204,204,204);border:medium none;clear:both;display:block;font-size:0px;min-height:1px;line-height:0; margin: 16px 0px 16px 0px;"
/>
<div
align="left"
style="margin: 16px 0px 16px 0px;"
><strong
>Additional Information</strong></div>
${object.pms_property_id.mail_information|safe}
% endif
</div>
</td></tr>
<tr><td valign="top" style="font-size: 14px;">
<hr
width="100%"
style="background-color:rgb(204,204,204);border:medium none;clear:both;display:block;font-size:0px;min-height:1px;line-height:0; margin: 16px 0px 16px 0px;"
/>
<!-- CONTACT -->
<div>
<span
style="font-weight:300;margin:10px 0px"
>Questions about the reservation?</span>
<div>Please contact with us:</div>
<ul>
<li
>${object.pms_property_id.name}</li>
% if object.pms_property_id.partner_id.email
<li>Mail: <a
href="mailto:${object.pms_property_id.partner_id.email}"
style="text-decoration:none;color:#875A7B;"
>${object.pms_property_id.partner_id.email}</a></li>
% endif
% if object.pms_property_id.partner_id.phone
<li
>Phone: ${object.pms_property_id.partner_id.phone}</li>
% endif
% if object.pms_property_id.partner_id.mobile
<li
>Mobile: ${object.pms_property_id.partner_id.mobile}</li>
% endif
</ul>
</div>
</td></tr>
</table>
</td>
</tr>
</tbody>
</table>
</td></tr>
<!-- FOOTER -->
<tr><td align="center" style="min-width: 590px;">
% if object.pms_property_id.privacy_policy
<table
width="590"
border="0"
cellpadding="0"
cellspacing="0"
style="min-width: 590px; background-color: #F1F1F1; color: #454748; padding: 8px; border-collapse:separate;"
>
<tr><td style="font-size: 10px;">
${object.pms_property_id.privacy_policy|safe}
</td></tr>
</table>
% endif
</td></tr>
<tr><td align="center" style="min-width: 590px;">
% if object.company_id
<table
width="590"
border="0"
cellpadding="0"
cellspacing="0"
style="min-width: 590px; background-color: #F1F1F1; color: #454748; padding: 8px; border-collapse:separate;"
>
<tr><td style="text-align: center; font-size: 10px;">
Sent by <a
target="_blank"
href="${object.company_id.website}"
style="color: #875A7B;"
>${object.company_id.name}</a>
<br />
</td></tr>
</table>
% endif
</td></tr>
</table>
</field>
<field name="lang">${object.partner_id.lang}</field>
</record>
</data>
</odoo>

View File

@@ -135,7 +135,40 @@ if (permit_first_letter.upper() in ['X','Y']) and id_number.name[1:8].isdigit()
else:
failed = True
</field>
<!-- <field name="has_unique_numbers">True</field>-->
</record>
<!-- pms.automated_mails-->
<record id="pms_auto_mail_confirm" model="pms.automated.mails">
<field name="name">Confirmed Reservation</field>
<field name="active">False</field>
<field name="template_id" ref="pms.confirmed_reservation_email" />
<field name="action">creation</field>
<field
name="pms_property_ids"
eval="[(6, False, [ref('main_pms_property')])]"
/>
<field name="moment">in_act</field>
</record>
<record id="pms_auto_mail_write" model="pms.automated.mails">
<field name="name">Modified Reservation</field>
<field name="active">False</field>
<field name="template_id" ref="pms.modified_reservation_email" />
<field name="action">write</field>
<field
name="pms_property_ids"
eval="[(6, False, [ref('main_pms_property')])]"
/>
<field name="moment">in_act</field>
</record>
<record id="pms_auto_mail_cancel" model="pms.automated.mails">
<field name="name">Cancelled Reservation</field>
<field name="active">False</field>
<field name="template_id" ref="pms.cancelled_reservation_email" />
<field name="action">cancel</field>
<field
name="pms_property_ids"
eval="[(6, False, [ref('main_pms_property')])]"
/>
<field name="moment">in_act</field>
</record>
</data>
</odoo>

View File

@@ -0,0 +1,262 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data>
<record id="modified_reservation_email" model="mail.template">
<field name="name">Modified Reservation</field>
<field name="model_id" ref="pms.model_pms_reservation" />
<field
name="subject"
>Your reservation in ${object.pms_property_id.name} has been modified</field>
<field
name="email_from"
>${object.pms_property_id.partner_id.email | safe}</field>
<field
name="email_to"
>${(object.email and '"%s" &lt;%s&gt;' % (object.name, object.email) or object.partner_id.email_formatted or '') | safe}</field>
<field name="body_html" type="html">
<table
border="0"
cellpadding="0"
cellspacing="0"
style="padding-top: 16px; background-color: #F1F1F1; font-family:Verdana, Arial,sans-serif; color: #454748; width: 100%; border-collapse:separate;"
><tr><td align="center">
<table
border="0"
cellpadding="0"
cellspacing="0"
width="590"
style="padding: 16px; background-color: white; color: #454748; border-collapse:separate;"
>
<head>
<link
rel="stylesheet"
href="https://use.fontawesome.com/releases/v5.8.1/css/all.css"
integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf"
crossorigin="anonymous"
/>
</head>
<tbody>
<!-- HEADER -->
<!-- PROPERTY DESCRIPTION -->
<tr>
<td align="center" style="min-width: 590px;">
<table
width="590"
border="0"
cellpadding="0"
cellspacing="0"
style="min-width: 590px; background-color: white; padding: 0px 0px 0px 0px; border-collapse:separate;"
>
<tr><td align="right">
<div class="col-sm-4">
% if object.pms_property_id.partner_id.street
<p
>${object.pms_property_id.partner_id.street}</p>
% endif
% if object.pms_property_id.partner_id.street2
<p
>${object.pms_property_id.partner_id.street2}</p>
% endif
<p
>${object.pms_property_id.partner_id.zip}</p>
<p
>${object.pms_property_id.partner_id.city}</p>
<p
>${object.pms_property_id.partner_id.country_id.name}</p>
</div>
</td></tr>
<tr><td valign="top" style="font-size: 14px;">
<hr
width="100%"
style="background-color:rgb(204,204,204);border:medium none;clear:both;display:block;font-size:0px;min-height:1px;line-height:0; margin: 16px 0px 16px 0px;"
/>
<div>
Hello ${object.partner_id.name or ''},<br
/>
Your reservation in ${object.pms_property_id.name} has been modified
</div>
<div>
See you soon,<br />
<span style="color: #454748;">
<br />
${object.company_id.name}
</span>
</div>
</td></tr>
</table>
</td>
</tr>
<!-- DETAILS -->
<tr>
<td align="center" style="min-width: 590px;">
<hr
width="100%"
style="background-color:rgb(204,204,204);border:medium none;clear:both;display:block;font-size:0px;min-height:1px;line-height:0; margin: 16px 0px 16px 0px;"
/>
<div
align="left"
style="margin: 16px 0px 16px 0px;"
><strong>Reservation Details</strong></div>
<table
width="590"
border="0"
cellpadding="0"
cellspacing="0"
style="min-width: 590px; background-color: white; padding: 0px 8px 0px 8px; border-collapse:separate;"
>
<tr><td valign="top" style="font-size: 14px;">
<table style="width:50%;">
<tr>
<td>
<div
class="far fa-calendar-alt fa-2x"
style="margin: 0px 16px 0px 0px;"
/>
</td>
<td
style="margin: 16px 0px 16px 0px; font-size: 14px;"
>
<div><strong
>From</strong> ${object.checkin} <strong
>At</strong> ${object.arrival_hour}</div>
<div><strong
>To</strong> ${object.checkout} <strong
>At</strong> ${object.departure_hour}</div>
<div
style="font-size:12px;color:#9e9e9e"
><i><strong
>TZ</strong> ${object.pms_property_id.tz}</i></div>
</td>
</tr>
<tr>
<td
style="margin: 16px 0px 16px 0px;"
>
<br />
<div
class="fas fa-bed fa-2x"
style="margin: 0px 16px 0px 0px;"
/>
</td>
<td style="vertical-align:top;">
<br />
<div><strong
>Room: </strong> ${object.room_type_id.name}</div>
</td>
</tr>
<tr>
<td
style="margin: 16px 0px 16px 0px;"
>
<br />
<div
class="fas fa-coins fa-2x"
style="margin: 0px 16px 0px 0px;"
/>
</td>
<td
style="margin: 16px 0px 16px 0px; font-size: 14px;"
>
<br />
<div><strong
>Price: </strong> ${object.price_total} ${object.pms_property_id.country_id.currency_id.symbol}</div>
</td>
</tr>
</table>
</td></tr>
<tr><td valign="top" style="font-size: 14px;">
<div>
% if object.pms_property_id.mail_information
<hr
width="100%"
style="background-color:rgb(204,204,204);border:medium none;clear:both;display:block;font-size:0px;min-height:1px;line-height:0; margin: 16px 0px 16px 0px;"
/>
<div
align="left"
style="margin: 16px 0px 16px 0px;"
><strong
>Additional Information</strong></div>
<p
>${object.pms_property_id.mail_information|safe}</p>
% endif
</div>
</td></tr>
<tr><td valign="top" style="font-size: 14px;">
<hr
width="100%"
style="background-color:rgb(204,204,204);border:medium none;clear:both;display:block;font-size:0px;min-height:1px;line-height:0; margin: 16px 0px 16px 0px;"
/>
<!-- CONTACT -->
<div>
<span
style="font-weight:300;margin:10px 0px"
>Questions about the reservation?</span>
<div>Please contact with us:</div>
<ul>
<li
>${object.pms_property_id.name}</li>
% if object.pms_property_id.partner_id.email
<li>Mail: <a
href="mailto:${object.pms_property_id.partner_id.email}"
style="text-decoration:none;color:#875A7B;"
>${object.pms_property_id.partner_id.email}</a></li>
% endif
% if object.pms_property_id.partner_id.phone
<li
>Phone: ${object.pms_property_id.partner_id.phone}</li>
% endif
% if object.pms_property_id.partner_id.mobile
<li
>Mobile: ${object.pms_property_id.partner_id.mobile}</li>
% endif
</ul>
</div>
</td></tr>
</table>
</td>
</tr>
</tbody>
</table>
</td></tr>
<!-- FOOTER -->
<tr><td align="center" style="min-width: 590px;">
% if object.pms_property_id.privacy_policy
<table
width="590"
border="0"
cellpadding="0"
cellspacing="0"
style="min-width: 590px; background-color: #F1F1F1; color: #454748; padding: 8px; border-collapse:separate;"
>
<tr><td style="font-size: 10px;">
${object.pms_property_id.privacy_policy|safe}
</td></tr>
</table>
% endif
</td></tr>
<tr><td align="center" style="min-width: 590px;">
% if object.company_id
<table
width="590"
border="0"
cellpadding="0"
cellspacing="0"
style="min-width: 590px; background-color: #F1F1F1; color: #454748; padding: 8px; border-collapse:separate;"
>
<tr><td style="text-align: center; font-size: 10px;">
Sent by <a
target="_blank"
href="${object.company_id.website}"
style="color: #875A7B;"
>${object.company_id.name}</a>
<br />
</td></tr>
</table>
% endif
</td></tr>
</table>
</field>
<field name="lang">${object.partner_id.lang}</field>
</record>
</data>
</odoo>

View File

@@ -31,7 +31,7 @@ from . import product_pricelist_item
from . import res_partner
from . import pms_sale_channel
# from . import mail_compose_message
from . import mail_compose_message
from . import pms_room_type_class
from . import pms_room_closure_reason
from . import pms_service_line
@@ -46,3 +46,4 @@ from . import account_bank_statement
from . import account_journal
from . import pms_availability
from . import res_partner_id_number
from . import pms_automated_mails

View File

@@ -1,24 +1,43 @@
# Copyright 2017 Alexandre Díaz
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models
from odoo import api, models
class MailComposeMessage(models.TransientModel):
_inherit = "mail.compose.message"
@api.model
def default_get(self, fields):
res = super(MailComposeMessage, self).default_get(fields)
template = self.env["mail.template"].browse(self._context.get("template_id"))
res.update(
{
"composition_mode": "comment",
"attachment_ids": False,
"template_id": template.id,
}
)
return res
def send_mail(self, auto_commit=False):
if (
self._context.get("default_model") == "pms.folio"
and self._context.get("default_res_id")
and self._context.get("mark_so_as_sent")
):
# TODO: WorkFlow Mails
folio = self.env["pms.folio"].browse([self._context["default_res_id"]])
if folio:
cmds = [
(1, lid, {"to_send": False}) for lid in folio.reservation_ids.ids
]
if any(cmds):
folio.reservation_ids = cmds
return super(MailComposeMessage, self).send_mail(auto_commit=auto_commit)
# if (
# self._context.get("default_model") == "pms.folio"
# and self._context.get("default_res_id")
# and self._context.get("mark_so_as_sent")
# ):
# # TODO: WorkFlow Mails
# folio = self.env["pms.folio"].browse([self._context["default_res_id"]])
# if folio:
# cmds = [
# (1, lid, {"to_send": False}) for lid in folio.reservation_ids.ids
# ]
# if any(cmds):
# 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(
[("id", "=", self._context.get("record_id"))]
)
reservation.is_mail_send = True
return res

View File

@@ -0,0 +1,367 @@
from odoo import _, api, fields, models
from odoo.exceptions import UserError
class PmsAutomatedMails(models.Model):
_name = "pms.automated.mails"
_description = "Automatic Mails"
name = fields.Char(string="Name", help="Name of the automated mail.", required=True)
pms_property_ids = fields.Many2many(
string="Property",
help="Properties with access to the element;"
" if not set, all properties can access",
comodel_name="pms.property",
)
automated_actions_id = fields.Many2one(
string="Automated Actions",
help="automated action that is created when creating automated emails ",
comodel_name="base.automation",
)
time = fields.Integer(string="Time", help="Amount of time")
time_type = fields.Selection(
string="Time Range",
help="Type of date range",
selection=[
("minutes", "Minutes"),
("hour", "Hour"),
("day", "Days"),
("month", "Months"),
],
default="day",
)
template_id = fields.Many2one(
string="Template",
help="The template that will be sent by email",
comodel_name="mail.template",
required=True,
)
action = fields.Selection(
string="Action",
help="The action that will cause the email to be sent ",
selection=[
("creation", "Reservation creation"),
("write", "Reservation modification"),
("cancel", "Reservation cancellation"),
("checkin", "Checkin"),
("checkout", "Checkout"),
("payment", "Payment"),
("invoice", "Invoice"),
],
default="creation",
required=True,
)
moment = fields.Selection(
string="Moment",
help="Moment in relation to the action in which the email will be sent",
selection=[
("before", "Before"),
("after", "After"),
("in_act", "In the act"),
],
default="before",
)
active = fields.Boolean(
string="Active", help="Indicates if the automated mail is active", default=True
)
@api.model
def create(self, vals):
name = vals.get("name")
action = vals.get("action")
time = vals.get("time")
date_range_type = vals.get("time_type")
template_id = vals.get("template_id")
active = vals.get("active")
moment = vals.get("moment")
properties = vals.get("pms_property_ids")
is_create = True
if action in ("creation", "write", "cancel", "invoice") and moment == "before":
raise UserError(_("The moment for this action cannot be 'Before'"))
dict_val = self._prepare_automated_actions_id(
action, time, moment, properties, is_create
)
action_server_vals = {
"name": name,
"state": "email",
"usage": "ir_cron",
"model_id": dict_val["model_id"],
}
action_server = self.env["ir.actions.server"].create(action_server_vals)
automated_actions_vals = {
"active": active,
"action_server_id": action_server.id,
"trigger": dict_val["trigger"],
"filter_domain": dict_val["filter_domain"],
"filter_pre_domain": dict_val["filter_pre_domain"],
"trg_date_range": dict_val["time"],
"trg_date_range_type": date_range_type,
"template_id": template_id,
}
model_field = dict_val["model_field"]
if model_field:
automated_actions_vals.update(
{
"trg_date_id": dict_val["model_field"].id,
}
)
trigger_field = dict_val["trigger_fields"]
if trigger_field:
automated_actions_vals.update(
{
"trigger_field_ids": dict_val["trigger_fields"].ids,
}
)
automated_action = self.env["base.automation"].create(automated_actions_vals)
vals.update({"automated_actions_id": automated_action.id})
return super(PmsAutomatedMails, self).create(vals)
def write(self, vals):
result = super(PmsAutomatedMails, self).write(vals)
is_create = False
if (
self.action in ("creation", "write", "cancel", "invoice")
and self.moment == "before"
):
raise UserError(_("The moment for this action cannot be 'Before'"))
dict_val = self._prepare_automated_actions_id(
self.action, self.time, self.moment, self.pms_property_ids, is_create
)
automated_actions_id = self.automated_actions_id
action_server = automated_actions_id.action_server_id
action_server_vals = {
"name": self.name,
"state": "email",
"usage": "ir_cron",
"model_id": dict_val["model_id"],
}
action_server.write(action_server_vals)
automated_actions_vals = {
"active": self.active,
"action_server_id": action_server.id,
"trigger": dict_val["trigger"],
"filter_domain": dict_val["filter_domain"],
"filter_pre_domain": dict_val["filter_pre_domain"],
"trg_date_range": dict_val["time"],
"trg_date_range_type": self.time_type,
"template_id": self.template_id,
}
model_field = dict_val["model_field"]
if model_field:
automated_actions_vals.update(
{
"trg_date_id": dict_val["model_field"].id,
}
)
trigger_field = dict_val["trigger_fields"]
if trigger_field:
automated_actions_vals.update(
{
"trigger_field_ids": dict_val["trigger_fields"].ids,
}
)
automated_actions_id.write(automated_actions_vals)
vals.update({"automated_actions_id": automated_actions_id.id})
return result
def unlink(self):
automated_actions_id = self.automated_actions_id
action_server = automated_actions_id.action_server_id
automated_actions_id.unlink()
action_server.unlink()
return super(PmsAutomatedMails, self).unlink()
@api.model
def _get_auto_action_fields_in_creation_action(self, moment, time):
model_field = False
model_id = self.env["ir.model"].search([("model", "=", "pms.reservation")]).id
if moment == "in_act":
trigger = "on_create"
time = 0
else:
trigger = "on_time"
model_field = self.env["ir.model.fields"].search(
[("model", "=", "pms.reservation"), ("name", "=", "create_date")]
)
result = {
"model_id": model_id,
"trigger": trigger,
"model_field": model_field,
"time": time,
}
return result
@api.model
def _get_auto_action_fields_in_write_or_cancel_action(self, moment, time):
model_field = False
model_id = self.env["ir.model"].search([("model", "=", "pms.reservation")]).id
if moment == "in_act":
trigger = "on_write"
time = 0
else:
trigger = "on_time"
model_field = self.env["ir.model.fields"].search(
[("model", "=", "pms.reservation"), ("name", "=", "write_date")]
)
result = {
"model_id": model_id,
"trigger": trigger,
"model_field": model_field,
"time": time,
}
return result
@api.model
def _get_auto_action_fields_in_checkin_action(self, moment, time):
model_id = self.env["ir.model"].search([("model", "=", "pms.reservation")]).id
trigger = "on_time"
model_field = self.env["ir.model.fields"].search(
[("model", "=", "pms.reservation"), ("name", "=", "checkin")]
)
if moment == "before":
time = time * (-1)
if moment == "in_act":
trigger = "on_write"
time = 0
result = {
"model_id": model_id,
"trigger": trigger,
"model_field": model_field,
"time": time,
}
return result
@api.model
def _get_auto_action_fields_in_checkout_action(self, moment, time):
model_id = self.env["ir.model"].search([("model", "=", "pms.reservation")]).id
trigger = "on_time"
model_field = self.env["ir.model.fields"].search(
[("model", "=", "pms.reservation"), ("name", "=", "checkout")]
)
if moment == "before":
time = time * (-1)
if moment == "in_act":
trigger = "on_write"
time = 0
result = {
"model_id": model_id,
"trigger": trigger,
"model_field": model_field,
"time": time,
}
return result
@api.model
def _get_auto_action_fields_in_payment_action(self, moment, time):
model_field = False
model_id = (
self.env["ir.model"]
.search([("model", "=", "account.payment"), ("transient", "=", False)])
.id
)
if moment == "in_act":
trigger = "on_create"
time = 0
else:
trigger = "on_time"
model_field = self.env["ir.model.fields"].search(
[("model", "=", "account.payment"), ("name", "=", "date")]
)
if moment == "before":
time = time * (-1)
result = {
"model_id": model_id,
"trigger": trigger,
"model_field": model_field,
"time": time,
}
return result
@api.model
def _get_auto_action_fields_in_invoice_action(self, moment, time):
trigger = False
model_id = self.env["ir.model"].search([("model", "=", "account.move")]).id
if moment == "in_act":
trigger = "on_create"
time = 0
result = {
"model_id": model_id,
"time": time,
"trigger": trigger,
"model_field": False,
}
return result
def _prepare_automated_actions_id(
self, action, time, moment, properties, is_create
):
filter_domain = []
filter_pre_domain = []
trigger_fields = False
dict_val = {}
if action == "creation":
dict_val = self._get_auto_action_fields_in_creation_action(moment, time)
elif action == "write" or action == "cancel":
dict_val = self._get_auto_action_fields_in_write_or_cancel_action(
moment, time
)
if action == "cancel":
filter_domain = [
("state", "=", "cancelled"),
]
elif action == "checkin":
dict_val = self._get_auto_action_fields_in_checkin_action(moment, time)
if moment == "in_act":
trigger_fields = self.env["ir.model.fields"].search(
[("model", "=", "pms.reservation"), ("name", "=", "state")]
)
filter_pre_domain = [("state", "=", "confirm")]
filter_domain = [
("state", "=", "onboard"),
]
elif action == "checkout":
dict_val = self._get_auto_action_fields_in_checkout_action(moment, time)
if moment == "in_act":
trigger_fields = self.env["ir.model.fields"].search(
[("model", "=", "pms.reservation"), ("name", "=", "state")]
)
filter_pre_domain = [("state", "=", "onboard")]
filter_domain = [
("state", "=", "out"),
]
elif action == "payment":
dict_val = self._get_auto_action_fields_in_payment_action(moment, time)
elif action == "invoice":
dict_val = self._get_auto_action_fields_in_invoice_action(moment, time)
filter_domain = [
("folio_ids", "!=", False),
]
pms_property_ids = self._get_pms_property_ids(properties, is_create)
if pms_property_ids:
filter_domain.append(("pms_property_id", "in", pms_property_ids))
result = {
"trigger": dict_val["trigger"],
"model_field": dict_val["model_field"],
"trigger_fields": trigger_fields,
"filter_pre_domain": filter_pre_domain,
"filter_domain": filter_domain,
"time": dict_val["time"],
"model_id": dict_val["model_id"],
}
return result
def _get_pms_property_ids(self, properties, is_create):
pms_property_ids = []
if is_create:
pms_property_ids = properties[0][2]
else:
for pms_property in properties:
pms_property_ids.append(pms_property.id)
return pms_property_ids

View File

@@ -115,6 +115,39 @@ class PmsProperty(models.Model):
compute="_compute_availability",
)
mail_information = fields.Html(
string="Mail Information", help="Additional information of the mail"
)
privacy_policy = fields.Html(string="Privacy Policy", help="Mail privacy policy ")
property_confirmed_template = fields.Many2one(
string="Confirmation Template",
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",
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",
help="Cancellation email template",
comodel_name="mail.template",
default=lambda self: self.env["mail.template"]
.search([("name", "=", "Cancelled Reservation")])
.id,
)
@api.depends_context(
"checkin",
"checkout",

View File

@@ -644,6 +644,19 @@ class PmsReservation(models.Model):
add_possible_customer = fields.Boolean(string="Add possible Customer")
is_mail_send = fields.Boolean(string="Mail Sent", default=False)
is_modified_reservation = fields.Boolean(
string="Is A Modified Reservation",
compute="_compute_is_modified_reservation",
readonly=False,
store=True,
)
lang = fields.Many2one(
string="Language", comodel_name="res.lang", compute="_compute_lang"
)
def _compute_date_order(self):
for record in self:
record.date_order = datetime.datetime.today()
@@ -1428,6 +1441,25 @@ class PmsReservation(models.Model):
for record in self:
self.env["pms.folio"]._apply_is_possible_existing_customer_id(record)
@api.depends("checkin", "checkout")
def _compute_is_modified_reservation(self):
for record in self:
if record.state in "draft":
record.is_modified_reservation = False
elif record.state in ("confirm", "onboard") and record.is_mail_send:
record.is_modified_reservation = True
record.is_mail_send = False
else:
record.is_modified_reservation = False
@api.depends("partner_id")
def _compute_lang(self):
for record in self:
if record.partner_id:
record.lang = record.partner_id.lang
else:
record.lang = self.env["res.lang"].get_installed()
def _search_allowed_checkin(self, operator, value):
if operator not in ("=",):
raise UserError(
@@ -1666,6 +1698,54 @@ class PmsReservation(models.Model):
},
}
def action_open_mail_composer(self):
self.ensure_one()
template = False
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
)
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
)
elif not self.is_mail_send and self.state in "cancel":
template = self.env.ref(
"pms.cancelled_reservation_email", raise_if_not_found=False
)
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,
template_id=template and template.id or False,
composition_mode="comment",
partner_ids=[self.partner_id.id],
force_email=True,
record_id=self.id,
)
return {
"name": _("Send Confirmed Reservation Mail "),
"type": "ir.actions.act_window",
"view_type": "form",
"view_mode": "form",
"res_model": "mail.compose.message",
"views": [(compose_form.id, "form")],
"view_id": compose_form.id,
"target": "new",
"context": ctx,
}
@api.model
def name_search(self, name="", args=None, operator="ilike", limit=100):
if args is None:
@@ -1811,6 +1891,7 @@ class PmsReservation(models.Model):
else:
record.state = "cancel"
record.folio_id._compute_amount()
record.is_mail_send = False
def action_assign(self):
for record in self:

View File

@@ -60,3 +60,4 @@ user_access_wizard_payment_folio,user_access_wizard_payment_folio,model_wizard_p
user_access_wizard_folio_changes,user_access_wizard_folio_changes,model_wizard_folio_changes,pms.group_pms_user,1,1,1,1
user_access_pms_folio_portal,user_access_pms_folio_portal,model_pms_folio,base.group_portal,1,0,0,0
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
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
60 user_access_wizard_folio_changes user_access_wizard_folio_changes model_wizard_folio_changes pms.group_pms_user 1 1 1 1
61 user_access_pms_folio_portal user_access_pms_folio_portal model_pms_folio base.group_portal 1 0 0 0
62 user_access_pms_reservation_portal user_access_pms_reservation_portal model_pms_reservation base.group_portal 1 0 0 0
63 user_access_pms_automated_mails user_access_pms_automated_mails model_pms_automated_mails pms.group_pms_user 1 1 1 1

View File

@@ -38,3 +38,4 @@ from . import test_pms_wizard_split_join_swap_reservation
from . import test_product_template
from . import test_pms_multiproperty
from . import test_shared_room
from . import test_automated_mails

View File

@@ -0,0 +1,618 @@
from odoo.exceptions import UserError
from .common import TestPms
class TestPmsAutomatedMails(TestPms):
def setUp(self):
super().setUp()
self.template = self.env["mail.template"].search(
[("name", "=", "Confirmed Reservation")]
)
def test_create_automated_action(self):
"""
Checks that an automated_action is created correctly when an
automated_mail is created.
---------------------
An automated_mail is created and then it is verified that
the automated_action was created.
"""
# ARRANGE
automated_mail_vals = {
"name": "Auto Mail 1",
"template_id": self.template.id,
"action": "creation",
"moment": "in_act",
"pms_property_ids": [(6, 0, [self.pms_property1.id])],
}
# ACT
auto_mail = self.env["pms.automated.mails"].create(automated_mail_vals)
# ASSERT
self.assertTrue(
auto_mail.automated_actions_id, "Automated action should be created "
)
def test_no_action_creation_before(self):
"""
Check that an automated mail cannot be created with action='creation'
and moment='before'.
-----------------------
An automated mail is created with action = 'creation' and moment = 'before'.
Then it is verified that a UserError was thrown because an automated_mail with
these parameters cannot be created.
"""
# ARRANGE
automated_mail_vals = {
"name": "Auto Mail 1",
"template_id": self.template.id,
"action": "creation",
"moment": "before",
"pms_property_ids": [(6, 0, [self.pms_property1.id])],
}
# ACT & ASSERT
with self.assertRaises(
UserError,
msg="It should not be allowed to create the automated mail "
"with action 'creation' and moment 'before' values",
):
self.env["pms.automated.mails"].create(automated_mail_vals)
def test_trigger_moment_in_act_creation(self):
"""
Check that when creating an automated mail with parameters
action = 'creation' and moment = 'in_act' the trigger of the
automated_action created is 'on_create'.
"""
# ARRANGE
automated_mail_vals = {
"name": "Auto Mail 1",
"template_id": self.template.id,
"action": "creation",
"moment": "in_act",
"pms_property_ids": [(6, 0, [self.pms_property1.id])],
}
# ACT
auto_mail = self.env["pms.automated.mails"].create(automated_mail_vals)
# ASSERT
self.assertEqual(
auto_mail.automated_actions_id.trigger,
"on_create",
"The trigger of the automated action must be 'on_create'",
)
def test_trigger_moment_after_in_creation_action(self):
"""
Check that when creating an automated mail with parameters
action = 'creation' and moment = 'after' the trigger of the
automated_action created is 'on_time'.
"""
# ARRANGE
automated_mail_vals = {
"name": "Auto Mail 1",
"template_id": self.template.id,
"action": "creation",
"moment": "after",
"pms_property_ids": [(6, 0, [self.pms_property1.id])],
"time": 1,
"time_type": "hour",
}
# ACT
auto_mail = self.env["pms.automated.mails"].create(automated_mail_vals)
# ASSERT
self.assertEqual(
auto_mail.automated_actions_id.trigger,
"on_time",
"The trigger of the automated action must be 'on_time'",
)
def test_trigger_moment_in_act_in_write_action(self):
"""
Check that when creating an automated mail with parameters
action = 'write' and moment = 'in_act' the trigger of the
automated_action created is 'on_write'.
"""
# ARRANGE
automated_mail_vals = {
"name": "Auto Mail 1",
"template_id": self.template.id,
"action": "write",
"moment": "in_act",
"pms_property_ids": [(6, 0, [self.pms_property1.id])],
}
# ACT
auto_mail = self.env["pms.automated.mails"].create(automated_mail_vals)
# ASSERT
self.assertEqual(
auto_mail.automated_actions_id.trigger,
"on_write",
"The trigger of the automated action must be 'on_write'",
)
def test_trigger_moment_after_in_write_action(self):
"""
Check that when creating an automated mail with parameters
action = 'write' and moment = 'after' the trigger of the
automated_action created is 'on_time'.
"""
# ARRANGE
automated_mail_vals = {
"name": "Auto Mail 1",
"template_id": self.template.id,
"action": "write",
"moment": "after",
"pms_property_ids": [(6, 0, [self.pms_property1.id])],
"time": 1,
"time_type": "hour",
}
# ACT
auto_mail = self.env["pms.automated.mails"].create(automated_mail_vals)
# ASSERT
self.assertEqual(
auto_mail.automated_actions_id.trigger,
"on_time",
"The trigger of the automated action must be 'on_time'",
)
def test_time_moment_before_in_checkin(self):
"""
Check that when creating an automated mail with parameters
action = 'checkin' and moment = 'before' the trg_date_range
of the automated_action created is equal to
(automated_mail.time * -1)'.
"""
# ARRANGE
automated_mail_vals = {
"name": "Auto Mail 1",
"template_id": self.template.id,
"action": "checkin",
"moment": "before",
"pms_property_ids": [(6, 0, [self.pms_property1.id])],
"time": 60,
"time_type": "minutes",
}
# ACT
auto_mail = self.env["pms.automated.mails"].create(automated_mail_vals)
# ASSERT
self.assertEqual(
auto_mail.automated_actions_id.trg_date_range,
-60,
"The trg_date_range of the automated action must be '-60'",
)
def test_time_moment_in_act_in_checkin(self):
"""
Check that when creating an automated mail with parameters
action = 'checkin' and moment = 'in_act' the trg_date_range
of the automated_action created is equal to 0
"""
# ARRANGE
automated_mail_vals = {
"name": "Auto Mail 1",
"template_id": self.template.id,
"action": "checkin",
"moment": "in_act",
"pms_property_ids": [(6, 0, [self.pms_property1.id])],
}
# ACT
auto_mail = self.env["pms.automated.mails"].create(automated_mail_vals)
# ASSERT
self.assertEqual(
auto_mail.automated_actions_id.trg_date_range,
0,
"The trg_date_range of the automated action must be '0'",
)
def test_trigger_moment_before_in_checkin(self):
"""
Check that when creating an automated mail with parameters
action = 'checkin' and moment = 'before' the trigger of the
automated_action created is 'on_time'.
"""
# ARRANGE
automated_mail_vals = {
"name": "Auto Mail 1",
"template_id": self.template.id,
"action": "checkin",
"moment": "before",
"pms_property_ids": [(6, 0, [self.pms_property1.id])],
"time": 24,
"time_type": "hour",
}
# ACT
auto_mail = self.env["pms.automated.mails"].create(automated_mail_vals)
# ASSERT
self.assertEqual(
auto_mail.automated_actions_id.trigger,
"on_time",
"The trigger of the automated action must be 'on_time'",
)
def test_trigger_moment_in_act_in_checkin(self):
"""
Check that when creating an automated mail with parameters
action = 'checkin' and moment = 'in_act' the trigger of the
automated_action created is 'on_write'.
"""
# ARRANGE
automated_mail_vals = {
"name": "Auto Mail 1",
"template_id": self.template.id,
"action": "checkin",
"moment": "in_act",
"pms_property_ids": [(6, 0, [self.pms_property1.id])],
}
# ACT
auto_mail = self.env["pms.automated.mails"].create(automated_mail_vals)
# ASSERT
self.assertEqual(
auto_mail.automated_actions_id.trigger,
"on_write",
"The trigger of the automated action must be 'on_write'",
)
def test_time_moment_before_in_checkout(self):
"""
Check that when creating an automated mail with parameters
action = 'checkout' and moment = 'before' the trg_date_range
of the automated_action created is equal to
(automated_mail.time * -1)'.
"""
# ARRANGE
automated_mail_vals = {
"name": "Auto Mail 1",
"template_id": self.template.id,
"action": "checkout",
"moment": "before",
"pms_property_ids": [(6, 0, [self.pms_property1.id])],
"time": 60,
"time_type": "minutes",
}
# ACT
auto_mail = self.env["pms.automated.mails"].create(automated_mail_vals)
# ASSERT
self.assertEqual(
auto_mail.automated_actions_id.trg_date_range,
-60,
"The trg_date_range of the automated action must be '-60'",
)
def test_time_moment_in_act_in_checkout(self):
"""
Check that when creating an automated mail with parameters
action = 'checkout' and moment = 'in_act' the trg_date_range
of the automated_action created is equal to 0.
"""
# ARRANGE
automated_mail_vals = {
"name": "Auto Mail 1",
"template_id": self.template.id,
"action": "checkout",
"moment": "in_act",
"pms_property_ids": [(6, 0, [self.pms_property1.id])],
}
# ACT
auto_mail = self.env["pms.automated.mails"].create(automated_mail_vals)
# ASSERT
self.assertEqual(
auto_mail.automated_actions_id.trg_date_range,
0,
"The trg_date_range of the automated action must be '0'",
)
def test_trigger_moment_before_in_checkout(self):
"""
Check that when creating an automated mail with parameters
action = 'checkout' and moment = 'before' the trigger of the
automated_action created is 'on_time'.
"""
# ARRANGE
automated_mail_vals = {
"name": "Auto Mail 1",
"template_id": self.template.id,
"action": "checkout",
"moment": "before",
"pms_property_ids": [(6, 0, [self.pms_property1.id])],
"time": 24,
"time_type": "hour",
}
# ACT
auto_mail = self.env["pms.automated.mails"].create(automated_mail_vals)
# ASSERT
self.assertEqual(
auto_mail.automated_actions_id.trigger,
"on_time",
"The trigger of the automated action must be 'on_time'",
)
def test_trigger_moment_in_act_in_checkout(self):
"""
Check that when creating an automated mail with parameters
action = 'checkout' and moment = 'in_act' the trigger of the
automated_action created is 'on_write'.
"""
# ARRANGE
automated_mail_vals = {
"name": "Auto Mail 1",
"template_id": self.template.id,
"action": "checkout",
"moment": "in_act",
"pms_property_ids": [(6, 0, [self.pms_property1.id])],
}
# ACT
auto_mail = self.env["pms.automated.mails"].create(automated_mail_vals)
# ASSERT
self.assertEqual(
auto_mail.automated_actions_id.trigger,
"on_write",
"The trigger of the automated action must be 'on_write'",
)
def test_trigger_moment_in_act_in_payment_action(self):
"""
Check that when creating an automated mail with parameters
action = 'payment' and moment = 'in_act' the trigger of the
automated_action created is 'on_create'.
"""
# ARRANGE
automated_mail_vals = {
"name": "Auto Mail 1",
"template_id": self.template.id,
"action": "payment",
"moment": "in_act",
"pms_property_ids": [(6, 0, [self.pms_property1.id])],
}
# ACT
auto_mail = self.env["pms.automated.mails"].create(automated_mail_vals)
# ASSERT
self.assertEqual(
auto_mail.automated_actions_id.trigger,
"on_create",
"The trigger of the automated action must be 'on_create'",
)
def test_trigger_moment_before_in_payment_action(self):
"""
Check that when creating an automated mail with parameters
action = 'payment' and moment = 'before' the trigger of the
automated_action created is 'on_time'.
"""
# ARRANGE
automated_mail_vals = {
"name": "Auto Mail 1",
"template_id": self.template.id,
"action": "payment",
"moment": "before",
"pms_property_ids": [(6, 0, [self.pms_property1.id])],
"time": 24,
"time_type": "hour",
}
# ACT
auto_mail = self.env["pms.automated.mails"].create(automated_mail_vals)
# ASSERT
self.assertEqual(
auto_mail.automated_actions_id.trigger,
"on_time",
"The trigger of the automated action must be 'on_time'",
)
def test_time_moment_before_in_payment_action(self):
"""
Check that when creating an automated mail with parameters
action = 'payment' and moment = 'before' the trg_date_range
field of the automated_action is (automated_mail.time * -1).
"""
# ARRANGE
automated_mail_vals = {
"name": "Auto Mail 1",
"template_id": self.template.id,
"action": "payment",
"moment": "before",
"pms_property_ids": [(6, 0, [self.pms_property1.id])],
"time": 24,
"time_type": "hour",
}
# ACT
auto_mail = self.env["pms.automated.mails"].create(automated_mail_vals)
# ASSERT
self.assertEqual(
auto_mail.automated_actions_id.trg_date_range,
-24,
"The trg_date_range of the automated action must be '-24'",
)
def test_trigger_moment_in_act_in_invoice_action(self):
"""
Check that when creating an automated mail with parameters
action = 'invoice' and moment = 'in_act' the trigger field
of the automated_action created is 'on_create'.
"""
# ARRANGE
automated_mail_vals = {
"name": "Auto Mail 1",
"template_id": self.template.id,
"action": "invoice",
"moment": "in_act",
"pms_property_ids": [(6, 0, [self.pms_property1.id])],
}
# ACT
auto_mail = self.env["pms.automated.mails"].create(automated_mail_vals)
# ASSERT
self.assertEqual(
auto_mail.automated_actions_id.trigger,
"on_create",
"The trigger of the automated action must be 'on_create'",
)
def test_time_moment_in_act_in_invoice_action(self):
"""
Check that when creating an automated mail with parameters
action = 'invoice' and moment = 'in_act' the trg_date_range
field of the automated_action is 0.
"""
# ARRANGE
automated_mail_vals = {
"name": "Auto Mail 1",
"template_id": self.template.id,
"action": "invoice",
"moment": "in_act",
"pms_property_ids": [(6, 0, [self.pms_property1.id])],
}
# ACT
auto_mail = self.env["pms.automated.mails"].create(automated_mail_vals)
# ASSERT
self.assertEqual(
auto_mail.automated_actions_id.trg_date_range,
0,
"The trg_date_range of the automated action must be '0'",
)
def test_filter_pre_domain_moment_in_act_in_checkin(self):
"""
Check that when creating an automated mail with parameters
action = 'checkin' and moment = 'in_act' the filter_pre_domain
field of the automated_action is [('state', '=', 'confirm')].
"""
# ARRANGE
automated_mail_vals = {
"name": "Auto Mail 1",
"template_id": self.template.id,
"action": "checkin",
"moment": "in_act",
"pms_property_ids": [(6, 0, [self.pms_property1.id])],
}
# ACT
auto_mail = self.env["pms.automated.mails"].create(automated_mail_vals)
# ASSERT
self.assertEqual(
auto_mail.automated_actions_id.filter_pre_domain,
"[('state', '=', 'confirm')]",
"The filter_pre_domain of the automated action "
"must be '[('state', '=', 'confirm')]'",
)
def test_filter_domain_moment_in_act_in_checkin(self):
"""
Check that when creating an automated mail with parameters
action = 'checkin' and moment = 'in_act' the filter_domain
field of the automated_action is
[('state', '=', 'onboard'), ('pms_property_id', '=', [value of property_id.id])]].
"""
# ARRANGE
automated_mail_vals = {
"name": "Auto Mail 1",
"template_id": self.template.id,
"action": "checkin",
"moment": "in_act",
"pms_property_ids": [(6, 0, [self.pms_property1.id])],
}
# ACT
auto_mail = self.env["pms.automated.mails"].create(automated_mail_vals)
pms_property_id_str = str(auto_mail.pms_property_ids.ids)
# ASSERT
self.assertEqual(
auto_mail.automated_actions_id.filter_domain,
"[('state', '=', 'onboard'), ('pms_property_id', 'in', "
+ pms_property_id_str
+ ")]",
"The filter_domain of the automated action must be "
"'[('state', '=', 'onboard'), "
"('pms_property_id', '=', [value of property_id.id])]'",
)
def test_filter_pre_domain_moment_in_act_in_checkout(self):
"""
Check that when creating an automated mail with parameters
action = 'checkout' and moment = 'in_act' the filter_pre_domain
field of the automated_action is [('state', '=', 'onboard')].
"""
# ARRANGE
automated_mail_vals = {
"name": "Auto Mail 1",
"template_id": self.template.id,
"action": "checkout",
"moment": "in_act",
"pms_property_ids": [(6, 0, [self.pms_property1.id])],
}
# ACT
auto_mail = self.env["pms.automated.mails"].create(automated_mail_vals)
# ASSERT
self.assertEqual(
auto_mail.automated_actions_id.filter_pre_domain,
"[('state', '=', 'onboard')]",
"The filter_pre_domain of the automated action must "
"be '[('state', '=', 'onboard')]'",
)
def test_filter_domain_moment_in_act_in_checkout(self):
"""
Check that when creating an automated mail with parameters
action = 'checkout' and moment = 'in_act' the filter_domain
field of the automated_action is
[('state', '=', 'out'), ('pms_property_id', '=', [value of property_id.id])]].
"""
# ARRANGE
automated_mail_vals = {
"name": "Auto Mail 1",
"template_id": self.template.id,
"action": "checkout",
"moment": "in_act",
"pms_property_ids": [(6, 0, [self.pms_property1.id])],
}
# ACT
auto_mail = self.env["pms.automated.mails"].create(automated_mail_vals)
pms_property_id_str = str(auto_mail.pms_property_ids.ids)
# ASSERT
self.assertEqual(
auto_mail.automated_actions_id.filter_domain,
"[('state', '=', 'out'), ('pms_property_id', 'in', "
+ pms_property_id_str
+ ")]",
"The filter_pre_domain of the automated action must "
"be '[('state', '=', 'out'), ('pms_property_id', '=', [value of property_id.id])]",
)

View File

@@ -3424,3 +3424,77 @@ class TestPmsReservations(TestPms):
partner.id,
"The partner was not added to the reservation ",
)
def test_is_modified_reservation(self):
"""
Checked that the is_modified_reservation field is correctly set
to True when the checkin or checkout fields are modified in a
reservation.
----------------------
A reservation is created. The checkin and checkout fields of
the reservation are modified. The state of the boolean
is_mail_send is changed to True so that the compute of
the is_modified_reservation field is activated correctly
and it is verified that the state of this field is True.
"""
# ARRANGE
checkin = fields.date.today()
checkout = fields.date.today() + datetime.timedelta(days=2)
reservation_vals = {
"checkin": checkin,
"checkout": checkout,
"room_type_id": self.room_type_double.id,
"partner_id": self.partner1.id,
"pms_property_id": self.pms_property1.id,
}
reservation = self.env["pms.reservation"].create(reservation_vals)
# ACT
writed_checkin = fields.date.today() + datetime.timedelta(days=4)
writed_checkout = fields.date.today() + datetime.timedelta(days=6)
reservation.is_mail_send = True
reservation.update(
{
"checkin": writed_checkin,
"checkout": writed_checkout,
}
)
# ASSERT
self.assertTrue(
reservation.is_modified_reservation,
"is_modified_reservation field should be True ",
)
def test_is_not_modified_reservation(self):
"""
Checked that the is_modified_reservation field is correctly set
to False when the reservation is modified but not the checkin
or checkout fields.
----------------------
A reservation is created. The adults, arrival_hour and departure_hours
fields of the reservation are modified.The it is verified that the state
of this field is False.
"""
# ARRANGE
checkin = fields.date.today()
checkout = fields.date.today() + datetime.timedelta(days=2)
reservation_vals = {
"checkin": checkin,
"checkout": checkout,
"room_type_id": self.room_type_double.id,
"partner_id": self.partner1.id,
"pms_property_id": self.pms_property1.id,
}
reservation = self.env["pms.reservation"].create(reservation_vals)
reservation.update(
{"adults": 1, "arrival_hour": "18:00", "departure_hour": "08:00"}
)
# ASSERT
self.assertFalse(
reservation.is_modified_reservation,
"is_modified_reservation field should be False ",
)

View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record model="ir.ui.view" id="pms_automated_mails_view">
<field name="name">pms.automated_mails_view_form</field>
<field name="model">pms.automated.mails</field>
<field name="arch" type="xml">
<form string="Automated Mails" class="pt-1">
<sheet>
<div class="col-5">
<label for="name" />
<group>
<h2><field name="name" /></h2>
</group>
</div>
<div class="row">
<div class="col-5">
<group>
<field name="active" widget="boolean_toggle" />
<field name="template_id" />
<field name="action" />
<field
name="pms_property_ids"
widget="many2many_tags"
options="{'no_create': True,'no_open': True}"
/>
</group>
</div>
<div class="col-5">
<group>
<field name="moment" />
<field
name="time"
attrs="{'invisible':[('moment','=','in_act')]}"
/>
<field
name="time_type"
attrs="{'invisible':[('moment','=','in_act')]}"
/>
</group>
</div>
</div>
</sheet>
</form>
</field>
</record>
<record id="view_automated_mails_tree" model="ir.ui.view">
<field name="name">pms.automated.mails.tree</field>
<field name="model">pms.automated.mails</field>
<field name="arch" type="xml">
<tree string="Automated Mails">
<field name="name" />
<field name="action" />
<field name="template_id" />
<field name="moment" />
<field name="time" />
<field name="time_type" />
</tree>
</field>
</record>
<record model="ir.actions.act_window" id="open_pms_automated_mails_tree">
<field name="name">Automated Mails</field>
<field name="res_model">pms.automated.mails</field>
<field name="view_id" ref="view_automated_mails_tree" />
<field name="view_mode">tree,form</field>
</record>
<menuitem
name="Automated Mails"
id="menu_pms_automated_mails"
action="open_pms_automated_mails_tree"
sequence="40"
parent="pms.pms_configuration_menu"
/>
</odoo>

View File

@@ -85,6 +85,20 @@
<field name="room_ids" />
</group>
</page>
<page string="Email Configuration">
<group string="Templates">
<field name="property_confirmed_template" />
<field name="property_modified_template" />
<field name="property_canceled_template" />
</group>
<group string="Mail Information" colspan="4">
<field
name="mail_information"
string="Aditional Mail Information"
/>
<field name="privacy_policy" />
</group>
</page>
</notebook>
</sheet>
</form>

View File

@@ -43,7 +43,27 @@
states="onboard,departure_delayed"
type="object"
/>
<button
name="action_open_mail_composer"
string="Send Confirmation Email "
type="object"
attrs="{'invisible':['|','|',('is_mail_send', '=', True),('is_modified_reservation', '=', True),('state', 'in', 'cancel')]}"
/>
<button
name="action_open_mail_composer"
string="Send Modification Email "
type="object"
attrs="{'invisible':['|','|',('is_mail_send', '=', True), ('is_modified_reservation', '=', False), ('state', 'in', 'cancel')]}"
/>
<button
name="action_open_mail_composer"
string="Send Cancellation Email "
type="object"
attrs="{'invisible':['|',('is_mail_send', '=', True), ('state', 'not in', 'cancel')]}"
/>
<field name="state" widget="statusbar" />
<field name="is_mail_send" invisible="1" />
<field name="is_modified_reservation" invisible="1" />
</header>
<div
class="alert alert-info"
@@ -120,7 +140,7 @@
class="alert alert-warning"
role="alert"
style="margin-bottom:0px;"
attrs="{'invisible': [('is_possible_existing_customer_id','=',False)]}"
attrs="{'invisible': [('is_possible_existing_customer_id','=',[])]}"
>
There is a customer with this email or mobile, do you want to add it to the reservation?
<field name="is_possible_existing_customer_id" invisible="1" />
@@ -1043,4 +1063,45 @@
<field name="binding_view_types">form</field>
</record>
<record id="action_resend_confirmation_email" model="ir.actions.act_window">
<field name="name">Resend confirmation email</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">mail.compose.message</field>
<field name="view_mode">form</field>
<field name="target">new</field>
<field name="binding_model_id" ref="pms.model_pms_reservation" />
<field name="binding_view_types">form</field>
<field
name="context"
eval="{'template_id': ref('pms.confirmed_reservation_email')}"
/>
</record>
<record id="action_resend_modification_email" model="ir.actions.act_window">
<field name="name">Resend modification email</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">mail.compose.message</field>
<field name="view_mode">form</field>
<field name="target">new</field>
<field name="binding_model_id" ref="pms.model_pms_reservation" />
<field name="binding_view_types">form</field>
<field
name="context"
eval="{'template_id': ref('pms.modified_reservation_email')}"
/>
</record>
<record id="action_resend_cancellation_email" model="ir.actions.act_window">
<field name="name">Resend cancellation email</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">mail.compose.message</field>
<field name="view_mode">form</field>
<field name="target">new</field>
<field name="binding_model_id" ref="pms.model_pms_reservation" />
<field name="binding_view_types">form</field>
<field
name="context"
eval="{'template_id': ref('pms.cancelled_reservation_email')}"
/>
</record>
</odoo>