Browse Source

Merge pull request #164 from Rusllan/12.0-29b06ca8cdacccfe9e952dc3df57115085923760

12.0 29b06ca8cd
pull/168/head
Ivan Yelizariev 6 years ago
committed by GitHub
parent
commit
e9ac1819fb
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      mail_all/static/description/index.html
  2. 2
      mail_archives/static/description/index.html
  3. 2
      mail_check_immediately/static/description/index.html
  4. 2
      mail_move_message/__manifest__.py
  5. 6
      mail_move_message/data/mail_move_message_data.xml
  6. 5
      mail_move_message/doc/changelog.rst
  7. 48
      mail_move_message/mail_move_message_models.py
  8. 2
      mail_move_message/mail_move_message_views.xml
  9. 2
      mail_move_message/static/description/index.html
  10. 43
      mail_move_message/static/src/js/mail_move_message.js
  11. 3
      mail_move_message/tests/__init__.py
  12. 52
      mail_move_message/tests/test_mail_move.py
  13. 62
      mail_multi_website/README.rst
  14. 40
      mail_multi_website/__init__.py
  15. 51
      mail_multi_website/__manifest__.py
  16. 4
      mail_multi_website/doc/changelog.rst
  17. 73
      mail_multi_website/doc/index.rst
  18. BIN
      mail_multi_website/images/main.jpg
  19. 7
      mail_multi_website/models/__init__.py
  20. 20
      mail_multi_website/models/ir_property.py
  21. 16
      mail_multi_website/models/mail_message.py
  22. 151
      mail_multi_website/models/mail_template.py
  23. 26
      mail_multi_website/models/mail_thread.py
  24. 45
      mail_multi_website/models/res_users.py
  25. 10
      mail_multi_website/models/website.py
  26. BIN
      mail_multi_website/static/description/icon.png
  27. 97
      mail_multi_website/static/description/index.html
  28. 4
      mail_multi_website/tests/__init__.py
  29. 41
      mail_multi_website/tests/test_fetch.py
  30. 10
      mail_multi_website/tests/test_mail_model.py
  31. 114
      mail_multi_website/tests/test_render.py
  32. 62
      mail_multi_website/tests/test_send.py
  33. 14
      mail_multi_website/views/website_views.xml
  34. 2
      mail_multi_website/wizard/__init__.py
  35. 20
      mail_multi_website/wizard/mail_compose_message.py
  36. 30
      mail_private/README.rst
  37. 2
      mail_private/__openerp__.py
  38. 5
      mail_private/doc/changelog.rst
  39. 2
      mail_private/full_composer_wizard.xml
  40. 2
      mail_private/static/description/index.html
  41. 9
      mail_private/static/src/js/mail_private.js
  42. 6
      mail_private/template.xml
  43. 2
      mail_recovery/static/description/index.html
  44. 4
      mail_reply/doc/index.rst
  45. 2
      mail_reply/static/description/index.html
  46. 45
      mail_sent/static/description/index.html
  47. 2
      mail_to/static/description/index.html
  48. 1
      mail_to/tests/test_default.py
  49. 2
      mailgun/static/description/index.html
  50. 2
      res_partner_mails_count/static/description/index.html

2
mail_all/static/description/index.html

@ -38,6 +38,8 @@ This menu shows all messages.
<ul>
<li><a href="mailto:apps@it-projects.info">apps@it-projects.info <i class="fa fa-envelope-o"></i></a></li>
<li><a href="https://www.it-projects.info/page/website.contactus " target="_blank">https://www.it-projects.info/page/website.contactus <i class="fa fa-list-alt"></i></a></li>
<li><a href="https://m.me/itprojectsllc" target="_blank">https://m.me/itprojectsllc <i class="fa fa-facebook-square"></i></a></li>
<li>skype@it-projects.info <i class="fa fa-skype"></i></li>
</ul>
</div>
<div class="oe_span4">

2
mail_archives/static/description/index.html

