19.0 vanilla

This commit is contained in:
Ernad Husremovic 2026-03-09 09:31:39 +01:00
parent 5df8c07b59
commit daa394e8b0
2114 changed files with 564841 additions and 299642 deletions

View file

@ -29,14 +29,14 @@
</record>
<record id="mailing_contact_view_tree" model="ir.ui.view">
<field name="name">mailing.contact.view.tree.inherit.sms</field>
<field name="name">mailing.contact.view.list.inherit.sms</field>
<field name="model">mailing.contact</field>
<field name="inherit_id" ref="mass_mailing.mailing_contact_view_tree"/>
<field name="priority">20</field>
<field name="arch" type="xml">
<xpath expr="//field[@name='country_id']" position="after">
<field name="mobile" class="o_force_ltr" readonly="1"/>
<field name="phone_sanitized" invisible="1"/>
<field name="phone_sanitized" column_invisible="True"/>
<field name="phone_sanitized_blacklisted"/>
</xpath>
</field>
@ -53,10 +53,9 @@
<button name="phone_action_blacklist_remove" class="fa fa-ban text-danger"
title="This phone number is blacklisted for SMS Marketing. Click to unblacklist."
type="object" context="{'default_phone': mobile}" groups="base.group_user"
attrs="{'invisible': [('mobile_blacklisted', '=', False)]}"/>
invisible="not phone_blacklisted"/>
<field name="mobile" widget="phone" options="{'enable_sms': True}"/>
<field name="phone_sanitized" invisible="1"/>
<field name="mobile_blacklisted" invisible="1"/>
</div>
</xpath>
</field>
@ -68,11 +67,7 @@
<field name="inherit_id" ref="mass_mailing.mailing_contact_view_kanban"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='email']" position="after">
<field name="mobile" widget="phone"/>
<field name="phone_sanitized" invisible="1"/>
</xpath>
<xpath expr="//t[@t-esc='record.email.value']" position="after">
<t t-esc="record.mobile.value"/>
<field name="mobile" class="fw-bolder"/>
</xpath>
</field>
</record>
@ -80,7 +75,7 @@
<record id="mailing_contact_action_sms" model="ir.actions.act_window">
<field name="name">Mailing List Contacts</field>
<field name="res_model">mailing.contact</field>
<field name="view_mode">tree,form</field>
<field name="view_mode">list,form</field>
<field name="context">{'mailing_sms': True, 'search_default_filter_not_phone_bl': 1, }</field>
<field name="view_id" ref="mailing_contact_view_tree"/>
<field name="help" type="html">

View file

@ -5,23 +5,12 @@
<field name="model">mailing.list</field>
<field name="inherit_id" ref="mass_mailing.mailing_list_view_kanban"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='contact_count_email']" position="after">
<field name="contact_count_sms"/>
</xpath>
<xpath expr="//div[hasclass('o_mass_mailing_kanban_contact_links')]" position="inside">
<a name="action_view_contacts_sms" type="object">
<span >Valid SMS Recipients</span>
<span t-esc="record.contact_count_sms.value" class="ms-3"/>
</a>
</xpath>
<xpath expr="//div[hasclass('o_mailing_list_kanban_stats')]//a" position="after">
<a class="me-sm-0 me-3 text-large" tabindex="-1"
<a class="me-sm-0 me-3 fs-4 fw-light lh-1" tabindex="-1"
name="action_view_contacts_sms" type="object">
<span class="fw-normal">
<field name="contact_count_sms"/>
</span>
<field name="contact_count_sms" class="fw-normal"/>
<br/>
<span class="text-secondary">
<span class="text-muted">
<i class="fa fa-phone"/> Contacts
</span>
</a>
@ -29,16 +18,28 @@
</field>
</record>
<record id="mailing_list_view_form" model="ir.ui.view">
<field name="name">mailing.list.view.form.inherit.sms</field>
<field name="model">mailing.list</field>
<field name="inherit_id" ref="mass_mailing.mailing_list_view_form"/>
<field name="arch" type="xml">
<xpath expr="//button[@name='action_send_mailing']" position="after">
<button name="action_send_mailing_sms" string="Send SMS"
type="object" class="btn btn-primary"/>
</xpath>
</field>
</record>
<record id="mailing_list_action_sms" model="ir.actions.act_window">
<field name="name">Mailing Lists</field>
<field name="res_model">mailing.list</field>
<field name="view_mode">kanban,tree,form</field>
<field name="view_mode">kanban,list,form</field>
<field name="context">{'mailing_sms': True}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a Mailing List
</p><p>
No need to import mailing lists, you can send SMS Text Messages to contacts saved in other Odoo apps.
No need to import mailing lists, you can send SMS to contacts saved in other Odoo apps.
</p>
</field>
</record>

View file

