diff --git a/mail_move_message/static/src/js/mail_move_message.js b/mail_move_message/static/src/js/mail_move_message.js
index b3f5fc0..f8487ba 100644
--- a/mail_move_message/static/src/js/mail_move_message.js
+++ b/mail_move_message/static/src/js/mail_move_message.js
@@ -21,7 +21,11 @@ odoo.define('mail_move_message.relocate', function (require) {
var session = require('web.Session');
var FormController = require('web.FormController');
var FormView = require('web.FormView');
- var registry = require('web.field_registry');
+ var FormRenderer = require('web.FormRenderer');
+ var dialogs = require('web.view_dialogs');
+ var Dialog = require('web.Dialog');
+ var relational_fields = require('web.relational_fields');
+ var Widget = require('web.Widget');
var _t = core._t;
@@ -43,7 +47,7 @@ odoo.define('mail_move_message.relocate', function (require) {
view_type: 'form',
views: [[false, 'form']],
target: 'new',
- context: {'default_message_id': message_id}
+ context: {'default_message_id': message_id},
};
this.do_action(action, {
'on_close': function(){}
@@ -114,4 +118,39 @@ odoo.define('mail_move_message.relocate', function (require) {
return this._super(recordID, values, options)
}
});
+
+ FormController.include({
+ _onButtonClicked: function(event){
+ if(event.data.attrs.special === 'quick_create' && event.data.attrs.field === 'partner_id'){
+ var self = this;
+ var field_data = event.data.record.data;
+ this.on_saved = function(record, bool) {
+ var values = [{
+ id: record.res_id,
+ display_name: record.data.display_name,
+ }];
+ };
+ var wid = self.initialState.fieldsInfo.form.partner_id.Widget;
+ var relField = new relational_fields.FieldMany2One(wid,
+ 'partner_id',
+ self.initialState,
+ {
+ mode: 'edit',
+ viewType: 'form',
+ });
+ relField.getParent = function() {
+ // necessary for correct _trigger_up implementation in mixins.js
+ return self;
+ };
+ var wizard_popup = relField._searchCreatePopup("form", false, {
+ 'message_name_from': field_data.message_name_from && field_data.message_name_from.split('@')[0],
+ 'message_email_from': field_data.message_email_from,
+ 'message_id': field_data.res_id,
+ 'mail_move_message': 1,
+ });
+ } else {
+ this._super.apply(this, arguments);
+ }
+ },
+ });
});
diff --git a/mail_move_message/tests/__init__.py b/mail_move_message/tests/__init__.py
new file mode 100644
index 0000000..44c544d
--- /dev/null
+++ b/mail_move_message/tests/__init__.py
@@ -0,0 +1,3 @@
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
+from . import test_mail_move
+
diff --git a/mail_move_message/tests/test_mail_move.py b/mail_move_message/tests/test_mail_move.py
new file mode 100644
index 0000000..014bb93
--- /dev/null
+++ b/mail_move_message/tests/test_mail_move.py
@@ -0,0 +1,52 @@
+# Copyright 2018 Kolushov Alexandr
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
+
+import odoo.tests
+from odoo.api import Environment
+
+
+@odoo.tests.common.at_install(True)
+@odoo.tests.common.post_install(True)
+class TestUi(odoo.tests.HttpCase):
+
+ def test_create_new_partner_and_move_message(self):
+ env = Environment(self.registry.test_cr, self.uid, {})
+ # needed because tests are run before the module is marked as
+ # installed. In js web will only load qweb coming from modules
+ # that are returned by the backend in module_boot. Without
+ # this you end up with js, css but no qweb.
+ env['ir.module.module'].search([('name', '=', 'mail_move_message')], limit=1).state = 'installed'
+ self.registry.cursor().release()
+
+ # updating models, to be able relocate messages to a partner at_install
+ config_parameters = self.env["ir.config_parameter"].sudo()
+ config_parameters.set_param("mail_relocation_models", "crm.lead,project.task,res.partner")
+
+ code = """
+ var delayed_button_click = function(delay, button){
+ setTimeout(function(){
+ if (button.length) {
+ return button.click();
+ }
+ return console.log('error', 'There is no element with the next selector: ' + button.selector);
+ }, delay);
+ };
+ var delay = 1000;
+ var message = $('.o_thread_message_core:contains("virginie")');
+ var relocate = message.find('.o_thread_icons .fa-exchange');
+ delayed_button_click(delay, relocate);
+ // form is opened
+
+ var create_partner_button = $('button[special="quick_create"]');
+ delayed_button_click(delay, create_partner_button);
+ // partner creation wizard is opened
+
+ var save_button = $('.modal-content .btn-primary:contains("Save")');
+ delayed_button_click(delay, save_button);
+
+ var move_button = $('.btn-sm.oe_highlight:contains("Move")');
+ delayed_button_click(delay, move_button);
+ console.log('ok')
+ """
+
+ self.phantom_js('/web', code, login="admin", ready="$('.o_thread_icons').length")
diff --git a/mail_multi_website/README.rst b/mail_multi_website/README.rst
new file mode 100644
index 0000000..a7c4dd1
--- /dev/null
+++ b/mail_multi_website/README.rst
@@ -0,0 +1,62 @@
+.. image:: https://img.shields.io/badge/license-LGPL--3-blue.png
+ :target: https://www.gnu.org/licenses/lgpl
+ :alt: License: LGPL-3
+
+===========================================
+ Email Addresses and Templates per Website
+===========================================
+
+Mail-related stuff for multi-website support
+
+* Makes following field in ``res.users`` website-dependent:
+
+ * ``email``
+ * ``signature``
+
+* Makes following fields in ``mail.template`` website-dependent:
+
+ * ``body_html``
+ * ``mail_server_id``
+ * ``report_template``
+
+* Overrides ``mail.template``'s ``render_template`` method to add ``website``
+ variable. It may cause incompatibility with other modules that redefine that
+ method too.
+
+Credits
+=======
+
+Contributors
+------------
+* `Ivan Yelizariev `__
+
+Sponsors
+--------
+* `e-thos SSII `__
+
+Maintainers
+-----------
+* `IT-Projects LLC `__
+
+ To get a guaranteed support
+ you are kindly requested to purchase the module
+ at `odoo apps store `__.
+
+ Thank you for understanding!
+
+ `IT-Projects Team `__
+
+Further information
+===================
+
+Demo: http://runbot.it-projects.info/demo/mail-addons/11.0
+
+HTML Description: https://apps.odoo.com/apps/modules/11.0/mail_multi_website/
+
+Usage instructions: ``_
+
+Changelog: ``_
+
+Notifications on updates: `via Atom `_, `by Email `_
+
+Tested on Odoo 11.0 4d0a1330e05bd688265bea14df4ad12838f9f2d7
diff --git a/mail_multi_website/__init__.py b/mail_multi_website/__init__.py
new file mode 100644
index 0000000..5af1037
--- /dev/null
+++ b/mail_multi_website/__init__.py
@@ -0,0 +1,40 @@
+# Copyright 2018 Ivan Yelizariev
+# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
+from . import models
+from . import wizard
+from .tests import test_mail_model
+
+
+def post_init_hook(cr, registry):
+ from odoo import api, SUPERUSER_ID
+
+ env = api.Environment(cr, SUPERUSER_ID, {})
+
+ env.cr.execute("ALTER TABLE res_users ADD COLUMN email_multi_website VARCHAR")
+
+ # fill new email column with values from partner
+ for user in env['res.users'].with_context(active_test=False).search([]):
+ email = user.partner_id.email
+ if email:
+ user._force_default('email_multi_website', email)
+
+
+def uninstall_hook(cr, registry):
+ from odoo import api, SUPERUSER_ID
+
+ env = api.Environment(cr, SUPERUSER_ID, {})
+
+ # remove properties
+ field_ids = [
+ env.ref('base.field_res_users_email').id,
+ env.ref('base.field_res_users_signature').id,
+ env.ref('mail.field_mail_template_body_html').id,
+ env.ref('mail.field_mail_template_mail_server_id').id,
+ env.ref('mail.field_mail_template_report_template').id,
+ ]
+ env['ir.property'].search([('fields_id', 'in', field_ids)]).unlink()
+
+ # copy emails from partner to user
+ cr.execute("SELECT partner_id,email_multi_website FROM res_users")
+ for partner_id, default_email in cr.fetchall():
+ env['res.partner'].browse(partner_id).email = default_email
diff --git a/mail_multi_website/__manifest__.py b/mail_multi_website/__manifest__.py
new file mode 100644
index 0000000..b447932
--- /dev/null
+++ b/mail_multi_website/__manifest__.py
@@ -0,0 +1,51 @@
+# Copyright 2018 Ivan Yelizariev
+# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
+{
+ "name": """Email Addresses and Templates per Website""",
+ "summary": """Use single Backend to manage several Websites""",
+ "category": "Discuss",
+ "live_test_url": "http://apps.it-projects.info/shop/product/website-multi-company?version=11.0",
+ "images": ["images/main.jpg"],
+ "version": "11.0.1.0.0",
+ "application": False,
+
+ "author": "IT-Projects LLC, Ivan Yelizariev",
+ "support": "apps@it-projects.info",
+ "website": "https://it-projects.info/team/yelizariev",
+ "license": "LGPL-3",
+ "price": 230.00,
+ "currency": "EUR",
+
+ "depends": [
+ "ir_config_parameter_multi_company",
+ "web_website",
+ "mail",
+ ],
+ "external_dependencies": {"python": [], "bin": []},
+ "data": [
+ "views/website_views.xml",
+ ],
+ "demo": [
+ ],
+ "qweb": [
+ ],
+
+ "post_load": None,
+ "pre_init_hook": None,
+ "post_init_hook": "post_init_hook",
+ "uninstall_hook": "uninstall_hook",
+
+ "auto_install": False,
+ "installable": False,
+
+ # "demo_title": "Email Addresses per Website",
+ # "demo_addons": [
+ # ],
+ # "demo_addons_hidden": [
+ # ],
+ # "demo_url": "DEMO-URL",
+ # "demo_summary": "Use single Backend to manage several Websites",
+ # "demo_images": [
+ # "images/MAIN_IMAGE",
+ # ]
+}
diff --git a/mail_multi_website/doc/changelog.rst b/mail_multi_website/doc/changelog.rst
new file mode 100644
index 0000000..5583eb3
--- /dev/null
+++ b/mail_multi_website/doc/changelog.rst
@@ -0,0 +1,4 @@
+`1.0.0`
+-------
+
+- **Init version**
diff --git a/mail_multi_website/doc/index.rst b/mail_multi_website/doc/index.rst
new file mode 100644
index 0000000..bdfaf0b
--- /dev/null
+++ b/mail_multi_website/doc/index.rst
@@ -0,0 +1,73 @@
+===========================================
+ Email Addresses and Templates per Website
+===========================================
+
+Installation
+============
+
+* `Install `__ this module in a usual way
+
+Configuration
+=============
+
+
+Access to websites
+------------------
+
+* Go to menu ``[[ Settings ]] >> Users & Companies >> Users``
+* Select a user
+* Grant access ``[x] Multi Websites for Backend``
+* Configure **Allowed Websites**
+
+User's email per website
+------------------------
+
+* Refresh page if you just granted your user access to websites
+* Use top right-hand corner button with current website name to switch between websites
+* Use top right-hand corner button with user name and avatar to open
+ Preference popup. When you edit **Email** field, it will be saved as a value
+ for current website.
+
+Email template per website
+--------------------------
+
+* Refresh page if you just granted your user access to websites
+* `Activate Developer Mode `__
+* Use top right-hand corner button with current website name to switch between websites
+* Go to menu ``[[ Settings ]] >> Technical >> Email >> Templates``
+* When you edit template, following fields will be saved as a value for current website:
+
+ * **Body**
+ * **Outgoing Mail Server**
+ * **Optional report to print and attach**
+
+* Additional variable ``website`` is available to configure rest fields (**Subject**, **From**, etc.)
+
+Note. If related record (e.g. ``sale.order``) has field ``company_id`` or ``website_id`` those values will be used instead of currently selected in Website / Company Switchers
+
+Alias domain per website
+------------------------
+
+Configure ``mail.catchall.domain`` per website. See Documentation of the module `Context-dependent values in System Parameters`__.
+
+Outgoing mails servers per
+--------------------------
+
+If each domain has different Outgoing Mail Server you need following adjustments
+
+* Got to menu ``[[ Website ]] >> Configuration >> Websites``
+* In each Website specify field **Outgoing Mails**
+
+Properties
+----------
+
+To review properties by website use menu ``[[ Settings ]] >> Technical >> Parameters >> Company Properties``. See **How it works** in Documentation of module `Website Switcher in Backend`__.
+
+Usage
+=====
+
+When you work from backend, Email for current website is used.
+
+When a user do something on website (e.g. purchase products) and some mail is sent, then email address for that website will be used (mostly Administrator's email address).
+
+When email is sent, template's value like body, subject, etc. for current values are used.
diff --git a/mail_multi_website/images/main.jpg b/mail_multi_website/images/main.jpg
new file mode 100644
index 0000000..390e6be
Binary files /dev/null and b/mail_multi_website/images/main.jpg differ
diff --git a/mail_multi_website/models/__init__.py b/mail_multi_website/models/__init__.py
new file mode 100644
index 0000000..c2230c2
--- /dev/null
+++ b/mail_multi_website/models/__init__.py
@@ -0,0 +1,7 @@
+# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
+from . import res_users
+from . import ir_property
+from . import mail_template
+from . import mail_thread
+from . import mail_message
+from . import website
diff --git a/mail_multi_website/models/ir_property.py b/mail_multi_website/models/ir_property.py
new file mode 100644
index 0000000..bbf1cb4
--- /dev/null
+++ b/mail_multi_website/models/ir_property.py
@@ -0,0 +1,20 @@
+# Copyright 2018 Ivan Yelizariev
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
+from odoo import models, api
+
+
+class IrProperty(models.Model):
+ _inherit = 'ir.property'
+
+ @api.multi
+ def write(self, vals):
+ res = super(IrProperty, self).write(vals)
+ field_object_list = [
+ self.env.ref('base.field_res_users_email'),
+ self.env.ref('mail.field_mail_template_body_html'),
+ self.env.ref('mail.field_mail_template_mail_server_id'),
+ self.env.ref('mail.field_mail_template_report_template'),
+ ]
+ for fobj in field_object_list:
+ self._update_db_value_website_dependent(fobj)
+ return res
diff --git a/mail_multi_website/models/mail_message.py b/mail_multi_website/models/mail_message.py
new file mode 100644
index 0000000..174da1d
--- /dev/null
+++ b/mail_multi_website/models/mail_message.py
@@ -0,0 +1,16 @@
+# Copyright 2018 Ivan Yelizariev
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
+from odoo import models, fields
+
+
+class Message(models.Model):
+ _inherit = 'mail.message'
+
+ def _default_mail_server_id(self):
+ website = self.env.context.get('website_id')
+ if not website:
+ return
+ website = self.env['website'].sudo().browse(website)
+ return website.mail_server_id.id
+
+ mail_server_id = fields.Many2one(default=_default_mail_server_id)
diff --git a/mail_multi_website/models/mail_template.py b/mail_multi_website/models/mail_template.py
new file mode 100644
index 0000000..7342663
--- /dev/null
+++ b/mail_multi_website/models/mail_template.py
@@ -0,0 +1,151 @@
+# Copyright 2018 Ivan Yelizariev
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
+import logging
+from odoo import models, fields, api, tools, _
+from odoo.exceptions import UserError
+from odoo.tools import pycompat
+from odoo.addons.mail.models.mail_template import format_date, format_tz, format_amount
+
+_logger = logging.getLogger(__name__)
+FIELDS = ['body_html', 'mail_server_id', 'report_template']
+
+try:
+ from odoo.addons.mail.models.mail_template import mako_safe_template_env, mako_template_env
+except ImportError:
+ _logger.warning("jinja2 not available, templating features will not work!")
+
+
+class MailTemplate(models.Model):
+
+ _inherit = ['mail.template', 'website_dependent.mixin']
+ _name = 'mail.template'
+
+ body_html = fields.Html(company_dependent=True, website_dependent=True)
+ mail_server_id = fields.Many2one(string='Outgoing Mail Server (Multi-Website)', company_dependent=True, website_dependent=True)
+ report_template = fields.Many2one(string='Optional report to print and attach (Multi-Website)', company_dependent=True, website_dependent=True)
+
+ @api.multi
+ def generate_email(self, res_ids, fields=None):
+ """Remove mail_server_id when not set to recompute in _default_mail_server_id in mail.message"""
+ multi_mode = True
+ if isinstance(res_ids, pycompat.integer_types):
+ multi_mode = False
+ res = super(MailTemplate, self).generate_email(res_ids, fields=fields)
+ if not multi_mode:
+ list_of_dict = {0: res}
+ else:
+ list_of_dict = res
+
+ for _unused, data in list_of_dict.items():
+ if 'mail_server_id' in data and not data.get('mail_server_id'):
+ del data['mail_server_id']
+
+ return res
+
+ @api.model
+ def render_template(self, template_txt, model, res_ids, post_process=False):
+ """Override to add website to context"""
+ multi_mode = True
+ if isinstance(res_ids, pycompat.integer_types):
+ multi_mode = False
+ res_ids = [res_ids]
+
+ results = dict.fromkeys(res_ids, u"")
+
+ # try to load the template
+ try:
+ mako_env = mako_safe_template_env if self.env.context.get('safe') else mako_template_env
+ template = mako_env.from_string(tools.ustr(template_txt))
+ except Exception:
+ _logger.info("Failed to load template %r", template_txt, exc_info=True)
+ return multi_mode and results or results[res_ids[0]]
+
+ # prepare template variables
+ records = self.env[model].browse(it for it in res_ids if it) # filter to avoid browsing [None]
+ res_to_rec = dict.fromkeys(res_ids, None)
+ for record in records:
+ res_to_rec[record.id] = record
+
+ variables = {
+ 'format_date': lambda date, format=False, context=self._context: format_date(self.env, date, format),
+ 'format_tz': lambda dt, tz=False, format=False, context=self._context: format_tz(self.env, dt, tz, format),
+ 'format_amount': lambda amount, currency, context=self._context: format_amount(self.env, amount, currency),
+ 'user': self.env.user,
+ 'ctx': self._context, # context kw would clash with mako internals
+ }
+
+ # [NEW] Check website and company context
+ company = self.env['res.company'] # empty value
+
+ company_id = self.env.context.get('force_company')
+ if company_id:
+ company = self.env['res.company'].sudo().browse(company_id)
+
+ if self.env.context.get('website_id'):
+ website = self.env['website'].browse(self.env.context.get('website_id'))
+ else:
+ website = self.env.user.backend_website_id
+
+ for res_id, record in res_to_rec.items():
+ record_company = company
+ if not record_company:
+ if hasattr(record, 'company_id') and record.company_id:
+ record_company = record.company_id
+
+ record_website = website
+ if hasattr(record, 'website_id') and record.website_id:
+ record_website = record.website_id
+
+ if record_company and record_website \
+ and record_website.company_id != company:
+ # company and website are incompatible, so keep only website
+ record_website = self.env['website'] # empty value
+
+ record_context = dict(force_company=record_company.id, website_id=record_website.id)
+ variables['object'] = record.with_context(**record_context)
+ variables['website'] = record_website
+
+ try:
+ render_result = template.render(variables)
+ except Exception:
+ _logger.info("Failed to render template %r using values %r" % (template, variables), exc_info=True)
+ raise UserError(_("Failed to render template %r using values %r") % (template, variables))
+ if render_result == u"False":
+ render_result = u""
+
+ if post_process:
+ render_result = self.with_context(**record_context).render_post_process(render_result)
+
+ results[res_id] = render_result
+
+ return multi_mode and results or results[res_ids[0]]
+
+ @api.model
+ def create(self, vals):
+ res = super(MailTemplate, self).create(vals)
+ # make value company independent
+ for f in FIELDS:
+ res._force_default(f, vals.get(f))
+ return res
+
+ @api.multi
+ def write(self, vals):
+ res = super(MailTemplate, self).write(vals)
+
+ # TODO: will it work with OCA's partner_firstname module?
+ if 'name' in vals:
+ fields_to_update = FIELDS
+ else:
+ fields_to_update = [
+ f for f in FIELDS
+ if f in vals
+ ]
+ for f in fields_to_update:
+ self._update_properties_label(f)
+
+ return res
+
+ def _auto_init(self):
+ for f in FIELDS:
+ self._auto_init_website_dependent(f)
+ return super(MailTemplate, self)._auto_init()
diff --git a/mail_multi_website/models/mail_thread.py b/mail_multi_website/models/mail_thread.py
new file mode 100644
index 0000000..b59ab33
--- /dev/null
+++ b/mail_multi_website/models/mail_thread.py
@@ -0,0 +1,26 @@
+# Copyright 2018 Ivan Yelizariev
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
+from odoo import models, api, tools
+
+
+class MailThread(models.AbstractModel):
+ _inherit = 'mail.thread'
+
+ @api.model
+ def message_route_process(self, message, message_dict, routes):
+ rcpt_tos = ','.join([
+ tools.decode_message_header(message, 'Delivered-To'),
+ tools.decode_message_header(message, 'To'),
+ tools.decode_message_header(message, 'Cc'),
+ tools.decode_message_header(message, 'Resent-To'),
+ tools.decode_message_header(message, 'Resent-Cc')])
+ rcpt_tos_websiteparts = [e.split('@')[1].lower() for e in tools.email_split(rcpt_tos)]
+ website = self.env['website'].sudo().search([
+ ('domain', 'in', rcpt_tos_websiteparts)
+ ])
+ if website:
+ self = self.with_context(website_id=website[0].id)
+
+ return super(MailThread, self).message_route_process(
+ message, message_dict, routes
+ )
diff --git a/mail_multi_website/models/res_users.py b/mail_multi_website/models/res_users.py
new file mode 100644
index 0000000..07a77a0
--- /dev/null
+++ b/mail_multi_website/models/res_users.py
@@ -0,0 +1,45 @@
+# Copyright 2018 Ivan Yelizariev
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
+import logging
+from odoo import models, fields, api
+
+
+_logger = logging.getLogger(__name__)
+FIELD_NAME = 'email_multi_website'
+FIELDS = ['signature']
+ALL_FIELDS = [FIELD_NAME] + FIELDS
+
+
+class User(models.Model):
+
+ _inherit = ['res.users', 'website_dependent.mixin']
+ _name = 'res.users'
+
+ signature = fields.Html(company_dependent=True, website_dependent=True)
+
+ # extra field to detach email field from res.partner
+ email = fields.Char(related='email_multi_website', inherited=False)
+ email_multi_website = fields.Char(company_dependent=True, website_dependent=True)
+
+ @api.model
+ def create(self, vals):
+ res = super(User, self).create(vals)
+ # make value company independent
+ res._force_default(FIELD_NAME, vals.get('email'))
+ for f in FIELDS:
+ res._force_default(f, vals.get(f))
+ return res
+
+ @api.multi
+ def write(self, vals):
+ res = super(User, self).write(vals)
+ # TODO: will it work with OCA's partner_firstname module?
+ if any(k in vals for k in ['name', 'email'] + FIELDS):
+ for f in ALL_FIELDS:
+ self._update_properties_label(f)
+ return res
+
+ def _auto_init(self):
+ for f in FIELDS:
+ self._auto_init_website_dependent(f)
+ return super(User, self)._auto_init()
diff --git a/mail_multi_website/models/website.py b/mail_multi_website/models/website.py
new file mode 100644
index 0000000..ec81942
--- /dev/null
+++ b/mail_multi_website/models/website.py
@@ -0,0 +1,10 @@
+# Copyright 2017 Ivan Yelizariev
+# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
+
+from odoo import models, fields
+
+
+class Website(models.Model):
+ _inherit = "website"
+
+ mail_server_id = fields.Many2one('ir.mail_server', 'Outgoing Mails', help='Default outgoing mail server')
diff --git a/mail_multi_website/static/description/icon.png b/mail_multi_website/static/description/icon.png
new file mode 100644
index 0000000..79f7d8f
Binary files /dev/null and b/mail_multi_website/static/description/icon.png differ
diff --git a/mail_multi_website/static/description/index.html b/mail_multi_website/static/description/index.html
new file mode 100644
index 0000000..4b57adf
--- /dev/null
+++ b/mail_multi_website/static/description/index.html
@@ -0,0 +1,97 @@
+
+
+
+
Email Addresses and Templates per Website
+
+ Use single Backend to manage several Websites
+
+
+
+
+
+
+
+
+
+
Key features:
+
+
+ -
+
+ Separate Mail Templates per website
+
+
+ -
+
+ From address in email has address for current Website
+
+
+ -
+
+ Reply-To address in email has domain of current Website
+
+
+ -
+
+ User's signature per Website
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Tested on Odoo
11.0 community
+
+
+
+
+
+
diff --git a/mail_multi_website/tests/__init__.py b/mail_multi_website/tests/__init__.py
new file mode 100644
index 0000000..9ebbe03
--- /dev/null
+++ b/mail_multi_website/tests/__init__.py
@@ -0,0 +1,4 @@
+# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
+from . import test_send
+from . import test_render
+from . import test_fetch
diff --git a/mail_multi_website/tests/test_fetch.py b/mail_multi_website/tests/test_fetch.py
new file mode 100644
index 0000000..7c34a07
--- /dev/null
+++ b/mail_multi_website/tests/test_fetch.py
@@ -0,0 +1,41 @@
+# Copyright 2018 Ivan Yelizariev
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
+from odoo.addons.mail.tests.common import TestMail
+from odoo.tools import mute_logger
+from odoo.addons.mail.tests.test_mail_gateway import MAIL_TEMPLATE
+
+
+class TestFetch(TestMail):
+ at_install = True
+ post_install = True
+
+ def setUp(self):
+ super(TestFetch, self).setUp()
+ self.website = self.env['website'].create({
+ 'name': 'Test Website',
+ 'domain': 'example.com',
+ })
+ self.company = self.env['res.company'].create({
+ 'name': 'New Test Website'
+ })
+ self.website.company_id = self.company
+
+ # copy-paste from mail.tests.test_mail_gateway
+ mail_test_model = self.env['ir.model']._get('mail.test')
+ # groups@.. will cause the creation of new mail.test
+ self.alias = self.env['mail.alias'].create({
+ 'alias_name': 'groups',
+ 'alias_user_id': False,
+ 'alias_model_id': mail_test_model.id,
+ 'alias_contact': 'everyone'})
+
+ @mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models')
+ def test_fetch_multi_website(self):
+ """ Incoming email on an alias creating a new record + message_new + message details """
+ new_groups = self.format_and_process(MAIL_TEMPLATE, subject='My Frogs', to='groups@example.com, other@gmail.com')
+
+ # Test: one group created by mailgateway administrator
+ self.assertEqual(len(new_groups), 1, 'message_process: a new mail.test should have been created')
+
+ self.assertEqual(new_groups.website_id, self.website, 'New record is created with wrong website')
+ self.assertEqual(new_groups.company_id, self.company, 'New record is created with wrong company')
diff --git a/mail_multi_website/tests/test_mail_model.py b/mail_multi_website/tests/test_mail_model.py
new file mode 100644
index 0000000..040225d
--- /dev/null
+++ b/mail_multi_website/tests/test_mail_model.py
@@ -0,0 +1,10 @@
+# Copyright 2018 Ivan Yelizariev
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
+from odoo import models, fields
+
+
+class MailTest(models.Model):
+ _inherit = 'mail.test'
+
+ company_id = fields.Many2one('res.company', default=lambda self: self.env['res.company']._company_default_get())
+ website_id = fields.Many2one('website', default=lambda self: self.env['website'].browse(self.env.context.get('website_id')))
diff --git a/mail_multi_website/tests/test_render.py b/mail_multi_website/tests/test_render.py
new file mode 100644
index 0000000..b3d0c22
--- /dev/null
+++ b/mail_multi_website/tests/test_render.py
@@ -0,0 +1,114 @@
+# Copyright 2018 Ivan Yelizariev
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
+import base64
+
+from odoo.addons.mail.tests.common import TestMail
+
+
+class TestRender(TestMail):
+ at_install = True
+ post_install = True
+
+ def setUp(self):
+ super(TestRender, self).setUp()
+
+ self.original_email = self.env.user.email
+ self.original_company = self.env.user.company_id
+ self.email = 'superadmin@second-website.example'
+ self.assertNotEqual(self.original_email, self.email)
+
+ self.website = self.env.ref('website.website2')
+ self.company = self.env['res.company'].create({
+ 'name': 'New Test Website'
+ })
+ self.website.company_id = self.company
+ self.mail_server_id = self.env['ir.mail_server'].create({
+ 'name': 'mail server',
+ 'smtp_host': 'mail.example.com',
+ })
+ self.website.mail_server_id = self.mail_server_id
+
+ # copy-paste from mail.tests.test_mail_template
+ self._attachments = [{
+ 'name': '_Test_First',
+ 'datas_fname':
+ 'first.txt',
+ 'datas': base64.b64encode(b'My first attachment'),
+ 'res_model': 'res.partner',
+ 'res_id': self.user_admin.partner_id.id
+ }, {
+ 'name': '_Test_Second',
+ 'datas_fname': 'second.txt',
+ 'datas': base64.b64encode(b'My second attachment'),
+ 'res_model': 'res.partner',
+ 'res_id': self.user_admin.partner_id.id
+ }]
+
+ self.email_1 = 'test1@example.com'
+ self.email_2 = 'test2@example.com'
+ self.email_3 = self.partner_1.email
+ self.email_template = self.env['mail.template'].create({
+ 'model_id': self.env['ir.model']._get('mail.test').id,
+ 'name': 'Pigs Template',
+ 'subject': '${website.name}',
+ 'body_html': '${object.description}',
+ 'user_signature': False,
+ 'attachment_ids': [(0, 0, self._attachments[0]), (0, 0, self._attachments[1])],
+ 'partner_to': '%s,%s' % (self.partner_2.id, self.user_employee.partner_id.id),
+ 'email_to': '%s, %s' % (self.email_1, self.email_2),
+ 'email_cc': '%s' % self.email_3})
+
+ def switch_user_website(self):
+ # add website to allowed
+ self.env.user.write(dict(
+ backend_website_ids=[(4, self.website.id)],
+ backend_website_id=self.website.id,
+ company_id=self.company.id,
+ company_ids=[(4, self.company.id)]
+ ))
+
+ def test_website_in_render_variables(self):
+ """Mail values are per website"""
+
+ self.env.user.backend_website_id = None
+
+ # sending without website
+ mail_id = self.email_template.send_mail(self.test_pigs.id)
+ mail = self.env['mail.mail'].browse(mail_id)
+ self.assertEqual(mail.subject, '')
+ self.assertFalse(mail.mail_server_id)
+
+ # sending from frontend
+ self.test_pigs.company_id = None
+ mail_id = self.email_template.with_context(wdb=True, website_id=self.website.id).send_mail(self.test_pigs.id)
+ mail = self.env['mail.mail'].browse(mail_id)
+ self.assertEqual(mail.subject, self.website.name)
+ self.assertEqual(mail.mail_server_id, self.mail_server_id)
+
+ # copy-pasted tests
+ self.assertEqual(mail.email_to, self.email_template.email_to)
+ self.assertEqual(mail.email_cc, self.email_template.email_cc)
+ self.assertEqual(mail.recipient_ids, self.partner_2 | self.user_employee.partner_id)
+
+ # sending from frontend
+ self.switch_user_website()
+ mail_id = self.email_template.send_mail(self.test_pigs.id)
+ mail = self.env['mail.mail'].browse(mail_id)
+ self.assertEqual(mail.subject, self.website.name)
+
+ def _test_message_post_with_template(self):
+ # It's deactivated, because workaround is based on checking host value in get_current_website()
+ """Simulate sending email on eCommerce checkout"""
+ self.switch_user_website()
+ self.env.user.email = self.email
+ self.env.user.invalidate_cache()
+ self.env.user.invalidate_cache()
+ self.assertEqual(self.env.user.email, self.email)
+ # switch admin user back
+ self.env.user.company_id = self.original_company
+ self.env.user.invalidate_cache()
+ self.assertEqual(self.env.user.email, self.original_email)
+
+ self.test_pigs.with_context(website_id=self.website.id).message_post_with_template(self.email_template.id)
+ message = self.env['mail.message'].search([], order='id desc', limit=1)
+ self.assertIn('<%s>' % self.email, message.email_from)
diff --git a/mail_multi_website/tests/test_send.py b/mail_multi_website/tests/test_send.py
new file mode 100644
index 0000000..97d9306
--- /dev/null
+++ b/mail_multi_website/tests/test_send.py
@@ -0,0 +1,62 @@
+# Copyright 2018 Ivan Yelizariev
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
+from odoo.tests.common import TransactionCase
+
+
+class TestSendMail(TransactionCase):
+ at_install = True
+ post_install = True
+
+ def setUp(self):
+ super(TestSendMail, self).setUp()
+ self.website = self.env.ref('website.website2')
+ self.company = self.env['res.company'].create({
+ 'name': 'New Test Website'
+ })
+ self.original_email = self.env.user.email
+ self.original_company = self.env.user.company_id
+ self.email = 'superadmin@second-website.example'
+ # Check that current email is set and differs
+ self.assertTrue(self.email)
+ self.assertNotEqual(self.original_email, self.email)
+ self.website.company_id = self.company
+
+ def switch_user_website(self):
+ # add website to allowed
+ self.env.user.write(dict(
+ backend_website_ids=[(4, self.website.id)],
+ backend_website_id=self.website.id,
+ company_id=self.company.id,
+ company_ids=[(4, self.company.id)]
+ ))
+
+ def test_multi_email(self):
+ """User has email addresses per website"""
+ self.switch_user_website()
+ # update user's email
+ self.env.user.email = self.email
+ # Check that writing works
+ self.env.user.invalidate_cache()
+ self.assertEqual(self.env.user.email, self.email, 'Write methods doesn\'t work (Field is not in registry?)')
+
+ # changing company will automatically update website value to empty value
+ self.env.user.company_id = self.original_company
+ self.env.user.invalidate_cache()
+ self.assertEqual(self.env.user.email, self.original_email, 'Multi-email doesn\'t work on switching websites')
+
+ def test_multi_email_partner(self):
+ """Partner doesn't have email addresses per website"""
+ original_email = 'original@email1'
+ new_email = 'new@email2'
+ partner = self.env['res.partner'].create({
+ 'name': 'test',
+ 'email': original_email,
+ })
+ self.switch_user_website()
+ # update partner's email
+ partner.email = new_email
+ self.assertEqual(partner.email, new_email)
+ # changing company will automatically update website value to empty value
+ self.env.user.company_id = self.original_company
+ self.env.user.invalidate_cache()
+ self.assertEqual(partner.email, new_email, 'Partner\'s email must not be Multi-website')
diff --git a/mail_multi_website/views/website_views.xml b/mail_multi_website/views/website_views.xml
new file mode 100644
index 0000000..04d3fed
--- /dev/null
+++ b/mail_multi_website/views/website_views.xml
@@ -0,0 +1,14 @@
+
+
+
+
+ website
+
+
+
+
+
+
+
+
diff --git a/mail_multi_website/wizard/__init__.py b/mail_multi_website/wizard/__init__.py
new file mode 100644
index 0000000..20d4784
--- /dev/null
+++ b/mail_multi_website/wizard/__init__.py
@@ -0,0 +1,2 @@
+# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
+from . import mail_compose_message
diff --git a/mail_multi_website/wizard/mail_compose_message.py b/mail_multi_website/wizard/mail_compose_message.py
new file mode 100644
index 0000000..5c9e4ec
--- /dev/null
+++ b/mail_multi_website/wizard/mail_compose_message.py
@@ -0,0 +1,20 @@
+# Copyright 2018 Ivan Yelizariev
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
+from odoo import models, api
+from odoo.http import request
+
+
+class MailComposer(models.TransientModel):
+
+ _inherit = 'mail.compose.message'
+
+ @api.model
+ def create(self, vals):
+ """Workaround for https://github.com/odoo/odoo/pull/26589"""
+ if 'website_id' not in self.env.context:
+ website = request and hasattr(request, 'website') and request.website or None
+ if not website:
+ website = self.env['website'].get_current_website()
+ if website:
+ self = self.with_context(website_id=website.id)
+ return super(MailComposer, self).create(vals)
diff --git a/mail_private/README.rst b/mail_private/README.rst
index ac2133a..ea60ffe 100644
--- a/mail_private/README.rst
+++ b/mail_private/README.rst
@@ -1,3 +1,7 @@
+.. image:: https://img.shields.io/badge/license-LGPL--3-blue.png
+ :target: https://www.gnu.org/licenses/lgpl
+ :alt: License: LGPL-3
+
====================
Internal Messaging
====================
@@ -9,21 +13,35 @@ Credits
Contributors
------------
-* Pavel Romanchenko
+* Pavel Romanchenko
Sponsors
--------
* `IT-Projects LLC `__
+Maintainers
+-----------
+* `IT-Projects LLC `__
+
+ To get a guaranteed support
+ you are kindly requested to purchase the module
+ at `odoo apps store `__.
+
+ Thank you for understanding!
+
+ `IT-Projects Team `__
+
Further information
===================
-Demo: http://runbot.it-projects.info/demo/mail-addons/10.0
+Demo: http://runbot.it-projects.info/demo/mail-addons/11.0
+
+HTML Description: https://apps.odoo.com/apps/modules/11.0/mail_private/
-HTML Description: https://apps.odoo.com/apps/modules/10.0/mail_private/
+Usage instructions: ``_
-Usage instructions: ``__
+Changelog: ``_
-Changelog: ``__
+Notifications on updates: `via Atom `_, `by Email `_
-Tested on Odoo 10.0 ffba5c688ff74a0630f9f70be1d7760a43a7deba
+Tested on Odoo 11.0 3d09560ffc779e169ed9488e4e07928204dd234d
diff --git a/mail_private/__openerp__.py b/mail_private/__openerp__.py
index 7cd6ffc..9ae93b5 100644
--- a/mail_private/__openerp__.py
+++ b/mail_private/__openerp__.py
@@ -3,7 +3,7 @@
"summary": """Send private messages to specified recipients, regardless of who are in followers list.""",
"category": "Discuss",
"images": ['images/mail_private_image.png'],
- "version": "1.0.1",
+ "version": "11.0.1.0.2",
"application": False,
"author": "IT-Projects LLC, Pavel Romanchenko",
diff --git a/mail_private/doc/changelog.rst b/mail_private/doc/changelog.rst
index f3b7c08..20569d5 100644
--- a/mail_private/doc/changelog.rst
+++ b/mail_private/doc/changelog.rst
@@ -1,3 +1,8 @@
+`1.0.2`
+-------
+
+- **FIX:** Error when choosing a message template
+
`1.0.1`
-------
diff --git a/mail_private/full_composer_wizard.xml b/mail_private/full_composer_wizard.xml
index 7bb5471..9f57a20 100644
--- a/mail_private/full_composer_wizard.xml
+++ b/mail_private/full_composer_wizard.xml
@@ -1,6 +1,5 @@
-
mail.compose.message.form.private
@@ -23,5 +22,4 @@
-
diff --git a/mail_private/static/description/index.html b/mail_private/static/description/index.html
index 6b7afe1..64c2ba7 100644
--- a/mail_private/static/description/index.html
+++ b/mail_private/static/description/index.html
@@ -72,6 +72,8 @@
diff --git a/mail_private/static/src/js/mail_private.js b/mail_private/static/src/js/mail_private.js
index 9ee48e1..4b3a7d0 100644
--- a/mail_private/static/src/js/mail_private.js
+++ b/mail_private/static/src/js/mail_private.js
@@ -1,3 +1,8 @@
+/* Copyright 2016-2018 Ivan Yelizariev
+ Copyright 2016 manavi
+ Copyright 2017-2018 Artyom Losev
+ Copyright 2018 Kolushov Alexandr
+ License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). */
odoo.define('mail_private', function (require) {
'use strict';
@@ -100,6 +105,10 @@ ChatterComposer.include({
init: function (parent, model, suggested_partners, options) {
this._super(parent, model, suggested_partners, options);
this.events['click .oe_composer_uncheck'] = 'on_uncheck_recipients';
+ if (typeof options.is_private === 'undefined') {
+ // otherwise it causes an error in context creating function
+ options.is_private = false;
+ }
},
preprocess_message: function () {
diff --git a/mail_private/template.xml b/mail_private/template.xml
index 534e53c..8f26202 100644
--- a/mail_private/template.xml
+++ b/mail_private/template.xml
@@ -1,6 +1,5 @@
-
-
+
-
-
+
diff --git a/mail_recovery/static/description/index.html b/mail_recovery/static/description/index.html
index 40752e4..89d4eb6 100644
--- a/mail_recovery/static/description/index.html
+++ b/mail_recovery/static/description/index.html
@@ -74,6 +74,8 @@
diff --git a/mail_reply/doc/index.rst b/mail_reply/doc/index.rst
index 21314df..b3f2852 100644
--- a/mail_reply/doc/index.rst
+++ b/mail_reply/doc/index.rst
@@ -16,7 +16,7 @@ Usage
=====
* Open ``[[ Discuss ]]`` menu
-* RESULT: you can see, that messages not attached to any record now has Reply button
+* RESULT: you can see, that messages not attached to any record now have Reply button
* Note: messages from Channels (including Direct messages) don’t have this button. You need to open corresponding channel instead.
* To easily know and navigate to corresponding channel, you need to get module `Show message recipients