@ -38,6 +38,8 @@ This menu shows archive messages, i.e. ones you sent or received.
<ul>
<li><a href="mailto:apps@it-projects.info">apps@it-projects.info <i class="fa fa-envelope-o"></i></a></li>
<li><a href="https://www.it-projects.info/page/website.contactus " target="_blank">https://www.it-projects.info/page/website.contactus <i class="fa fa-list-alt"></i></a></li>
<li><a href="https://m.me/itprojectsllc" target="_blank">https://m.me/itprojectsllc <i class="fa fa-facebook-square"></i></a></li>
<li>skype@it-projects.info <i class="fa fa-skype"></i></li>
</ul>
</div>
<div class="oe_span4">

2
mail_check_immediately/static/description/index.html

@ -41,6 +41,8 @@
<li><a href="mailto:apps@it-projects.info">apps@it-projects.info <i class="fa fa-envelope-o"></i></a></li>
<li><a href="https://www.it-projects.info/page/website.contactus " target="_blank">
https://www.it-projects.info/page/website.contactus <i class="fa fa-list-alt"></i></a></li>
<li><a href="https://m.me/itprojectsllc" target="_blank">https://m.me/itprojectsllc <i class="fa fa-facebook-square"></i></a></li>
<li>skype@it-projects.info <i class="fa fa-skype"></i></li>
</ul>
</div>
</div>

2
mail_move_message/__manifest__.py

@ -7,7 +7,7 @@
{
'name': 'Mail Relocation',
'version': '11.0.1.0.5',
'version': '11.0.1.0.6',
'author': 'IT-Projects LLC, Ivan Yelizariev, Pavel Romanchenko',
'license': 'LGPL-3',
'category': 'Discuss',

6
mail_move_message/data/mail_move_message_data.xml

@ -3,11 +3,9 @@
# Copyright 2017 Ivan Yelizariev <https://it-projects.info/team/yelizariev>
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).-->
<openerp>
<data noupdate="1">
<odoo>
<record id="mail_relocation_models" model="ir.config_parameter">
<field name="key">mail_relocation_models</field>
<field name="value">crm.lead,project.task</field>
</record>
</data>
</openerp>
</odoo>

5
mail_move_message/doc/changelog.rst

@ -1,3 +1,8 @@
`1.0.6`
-------
- FIX: Error related to *Create Partner* button on the mail move wizard form.
`1.0.5`
-------

48
mail_move_message/mail_move_message_models.py