@ -20,24 +20,26 @@
<field name="arch" type="xml">
<!-- Buttons / Actions -->
<xpath expr="//button[@name='action_launch']" position="attributes">
<attribute name="attrs">{'invisible': ['|', ('mailing_type', '!=', 'mail'), ('state', 'in', ('in_queue', 'sending', 'done'))]}</attribute>
<attribute name="invisible">mailing_type != 'mail' or state in ('in_queue', 'sending', 'processing', 'done')</attribute>
</xpath>
<xpath expr="//button[@name='action_schedule']" position="before">
<field name="sms_force_send" invisible="1"/>
<field name="schedule_type" invisible="1"/>
<field name="schedule_type" invisible="1" readonly="state not in ['draft', 'in_queue']"/>
<button name="action_put_in_queue" type="object"
string="Send" class="oe_highlight" data-hotkey="v"
attrs="{'invisible': ['|', '|', ('mailing_type', '=', 'mail'), ('state', 'in', ('in_queue', 'sending', 'done')), ('sms_force_send', '=', True)]}"
confirm="This will send SMS to all recipients. Do you still want to proceed ?"/>
invisible="mailing_type == 'mail' or state in ('in_queue', 'sending', 'processing', 'done') or sms_force_send"
confirm="Once you send these text messages, they'll be making a grand entrance in all pockets, creating quite the bzzzzz!"
confirm-title="Ready to unleash your text messages?" confirm-label="Send to all"/>
<button name="action_send_mail" type="object"
string="Send Now" class="oe_highlight" data-hotkey="g"
attrs="{'invisible': ['|', '|', '|', ('mailing_type', '=', 'mail'), ('state', 'in', ('in_queue', 'done')), ('schedule_type', '=', 'scheduled'), ('sms_force_send', '!=', True)]}"
confirm="This will send SMS to all recipients now. Do you still want to proceed ?"/>
invisible="mailing_type == 'mail' or state in ('in_queue', 'processing', 'done') or schedule_type == 'scheduled' or not sms_force_send"
confirm="Once you send these text messages, they'll be making a grand entrance in all pockets, creating quite the bzzzzz!"
confirm-title="Ready to unleash your text messages?" confirm-label="Send to all"/>
</xpath>
<!-- Headers / Warnings -->
<xpath expr="//header" position="after">
<field name="sms_has_insufficient_credit" invisible="1"/>
<div class="alert alert-warning text-center o-hidden-ios" attrs="{'invisible': [('sms_has_insufficient_credit', '=', False)]}" role="alert">
<div class="alert alert-warning text-center o-hidden-ios" invisible="not sms_has_insufficient_credit" role="alert">
<button class="btn-link py-0"
name="action_buy_sms_credits"
type="object">
@ -47,7 +49,7 @@
</button>
</div>
<field name="sms_has_unregistered_account" invisible="1"/>
<div class="alert alert-warning text-center o-hidden-ios" attrs="{'invisible': [('sms_has_unregistered_account', '=', False)]}" role="alert">
<div class="alert alert-warning text-center o-hidden-ios" invisible="not sms_has_unregistered_account" role="alert">
<button class="btn-link py-0"
name="action_buy_sms_credits"
type="object">
@ -58,80 +60,88 @@
</div>
</xpath>
<xpath expr="//span[@name='canceled_text']" position="attributes">
<attribute name="attrs">{'invisible': [('mailing_type', '!=', 'mail')]}</attribute>
<attribute name="invisible">mailing_type != 'mail'</attribute>
</xpath>
<xpath expr="//span[@name='canceled_text']" position="after">
<span name="canceled_text_sms" attrs="{'invisible': [('mailing_type', '!=', 'sms')]}">SMS Text Message have been canceled and will not be sent.</span>
<span name="canceled_text_sms" invisible="mailing_type != 'sms'">SMS Text Message have been cancelled and will not be sent.</span>
</xpath>
<xpath expr="//span[@name='scheduled_text']" position="attributes">
<attribute name="attrs">{'invisible': [('mailing_type', '!=', 'mail')]}</attribute>
<attribute name="invisible">mailing_type != 'mail'</attribute>
</xpath>
<xpath expr="//span[@name='scheduled_text']" position="after">
<span name="scheduled_text_sms" attrs="{'invisible': [('mailing_type', '!=', 'sms')]}">SMS Text Message are in queue and will be sent soon.</span>
<span name="scheduled_text_sms" invisible="mailing_type != 'sms'">SMS Text Messages are in queue and will be sent soon.</span>
</xpath>
<xpath expr="//span[@name='process_text']" position="attributes">
<attribute name="invisible">mailing_type != 'mail'</attribute>
</xpath>
<xpath expr="//span[@name='process_text']" position="after">
<span name="process_text_sms" invisible="mailing_type != 'sms'">SMS Text Messages are being processed.</span>
</xpath>
<xpath expr="//span[@name='sent']" position="attributes">
<attribute name="attrs">{'invisible': [('mailing_type', '!=', 'mail')]}</attribute>
<attribute name="invisible">mailing_type != 'mail'</attribute>
</xpath>
<xpath expr="//span[@name='sent']" position="after">
<span name="sent_sms" attrs="{'invisible': [('mailing_type', '!=', 'sms')]}">SMS Text Message have been sent.</span>
<span name="sent_sms" invisible="mailing_type != 'sms'">SMS Text Messages have been sent.</span>
</xpath>
<xpath expr="//span[@name='failed_text']" position="attributes">
<attribute name="attrs">{'invisible': [('mailing_type', '!=', 'mail')]}</attribute>
<attribute name="invisible">mailing_type != 'mail'</attribute>
</xpath>
<xpath expr="//span[@name='failed_text']" position="after">
<span name="failed_text_sms" attrs="{'invisible': [('mailing_type', '!=', 'sms')]}">SMS Text Message could not be sent.</span>
<span name="failed_text_sms" invisible="mailing_type != 'sms'">SMS Text Messages could not be delivered.</span>
</xpath>
<xpath expr="//span[@name='next_departure_text']" position='attributes'>
<attribute name="attrs">{'invisible': [('mailing_type', '!=', 'mail')]}</attribute>
<xpath expr="//span[@name='next_departure_text']" position="attributes">
<attribute name="invisible">mailing_type != 'mail'</attribute>
</xpath>
<xpath expr="//span[@name='next_departure_text']" position='after'>
<span name="next_departure_text" attrs="{'invisible': [('mailing_type', '!=', 'sms')]}">This SMS marketing is scheduled for </span>
<span name="next_departure_text" invisible="mailing_type != 'sms'">This SMS marketing is scheduled for </span>
</xpath>
<!-- Stat Buttons -->
<xpath expr="//button[@name='action_view_opened']" position="attributes">
<attribute name="attrs">{'invisible': ['|',('mailing_type', '!=', 'mail'),('state', 'in', ('draft','test'))]}</attribute>
<attribute name="invisible">mailing_type != 'mail' or state in ('draft', 'test')</attribute>
</xpath>
<xpath expr="//button[@name='action_view_replied']" position="attributes">
<attribute name="attrs">{'invisible': ['|',('mailing_type', '!=', 'mail'),('state', 'in', ('draft','test'))]}</attribute>
<attribute name="invisible">mailing_type != 'mail' or state in ('draft', 'test')</attribute>
</xpath>
<!-- Form -->
<xpath expr="//label[@for='subject']" position="attributes">
<attribute name="attrs">{'invisible': [('mailing_type', '!=', 'mail')]}</attribute>
</xpath>
<xpath expr="//label[@for='subject']" position="after">
<label for="sms_subject" attrs="{'invisible': [('mailing_type', '!=', 'sms')]}" />
<xpath expr="//field[@name='subject']" position="attributes">
<attribute name="invisible">mailing_type != 'mail'</attribute>
</xpath>
<xpath expr="//field[@name='subject']" position="attributes">
<attribute name="attrs">{'invisible': [('mailing_type', '!=', 'mail')], 'readonly': [('state', 'in', ('sending', 'done'))], 'required': [('mailing_type', '=', 'mail')]}</attribute>
<attribute name="invisible">mailing_type != 'mail'</attribute>
<attribute name="readonly">state in ('sending', 'done')</attribute>
<attribute name="required">mailing_type == 'mail'</attribute>
<!-- overrided in xml view to prevent remaining helper changes (on mass_mailing module) when mass_mailing_sms uninstalled-->
<attribute name="help">For an Email, Subject your Recipients will see in their inbox.
For an SMS Text Message, internal Title of the Message.</attribute>
</xpath>
<xpath expr="//field[@name='subject']" position="after">
<field class="text-break" name="sms_subject" string="Title" placeholder="e.g. Black Friday SMS coupon" attrs="{'invisible': [('mailing_type', '!=', 'sms')], 'readonly': [('state', 'in', ('sending', 'done'))], 'required': [('mailing_type', '=', 'sms')]}"/>
<field class="text-break" name="sms_subject" string="Title" placeholder="e.g. Black Friday SMS coupon" invisible="mailing_type != 'sms'" readonly="state in ('sending', 'done')" required="mailing_type == 'sms'"/>
</xpath>
<xpath expr="//button[@name='action_set_favorite']" position="attributes">
<attribute name="attrs">{'invisible': ['|', ('mailing_type', '!=', 'mail'), ('favorite', '=', True)]}</attribute>
<attribute name="invisible" separator=" or " add="mailing_type != 'mail'"/>
</xpath>
<xpath expr="//button[@name='action_remove_favorite']" position="attributes">
<attribute name="attrs">{'invisible': ['|', ('mailing_type', '!=', 'mail'), ('favorite', '=', False)]}</attribute>
<attribute name="invisible">mailing_type != 'mail' or not favorite</attribute>
</xpath>
<xpath expr="//field[@name='preview']" position="attributes">
<attribute name="attrs">{'readonly': [('state', 'in', ('sending', 'done'))], 'invisible': [('mailing_type', '!=', 'mail')]}</attribute>
<attribute name="invisible">mailing_type != 'mail'</attribute>
<attribute name="readonly">state in ('sending', 'done')</attribute>
</xpath>
<xpath expr="//page[@name='mail_body']" position="attributes">
<attribute name="attrs">{'invisible': [('mailing_type', '!=', 'mail')]}</attribute>
<attribute name="invisible">mailing_type != 'mail'</attribute>
</xpath>
<xpath expr="//page[@name='mail_body']" position="after">
<page string="SMS Content" name="sms_body" attrs="{'invisible': [('mailing_type', '!=', 'sms')]}">
<page string="SMS Content" name="sms_body" invisible="mailing_type != 'sms'">
<field name="body_plaintext" widget="sms_widget"
attrs="{'required': [('mailing_type', '=', 'sms')], 'readonly': [('state', 'in', ('sending', 'done'))]}"
options="{'dynamic_placeholder': true}" enable_emojis="true"/>
readonly="state in ('sending', 'done')"
required="mailing_type == 'sms'"
options="{'dynamic_placeholder': true, 'dynamic_placeholder_model_reference_field': 'mailing_model_real'}"
enable_emojis="true"/>
</page>
</xpath>
<xpath expr="//page[@name='settings']/group/group[@name='email_content']" position="after">
<group string="Options" attrs="{'invisible': [('mailing_type', '!=', 'sms')]}">
<field name="sms_allow_unsubscribe" attrs="{'invisible': [('mailing_type', '!=', 'sms')], 'readonly': [('state', 'in', ('sending', 'done'))]}"/>
<group string="Options" invisible="mailing_type != 'sms'">
<field name="sms_allow_unsubscribe" invisible="mailing_type != 'sms'" readonly="state in ('sending', 'done')"/>
</group>
</xpath>
@ -143,50 +153,52 @@
</xpath>
<!-- Option page tweaks -->
<xpath expr="//field[@name='email_from']" position="attributes">
<attribute name="attrs">{
'invisible': [('mailing_type', '!=', 'mail')],
'readonly': [('state', 'in', ('sending', 'done'))]}
</attribute>
<attribute name="invisible">mailing_type != 'mail'</attribute>
</xpath>
<xpath expr="//label[@for='reply_to']" position="attributes">
<attribute name="attrs">{'invisible': [('mailing_type', '!=', 'mail')]}</attribute>
<attribute name="invisible">mailing_type != 'mail'</attribute>
</xpath>
<xpath expr="//field[@name='reply_to']" position="attributes">
<attribute name="required">mailing_type == 'mail'</attribute>
</xpath>
<xpath expr="//div[@name='reply_to_details']" position="attributes">
<attribute name="attrs">{'invisible': [('mailing_type', '!=', 'mail')]}</attribute>
<attribute name="invisible">mailing_type != 'mail'</attribute>
</xpath>
<xpath expr="//label[@for='attachment_ids']" position="attributes">
<attribute name="attrs">{'invisible': [('mailing_type', '!=', 'mail')]}</attribute>
<attribute name="invisible">mailing_type != 'mail'</attribute>
</xpath>
<xpath expr="//div[@name='attachment_ids_details']" position="attributes">
<attribute name="attrs">{'invisible': [('mailing_type', '!=', 'mail')]}</attribute>
<attribute name="invisible">mailing_type != 'mail'</attribute>
</xpath>
<xpath expr="//field[@name='mail_server_id']" position="attributes">
<attribute name="attrs">{'invisible': ['|', ('mailing_type', '!=', 'mail'),
('mail_server_available', '=', False)], 'readonly': [('state', 'in', ('sending', 'done'))]}</attribute>
<attribute name="invisible" add="mailing_type != 'mail'" separator=" or "/>
</xpath>
<!-- A/B Testing -->
<xpath expr="//field[@name='ab_testing_mailings_count']" position="after">
<field name="ab_testing_mailings_sms_count" invisible="1"/>
</xpath>
<xpath expr="//field[@name='ab_testing_winner_selection']" position="after">
<label for="ab_testing_sms_winner_selection" string="Winner Selection"
attrs="{'invisible': ['|', ('ab_testing_enabled', '=', False), ('mailing_type', '!=', 'sms')]}"/>
invisible="not ab_testing_enabled or mailing_type != 'sms'"/>
<field name="ab_testing_sms_winner_selection" nolabel="1"
attrs="{'required': [('ab_testing_enabled', '=', True), ('mailing_type', '=', 'sms')], 'invisible': ['|', ('ab_testing_enabled', '=', False), ('mailing_type', '!=', 'sms')], 'readonly': [('state', '!=', 'draft')]}"/>
invisible="not ab_testing_enabled or mailing_type != 'sms'"
readonly="state != 'draft'"
required="ab_testing_enabled and mailing_type == 'sms'"/>
</xpath>
<xpath expr="//field[@name='ab_testing_schedule_datetime']" position="replace">
<field name="ab_testing_schedule_datetime"
attrs="{'required': [('ab_testing_enabled', '=', True), ('ab_testing_winner_selection', '!=', 'manual'), ('ab_testing_sms_winner_selection', '!=', 'manual')], 'readonly': ['|', ('ab_testing_enabled', '=', False), ('state', '!=', 'draft')], 'invisible': ['|', '|', ('ab_testing_enabled', '=', False), ('ab_testing_winner_selection', '=', 'manual'), ('ab_testing_sms_winner_selection', '=', 'manual')]}"/>
invisible="not ab_testing_enabled or ab_testing_winner_selection == 'manual' or ab_testing_sms_winner_selection == 'manual'"
readonly="not ab_testing_enabled or state != 'draft'"
required="ab_testing_enabled and ab_testing_winner_selection != 'manual' and ab_testing_sms_winner_selection != 'manual'"/>
</xpath>
<xpath expr="//span[@name='ab_test_manual']" position="attributes">
<attribute name="attrs">{'invisible': ['|', ('ab_testing_winner_selection', '!=', 'manual'),
('ab_testing_sms_winner_selection', '!=', 'manual')]}</attribute>
<xpath expr="//div[@id='mailing_form_ab_buttons']" position="attributes">
<attribute name="invisible">not ab_testing_enabled or ab_testing_mailings_count &lt; 2 and ab_testing_mailings_sms_count &lt; 2</attribute>
</xpath>
<xpath expr="//span[@name='ab_test_auto']" position="attributes">
<attribute name="attrs">{'invisible': [('ab_testing_winner_selection', '=', 'manual'),
('ab_testing_sms_winner_selection', '=', 'manual')]}</attribute>
<xpath expr="//button[@name='action_send_winner_mailing']" position="attributes">
<attribute name="invisible">not is_ab_test_sent or ab_testing_completed or ab_testing_winner_selection == 'manual' or ab_testing_sms_winner_selection == 'manual'</attribute>
</xpath>
<xpath expr="//button[@name='action_select_as_winner']" position="attributes">
<attribute name="attrs">{'invisible': ['|', ('ab_testing_completed', '!=', False), '|',
('ab_testing_winner_selection', '=', 'manual'),
('ab_testing_sms_winner_selection', '=', 'manual')]}</attribute>
<xpath expr="//button[@name='action_duplicate'][hasclass('btn-primary')]" position="attributes">
<attribute name="invisible">not ab_testing_enabled or ab_testing_mailings_count &gt;= 2 or ab_testing_mailings_sms_count &gt;= 2</attribute>
</xpath>
</field>
</record>
@ -216,17 +228,11 @@
<field name="sms_has_insufficient_credit"/>
<field name="sms_has_unregistered_account"/>
</xpath>
<xpath expr="//div[@name='stat_opened']" position="attributes">
<attribute name="attrs">{'invisible': [('mailing_type', '!=', 'mail')]}</attribute>
</xpath>
<xpath expr="//div[@name='stat_replied']" position="attributes">
<attribute name="attrs">{'invisible': [('mailing_type', '!=', 'mail')]}</attribute>
</xpath>
<xpath expr="//div[@name='div_responsible_avatar']" position="after">
<div class="alert alert-warning mb-0 mt-3 o-hidden-ios" role="alert" attrs="{'invisible': [('sms_has_insufficient_credit', '=', False)]}">
<xpath expr="//footer" position="after">
<div class="alert alert-warning mb-0 mt-3 o-hidden-ios" role="alert" invisible="not sms_has_insufficient_credit">
<a name="action_buy_sms_credits" type="object">Insufficient credits</a>
</div>
<div class="alert alert-warning mb-0 mt-3" role="alert" attrs="{'invisible': [('sms_has_unregistered_account', '=', False)]}">
<div class="alert alert-warning mb-0 mt-3" role="alert" invisible="not sms_has_unregistered_account">
<a name="action_buy_sms_credits" type="object">Unregistered account</a>
</div>
</xpath>
@ -234,14 +240,14 @@
</record>
<record id="mailing_mailing_view_tree_sms" model="ir.ui.view">
<field name="name">mailing.mailing.view.tree.sms</field>
<field name="name">mailing.mailing.view.list.sms</field>
<field name="model">mailing.mailing</field>
<field name="priority">20</field>
<field name="arch" type="xml">
<tree string="SMS Marketing" sample="1" decoration-info="state == 'draft'">
<list string="SMS Marketing" sample="1" decoration-info="state == 'draft'">
<field name="calendar_date" string="Date"/>
<field name="subject" string="Title"/>
<field name="mailing_type" invisible="1"/>
<field name="mailing_type" column_invisible="True"/>
<field name="mailing_model_id" string="Recipients" optional="hide"/>
<field name="user_id" widget="many2one_avatar_user"/>
<field name="campaign_id" string="Campaign" groups="mass_mailing.group_mass_mailing_campaign" optional="hide"/>
@ -250,14 +256,15 @@
<field name="clicked" string="Clicked (%)" widget="progressbar" avg="Average of Clicked"/>
<field name="bounced" string="Bounced (%)" widget="progressbar" optional="hide" avg="Average of Bounced"/>
<field name="state" decoration-info="state in ('draft', 'in_queue')" decoration-success="state in ('sending', 'done')" widget="badge"/>
</tree>
</list>
</field>
</record>
<record id="mailing_mailing_action_sms" model="ir.actions.act_window">
<field name="name">SMS Marketing</field>
<field name="path">sms-marketing</field>
<field name="res_model">mailing.mailing</field>
<field name="view_mode">kanban,tree,form,calendar,graph</field>
<field name="view_mode">list,kanban,form,calendar,graph</field>
<field name="search_view_id" ref="mailing_mailing_view_search_sms"/>
<field name="domain">[('mailing_type', '=', 'sms')]</field>
<field name="context">{
@ -274,17 +281,17 @@
</p>
</field>
</record>
<record id="mailing_mailing_action_sms_view_kanban" model="ir.actions.act_window.view">
<record id="mailing_mailing_action_sms_view_tree" model="ir.actions.act_window.view">
<field name="sequence">1</field>
<field name="view_mode">list</field>
<field name="view_id" ref="mailing_mailing_view_tree_sms"/>
<field name="act_window_id" ref="mailing_mailing_action_sms"/>
</record>
<record id="mailing_mailing_action_sms_view_kanban" model="ir.actions.act_window.view">
<field name="sequence">2</field>
<field name="view_mode">kanban</field>
<field name="view_id" ref="mailing_mailing_view_kanban_sms"/>
<field name="act_window_id" ref="mailing_mailing_action_sms"/>
</record>
<record id="mailing_mailing_action_sms_view_tree" model="ir.actions.act_window.view">
<field name="sequence">2</field>
<field name="view_mode">tree</field>
<field name="view_id" ref="mailing_mailing_view_tree_sms"/>
<field name="act_window_id" ref="mailing_mailing_action_sms"/>
</record>
</data></odoo>

View file

@ -4,7 +4,7 @@
<menuitem id="mass_mailing_sms_menu_root"
name="SMS Marketing"
sequence="120"
web_icon="mass_mailing_sms,static/description/icon.svg"
web_icon="mass_mailing_sms,static/description/icon.png"
groups="mass_mailing.group_mass_mailing_user"/>
<!-- SMS Marketing / SMS Marketing -->

View file

@ -6,15 +6,15 @@
<field name="inherit_id" ref="mass_mailing.mailing_trace_view_search"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='email']" position="after">
<field name="sms_sms_id_int"/>
<field name="sms_sms_id"/>
<field name="sms_id_int"/>
<field name="sms_id"/>
<field name="sms_number"/>
</xpath>
</field>
</record>
<record id="mailing_trace_view_tree" model="ir.ui.view">
<field name="name">mailing.trace.view.tree.inherit.sms</field>
<field name="name">mailing.trace.view.list.inherit.sms</field>
<field name="model">mailing.trace</field>
<field name="inherit_id" ref="mass_mailing.mailing_trace_view_tree"/>
<field name="arch" type="xml">
@ -28,11 +28,11 @@
</record>
<record id="mailing_trace_view_tree_sms" model="ir.ui.view">
<field name="name">mailing.trace.view.tree.sms</field>
<field name="name">mailing.trace.view.list.sms</field>
<field name="model">mailing.trace</field>
<field name="priority">20</field>
<field name="arch" type="xml">
<tree string="SMS Traces" create="0">
<list string="SMS Traces" create="0">
<field name="mass_mailing_id"/>
<field name="sms_number"/>
<field name="sent_datetime"/>
@ -41,9 +41,10 @@
<field name="failure_type" optional="show"/>
<field name="open_datetime" optional="hide"/>
<field name="reply_datetime" optional="hide"/>
<field name="is_test_trace" optional="hide"/>
<button name="action_view_contact" type="object"
string="Open Recipient" icon="fa-user"/>
</tree>
</list>
</field>
</record>
@ -52,23 +53,26 @@
<field name="model">mailing.trace</field>
<field name="inherit_id" ref="mass_mailing.mailing_trace_view_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='trace_status']" position="attributes">
<attribute name="statusbar_visible">outgoing,pending,sent,error</attribute>
</xpath>
<xpath expr="//field[@name='email']" position="attributes">
<attribute name="attrs">{'invisible': [('trace_type', '!=', 'mail')]}</attribute>
<attribute name="invisible">trace_type != 'mail'</attribute>
</xpath>
<xpath expr="//field[@name='mail_mail_id_int']" position="attributes">
<attribute name="attrs">{'invisible': [('trace_type', '!=', 'mail')]}</attribute>
<attribute name="invisible">trace_type != 'mail'</attribute>
</xpath>
<xpath expr="//field[@name='message_id']" position="attributes">
<attribute name="attrs">{'invisible': [('trace_type', '!=', 'mail')]}</attribute>
<attribute name="invisible">trace_type != 'mail'</attribute>
</xpath>
<xpath expr="//field[@name='email']" position="after">
<field name="sms_number" attrs="{'invisible': [('trace_type', '!=', 'sms')]}"/>
<field name="sms_number" invisible="trace_type != 'sms'"/>
</xpath>
<xpath expr="//field[@name='message_id']" position="after">
<field name="sms_sms_id_int" string="SMS ID"
attrs="{'invisible': [('trace_type', '!=', 'sms')]}"
<field name="sms_id_int" string="SMS ID"
invisible="trace_type != 'sms'"
groups="base.group_no_one"/>
<field name="sms_code" attrs="{'invisible': [('trace_type', '!=', 'sms')]}"
<field name="sms_code" invisible="trace_type != 'sms'"
groups="base.group_no_one"/>
</xpath>
</field>
@ -80,6 +84,12 @@
<field name="priority">20</field>
<field name="arch" type="xml">
<form string="SMS Trace" create="0" edit="0">
<div class="alert alert-info text-center"
invisible="trace_status != 'error' or
failure_type in ('sms_not_delivered', 'sms_not_allowed', 'sms_invalid_destination', 'sms_rejected', 'sms_rejected')"
role="alert">
<strong>This SMS could not be sent.</strong>
</div>
<sheet>
<div class="oe_button_box" name="button_box">
<button name="action_view_contact"
@ -87,33 +97,38 @@
<span widget="statinfo">Open Recipient</span>
</button>
</div>
<div class="alert alert-info text-center" attrs="{'invisible': [('trace_status', '!=', 'error')]}" role="alert">
<strong>This SMS could not be sent.</strong>
<field name="is_test_trace" invisible="1"/>
<widget name="web_ribbon" title="Test" bg_color="text-bg-danger" invisible="is_test_trace != True"/>
<div class="alert alert-info text-center"
invisible="trace_status != 'error' or
failure_type not in ('sms_not_delivered', 'sms_not_allowed', 'sms_invalid_destination', 'sms_rejected', 'sms_rejected')"
role="alert">
<strong>This SMS could not be delivered.</strong>
</div>
<div class="alert alert-info text-center" attrs="{'invisible': [('trace_status', '!=', 'bounce')]}" role="alert">
<div class="alert alert-info text-center" invisible="trace_status != 'bounce'" role="alert">
<strong>This number appears to be invalid.</strong>
</div>
<group>
<group string="Status">
<field name="trace_status"/>
<field name="failure_type" attrs="{'invisible' : [('failure_type', '=', False)]}"/>
<field name="sent_datetime" attrs="{'invisible' : [('sent_datetime', '=', False)]}"/>
<field name="links_click_datetime" attrs="{'invisible' : [('links_click_datetime', '=', False)]}"/>
<field name="open_datetime" attrs="{'invisible' : [('open_datetime', '=', False)]}"/>
<field name="reply_datetime" attrs="{'invisible' : [('reply_datetime', '=', False)]}"/>
<field name="failure_type" invisible="not failure_type"/>
<field name="sent_datetime" invisible="not sent_datetime"/>
<field name="links_click_datetime" invisible="not links_click_datetime"/>
<field name="open_datetime" invisible="not open_datetime"/>
<field name="reply_datetime" invisible="not reply_datetime"/>
</group>
<group string="Mailing">
<field name="trace_type" invisible="1"/>
<field name="sms_number"/>
<field name="mass_mailing_id"/>
<field name="sms_sms_id_int" string="SMS ID" groups="base.group_no_one"/>
<field name="sms_id_int" string="SMS ID" groups="base.group_no_one"/>
<field name="sms_code" groups="base.group_no_one"/>
</group>
<group string="Marketing">
<field name="campaign_id" groups="mass_mailing.group_mass_mailing_campaign"/>
<field name="medium_id"/>
<field name="source_id"/>
<field name="sms_sms_id_int" groups="base.group_no_one"/>
<field name="sms_id" groups="base.group_no_one" invisible="not sms_id"/>
</group>
</group>
</sheet>

View file

@ -4,27 +4,28 @@
<t t-call="portal.frontend_layout">
<div class="container mb64">
<div class="row">
<div class="col-lg-6 offset-lg-3">
<h3>SMS Subscription</h3>
<form t-att-action="'/sms/%s/unsubscribe/%s' % (mailing_id, trace_code)" method="post">
<p>Please enter your phone number</p>
<div class="col-lg-6 offset-lg-3 mt-5">
<form t-att-action="'/sms/%s/%s' % (mailing_id, trace_code)" method="post">
<p>Please confirm your phone number to unsubscribe :</p>
<div class="mb-3 row">
<label for="sms_number" class="col-sm-2 col-form-label">Number</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="sms_number" id="sms_number" t-att-required="true"/>
<input type="text" class="form-control" name="sms_number" id="sms_number" t-att-required="true" placeholder='e.g. "+1 (555) 123-4567"'/>
</div>
</div>
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
<input type="hidden" name="trace_code" t-att-value="trace_code"/>
<input type="hidden" name="mailing_id" t-att-value="mailing_id"/>
<div class="mb-3 row">
<div class="col-sm-10 offset-sm-2">
<button type="submit" class="btn btn-primary">Unsubscribe me</button>
<div class="col-sm-10">
<button type="submit" class="btn btn-primary">Unsubscribe</button>
</div>
</div>
</form>
</div>
<div t-if="unsubscribe_error" class="alert alert-danger text-center w-auto offset-lg-3" role="alert">
<p>There was an error when trying to unsubscribe <strong t-out="sms_number"/><br />
<t t-out="unsubscribe_error"/></p>
</div>
</div>
</div>
</t>
@ -37,15 +38,14 @@
<div class="col-lg-6 offset-lg-3">
<h3>SMS Subscription</h3>
<div t-if="unsubscribe_error" class="alert alert-danger text-center" role="alert">
<p>There was an error when trying to unsubscribe <strong t-esc="sms_number"/></p>
<p t-esc="unsubscribe_error"/>
</div>
<div t-else="" class="alert alert-success text-center" role="status">
<div class="alert alert-success text-center" role="status">
<t t-if="lists_optout">
<p><strong t-esc="sms_number"/> has been successfully removed from</p>
<t t-foreach="lists_optout" t-as="list_id">
<strong t-esc="list_id.name"/><br />
<t t-if="list_id.is_public">
<strong t-out="list_id.name"/><br />
</t>
<t t-else=""><strong>Mailing List</strong></t>
</t>
</t>
<p t-else="">