@ -203,7 +203,6 @@ class Wizard(models.TransientModel):
for r in self:
if not r.model:
raise exceptions.except_orm(_('Record field is empty!'), _('Select a record for relocation first'))
for r in self:
r.check_access()
if not r.parent_id or not (r.parent_id.model == r.model and
@ -211,7 +210,7 @@ class Wizard(models.TransientModel):
# link with the first message of record
parent = self.env['mail.message'].search([('model', '=', r.model), ('res_id', '=', r.res_id)], order='id', limit=1)
r.parent_id = parent.id or None
r.message_id.move(r.parent_id.id, r.res_id, r.model, r.move_back, r.move_followers, r.message_to_read)
r.message_id.move(r.parent_id.id, r.res_id, r.model, r.move_back, r.move_followers, r.message_to_read, r.partner_id)
if r.model in ['mail.message', 'mail.channel', False]:
return {
@ -247,30 +246,6 @@ class Wizard(models.TransientModel):
self.message_id.unlink()
return {}
@api.model
def create_partner(self, message_id, relation, partner_id, message_name_from, message_email_from):
model = self.env[relation]
message = self.env['mail.message'].browse(message_id)
if not partner_id and message_name_from:
partner_id = self.env['res.partner'].with_context({'update_message_author': True}).create({
'name': message_name_from,
'email': message_email_from
}).id
context = {'partner_id': partner_id}
if model._rec_name:
context.update({'default_%s' % model._rec_name: message.subject})
fields = model.fields_get()
contact_field = False
for n, f in fields.items():
if f['type'] == 'many2one' and f['relation'] == 'res.partner':
contact_field = n
break
if contact_field:
context.update({'default_%s' % contact_field: partner_id})
return context
@api.multi
def read_close(self):
for r in self:
@ -326,18 +301,23 @@ class MailMessage(models.Model):
self.env[model].browse(ids).message_subscribe([f.partner_id.id], [s.id for s in f.subtype_ids])
@api.multi
def move(self, parent_id, res_id, model, move_back, move_followers=False, message_to_read=False):
def move(self, parent_id, res_id, model, move_back, move_followers=False, message_to_read=False, author=False):
for r in self:
r.move_one(parent_id, res_id, model, move_back, move_followers=move_followers, message_to_read=message_to_read)
r.move_one(parent_id, res_id, model, move_back, move_followers=move_followers, message_to_read=message_to_read, author=author)
@api.multi
def move_one(self, parent_id, res_id, model, move_back, move_followers=False, message_to_read=False):
def move_one(self, parent_id, res_id, model, move_back, move_followers=False, message_to_read=False, author=False):
self.ensure_one()
if parent_id == self.id:
# if for any reason method is called to move message with parent
# equal to oneself, we need stop to prevent infinitive loop in
# building message tree
return
if not self.author_id:
self.write({
'author_id': author.id,
})
vals = {}
if move_back:
# clear variables if we move everything back
@ -477,3 +457,13 @@ class ResPartner(models.Model):
if messages:
messages.sudo().write({'author_id': res.id})
return res
@api.model
def default_get(self, default_fields):
contextual_self = self
if 'mail_move_message' in self.env.context and self.env.context['mail_move_message']:
contextual_self = self.with_context(
default_name=self.env.context['message_name_from'] or '',
default_email=self.env.context['message_email_from'] or '',
)
return super(ResPartner, contextual_self).default_get(default_fields)

2
mail_move_message/mail_move_message_views.xml

@ -46,7 +46,7 @@
<field name="partner_id" class="oe_inline"/>
<button string="Create Partner" attrs="{'invisible':[('partner_id','!=',False)]}"
class="oe_highlight oe_inline ml32"
special="quick_create" field="partner_id" context="{'force_email':True,'default_email':message_email_from,'default_name':message_name_from, 'update_message_author':True}" />
special="quick_create" model="res.partner" field="partner_id" context="{'force_email':True,'default_email':message_email_from,'default_name':message_name_from, 'update_message_author':True}" />
</div>
<label for="move_back" attrs="{'invisible':[('message_is_moved','=',False)]}"/>
<div attrs="{'invisible':[('message_is_moved','=',False)]}">

2
mail_move_message/static/description/index.html

@ -118,6 +118,8 @@
<ul>
<li><a href="mailto:apps@it-projects.info">apps@it-projects.info <i class="fa fa-envelope-o"></i></a></li>
<li><a href="https://www.it-projects.info/page/website.contactus " target="_blank">https://www.it-projects.info/page/website.contactus <i class="fa fa-list-alt"></i></a></li>
<li><a href="https://m.me/itprojectsllc" target="_blank">https://m.me/itprojectsllc <i class="fa fa-facebook-square"></i></a></li>
<li>skype@it-projects.info <i class="fa fa-skype"></i></li>
</ul>
</div>
<div class="oe_span4">

43
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);
}
},
});
});

3
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

52
mail_move_message/tests/test_mail_move.py

@ -0,0 +1,52 @@
# Copyright 2018 Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr>
# 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")

62
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 <https://it-projects.info/team/yelizariev>`__
Sponsors
--------
* `e-thos SSII <http://www.e-thos.fr/>`__
Maintainers
-----------
* `IT-Projects LLC <https://it-projects.info>`__
To get a guaranteed support
you are kindly requested to purchase the module
at `odoo apps store <https://apps.odoo.com/apps/modules/11.0/mail_multi_website/>`__.
Thank you for understanding!
`IT-Projects Team <https://www.it-projects.info/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: `<doc/index.rst>`_
Changelog: `<doc/changelog.rst>`_
Notifications on updates: `via Atom <https://github.com/it-projects-llc/mail-addons/commits/11.0/mail_multi_website.atom>`_, `by Email <https://blogtrottr.com/?subscribe=https://github.com/it-projects-llc/mail-addons/commits/11.0/mail_multi_website.atom>`_
Tested on Odoo 11.0 4d0a1330e05bd688265bea14df4ad12838f9f2d7