View file

@ -7,14 +7,14 @@
<field name="arch" type="xml">
<xpath expr="//header" position="inside">
<button name="action_create_mass_sms" type="object" class="oe_highlight" string="Send SMS"
attrs="{'invisible': [('is_mailing_campaign_activated', '=', False)]}"
invisible="not is_mailing_campaign_activated"
groups="mass_mailing.group_mass_mailing_user"/>
</xpath>
<xpath expr="//div[hasclass('oe_button_box')]" position="inside">
<button name="action_redirect_to_mailing_sms"
type="object"
class="oe_stat_button order-11"
attrs="{'invisible': ['|', ('mailing_sms_count', '=', 0), ('is_mailing_campaign_activated', '=', False)]}"
invisible="mailing_sms_count == 0 or not is_mailing_campaign_activated"
icon="fa-mobile" groups="mass_mailing.group_mass_mailing_user">
<field name="mailing_sms_count" widget="statinfo" string="SMS"/>
</button>
@ -24,32 +24,30 @@
</xpath>
<xpath expr="//notebook" position="inside">
<page string="SMS" name="sms"
attrs="{'invisible': ['|', ('mailing_sms_count', '=', 0), ('is_mailing_campaign_activated', '=', False)]}"
invisible="mailing_sms_count == 0 or not is_mailing_campaign_activated"
groups="mass_mailing.group_mass_mailing_user">
<group>
<field name="mailing_sms_ids" nolabel="1">
<tree>
<field name="calendar_date" string="Date"/>
<field name="subject" string="Title"/>
<field name="mailing_type" invisible="1"/>
<field name="mailing_model_id" string="Recipients" optional="hide"/>
<field name="user_id" widget="many2one_avatar_user"/>
<field name="campaign_id" string="Campaign" groups="mass_mailing.group_mass_mailing_campaign" optional="hide"/>
<field name="ab_testing_enabled" string="A/B Test"
groups="mass_mailing.group_mass_mailing_campaign"
attrs="{'column_invisible': [('parent.ab_testing_mailings_sms_count', '=', 0)]}"/>
<field name="sent" sum="Total Sent"/>
<field name="clicked" string="Clicked (%)" avg="Average of Clicked"/>
<field name="bounced" string="Bounced (%)" optional="hide" avg="Average of Bounced"/>
<field name="state" decoration-info="state in ('draft', 'in_queue')" decoration-success="state in ('sending', 'done')" widget="badge"/>
<button name="action_duplicate" type="object" string="Duplicate"/>
</tree>
</field>
</group>
<field name="mailing_sms_ids">
<list>
<field name="calendar_date" string="Date"/>
<field name="subject" string="Title"/>
<field name="mailing_type" column_invisible="True"/>
<field name="mailing_model_id" string="Recipients" optional="hide"/>
<field name="user_id" widget="many2one_avatar_user"/>
<field name="campaign_id" string="Campaign" groups="mass_mailing.group_mass_mailing_campaign" optional="hide"/>
<field name="ab_testing_enabled" string="A/B Test"
groups="mass_mailing.group_mass_mailing_campaign"
column_invisible="parent.ab_testing_mailings_sms_count == 0"/>
<field name="sent" sum="Total Sent"/>
<field name="clicked" string="Clicked (%)" avg="Average of Clicked"/>
<field name="bounced" string="Bounced (%)" optional="hide" avg="Average of Bounced"/>
<field name="state" decoration-info="state in ('draft', 'in_queue')" decoration-success="state in ('sending', 'done')" widget="badge"/>
<button name="action_duplicate" type="object" string="Duplicate"/>
</list>
</field>
</page>
</xpath>
<xpath expr="//group[@name='ab_test_group']" position="attributes">
<attribute name="attrs">{'invisible': [('ab_testing_mailings_sms_count', '=', 0), ('ab_testing_mailings_count', '=', 0)]}</attribute>
<attribute name="invisible">ab_testing_mailings_sms_count == 0 and ab_testing_mailings_count == 0</attribute>
</xpath>
</field>
</record>
@ -59,15 +57,12 @@
<field name="model">utm.campaign</field>
<field name="inherit_id" ref="utm.utm_campaign_view_kanban"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='user_id']" position="after">
<field name="mailing_sms_count" groups="mass_mailing.group_mass_mailing_user"/>
</xpath>
<xpath expr="//ul[@id='o_utm_actions']">
<a name="action_redirect_to_mailing_sms" type="object"
t-attf-class="oe_mailings #{record.mailing_sms_count.raw_value === 0 ? 'text-muted' : ''}"
t-attf-class="pe-2 oe_mailings #{record.mailing_sms_count.raw_value === 0 ? 'text-muted' : ''}"
t-if="record.is_mailing_campaign_activated.raw_value"
groups="mass_mailing.group_mass_mailing_user">
<t t-out="record.mailing_sms_count.raw_value"/> SMS
<field name="mailing_sms_count"/> SMS
</a>
</xpath>
</field>