40
mail_multi_website/__init__.py

@ -0,0 +1,40 @@
# Copyright 2018 Ivan Yelizariev <https://it-projects.info/team/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

51
mail_multi_website/__manifest__.py

@ -0,0 +1,51 @@
# Copyright 2018 Ivan Yelizariev <https://it-projects.info/team/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",
# ]
}

4
mail_multi_website/doc/changelog.rst

@ -0,0 +1,4 @@
`1.0.0`
-------
- **Init version**

73
mail_multi_website/doc/index.rst

@ -0,0 +1,73 @@
===========================================
Email Addresses and Templates per Website
===========================================
Installation
============
* `Install <https://odoo-development.readthedocs.io/en/latest/odoo/usage/install-module.html>`__ 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 <https://odoo-development.readthedocs.io/en/latest/odoo/usage/debug-mode.html>`__
* 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<https://apps.odoo.com/apps/modules/10.0/ir_config_parameter_multi_company/>`__.
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<https://apps.odoo.com/apps/modules/10.0/web_website/>`__.
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.

BIN
mail_multi_website/images/main.jpg

After

Width: 750  |  Height: 371  |  Size: 285 KiB

7
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

20
mail_multi_website/models/ir_property.py

@ -0,0 +1,20 @@
# Copyright 2018 Ivan Yelizariev <https://it-projects.info/team/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

16
mail_multi_website/models/mail_message.py

@ -0,0 +1,16 @@
# Copyright 2018 Ivan Yelizariev <https://it-projects.info/team/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)

151
mail_multi_website/models/mail_template.py

@ -0,0 +1,151 @@
# Copyright 2018 Ivan Yelizariev <https://it-projects.info/team/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()

26
mail_multi_website/models/mail_thread.py

@ -0,0 +1,26 @@
# Copyright 2018 Ivan Yelizariev <https://it-projects.info/team/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
)

45
mail_multi_website/models/res_users.py

@ -0,0 +1,45 @@
# Copyright 2018 Ivan Yelizariev <https://it-projects.info/team/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()

10
mail_multi_website/models/website.py

@ -0,0 +1,10 @@
# Copyright 2017 Ivan Yelizariev <https://it-projects.info/team/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')

BIN
mail_multi_website/static/description/icon.png

After

Width: 100  |  Height: 100  |  Size: 2.1 KiB

97
mail_multi_website/static/description/index.html

@ -0,0 +1,97 @@
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h2 class="oe_slogan" style="color:#875A7B;">Email Addresses and Templates per Website
</h2>
<h3 class="oe_slogan">Use single Backend to manage several Websites</h3>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<div class="alert alert-info oe_mt32" style="padding:0.3em 0.6em; font-size: 150%;">
<i class="fa fa-hand-o-right"></i><b> Key features: </b>
<ul class="list-unstyled">
<li>
<i class="fa fa-check-square-o text-primary"></i>
Separate Mail Templates per website
</li>
<li>
<i class="fa fa-check-square-o text-primary"></i>
<em>From</em> address in email has address for current Website
</li>
<li>
<i class="fa fa-check-square-o text-primary"></i>
<em>Reply-To</em> address in email has domain of current Website
</li>
<li>
<i class="fa fa-check-square-o text-primary"></i>
User's signature per Website
</li>
</ul>
</div>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span8">
<h2>Need our service?</h2>
<p class="oe_mt32">Contact us by <a href="mailto:apps@it-projects.info">email</a> or fill out <a href="https://www.it-projects.info/page/website.contactus " target="_blank">request form</a></p>
<ul>
<li><a href="mailto:apps@it-projects.info">apps@it-projects.info <i class="fa fa-envelope-o"></i></a></li>
<li><a href="https://www.it-projects.info/page/website.contactus " target="_blank">https://www.it-projects.info/page/website.contactus <i class="fa fa-list-alt"></i></a></li>
<li><a href="https://m.me/itprojectsllc" target="_blank">https://m.me/itprojectsllc <i class="fa fa-facebook-square"></i></a></li>
<li>skype@it-projects.info <i class="fa fa-skype"></i></li>
</ul>
</div>
<div class="oe_span4">
<div class="stamp" style="width:200px;">
<div style="margin-top: 15px;
position: relative;
font-family:'Vollkorn', serif;
font-size: 16px;
line-height: 25px;
text-transform: uppercase;
font-weight: bold;
color: #75526b;
border: 3px dashed #75526b;
float: left;
padding: 4px 12px;
-webkit-transform: rotate(1deg);
-o-transform: rotate(1deg);
-moz-transform: rotate(1deg);
-ms-transform: rotate(1deg);">
Tested on Odoo<br/>11.0 community
</div>
<!--<div style="margin-top: 15px;
position: relative;
font-family:'Vollkorn', serif;
font-size: 16px;
line-height: 25px;
text-transform: uppercase;
font-weight: bold;
color: #75526b;
border: 3px dashed #75526b;
float: left;
padding: 4px 12px;
-webkit-transform: rotate(1deg);
-o-transform: rotate(1deg);
-moz-transform: rotate(1deg);
-ms-transform: rotate(1deg);">
Tested on Odoo<br/>11.0 enterprise
</div>-->
</div>
</div>
</div>
</section>

4
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

41
mail_multi_website/tests/test_fetch.py

@ -0,0 +1,41 @@
# Copyright 2018 Ivan Yelizariev <https://it-projects.info/team/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')

10
mail_multi_website/tests/test_mail_model.py

@ -0,0 +1,10 @@
# Copyright 2018 Ivan Yelizariev <https://it-projects.info/team/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')))

114
mail_multi_website/tests/test_render.py

@ -0,0 +1,114 @@
# Copyright 2018 Ivan Yelizariev <https://it-projects.info/team/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)

62
mail_multi_website/tests/test_send.py

@ -0,0 +1,62 @@
# Copyright 2018 Ivan Yelizariev <https://it-projects.info/team/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')

14
mail_multi_website/views/website_views.xml

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2018 Ivan Yelizariev <https://it-projects.info/team/yelizariev>
License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). -->
<odoo>
<record id="view_website_multi_mail_form" model="ir.ui.view">
<field name="model">website</field>
<field name="inherit_id" ref="website.view_website_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='default_lang_id']" position="after">
<field name="mail_server_id"/>
</xpath>
</field>
</record>
</odoo>

2
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

20
mail_multi_website/wizard/mail_compose_message.py

@ -0,0 +1,20 @@
# Copyright 2018 Ivan Yelizariev <https://it-projects.info/team/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)

30
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 <romanchenko@it-projects.info>
* Pavel Romanchenko
Sponsors
--------
* `IT-Projects LLC <https://it-projects.info>`__
Maintainers
-----------
* `IT-Projects LLC <https://it-projects.info>`__
To get a guaranteed support
you are kindly requested to purchase the module
at `odoo apps store <https://apps.odoo.com/apps/modules/11.0/mail_private/>`__.
Thank you for understanding!
`IT-Projects Team <https://www.it-projects.info/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: `<doc/index.rst>`_
Usage instructions: `<doc/index.rst>`__
Changelog: `<doc/changelog.rst>`_
Changelog: `<doc/changelog.rst>`__
Notifications on updates: `via Atom <https://github.com/it-projects-llc/mail-addons/commits/11.0/mail_private.atom>`_, `by Email <https://blogtrottr.com/?subscribe=https://github.com/it-projects-llc/mail-addons/commits/11.0/mail_private.atom>`_
Tested on Odoo 10.0 ffba5c688ff74a0630f9f70be1d7760a43a7deba
Tested on Odoo 11.0 3d09560ffc779e169ed9488e4e07928204dd234d

2
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",

5
mail_private/doc/changelog.rst

@ -1,3 +1,8 @@
`1.0.2`
-------
- **FIX:** Error when choosing a message template
`1.0.1`
-------

2
mail_private/full_composer_wizard.xml

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record model="ir.ui.view" id="email_compose_message_wizard_form_private">
<field name="name">mail.compose.message.form.private</field>
@ -23,5 +22,4 @@
</field>
</record>
</data>
</odoo>

2
mail_private/static/description/index.html

@ -72,6 +72,8 @@
<ul>
<li><a href="mailto:apps@it-projects.info">apps@it-projects.info <i class="fa fa-envelope-o"></i></a></li>
<li><a href="https://www.it-projects.info/page/website.contactus " target="_blank">https://www.it-projects.info/page/website.contactus <i class="fa fa-list-alt"></i></a></li>
<li><a href="https://m.me/itprojectsllc" target="_blank">https://m.me/itprojectsllc <i class="fa fa-facebook-square"></i></a></li>
<li>skype@it-projects.info <i class="fa fa-skype"></i></li>
</ul>
</div>
<div class="oe_span4">

9
mail_private/static/src/js/mail_private.js

@ -1,3 +1,8 @@
/* Copyright 2016-2018 Ivan Yelizariev <https://it-projects.info/team/yelizariev>
Copyright 2016 manavi <https://github.com/manawi>
Copyright 2017-2018 Artyom Losev <https://github.com/ArtyomLosev>
Copyright 2018 Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr>
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 () {

6
mail_private/template.xml

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<odoo>
<template
id="assets_backend"
name="mail_private_assets_backend"
@ -11,5 +10,4 @@
src="/mail_private/static/src/js/mail_private.js"></script>
</xpath>
</template>
</data>
</openerp>
</odoo>

2
mail_recovery/static/description/index.html

@ -74,6 +74,8 @@
<ul>
<li><a href="mailto:apps@it-projects.info">apps@it-projects.info <i class="fa fa-envelope-o"></i></a></li>
<li><a href="https://www.it-projects.info/page/website.contactus " target="_blank">https://www.it-projects.info/page/website.contactus <i class="fa fa-list-alt"></i></a></li>
<li><a href="https://m.me/itprojectsllc" target="_blank">https://m.me/itprojectsllc <i class="fa fa-facebook-square"></i></a></li>
<li>skype@it-projects.info <i class="fa fa-skype"></i></li>
</ul>
</div>
</div>

4
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 <https://apps.odoo.com/apps/modules/11.0/mail_to/>`__.
@ -24,5 +24,5 @@ Usage
* Note: to see just sent message use one of the following modules:
* SentBox: https://apps.odoo.com/apps/modules/11.0/mail_sent/
* Arhive: https://apps.odoo.com/apps/modules/11.0/mail_archives/
* Archive: https://apps.odoo.com/apps/modules/11.0/mail_archives/
* All Messages: https://www.odoo.com/apps/modules/11.0/mail_all/

2
mail_reply/static/description/index.html

@ -23,6 +23,8 @@
<ul>
<li><a href="mailto:apps@it-projects.info">apps@it-projects.info <i class="fa fa-envelope-o"></i></a></li>
<li><a href="https://www.it-projects.info/page/website.contactus " target="_blank">https://www.it-projects.info/page/website.contactus <i class="fa fa-list-alt"></i></a></li>
<li><a href="https://m.me/itprojectsllc" target="_blank">https://m.me/itprojectsllc <i class="fa fa-facebook-square"></i></a></li>
<li>skype@it-projects.info <i class="fa fa-skype"></i></li>
</ul>
</div>
</div>

45
mail_sent/static/description/index.html

@ -34,14 +34,53 @@ This menu shows messages in threads (like in other menus), but shows only sent m
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<div class="oe_span8">
<h2>Need our service?</h2>
<p class="oe_mt32">Contact us by <a href="mailto:apps@it-projects.info">email</a> or fill out <a href="https://www.it-projects.info/page/website.contactus " target="_blank">request form</a></p>
<ul>
<li><a href="mailto:apps@it-projects.info">apps@it-projects.info <i class="fa fa-envelope-o"></i></a></li>
<li><a href="https://www.it-projects.info/page/website.contactus " target="_blank">
https://www.it-projects.info/page/website.contactus <i class="fa fa-list-alt"></i></a></li>
<li><a href="https://www.it-projects.info/page/website.contactus " target="_blank">https://www.it-projects.info/page/website.contactus <i class="fa fa-list-alt"></i></a></li>
<li><a href="https://m.me/itprojectsllc" target="_blank">https://m.me/itprojectsllc <i class="fa fa-facebook-square"></i></a></li>
<li>skype@it-projects.info <i class="fa fa-skype"></i></li>
</ul>
</div>
<div class="oe_span4">
<div class="stamp" style="width:200px;">
<div style="margin-top: 15px;
position: relative;
font-family:'Vollkorn', serif;
font-size: 16px;
line-height: 25px;
text-transform: uppercase;
font-weight: bold;
color: #75526b;
border: 3px dashed #75526b;
float: left;
padding: 4px 12px;
-webkit-transform: rotate(6deg);
-o-transform: rotate(6deg);
-moz-transform: rotate(6deg);
-ms-transform: rotate(6deg);">
Tested on Odoo<br/>11.0 community
</div>
<div style="margin-top: 15px;
position: relative;
font-family:'Vollkorn', serif;
font-size: 16px;
line-height: 25px;
text-transform: uppercase;
font-weight: bold;
color: #75526b;
border: 3px dashed #75526b;
float: left;
padding: 4px 12px;
-webkit-transform: rotate(-7deg);
-o-transform: rotate(-7deg);
-moz-transform: rotate(-7deg);
-ms-transform: rotate(-7deg);">
Tested on Odoo<br/>11.0 enterprise
</div>
</div>
</div>
</div>
</section>

2
mail_to/static/description/index.html

@ -20,6 +20,8 @@
<ul>
<li><a href="mailto:apps@it-projects.info">apps@it-projects.info <i class="fa fa-envelope-o"></i></a></li>
<li><a href="https://www.it-projects.info/page/website.contactus " target="_blank">https://www.it-projects.info/page/website.contactus <i class="fa fa-list-alt"></i></a></li>
<li><a href="https://m.me/itprojectsllc" target="_blank">https://m.me/itprojectsllc <i class="fa fa-facebook-square"></i></a></li>
<li>skype@it-projects.info <i class="fa fa-skype"></i></li>
</ul>
</div>
<div class="oe_span4">

1
mail_to/tests/test_default.py

@ -7,6 +7,7 @@ class TestUi(odoo.tests.HttpCase):
def test_01_mail_to(self):
# checks the presence of an element with a link to the recipient
# TODO: instead of timeout, try to put $('a.recipient_link') as ready argument of phantom_js (third parameter)
code = """
setTimeout(function () {
$('a.recipient_link')[0].click();

2
mailgun/static/description/index.html

@ -288,6 +288,8 @@
<ul>
<li><a href="mailto:apps@it-projects.info">apps@it-projects.info <i class="fa fa-envelope-o"></i></a></li>
<li><a href="https://www.it-projects.info/page/website.contactus " target="_blank">https://www.it-projects.info/page/website.contactus <i class="fa fa-list-alt"></i></a></li>
<li><a href="https://m.me/itprojectsllc" target="_blank">https://m.me/itprojectsllc <i class="fa fa-facebook-square"></i></a></li>
<li>skype@it-projects.info <i class="fa fa-skype"></i></li>
</ul>
</div>
<div class="oe_span4">

2
res_partner_mails_count/static/description/index.html

@ -28,6 +28,8 @@
<li><a href="mailto:apps@it-projects.info">apps@it-projects.info <i class="fa fa-envelope-o"></i></a></li>
<li><a href="https://www.it-projects.info/page/website.contactus " target="_blank">
https://www.it-projects.info/page/website.contactus <i class="fa fa-list-alt"></i></a></li>
<li><a href="https://m.me/itprojectsllc" target="_blank">https://m.me/itprojectsllc <i class="fa fa-facebook-square"></i></a></li>
<li>skype@it-projects.info <i class="fa fa-skype"></i></li>
</ul>
</div>
</div>

Loading…
Cancel
Save