Merge lp:~openerp-dev/openobject-addons/trunk-fetchmail-inbox-tde into lp:openobject-addons

Proposed by Thibault Delavallée (OpenERP)
Status: Merged
Merged at revision: 8037
Proposed branch: lp:~openerp-dev/openobject-addons/trunk-fetchmail-inbox-tde
Merge into: lp:openobject-addons
Diff against target: 1220 lines (+316/-199)
40 files modified
account_accountant/account_accountant_data.xml (+3/-5)
account_voucher/account_voucher_data.xml (+3/-5)
crm/crm_data.xml (+3/-2)
email_template/email_template.py (+2/-4)
email_template/tests/test_mail.py (+6/-6)
fetchmail/fetchmail.py (+5/-5)
hr/hr_data.xml (+4/-4)
hr_evaluation/hr_evaluation_data.xml (+2/-2)
hr_expense/hr_expense_data.xml (+3/-3)
hr_holidays/hr_holidays_data.xml (+3/-2)
hr_recruitment/hr_recruitment_data.xml (+3/-3)
hr_timesheet_sheet/hr_timesheet_sheet_data.xml (+2/-1)
mail/data/mail_demo.xml (+10/-6)
mail/data/mail_group_data.xml (+4/-5)
mail/mail_followers.py (+11/-10)
mail/mail_message.py (+5/-2)
mail/mail_thread.py (+82/-34)
mail/res_partner.py (+18/-0)
mail/security/ir.model.access.csv (+4/-3)
mail/security/mail_security.xml (+9/-1)
mail/static/src/css/mail.css (+4/-0)
mail/static/src/js/mail.js (+1/-2)
mail/tests/__init__.py (+1/-0)
mail/tests/test_mail.py (+8/-40)
mail/tests/test_mail_access_rights.py (+2/-2)
mail/tests/test_mail_mockup.py (+54/-0)
mrp/mrp_data.xml (+4/-4)
note/note.py (+1/-3)
pad/pad.py (+1/-1)
point_of_sale/point_of_sale_data.xml (+3/-3)
portal/mail_mail.py (+1/-1)
portal/portal_demo.xml (+32/-19)
portal/tests/test_portal.py (+2/-3)
portal/wizard/portal_wizard.py (+1/-2)
project/project_data.xml (+4/-4)
project_gtd/project_gtd_data.xml (+3/-2)
project_issue/project_issue_data.xml (+3/-2)
purchase/purchase_data.xml (+3/-3)
sale/sale_data.xml (+3/-3)
stock/stock_data.xml (+3/-2)
To merge this branch: bzr merge lp:~openerp-dev/openobject-addons/trunk-fetchmail-inbox-tde
Reviewer Review Type Date Requested Status
OpenERP Core Team Pending
Review via email: mp+134269@code.launchpad.net

This proposal supersedes a proposal from 2012-10-29.

Description of the change

Mail: improve incoming/outgoing emails behavior
Main:
- updated overall code to match the new mail openerp tools
- message_route: after checking the headers to find if the incoming email is a reply in an existing discussion, it checks whether the email is a reply to a private discussion (without model, res_id), based on the message_id of the mail; it then relies on the aliases then fetchmail, as before
- incoming emails and quick posting through Chatter now calls message_post_user_api (based on old message_post_api), that performs some things the composer do on its side (adding recipients of a replied message, cleaning the content)
Misc:
- general: updated modules according to the new tools mail functions
- general: message related to a new app installation now have a comment subtype, meaning they will effectively be pushed
- mail: improved set_message_read, fixed a bug with message_id
- fetchmail: fixed a bug in fetchmail module about non-existing variable
- portal: updated demo data

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'account_accountant/account_accountant_data.xml'
--- account_accountant/account_accountant_data.xml 2012-10-16 11:23:23 +0000
+++ account_accountant/account_accountant_data.xml 2012-11-14 14:39:22 +0000
@@ -26,12 +26,10 @@
26 <field name="model">mail.group</field>26 <field name="model">mail.group</field>
27 <field name="res_id" ref="mail.group_all_employees"/>27 <field name="res_id" ref="mail.group_all_employees"/>
28 <field name="type">notification</field>28 <field name="type">notification</field>
29 <field name="subtype_id" ref="mail.mt_comment"/>
29 <field name="subject">Accounting and Finance application installed!</field>30 <field name="subject">Accounting and Finance application installed!</field>
30 <field name="body"><![CDATA[31 <field name="body"><![CDATA[<p>With OpenERP's accounting, you get instant access to your financial data, and can setup analytic accounting, forecast taxes, control budgets, easily create and send invoices, record bank statements, etc.</p>
31 With OpenERP's accounting, you get instant access to your financial data, and can setup analytic accounting, forecast taxes, control budgets, easily create and send invoices, record bank statements, etc.32<p>The accounting features are fully integrated with other OpenERP applications to automate all your processes: creation of customer invoices, control of supplier invoices, point-of-sale integration, automated follow-ups, etc.</p>]]></field>
32
33<p>The accounting features are fully integrated with other OpenERP applications to automate all your processes: creation of customer invoices, control of supplier invoices, point-of-sale integration, automated follow-ups, etc.</p>
34 ]]></field>
35 </record>33 </record>
36 </data>34 </data>
37</openerp>35</openerp>
3836
=== modified file 'account_voucher/account_voucher_data.xml'
--- account_voucher/account_voucher_data.xml 2012-10-02 20:40:23 +0000
+++ account_voucher/account_voucher_data.xml 2012-11-14 14:39:22 +0000
@@ -7,12 +7,10 @@
7 <field name="model">mail.group</field>7 <field name="model">mail.group</field>
8 <field name="res_id" ref="mail.group_all_employees"/>8 <field name="res_id" ref="mail.group_all_employees"/>
9 <field name="type">notification</field>9 <field name="type">notification</field>
10 <field name="subtype_id" ref="mail.mt_comment"/>
10 <field name="subject">eInvoicing &amp; Payments application installed!</field>11 <field name="subject">eInvoicing &amp; Payments application installed!</field>
11 <field name="body"><![CDATA[12 <field name="body"><![CDATA[<p>OpenERP's electronic invoicing accelerates the creation of invoices and collection of customer payments. Invoices are created in a few clicks and your customers receive them by email. They can pay online and/or import them in their own system.</p>
12 OpenERP's electronic invoicing accelerates the creation of invoices and collection of customer payments. Invoices are created in a few clicks and your customers receive them by email. They can pay online and/or import them in their own system. 13<p>You can track customer payments easily and automate follow-ups. You get an overview of the discussion with your customers on each invoice for easier traceability. For advanced accounting features, you should install the "Accounting and Finance" module.</p>]]></field>
13
14<p>You can track customer payments easily and automate follow-ups. You get an overview of the discussion with your customers on each invoice for easier traceability. For advanced accounting features, you should install the "Accounting and Finance" module.</p>
15 ]]></field>
16 </record>14 </record>
1715
18 <!-- mail: subtypes -->16 <!-- mail: subtypes -->
1917
=== modified file 'crm/crm_data.xml'
--- crm/crm_data.xml 2012-09-17 06:57:40 +0000
+++ crm/crm_data.xml 2012-11-14 14:39:22 +0000
@@ -58,9 +58,10 @@
58 <field name="model">mail.group</field>58 <field name="model">mail.group</field>
59 <field name="res_id" ref="mail.group_all_employees"/>59 <field name="res_id" ref="mail.group_all_employees"/>
60 <field name="type">notification</field>60 <field name="type">notification</field>
61 <field name="subtype_id" ref="mail.mt_comment"/>
61 <field name="subject">CRM application installed!</field>62 <field name="subject">CRM application installed!</field>
62 <field name="body">From the top Sales menu you can track leads and opportunities, get accurate forecast on your sales pipeline, plan meetings and phonecalls, get realtime statistics and efficiently organize the communication with your prospects.63 <field name="body"><![CDATA[<p>From the top Sales menu you can track leads and opportunities, get accurate forecast on your sales pipeline, plan meetings and phonecalls, get realtime statistics and efficiently organize the communication with your prospects.</p>
63To manage quotations and sale orders, install the "Sales Management" application.</field>64<br />To manage quotations and sale orders, install the "Sales Management" application.</p>]]></field>
64 </record>65 </record>
6566
66 <record model="mail.alias" id="default_sales_alias">67 <record model="mail.alias" id="default_sales_alias">
6768
=== modified file 'email_template/email_template.py'
--- email_template/email_template.py 2012-11-07 11:39:25 +0000
+++ email_template/email_template.py 2012-11-14 14:39:22 +0000
@@ -28,8 +28,6 @@
28from osv import fields28from osv import fields
29import tools29import tools
30from tools.translate import _30from tools.translate import _
31from tools.html_sanitize import html_sanitize
32from tools import append_content_to_html
33from urllib import quote as quote31from urllib import quote as quote
34_logger = logging.getLogger(__name__)32_logger = logging.getLogger(__name__)
3533
@@ -293,10 +291,10 @@
293 or False291 or False
294 if template.user_signature:292 if template.user_signature:
295 signature = self.pool.get('res.users').browse(cr, uid, uid, context).signature293 signature = self.pool.get('res.users').browse(cr, uid, uid, context).signature
296 values['body_html'] = append_content_to_html(values['body_html'], signature)294 values['body_html'] = tools.append_content_to_html(values['body_html'], signature)
297295
298 if values['body_html']:296 if values['body_html']:
299 values['body'] = html_sanitize(values['body_html'])297 values['body'] = tools.html_sanitize(values['body_html'])
300298
301 values.update(mail_server_id=template.mail_server_id.id or False,299 values.update(mail_server_id=template.mail_server_id.id or False,
302 auto_delete=template.auto_delete,300 auto_delete=template.auto_delete,
303301
=== modified file 'email_template/tests/test_mail.py'
--- email_template/tests/test_mail.py 2012-11-13 13:10:44 +0000
+++ email_template/tests/test_mail.py 2012-11-14 14:39:22 +0000
@@ -20,10 +20,10 @@
20##############################################################################20##############################################################################
2121
22import base6422import base64
23from openerp.addons.mail.tests import test_mail23from openerp.addons.mail.tests import test_mail_mockup
2424
2525
26class test_message_compose(test_mail.TestMailMockups):26class test_message_compose(test_mail_mockup.TestMailMockups):
2727
28 def setUp(self):28 def setUp(self):
29 super(test_message_compose, self).setUp()29 super(test_message_compose, self).setUp()
@@ -52,8 +52,8 @@
52 # Mail data52 # Mail data
53 _subject1 = 'Pigs'53 _subject1 = 'Pigs'
54 _subject2 = 'Bird'54 _subject2 = 'Bird'
55 _body_html1 = 'Fans of Pigs, unite !\n<pre>Admin</pre>\n'55 _body_html1 = 'Fans of Pigs, unite !\n<p>Admin</p>\n'
56 _body_html2 = 'I am angry !\n<pre>Admin</pre>\n'56 _body_html2 = 'I am angry !\n<p>Admin</p>\n'
57 _attachments = [57 _attachments = [
58 {'name': 'First', 'datas_fname': 'first.txt', 'datas': base64.b64encode('My first attachment')},58 {'name': 'First', 'datas_fname': 'first.txt', 'datas': base64.b64encode('My first attachment')},
59 {'name': 'Second', 'datas_fname': 'second.txt', 'datas': base64.b64encode('My second attachment')}59 {'name': 'Second', 'datas_fname': 'second.txt', 'datas': base64.b64encode('My second attachment')}
6060
=== modified file 'fetchmail/fetchmail.py'
--- fetchmail/fetchmail.py 2012-10-25 13:09:30 +0000
+++ fetchmail/fetchmail.py 2012-11-14 14:39:22 +0000
@@ -243,20 +243,20 @@
243243
244 def create(self, cr, uid, values, context=None):244 def create(self, cr, uid, values, context=None):
245 if context is None:245 if context is None:
246 context={}246 context = {}
247 fetchmail_server_id = context.get('fetchmail_server_id')247 fetchmail_server_id = context.get('fetchmail_server_id')
248 if fetchmail_server_id:248 if fetchmail_server_id:
249 values['fetchmail_server_id'] = fetchmail_server_id249 values['fetchmail_server_id'] = fetchmail_server_id
250 res = super(mail_mail,self).create(cr, uid, values, context=context)250 res = super(mail_mail, self).create(cr, uid, values, context=context)
251 return res251 return res
252252
253 def write(self, cr, uid, ids, values, context=None):253 def write(self, cr, uid, ids, values, context=None):
254 if context is None:254 if context is None:
255 context={}255 context = {}
256 fetchmail_server_id = context.get('fetchmail_server_id')256 fetchmail_server_id = context.get('fetchmail_server_id')
257 if fetchmail_server_id:257 if fetchmail_server_id:
258 values['fetchmail_server_id'] = server_id258 values['fetchmail_server_id'] = fetchmail_server_id
259 res = super(mail_mail,self).write(cr, uid, ids, values, context=context)259 res = super(mail_mail, self).write(cr, uid, ids, values, context=context)
260 return res260 return res
261261
262262
263263
=== modified file 'hr/hr_data.xml'
--- hr/hr_data.xml 2012-08-30 14:18:52 +0000
+++ hr/hr_data.xml 2012-11-14 14:39:22 +0000
@@ -6,11 +6,11 @@
6 <field name="model">mail.group</field>6 <field name="model">mail.group</field>
7 <field name="res_id" ref="mail.group_all_employees"/>7 <field name="res_id" ref="mail.group_all_employees"/>
8 <field name="type">notification</field>8 <field name="type">notification</field>
9 <field name="subtype_id" ref="mail.mt_comment"/>
9 <field name="subject">Employee Directory application installed!</field>10 <field name="subject">Employee Directory application installed!</field>
10 <field name="body">Manage your human resources with OpenERP: employees and their hierarchy, HR departments and job positions.11 <field name="body"><![CDATA[<p>Manage your human resources with OpenERP: employees and their hierarchy, HR departments and job positions.</p>
1112<p>More HR features are available via extra applications: Recruitment Process (manage job positions and recruitment), Timesheet Validation (record timesheets and attendance),
12More HR features are available via extra applications: Recruitment Process (manage job positions and recruitment), Timesheet Validation (record timesheets and attendance),13Leave Management (keep track of employee leaves), Expense Management (manage employee expenses), Employee Appraisals (organize employee surveys, where employees evaluate their subordinates or their manager).</p>]]></field>
13Leave Management (keep track of employee leaves), Expense Management (manage employee expenses), Employee Appraisals (organize employee surveys, where employees evaluate their subordinates or their manager).</field>
14 </record>14 </record>
1515
16 <record id="employee" model="hr.employee">16 <record id="employee" model="hr.employee">
1717
=== modified file 'hr_evaluation/hr_evaluation_data.xml'
--- hr_evaluation/hr_evaluation_data.xml 2012-09-20 09:09:11 +0000
+++ hr_evaluation/hr_evaluation_data.xml 2012-11-14 14:39:22 +0000
@@ -11,9 +11,9 @@
11 <field name="model">mail.group</field>11 <field name="model">mail.group</field>
12 <field name="res_id" ref="mail.group_all_employees"/>12 <field name="res_id" ref="mail.group_all_employees"/>
13 <field name="type">notification</field>13 <field name="type">notification</field>
14 <field name="subtype_id" ref="mail.mt_comment"/>
14 <field name="subject">Employee Appraisals application installed!</field>15 <field name="subject">Employee Appraisals application installed!</field>
15 <field name="body">Manage employee reviews: you can define an appraisal campaign with several steps, with specific evaluation surveys according to hierarchy levels.16 <field name="body"><![CDATA[<p>Manage employee reviews: you can define an appraisal campaign with several steps, with specific evaluation surveys according to hierarchy levels. Evaluations filled by employees may be exported as pdf files.</p>]]></field>
16Evaluations filled by employees may be exported as pdf files.</field>
17 </record>17 </record>
1818
19 <record id="survey_2" model="survey">19 <record id="survey_2" model="survey">
2020
=== modified file 'hr_expense/hr_expense_data.xml'
--- hr_expense/hr_expense_data.xml 2012-08-30 14:18:52 +0000
+++ hr_expense/hr_expense_data.xml 2012-11-14 14:39:22 +0000
@@ -6,10 +6,10 @@
6 <field name="model">mail.group</field>6 <field name="model">mail.group</field>
7 <field name="res_id" ref="mail.group_all_employees"/>7 <field name="res_id" ref="mail.group_all_employees"/>
8 <field name="type">notification</field>8 <field name="type">notification</field>
9 <field name="subtype_id" ref="mail.mt_comment"/>
9 <field name="subject">Expense Management application installed!</field>10 <field name="subject">Expense Management application installed!</field>
10 <field name="body">Manage your employees' expenses, after due validation by their manager and the accountant, then generate and pay the corresponding invoices.11 <field name="body"><![CDATA[<p>Manage your employees' expenses, after due validation by their manager and the accountant, then generate and pay the corresponding invoices.</p>
1112<p>This feature is also linked to analytic accounting and compatible with timesheet invoices, so you will be able to automatically re-invoice project-related expenses to your customers.</p>]]></field>
12This feature is also linked to analytic accounting and compatible with timesheet invoices, so you will be able to automatically re-invoice project-related expenses to your customers.</field>
13 </record>13 </record>
1414
15 <!-- Resource: product.uom.categ -->15 <!-- Resource: product.uom.categ -->
1616
=== modified file 'hr_holidays/hr_holidays_data.xml'
--- hr_holidays/hr_holidays_data.xml 2012-10-02 20:40:23 +0000
+++ hr_holidays/hr_holidays_data.xml 2012-11-14 14:39:22 +0000
@@ -11,9 +11,10 @@
11 <field name="model">mail.group</field>11 <field name="model">mail.group</field>
12 <field name="res_id" ref="mail.group_all_employees"/>12 <field name="res_id" ref="mail.group_all_employees"/>
13 <field name="type">notification</field>13 <field name="type">notification</field>
14 <field name="subtype_id" ref="mail.mt_comment"/>
14 <field name="subject">Leave Management application installed!</field>15 <field name="subject">Leave Management application installed!</field>
15 <field name="body">Manage employee leaves from the top menu "Human Resources". Employees can create leave requests that are validated by their manager and/or HR officers.16 <field name="body"><![CDATA[<p>Manage employee leaves from the top menu "Human Resources". Employees can create leave requests that are validated by their manager and/or HR officers.</p>
16Once validated, they are visible in the employee's calendar. HR officers can define leave types and allocate leaves to employees and employee categories.</field>17<p>Once validated, they are visible in the employee's calendar. HR officers can define leave types and allocate leaves to employees and employee categories.</p>]]></field>
17 </record>18 </record>
1819
1920
2021
=== modified file 'hr_recruitment/hr_recruitment_data.xml'
--- hr_recruitment/hr_recruitment_data.xml 2012-10-08 09:50:03 +0000
+++ hr_recruitment/hr_recruitment_data.xml 2012-11-14 14:39:22 +0000
@@ -6,10 +6,10 @@
6 <field name="model">mail.group</field>6 <field name="model">mail.group</field>
7 <field name="res_id" ref="mail.group_all_employees"/>7 <field name="res_id" ref="mail.group_all_employees"/>
8 <field name="type">notification</field>8 <field name="type">notification</field>
9 <field name="subtype_id" ref="mail.mt_comment"/>
9 <field name="subject">Recruitment Process application installed!</field>10 <field name="subject">Recruitment Process application installed!</field>
10 <field name="body">Manage job positions and your company's recruitment process. This application is integrated with the Survey application to help you define interviews for different jobs.11 <field name="body"><![CDATA[<p>Manage job positions and your company's recruitment process. This application is integrated with the Survey application to help you define interviews for different jobs.</p>
1112<p>You can automatically receive job application though an email gateway, see the Human Resources settings.</p>]]></field>
12You can automatically receive job application though an email gateway, see the Human Resources settings.</field>
13 </record>13 </record>
1414
15 <!-- Meeting Types (for interview meetings) -->15 <!-- Meeting Types (for interview meetings) -->
1616
=== modified file 'hr_timesheet_sheet/hr_timesheet_sheet_data.xml'
--- hr_timesheet_sheet/hr_timesheet_sheet_data.xml 2012-09-24 08:23:00 +0000
+++ hr_timesheet_sheet/hr_timesheet_sheet_data.xml 2012-11-14 14:39:22 +0000
@@ -6,8 +6,9 @@
6 <field name="model">mail.group</field>6 <field name="model">mail.group</field>
7 <field name="res_id" ref="mail.group_all_employees"/>7 <field name="res_id" ref="mail.group_all_employees"/>
8 <field name="type">notification</field>8 <field name="type">notification</field>
9 <field name="subtype_id" ref="mail.mt_comment"/>
9 <field name="subject">Timesheet Validation application installed!</field>10 <field name="subject">Timesheet Validation application installed!</field>
10 <field name="body">From the top menu "Human Resources", enter and validate timesheets and attendances.</field>11 <field name="body"><![CDATA[<p>From the top menu "Human Resources", enter and validate timesheets and attendances.</p>]]></field>
11 </record>12 </record>
1213
13 <record id="ir_actions_server_timsheet_sheet" model="ir.actions.server">14 <record id="ir_actions_server_timsheet_sheet" model="ir.actions.server">
1415
=== modified file 'mail/data/mail_demo.xml'
--- mail/data/mail_demo.xml 2012-11-12 15:27:53 +0000
+++ mail/data/mail_demo.xml 2012-11-14 14:39:22 +0000
@@ -11,44 +11,48 @@
11 <record id="message_blogpost0" model="mail.message">11 <record id="message_blogpost0" model="mail.message">
12 <field name="model">mail.group</field>12 <field name="model">mail.group</field>
13 <field name="res_id" ref="mail.group_all_employees"/>13 <field name="res_id" ref="mail.group_all_employees"/>
14 <field name="body">Your monthly meal vouchers arrived. You can get them at Christine's office.14 <field name="body"><![CDATA[<p>Your monthly meal vouchers arrived. You can get them at Christine's office.</p>]]></field>
15This month you also get 250 EUR of eco-vouchers if you have been in the company for more than a year.</field>
16 <field name="type">comment</field>15 <field name="type">comment</field>
17 <field name="subtype_id" ref="mt_comment"/>16 <field name="subtype_id" ref="mt_comment"/>
17 <field name="author_id" ref="base.partner_root"/>
18 </record>18 </record>
19 <record id="message_blogpost0_comment0" model="mail.message">19 <record id="message_blogpost0_comment0" model="mail.message">
20 <field name="model">mail.group</field>20 <field name="model">mail.group</field>
21 <field name="res_id" ref="group_all_employees"/>21 <field name="res_id" ref="group_all_employees"/>
22 <field name="body"><![CDATA[Great.]]></field>22 <field name="body"><![CDATA[<p>Oh, I had forgotten. This month you also get 250 EUR of eco-vouchers if you have been in the company for more than a year.</p>]]></field>
23 <field name="parent_id" ref="message_blogpost0"/>23 <field name="parent_id" ref="message_blogpost0"/>
24 <field name="type">comment</field>24 <field name="type">comment</field>
25 <field name="subtype_id" ref="mt_comment"/>25 <field name="subtype_id" ref="mt_comment"/>
26 <field name="author_id" ref="base.partner_root"/>
26 </record>27 </record>
27 <record id="message_blogpost0_comment1" model="mail.message">28 <record id="message_blogpost0_comment1" model="mail.message">
28 <field name="model">mail.group</field>29 <field name="model">mail.group</field>
29 <field name="res_id" ref="group_all_employees"/>30 <field name="res_id" ref="group_all_employees"/>
30 <field name="body">Thanks, but where is Christine's office, if I may ask? (I'm new here)</field>31 <field name="body"><![CDATA[<p>Thanks! Could you please remind me where is Christine's office, if I may ask? I'm new here!</p>]]></field>
31 <field name="parent_id" ref="message_blogpost0"/>32 <field name="parent_id" ref="message_blogpost0"/>
32 <field name="type">comment</field>33 <field name="type">comment</field>
33 <field name="subtype_id" ref="mt_comment"/>34 <field name="subtype_id" ref="mt_comment"/>
35 <field name="author_id" ref="base.partner_demo"/>
34 </record>36 </record>
35 <!-- This one is starred for having mailboxes with demo data -->37 <!-- This one is starred for having mailboxes with demo data -->
36 <record id="message_blogpost0_comment2" model="mail.message">38 <record id="message_blogpost0_comment2" model="mail.message">
37 <field name="model">mail.group</field>39 <field name="model">mail.group</field>
38 <field name="res_id" ref="group_all_employees"/>40 <field name="res_id" ref="group_all_employees"/>
39 <field name="body">Building B3, second floor on the right :-)</field>41 <field name="body"><![CDATA[<p>Building B3, second floor on the right :-).</p>]]></field>
40 <field name="parent_id" ref="message_blogpost0"/>42 <field name="parent_id" ref="message_blogpost0"/>
41 <field name="type">comment</field>43 <field name="type">comment</field>
42 <field name="subtype_id" ref="mt_comment"/>44 <field name="subtype_id" ref="mt_comment"/>
45 <field name="author_id" ref="base.partner_root"/>
43 <field name="favorite_user_ids" eval="[(6, 0, [ref('base.user_root'), ref('base.user_demo')])]"/>46 <field name="favorite_user_ids" eval="[(6, 0, [ref('base.user_root'), ref('base.user_demo')])]"/>
44 </record>47 </record>
45 <record id="message_blogpost0_comment3" model="mail.message">48 <record id="message_blogpost0_comment3" model="mail.message">
46 <field name="model">mail.group</field>49 <field name="model">mail.group</field>
47 <field name="res_id" ref="group_all_employees"/>50 <field name="res_id" ref="group_all_employees"/>
48 <field name="body">Great news, I need to buy a new fridge, I think I can pay it with the eco-vouchers!</field>51 <field name="body"><![CDATA[<p>Many thanks. Actually that's good news, next year I'll have to buy a new fridge, I think I will pay it with the eco-vouchers!</p>]]></field>
49 <field name="parent_id" ref="message_blogpost0"/>52 <field name="parent_id" ref="message_blogpost0"/>
50 <field name="type">comment</field>53 <field name="type">comment</field>
51 <field name="subtype_id" ref="mt_comment"/>54 <field name="subtype_id" ref="mt_comment"/>
55 <field name="author_id" ref="base.partner_demo"/>
52 </record>56 </record>
5357
54 <!-- Demo user and admin conversation -->58 <!-- Demo user and admin conversation -->
5559
=== modified file 'mail/data/mail_group_data.xml'
--- mail/data/mail_group_data.xml 2012-11-12 23:04:18 +0000
+++ mail/data/mail_group_data.xml 2012-11-14 14:39:22 +0000
@@ -17,12 +17,11 @@
17 <field name="model">mail.group</field>17 <field name="model">mail.group</field>
18 <field name="res_id" ref="mail.group_all_employees"/>18 <field name="res_id" ref="mail.group_all_employees"/>
19 <field name="type">notification</field>19 <field name="type">notification</field>
20 <field name="subtype_id" ref="mail.mt_comment"/>
20 <field name="subject">Welcome to OpenERP!</field>21 <field name="subject">Welcome to OpenERP!</field>
21 <field name="body">Your homepage is a summary of messages you received and key information about documents you follow.22 <field name="body"><![CDATA[<p>Your homepage is a summary of messages you received and key information about documents you follow.<br />
2223The top menu bar contains all applications you installed. You can use this &lt;i&gt;Settings&lt;/i&gt; menu to install more applications, activate others features or give access to new users.<br />
23The top menu bar contains all applications you installed. You can use this &lt;i&gt;Settings&lt;/i&gt; menu to install more applications, activate others features or give access to new users.24To setup your preferences (name, email signature, avatar), click on the top right corner.</p>]]></field>
24
25To setup your preferences (name, email signature, avatar), click on the top right corner.</field>
26 </record>25 </record>
27 </data>26 </data>
28</openerp>27</openerp>
2928
=== modified file 'mail/mail_followers.py'
--- mail/mail_followers.py 2012-11-12 13:17:59 +0000
+++ mail/mail_followers.py 2012-11-14 14:39:22 +0000
@@ -84,11 +84,13 @@
84 return False84 return False
8585
86 def set_message_read(self, cr, uid, msg_ids, read=None, context=None):86 def set_message_read(self, cr, uid, msg_ids, read=None, context=None):
87 """ Set a message and its child messages as (un)read for uid.87 """ Set messages as (un)read. Technically, the notifications related
88 to uid are set to (un)read. If for some msg_ids there are missing
89 notifications (i.e. due to load more or thread parent fetching),
90 they are created.
8891
89 :param bool read: read / unread92 :param bool read: (un)read notification
90 """93 """
91 # TDE note: use child_of or front-end send correct values ?
92 user_pid = self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=context)['partner_id'][0]94 user_pid = self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=context)['partner_id'][0]
93 notif_ids = self.search(cr, uid, [95 notif_ids = self.search(cr, uid, [
94 ('partner_id', '=', user_pid),96 ('partner_id', '=', user_pid),
@@ -100,10 +102,9 @@
100 return self.write(cr, uid, notif_ids, {'read': read}, context=context)102 return self.write(cr, uid, notif_ids, {'read': read}, context=context)
101103
102 # some messages do not have notifications: find which one, create notification, update read status104 # some messages do not have notifications: find which one, create notification, update read status
103 exist_notification = dict.fromkeys(msg_ids, False)105 notified_msg_ids = [notification.message_id.id for notification in self.browse(cr, uid, notif_ids, context=context)]
104 for notification in self.browse(cr, uid, notif_ids, context=context):106 to_create_msg_ids = list(set(msg_ids) - set(notified_msg_ids))
105 exist_notification[notification.message_id.id] = True107 for msg_id in to_create_msg_ids:
106 for msg_id in exist_notification.keys():
107 self.create(cr, uid, {'partner_id': user_pid, 'read': read, 'message_id': msg_id}, context=context)108 self.create(cr, uid, {'partner_id': user_pid, 'read': read, 'message_id': msg_id}, context=context)
108 return self.write(cr, uid, notif_ids, {'read': read}, context=context)109 return self.write(cr, uid, notif_ids, {'read': read}, context=context)
109110
@@ -156,10 +157,10 @@
156 # add signature157 # add signature
157 body_html = msg.body158 body_html = msg.body
158 # if quote_context:159 # if quote_context:
159 # body_html = tools.append_content_to_html(body_html, quote_context, plaintext=False)160 # body_html = tools.append_content_to_html(body_html, quote_context, plaintext=False)
160 signature = msg.author_id and msg.author_id.user_ids[0].signature or ''161 signature = msg.author_id and msg.author_id.user_ids and msg.author_id.user_ids[0].signature or ''
161 if signature:162 if signature:
162 body_html = tools.append_content_to_html(body_html, signature)163 body_html = tools.append_content_to_html(body_html, signature, plaintext=True, container_tag='div')
163164
164 mail_values = {165 mail_values = {
165 'mail_message_id': msg.id,166 'mail_message_id': msg.id,
166167
=== modified file 'mail/mail_message.py'
--- mail/mail_message.py 2012-11-12 14:04:08 +0000
+++ mail/mail_message.py 2012-11-14 14:39:22 +0000
@@ -25,6 +25,7 @@
25from email.header import decode_header25from email.header import decode_header
26from openerp import SUPERUSER_ID26from openerp import SUPERUSER_ID
27from openerp.osv import osv, orm, fields27from openerp.osv import osv, orm, fields
28from openerp.tools import html_email_clean
28from openerp.tools.translate import _29from openerp.tools.translate import _
2930
30_logger = logging.getLogger(__name__)31_logger = logging.getLogger(__name__)
@@ -280,7 +281,7 @@
280281
281 return {'id': message.id,282 return {'id': message.id,
282 'type': message.type,283 'type': message.type,
283 'body': message.body,284 'body': html_email_clean(message.body),
284 'model': message.model,285 'model': message.model,
285 'res_id': message.res_id,286 'res_id': message.res_id,
286 'record_name': message.record_name,287 'record_name': message.record_name,
@@ -633,6 +634,8 @@
633 def create(self, cr, uid, values, context=None):634 def create(self, cr, uid, values, context=None):
634 if not values.get('message_id') and values.get('res_id') and values.get('model'):635 if not values.get('message_id') and values.get('res_id') and values.get('model'):
635 values['message_id'] = tools.generate_tracking_message_id('%(res_id)s-%(model)s' % values)636 values['message_id'] = tools.generate_tracking_message_id('%(res_id)s-%(model)s' % values)
637 elif not values.get('message_id'):
638 values['message_id'] = tools.generate_tracking_message_id('private')
636 newid = super(mail_message, self).create(cr, uid, values, context)639 newid = super(mail_message, self).create(cr, uid, values, context)
637 self._notify(cr, SUPERUSER_ID, newid, context=context)640 self._notify(cr, SUPERUSER_ID, newid, context=context)
638 return newid641 return newid
@@ -763,7 +766,7 @@
763 ], context=context)766 ], context=context)
764 fol_objs = fol_obj.read(cr, uid, fol_ids, ['partner_id'], context=context)767 fol_objs = fol_obj.read(cr, uid, fol_ids, ['partner_id'], context=context)
765 partners_to_notify |= set(fol['partner_id'][0] for fol in fol_objs)768 partners_to_notify |= set(fol['partner_id'][0] for fol in fol_objs)
766 # when writing to a wall769 # remove me from notified partners, unless the message is written on my own wall
767 if message.get('author_id') and message.get('model') == "res.partner" and message.get('res_id') == message.get('author_id')[0]:770 if message.get('author_id') and message.get('model') == "res.partner" and message.get('res_id') == message.get('author_id')[0]:
768 partners_to_notify |= set([message.get('author_id')[0]])771 partners_to_notify |= set([message.get('author_id')[0]])
769 elif message.get('author_id'):772 elif message.get('author_id'):
770773
=== modified file 'mail/mail_thread.py'
--- mail/mail_thread.py 2012-11-12 13:10:51 +0000
+++ mail/mail_thread.py 2012-11-14 14:39:22 +0000
@@ -319,10 +319,12 @@
319 """319 """
320 assert isinstance(message, Message), 'message must be an email.message.Message at this point'320 assert isinstance(message, Message), 'message must be an email.message.Message at this point'
321 message_id = message.get('Message-Id')321 message_id = message.get('Message-Id')
322 references = decode_header(message, 'References')
323 in_reply_to = decode_header(message, 'In-Reply-To')
322324
323 # 1. Verify if this is a reply to an existing thread325 # 1. Verify if this is a reply to an existing thread
324 references = decode_header(message, 'References') or decode_header(message, 'In-Reply-To')326 thread_references = references or in_reply_to
325 ref_match = references and tools.reference_re.search(references)327 ref_match = thread_references and tools.reference_re.search(thread_references)
326 if ref_match:328 if ref_match:
327 thread_id = int(ref_match.group(1))329 thread_id = int(ref_match.group(1))
328 model = ref_match.group(2) or model330 model = ref_match.group(2) or model
@@ -333,6 +335,14 @@
333 message_id, model, thread_id, custom_values, uid)335 message_id, model, thread_id, custom_values, uid)
334 return [(model, thread_id, custom_values, uid)]336 return [(model, thread_id, custom_values, uid)]
335337
338 # Verify this is a reply to a private message
339 message_ids = self.pool.get('mail.message').search(cr, uid, [('message_id', '=', in_reply_to)], limit=1, context=context)
340 if message_ids:
341 message = self.pool.get('mail.message').browse(cr, uid, message_ids[0], context=context)
342 _logger.debug('Routing mail with Message-Id %s: direct reply to a private message: %s, custom_values: %s, uid: %s',
343 message_id, message.id, custom_values, uid)
344 return [(False, 0, custom_values, uid)]
345
336 # 2. Look for a matching mail.alias entry346 # 2. Look for a matching mail.alias entry
337 # Delivered-To is a safe bet in most modern MTAs, but we have to fallback on To + Cc values347 # Delivered-To is a safe bet in most modern MTAs, but we have to fallback on To + Cc values
338 # for all the odd MTAs out there, as there is no standard header for the envelope's `rcpt_to` value.348 # for all the odd MTAs out there, as there is no standard header for the envelope's `rcpt_to` value.
@@ -376,14 +386,19 @@
376 def message_process(self, cr, uid, model, message, custom_values=None,386 def message_process(self, cr, uid, model, message, custom_values=None,
377 save_original=False, strip_attachments=False,387 save_original=False, strip_attachments=False,
378 thread_id=None, context=None):388 thread_id=None, context=None):
379 """Process an incoming RFC2822 email message, relying on389 """ Process an incoming RFC2822 email message, relying on
380 ``mail.message.parse()`` for the parsing operation,390 ``mail.message.parse()`` for the parsing operation,
381 and ``message_route()`` to figure out the target model.391 and ``message_route()`` to figure out the target model.
382392
383 Once the target model is known, its ``message_new`` method393 Once the target model is known, its ``message_new`` method
384 is called with the new message (if the thread record did not exist)394 is called with the new message (if the thread record did not exist)
385 or its ``message_update`` method (if it did).395 or its ``message_update`` method (if it did).
386396
397 There is a special case where the target model is False: a reply
398 to a private message. In this case, we skip the message_new /
399 message_update step, to just post a new message using mail_thread
400 message_post.
401
387 :param string model: the fallback model to use if the message402 :param string model: the fallback model to use if the message
388 does not match any of the currently configured mail aliases403 does not match any of the currently configured mail aliases
389 (may be None if a matching alias is supposed to be present)404 (may be None if a matching alias is supposed to be present)
@@ -425,15 +440,19 @@
425 for model, thread_id, custom_values, user_id in routes:440 for model, thread_id, custom_values, user_id in routes:
426 if self._name != model:441 if self._name != model:
427 context.update({'thread_model': model})442 context.update({'thread_model': model})
428 model_pool = self.pool.get(model)443 if model:
429 assert thread_id and hasattr(model_pool, 'message_update') or hasattr(model_pool, 'message_new'), \444 model_pool = self.pool.get(model)
430 "Undeliverable mail with Message-Id %s, model %s does not accept incoming emails" % \445 assert thread_id and hasattr(model_pool, 'message_update') or hasattr(model_pool, 'message_new'), \
431 (msg['message_id'], model)446 "Undeliverable mail with Message-Id %s, model %s does not accept incoming emails" % \
432 if thread_id and hasattr(model_pool, 'message_update'):447 (msg['message_id'], model)
433 model_pool.message_update(cr, user_id, [thread_id], msg, context=context)448 if thread_id and hasattr(model_pool, 'message_update'):
449 model_pool.message_update(cr, user_id, [thread_id], msg, context=context)
450 else:
451 thread_id = model_pool.message_new(cr, user_id, msg, custom_values, context=context)
434 else:452 else:
435 thread_id = model_pool.message_new(cr, user_id, msg, custom_values, context=context)453 assert thread_id == 0, "Posting a message without model should be with a null res_id, to create a private message."
436 model_pool.message_post(cr, uid, [thread_id], context=context, **msg)454 model_pool = self.pool.get('mail.thread')
455 model_pool.message_post_user_api(cr, uid, [thread_id], context=context, content_subtype='html', **msg)
437 return thread_id456 return thread_id
438457
439 def message_new(self, cr, uid, msg_dict, custom_values=None, context=None):458 def message_new(self, cr, uid, msg_dict, custom_values=None, context=None):
@@ -501,7 +520,7 @@
501 body = tools.ustr(body, encoding, errors='replace')520 body = tools.ustr(body, encoding, errors='replace')
502 if message.get_content_type() == 'text/plain':521 if message.get_content_type() == 'text/plain':
503 # text/plain -> <pre/>522 # text/plain -> <pre/>
504 body = tools.append_content_to_html(u'', body)523 body = tools.append_content_to_html(u'', body, preserve=True)
505 else:524 else:
506 alternative = (message.get_content_type() == 'multipart/alternative')525 alternative = (message.get_content_type() == 'multipart/alternative')
507 for part in message.walk():526 for part in message.walk():
@@ -516,7 +535,7 @@
516 # 2) text/plain -> <pre/>535 # 2) text/plain -> <pre/>
517 if part.get_content_type() == 'text/plain' and (not alternative or not body):536 if part.get_content_type() == 'text/plain' and (not alternative or not body):
518 body = tools.append_content_to_html(body, tools.ustr(part.get_payload(decode=True),537 body = tools.append_content_to_html(body, tools.ustr(part.get_payload(decode=True),
519 encoding, errors='replace'))538 encoding, errors='replace'), preserve=True)
520 # 3) text/html -> raw539 # 3) text/html -> raw
521 elif part.get_content_type() == 'text/html':540 elif part.get_content_type() == 'text/html':
522 html = tools.ustr(part.get_payload(decode=True), encoding, errors='replace')541 html = tools.ustr(part.get_payload(decode=True), encoding, errors='replace')
@@ -556,7 +575,6 @@
556 """575 """
557 msg_dict = {576 msg_dict = {
558 'type': 'email',577 'type': 'email',
559 'subtype': 'mail.mt_comment',
560 'author_id': False,578 'author_id': False,
561 }579 }
562 if not isinstance(message, Message):580 if not isinstance(message, Message):
@@ -588,7 +606,7 @@
588 else:606 else:
589 msg_dict['email_from'] = message.get('from')607 msg_dict['email_from'] = message.get('from')
590 partner_ids = self._message_find_partners(cr, uid, message, ['From', 'To', 'Cc'], context=context)608 partner_ids = self._message_find_partners(cr, uid, message, ['From', 'To', 'Cc'], context=context)
591 msg_dict['partner_ids'] = partner_ids609 msg_dict['partner_ids'] = [(4, partner_id) for partner_id in partner_ids]
592610
593 if 'Date' in message:611 if 'Date' in message:
594 date_hdr = decode(message.get('Date'))612 date_hdr = decode(message.get('Date'))
@@ -629,7 +647,8 @@
629 mail.message ID. Extra keyword arguments will be used as default647 mail.message ID. Extra keyword arguments will be used as default
630 column values for the new mail.message record.648 column values for the new mail.message record.
631 Auto link messages for same id and object649 Auto link messages for same id and object
632 :param int thread_id: thread ID to post into, or list with one ID650 :param int thread_id: thread ID to post into, or list with one ID;
651 if False/0, mail.message model will also be set as False
633 :param str body: body of the message, usually raw HTML that will652 :param str body: body of the message, usually raw HTML that will
634 be sanitized653 be sanitized
635 :param str subject: optional subject654 :param str subject: optional subject
@@ -639,10 +658,13 @@
639 ``(name,content)``, where content is NOT base64 encoded658 ``(name,content)``, where content is NOT base64 encoded
640 :return: ID of newly created mail.message659 :return: ID of newly created mail.message
641 """660 """
642 context = context or {}661 if context is None:
643 attachments = attachments or []662 context = {}
663 if attachments is None:
664 attachments = {}
665
644 assert (not thread_id) or isinstance(thread_id, (int, long)) or \666 assert (not thread_id) or isinstance(thread_id, (int, long)) or \
645 (isinstance(thread_id, (list, tuple)) and len(thread_id) == 1), "Invalid thread_id"667 (isinstance(thread_id, (list, tuple)) and len(thread_id) == 1), "Invalid thread_id; should be 0, False, an ID or a list with one ID"
646 if isinstance(thread_id, (list, tuple)):668 if isinstance(thread_id, (list, tuple)):
647 thread_id = thread_id and thread_id[0]669 thread_id = thread_id and thread_id[0]
648 mail_message = self.pool.get('mail.message')670 mail_message = self.pool.get('mail.message')
@@ -682,7 +704,6 @@
682 # avoid loops when finding ancestors704 # avoid loops when finding ancestors
683 processed_list = []705 processed_list = []
684 if message_ids:706 if message_ids:
685 _counter, _counter_max = 0, 200
686 message = mail_message.browse(cr, SUPERUSER_ID, message_ids[0], context=context)707 message = mail_message.browse(cr, SUPERUSER_ID, message_ids[0], context=context)
687 while (message.parent_id and message.parent_id.id not in processed_list):708 while (message.parent_id and message.parent_id.id not in processed_list):
688 processed_list.append(message.parent_id.id)709 processed_list.append(message.parent_id.id)
@@ -707,18 +728,45 @@
707728
708 return mail_message.create(cr, uid, values, context=context)729 return mail_message.create(cr, uid, values, context=context)
709730
710 def message_post_api(self, cr, uid, thread_id, body='', subject=False, parent_id=False, attachment_ids=None, context=None):731 def message_post_user_api(self, cr, uid, thread_id, body='', subject=False, parent_id=False,
711 """ Wrapper on message_post, used only in Chatter (JS). The purpose is732 attachment_ids=None, context=None, content_subtype='plaintext', **kwargs):
712 to handle attachments.733 """ Wrapper on message_post, used for user input :
713 # TDE FIXME: body is plaintext: convert it into html734 - mail gateway
735 - quick reply in Chatter (refer to mail.js), not
736 the mail.compose.message wizard
737 The purpose is to perform some pre- and post-processing:
738 - if body is plaintext: convert it into html
739 - if parent_id: handle reply to a previous message by adding the
740 parent partners to the message
741 - type and subtype: comment and mail.mt_comment by default
742 - attachment_ids: supposed not attached to any document; attach them
743 to the related document. Should only be set by Chatter.
714 """744 """
715 new_message_id = self.message_post(cr, uid, thread_id=thread_id, body=body, subject=subject, type='comment',745 ir_attachment = self.pool.get('ir.attachment')
716 subtype='mail.mt_comment', parent_id=parent_id, context=context)746 mail_message = self.pool.get('mail.message')
717747
718 # HACK FIXME: Chatter: attachments linked to the document (not done JS-side), load the message748 # 1. Pre-processing: body, partner_ids, type and subtype
749 if content_subtype == 'plaintext':
750 body = tools.text2html(body)
751
752 partner_ids = kwargs.pop('partner_ids', [])
753 if parent_id:
754 parent_message = self.pool.get('mail.message').browse(cr, uid, parent_id, context=context)
755 partner_ids += [(4, partner.id) for partner in parent_message.partner_ids]
756 # TDE FIXME HACK: mail.thread -> private message
757 if self._name == 'mail.thread' and parent_message.author_id.id:
758 partner_ids.append((4, parent_message.author_id.id))
759
760 message_type = kwargs.pop('type', 'comment')
761 message_subtype = kwargs.pop('subtype', 'mail.mt_comment')
762
763 # 2. Post message
764 new_message_id = self.message_post(cr, uid, thread_id=thread_id, body=body, subject=subject, type=message_type,
765 subtype=message_subtype, parent_id=parent_id, context=context, partner_ids=partner_ids, **kwargs)
766
767 # 3. Post-processing
768 # HACK TDE FIXME: Chatter: attachments linked to the document (not done JS-side), load the message
719 if attachment_ids:769 if attachment_ids:
720 ir_attachment = self.pool.get('ir.attachment')
721 mail_message = self.pool.get('mail.message')
722 filtered_attachment_ids = ir_attachment.search(cr, SUPERUSER_ID, [770 filtered_attachment_ids = ir_attachment.search(cr, SUPERUSER_ID, [
723 ('res_model', '=', 'mail.compose.message'),771 ('res_model', '=', 'mail.compose.message'),
724 ('res_id', '=', 0),772 ('res_id', '=', 0),
725773
=== modified file 'mail/res_partner.py'
--- mail/res_partner.py 2012-10-15 13:23:13 +0000
+++ mail/res_partner.py 2012-11-14 14:39:22 +0000
@@ -42,4 +42,22 @@
42 'notification_email_send': lambda *args: 'comment'42 'notification_email_send': lambda *args: 'comment'
43 }43 }
4444
45 def message_post(self, cr, uid, thread_id, body='', subject=None, type='notification',
46 subtype=None, parent_id=False, attachments=None, context=None, **kwargs):
47 """ Override related to res.partner. In case of email message, set it as
48 private:
49 - add the target partner in the message partner_ids
50 - set thread_id as None, because this will trigger the 'private'
51 aspect of the message (model=False, res_id=False)
52 """
53 if isinstance(thread_id, (list, tuple)):
54 thread_id = thread_id[0]
55 if type == 'email':
56 partner_ids = kwargs.get('partner_ids', [])
57 if thread_id not in partner_ids:
58 partner_ids.append(thread_id)
59 kwargs['partner_ids'] = partner_ids
60 return super(res_partner_mail, self).message_post(cr, uid, False, body=body, subject=subject,
61 type=type, subtype=subtype, parent_id=parent_id, attachments=attachments, context=context, **kwargs)
62
45# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:63# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
4664
=== modified file 'mail/security/ir.model.access.csv'
--- mail/security/ir.model.access.csv 2012-11-06 15:04:31 +0000
+++ mail/security/ir.model.access.csv 2012-11-14 14:39:22 +0000
@@ -7,12 +7,13 @@
7access_mail_followers_all,mail.followers.all,model_mail_followers,,1,0,0,07access_mail_followers_all,mail.followers.all,model_mail_followers,,1,0,0,0
8access_mail_followers_system,mail.followers.system,model_mail_followers,base.group_system,1,1,1,18access_mail_followers_system,mail.followers.system,model_mail_followers,base.group_system,1,1,1,1
9access_mail_notification_all,mail.notification.all,model_mail_notification,,1,0,0,09access_mail_notification_all,mail.notification.all,model_mail_notification,,1,0,0,0
10access_mail_notification_aystem,mail.notification.system,model_mail_notification,base.group_system,1,1,1,110access_mail_notification_group_user,mail.notification.user,model_mail_notification,base.group_user,1,1,1,0
11access_mail_notification_system,mail.notification.system,model_mail_notification,base.group_system,1,1,1,1
11access_mail_group_all,mail.group.all,model_mail_group,,1,0,0,012access_mail_group_all,mail.group.all,model_mail_group,,1,0,0,0
12access_mail_group_user,mail.group.user,model_mail_group,base.group_user,1,1,1,113access_mail_group_user,mail.group.user,model_mail_group,base.group_user,1,1,1,1
13access_mail_alias_all,mail.alias.all,model_mail_alias,,1,0,0,014access_mail_alias_all,mail.alias.all,model_mail_alias,,1,0,0,0
14access_mail_alias_user,mail.alias,model_mail_alias,base.group_user,1,1,1,015access_mail_alias_user,mail.alias.user,model_mail_alias,base.group_user,1,1,1,0
15access_mail_alias_system,mail.alias,model_mail_alias,base.group_system,1,1,1,116access_mail_alias_system,mail.alias.system,model_mail_alias,base.group_system,1,1,1,1
16access_mail_message_subtype_all,mail.message.subtype.all,model_mail_message_subtype,,1,0,0,017access_mail_message_subtype_all,mail.message.subtype.all,model_mail_message_subtype,,1,0,0,0
17access_mail_vote_all,mail.vote.all,model_mail_vote,,1,1,1,118access_mail_vote_all,mail.vote.all,model_mail_vote,,1,1,1,1
18access_mail_favorite_all,mail.favorite.all,model_mail_favorite,,1,1,1,119access_mail_favorite_all,mail.favorite.all,model_mail_favorite,,1,1,1,1
1920
=== modified file 'mail/security/mail_security.xml'
--- mail/security/mail_security.xml 2012-10-19 09:59:19 +0000
+++ mail/security/mail_security.xml 2012-11-14 14:39:22 +0000
@@ -10,7 +10,7 @@
10 <field name="domain_force">['|', '|', ('public', '=', 'public'), ('message_follower_ids', 'in', [user.partner_id.id]), '&amp;', ('public','=','groups'), ('group_public_id','in', [g.id for g in user.groups_id])]</field>10 <field name="domain_force">['|', '|', ('public', '=', 'public'), ('message_follower_ids', 'in', [user.partner_id.id]), '&amp;', ('public','=','groups'), ('group_public_id','in', [g.id for g in user.groups_id])]</field>
11 </record>11 </record>
1212
13 <record id="mail_followers_read_own" model="ir.rule">13 <record id="mail_followers_read_write_own" model="ir.rule">
14 <field name="name">mail.followers: read and write its own entries</field>14 <field name="name">mail.followers: read and write its own entries</field>
15 <field name="model_id" ref="model_mail_followers"/>15 <field name="model_id" ref="model_mail_followers"/>
16 <field name="domain_force">[('partner_id', '=', user.partner_id.id)]</field>16 <field name="domain_force">[('partner_id', '=', user.partner_id.id)]</field>
@@ -18,6 +18,14 @@
18 <field name="perm_unlink" eval="False"/>18 <field name="perm_unlink" eval="False"/>
19 </record>19 </record>
2020
21 <record id="mail_notification_read_write_own" model="ir.rule">
22 <field name="name">mail.notification: read and write its own entries</field>
23 <field name="model_id" ref="model_mail_notification"/>
24 <field name="domain_force">[('partner_id', '=', user.partner_id.id)]</field>
25 <field name="perm_create" eval="False"/>
26 <field name="perm_unlink" eval="False"/>
27 </record>
28
21 <!--29 <!--
22 This rule can not be uncommented, because we have a more wide method in mail.message. When we implement a many2one_variable field, we will be able to uncomment this.30 This rule can not be uncommented, because we have a more wide method in mail.message. When we implement a many2one_variable field, we will be able to uncomment this.
23 <record id="mail_message_read_partner_or_author" model="ir.rule">31 <record id="mail_message_read_partner_or_author" model="ir.rule">
2432
=== modified file 'mail/static/src/css/mail.css'
--- mail/static/src/css/mail.css 2012-11-13 10:35:30 +0000
+++ mail/static/src/css/mail.css 2012-11-14 14:39:22 +0000
@@ -87,6 +87,10 @@
87 margin-bottom: 0px;87 margin-bottom: 0px;
88 margin-top: 2px;88 margin-top: 2px;
89}89}
90.openerp .oe_mail .oe_msg .oe_msg_content .oe_msg_body p{
91 margin-top: 0px;
92 margin-bottom: 0px;
93}
9094
91/* a) Indented Messages */95/* a) Indented Messages */
9296
9397
=== modified file 'mail/static/src/js/mail.js'
--- mail/static/src/js/mail.js 2012-11-13 14:57:22 +0000
+++ mail/static/src/js/mail.js 2012-11-14 14:39:22 +0000
@@ -590,7 +590,7 @@
590590
591 if (body.match(/\S+/)) {591 if (body.match(/\S+/)) {
592 //session.web.blockUI();592 //session.web.blockUI();
593 this.parent_thread.ds_thread.call('message_post_api', [593 this.parent_thread.ds_thread.call('message_post_user_api', [
594 this.context.default_res_id, 594 this.context.default_res_id,
595 mail.ChatterUtils.get_text2html(body), 595 mail.ChatterUtils.get_text2html(body),
596 false, 596 false,
@@ -728,7 +728,6 @@
728728
729 mail.ThreadMessage = mail.MessageCommon.extend({729 mail.ThreadMessage = mail.MessageCommon.extend({
730 template: 'mail.thread.message',730 template: 'mail.thread.message',
731
732 731
733 start: function () {732 start: function () {
734 this._super.apply(this, arguments);733 this._super.apply(this, arguments);
735734
=== modified file 'mail/tests/__init__.py'
--- mail/tests/__init__.py 2012-09-14 11:58:15 +0000
+++ mail/tests/__init__.py 2012-11-14 14:39:22 +0000
@@ -18,6 +18,7 @@
18# along with this program. If not, see <http://www.gnu.org/licenses/>.18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19#19#
20##############################################################################20##############################################################################
21
21from . import test_mail, test_mail_access_rights22from . import test_mail, test_mail_access_rights
2223
23checks = [24checks = [
2425
=== modified file 'mail/tests/test_mail.py'
--- mail/tests/test_mail.py 2012-11-09 15:11:22 +0000
+++ mail/tests/test_mail.py 2012-11-14 14:39:22 +0000
@@ -21,8 +21,8 @@
2121
22import tools22import tools
2323
24from openerp.tests import common24from openerp.addons.mail.tests import test_mail_mockup
25from openerp.tools.html_sanitize import html_sanitize25from openerp.tools.mail import html_sanitize
2626
27MAIL_TEMPLATE = """Return-Path: <whatever-2a840@postmaster.twitter.com>27MAIL_TEMPLATE = """Return-Path: <whatever-2a840@postmaster.twitter.com>
28To: {to}28To: {to}
@@ -84,43 +84,11 @@
84"""84"""
8585
8686
87class TestMailMockups(common.TransactionCase):87class test_mail(test_mail_mockup.TestMailMockups):
88
89 def _mock_smtp_gateway(self, *args, **kwargs):
90 return True
91
92 def _init_mock_build_email(self):
93 self._build_email_args_list = []
94 self._build_email_kwargs_list = []
95
96 def _mock_build_email(self, *args, **kwargs):
97 """ Mock build_email to be able to test its values. Store them into
98 some internal variable for latter processing. """
99 self._build_email_args_list.append(args)
100 self._build_email_kwargs_list.append(kwargs)
101 return self._build_email(*args, **kwargs)
102
103 def setUp(self):
104 super(TestMailMockups, self).setUp()
105 # Install mock SMTP gateway
106 self._init_mock_build_email()
107 self._build_email = self.registry('ir.mail_server').build_email
108 self.registry('ir.mail_server').build_email = self._mock_build_email
109 self._send_email = self.registry('ir.mail_server').send_email
110 self.registry('ir.mail_server').send_email = self._mock_smtp_gateway
111
112 def tearDown(self):
113 # Remove mocks
114 self.registry('ir.mail_server').build_email = self._build_email
115 self.registry('ir.mail_server').send_email = self._send_email
116 super(TestMailMockups, self).tearDown()
117
118
119class test_mail(TestMailMockups):
12088
121 def _mock_send_get_mail_body(self, *args, **kwargs):89 def _mock_send_get_mail_body(self, *args, **kwargs):
122 # def _send_get_mail_body(self, cr, uid, mail, partner=None, context=None)90 # def _send_get_mail_body(self, cr, uid, mail, partner=None, context=None)
123 body = tools.append_content_to_html(args[2].body_html, kwargs.get('partner').name if kwargs.get('partner') else 'No specific partner')91 body = tools.append_content_to_html(args[2].body_html, kwargs.get('partner').name if kwargs.get('partner') else 'No specific partner', plaintext=False)
124 return body92 return body
12593
126 def setUp(self):94 def setUp(self):
@@ -375,10 +343,10 @@
375 _subject = 'Pigs'343 _subject = 'Pigs'
376 _mail_subject = '%s posted on %s' % (user_admin.name, group_pigs.name)344 _mail_subject = '%s posted on %s' % (user_admin.name, group_pigs.name)
377 _body1 = 'Pigs rules'345 _body1 = 'Pigs rules'
378 _mail_body1 = 'Pigs rules\n<pre>Admin</pre>\n'346 _mail_body1 = 'Pigs rules\n<div><p>Admin</p></div>\n'
379 _mail_bodyalt1 = 'Pigs rules\nAdmin'347 _mail_bodyalt1 = 'Pigs rules\nAdmin\n'
380 _body2 = '<html>Pigs rules</html>'348 _body2 = '<html>Pigs rules</html>'
381 _mail_body2 = html_sanitize('<html>Pigs rules\n<pre>Admin</pre>\n</html>')349 _mail_body2 = html_sanitize('<html>Pigs rules\n<div><p>Admin</p></div>\n</html>')
382 _mail_bodyalt2 = 'Pigs rules\nAdmin'350 _mail_bodyalt2 = 'Pigs rules\nAdmin'
383 _attachments = [('First', 'My first attachment'), ('Second', 'My second attachment')]351 _attachments = [('First', 'My first attachment'), ('Second', 'My second attachment')]
384352
@@ -399,7 +367,7 @@
399 # Test: sent_email: email send by server: correct subject, body, body_alternative367 # Test: sent_email: email send by server: correct subject, body, body_alternative
400 for sent_email in sent_emails:368 for sent_email in sent_emails:
401 self.assertEqual(sent_email['subject'], _subject, 'sent_email subject incorrect')369 self.assertEqual(sent_email['subject'], _subject, 'sent_email subject incorrect')
402 self.assertEqual(sent_email['body'], _mail_body1 + '\n<pre>Bert Tartopoils</pre>\n', 'sent_email body incorrect')370 self.assertEqual(sent_email['body'], _mail_body1 + '\nBert Tartopoils\n', 'sent_email body incorrect')
403 # the html2plaintext uses etree or beautiful soup, so the result may be slighly different371 # the html2plaintext uses etree or beautiful soup, so the result may be slighly different
404 # depending if you have installed beautiful soup.372 # depending if you have installed beautiful soup.
405 self.assertIn(sent_email['body_alternative'], _mail_bodyalt1 + '\nBert Tartopoils\n', 'sent_email body_alternative is incorrect')373 self.assertIn(sent_email['body_alternative'], _mail_bodyalt1 + '\nBert Tartopoils\n', 'sent_email body_alternative is incorrect')
406374
=== modified file 'mail/tests/test_mail_access_rights.py'
--- mail/tests/test_mail_access_rights.py 2012-10-25 11:30:48 +0000
+++ mail/tests/test_mail_access_rights.py 2012-11-14 14:39:22 +0000
@@ -19,11 +19,11 @@
19#19#
20##############################################################################20##############################################################################
2121
22from openerp.addons.mail.tests import test_mail22from openerp.addons.mail.tests import test_mail_mockup
23from osv.orm import except_orm23from osv.orm import except_orm
2424
2525
26class test_mail_access_rights(test_mail.TestMailMockups):26class test_mail_access_rights(test_mail_mockup.TestMailMockups):
2727
28 def setUp(self):28 def setUp(self):
29 super(test_mail_access_rights, self).setUp()29 super(test_mail_access_rights, self).setUp()
3030
=== added file 'mail/tests/test_mail_mockup.py'
--- mail/tests/test_mail_mockup.py 1970-01-01 00:00:00 +0000
+++ mail/tests/test_mail_mockup.py 2012-11-14 14:39:22 +0000
@@ -0,0 +1,54 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# OpenERP, Open Source Business Applications
5# Copyright (c) 2012-TODAY OpenERP S.A. <http://openerp.com>
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU Affero General Public License as
9# published by the Free Software Foundation, either version 3 of the
10# License, or (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU Affero General Public License for more details.
16#
17# You should have received a copy of the GNU Affero General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19#
20##############################################################################
21
22from openerp.tests import common
23
24
25class TestMailMockups(common.TransactionCase):
26
27 def _mock_smtp_gateway(self, *args, **kwargs):
28 return True
29
30 def _init_mock_build_email(self):
31 self._build_email_args_list = []
32 self._build_email_kwargs_list = []
33
34 def _mock_build_email(self, *args, **kwargs):
35 """ Mock build_email to be able to test its values. Store them into
36 some internal variable for latter processing. """
37 self._build_email_args_list.append(args)
38 self._build_email_kwargs_list.append(kwargs)
39 return self._build_email(*args, **kwargs)
40
41 def setUp(self):
42 super(TestMailMockups, self).setUp()
43 # Install mock SMTP gateway
44 self._init_mock_build_email()
45 self._build_email = self.registry('ir.mail_server').build_email
46 self.registry('ir.mail_server').build_email = self._mock_build_email
47 self._send_email = self.registry('ir.mail_server').send_email
48 self.registry('ir.mail_server').send_email = self._mock_smtp_gateway
49
50 def tearDown(self):
51 # Remove mocks
52 self.registry('ir.mail_server').build_email = self._build_email
53 self.registry('ir.mail_server').send_email = self._send_email
54 super(TestMailMockups, self).tearDown()
055
=== modified file 'mrp/mrp_data.xml'
--- mrp/mrp_data.xml 2012-10-02 20:40:23 +0000
+++ mrp/mrp_data.xml 2012-11-14 14:39:22 +0000
@@ -6,11 +6,11 @@
6 <field name="model">mail.group</field>6 <field name="model">mail.group</field>
7 <field name="res_id" ref="mail.group_all_employees"/>7 <field name="res_id" ref="mail.group_all_employees"/>
8 <field name="type">notification</field>8 <field name="type">notification</field>
9 <field name="subtype_id" ref="mail.mt_comment"/>
9 <field name="subject">MRP application installed!</field>10 <field name="subject">MRP application installed!</field>
10 <field name="body">Manage your manufacturing process with OpenERP by defining your bills of materials (BoM), routings and work centers.11 <field name="body"><![CDATA[<p>Manage your manufacturing process with OpenERP by defining your bills of materials (BoM), routings and work centers.<br />
11This application supports complete integration and production scheduling for stockable goods, consumables, and services.12This application supports complete integration and production scheduling for stockable goods, consumables, and services.</p>
1213<p>From the Manufacturing Settings, you can choose to compute production schedules periodically or just-in-time.</p>]]></field>
13From the Manufacturing Settings, you can choose to compute production schedules periodically or just-in-time.</field>
14 </record>14 </record>
15 15
16 <record id="sequence_mrp_prod_type" model="ir.sequence.type">16 <record id="sequence_mrp_prod_type" model="ir.sequence.type">
1717
=== modified file 'note/note.py'
--- note/note.py 2012-11-02 13:17:59 +0000
+++ note/note.py 2012-11-14 14:39:22 +0000
@@ -20,9 +20,7 @@
20##############################################################################20##############################################################################
2121
22from openerp.osv import osv, fields22from openerp.osv import osv, fields
23from tools.translate import _23from openerp.tools import html2plaintext
24import re
25from openerp.tools.misc import html2plaintext
2624
27class note_stage(osv.osv):25class note_stage(osv.osv):
28 """ Category of Note """26 """ Category of Note """
2927
=== modified file 'pad/pad.py'
--- pad/pad.py 2012-11-09 06:30:02 +0000
+++ pad/pad.py 2012-11-14 14:39:22 +0000
@@ -6,7 +6,7 @@
6import urllib26import urllib2
7import logging7import logging
8from tools.translate import _8from tools.translate import _
9from openerp.tools.misc import html2plaintext9from openerp.tools import html2plaintext
10from py_etherpad import EtherpadLiteClient10from py_etherpad import EtherpadLiteClient
1111
12_logger = logging.getLogger(__name__)12_logger = logging.getLogger(__name__)
1313
=== modified file 'point_of_sale/point_of_sale_data.xml'
--- point_of_sale/point_of_sale_data.xml 2012-09-16 11:42:49 +0000
+++ point_of_sale/point_of_sale_data.xml 2012-11-14 14:39:22 +0000
@@ -20,10 +20,10 @@
20 <field name="model">mail.group</field>20 <field name="model">mail.group</field>
21 <field name="res_id" ref="mail.group_all_employees"/>21 <field name="res_id" ref="mail.group_all_employees"/>
22 <field name="type">notification</field>22 <field name="type">notification</field>
23 <field name="subtype_id" ref="mail.mt_comment"/>
23 <field name="subject">Point of Sale application installed!</field>24 <field name="subject">Point of Sale application installed!</field>
24 <field name="body">Record sale orders, register payments, compute change to return, create invoices, and manage refunds through a specific web touch-screen interface.25 <field name="body"><![CDATA[<p>Record sale orders, register payments, compute change to return, create invoices, and manage refunds through a specific web touch-screen interface.</p>
2526<p>If you install the PoS proxy you will be able to interface OpenERP with retail hardware: barcode scanners, printers, cash registers, weighing machines, credit card payment terminals.</p>]]></field>
26If you install the PoS proxy you will be able to interface OpenERP with retail hardware: barcode scanners, printers, cash registers, weighing machines, credit card payment terminals.</field>
27 </record>27 </record>
2828
29 <record id="unreferenced_product" model="product.product">29 <record id="unreferenced_product" model="product.product">
3030
=== modified file 'portal/mail_mail.py'
--- portal/mail_mail.py 2012-10-01 09:14:41 +0000
+++ portal/mail_mail.py 2012-11-14 14:39:22 +0000
@@ -36,5 +36,5 @@
36 if partner:36 if partner:
37 context = dict(context or {}, signup_valid=True)37 context = dict(context or {}, signup_valid=True)
38 partner = self.pool.get('res.partner').browse(cr, uid, partner.id, context)38 partner = self.pool.get('res.partner').browse(cr, uid, partner.id, context)
39 body = tools.append_content_to_html(body, "Log in our portal at: %s" % partner.signup_url)39 body = tools.append_content_to_html(body, ("<div><p>Log in our portal at: %s</p></div>" % partner.signup_url), plaintext=False)
40 return body40 return body
4141
=== modified file 'portal/portal_demo.xml'
--- portal/portal_demo.xml 2012-09-20 14:57:53 +0000
+++ portal/portal_demo.xml 2012-11-14 14:39:22 +0000
@@ -1,17 +1,22 @@
1<?xml version="1.0"?>1<?xml version="1.0"?>
2<openerp>2<openerp>
3 <data>3 <data noupdate="1">
44
5 <!-- Create a portal member attached to a partner -->5 <!-- Create a partner, that is also a portal user -->
6 <record id="partner_demo_portal" model="res.partner">
7 <field name="name">Demo Portal User</field>
8 <field name="email">demo@portal.example.com</field>
9 <field name="supplier" eval="False"/>
10 <field name="customer" eval="True"/>
11 </record>
6 <record id="demo_user0" model="res.users">12 <record id="demo_user0" model="res.users">
7 <field name="name">Demo Portal User</field>13 <field name="partner_id" ref="partner_demo_portal"/>
8 <field name="login">portal</field>14 <field name="login">portal</field>
9 <field name="password">portal</field>15 <field name="password">portal</field>
16 <field name="signature">--
17Mr Demo Portal</field>
10 <!-- Avoid auto-including this user in any default group -->18 <!-- Avoid auto-including this user in any default group -->
11 <field name="groups_id" eval="[(5,)]"/>19 <field name="groups_id" eval="[(5,)]"/>
12 <field name="supplier" eval="False"/>
13 <field name="customer" eval="True"/>
14 <field name="email">demo@portal.wrong.address</field>
15 </record>20 </record>
1621
17 <!-- Add the demo user to the portal (and therefore to the portal member group) -->22 <!-- Add the demo user to the portal (and therefore to the portal member group) -->
@@ -24,33 +29,41 @@
24 <field name="subject">Our company's first blog-post !</field>29 <field name="subject">Our company's first blog-post !</field>
25 <field name="model">mail.group</field>30 <field name="model">mail.group</field>
26 <field name="res_id" ref="company_news_feed"/>31 <field name="res_id" ref="company_news_feed"/>
27 <field name="body"><![CDATA[Hello, and welcome to our company's portal !32 <field name="body"><![CDATA[<p>Hello, and welcome to our company's portal !</p>
2833<p>It is a great pleasure to announce you the creation of our portal by writing this first news! As you may have seen, a new discussion group is now present under your 'My groups' menu: <b>Company's News</b>. We will post news about the company and its employees in this discussion group. Moreover, we will be able to communicate with our partners that are given the opportunity to join us in our portal.</p>
29Lorem ipsum <b>sit amet</b>, consectetur <em>adipiscing elit</em>. Pellentesque et quam sapien, in sagittis tellus.34<p>A new era of communication has begun! <b>Feel free to post your feelings about our portal by replying on this message!</b></p>]]></field>
30Praesent vel massa sed massa consequat egestas in tristique orci. Praesent iaculis libero et neque vehicula iaculis. Vivamus placerat tincidunt orci ac ornare. Proin ut dolor fringilla velit ultricies consequat. Maecenas sit amet ipsum non leo interdum imperdiet. Donec sapien mi.
31
32Fusce tempus elit volutpat mi auctor adipiscing. Nam congue luctus suscipit. Sed tellus libero, venenatis ut mollis ut, luctus quis dui. Sed rhoncus pulvinar orci in consectetur.
33
34Nulla turpis leo, rhoncus ut egestas sit amet, consectetur vitae urna. Mauris in dolor in sapien tempus vehicula.]]></field>
35 <field name="type">comment</field>35 <field name="type">comment</field>
36 <field name="subtype_id" ref="mail.mt_comment"/>
36 <field name="author_id" ref="base.partner_root"/>37 <field name="author_id" ref="base.partner_root"/>
37 </record>38 </record>
3839
39 <record id="message_company_news0_comment0" model="mail.message">40 <record id="message_company_news0_comment0" model="mail.message">
40 <field name="model">mail.group</field>41 <field name="model">mail.group</field>
41 <field name="res_id" ref="company_news_feed"/>42 <field name="res_id" ref="company_news_feed"/>
42 <field name="body"><![CDATA[Great first blogpost ! (first comment)]]></field>43 <field name="body"><![CDATA[<p>As your first portal member, I am very pleased to be able to be able to communicate directly with you. Be sure I'll read all news carefully!</p>]]></field>
43 <field name="parent_id" ref="message_company_news0"/>44 <field name="parent_id" ref="message_company_news0"/>
44 <field name="type">comment</field>45 <field name="type">comment</field>
46 <field name="subtype_id" ref="mail.mt_comment"/>
47 <field name="author_id" ref="partner_demo_portal"/>
48 </record>
49
50 <record id="message_company_news0_comment1" model="mail.message">
51 <field name="model">mail.group</field>
52 <field name="res_id" ref="company_news_feed"/>
53 <field name="body"><![CDATA[<p>That's good news! As said by <i>Demo Portal User</i> in the previous post, I'm looking forward to hearing from you!</p>]]></field>
54 <field name="parent_id" ref="message_company_news0"/>
55 <field name="type">comment</field>
56 <field name="subtype_id" ref="mail.mt_comment"/>
45 <field name="author_id" ref="base.res_partner_1"/>57 <field name="author_id" ref="base.res_partner_1"/>
46 </record>58 </record>
4759
48 <record id="message_company_news0_comment1" model="mail.message">60 <record id="message_company_news0_comment2" model="mail.message">
49 <field name="model">mail.group</field>61 <field name="model">mail.group</field>
50 <field name="res_id" ref="company_news_feed"/>62 <field name="res_id" ref="company_news_feed"/>
51 <field name="body"><![CDATA[Thanks ! (second comment)]]></field>63 <field name="body"><![CDATA[<p>This feature is realy great! We will be able to communicate directly to our partners!</p>]]></field>
52 <field name="parent_id" ref="message_company_news0"/>64 <field name="parent_id" ref="message_company_news0"/>
53 <field name="type">comment</field>65 <field name="type">comment</field>
66 <field name="subtype_id" ref="mail.mt_comment"/>
54 <field name="author_id" ref="base.partner_demo"/>67 <field name="author_id" ref="base.partner_demo"/>
55 </record>68 </record>
5669
5770
=== modified file 'portal/tests/test_portal.py'
--- portal/tests/test_portal.py 2012-10-09 15:54:56 +0000
+++ portal/tests/test_portal.py 2012-11-14 14:39:22 +0000
@@ -19,12 +19,11 @@
19#19#
20##############################################################################20##############################################################################
2121
22from openerp.addons.mail.tests import test_mail22from openerp.addons.mail.tests import test_mail_mockup
23from openerp.tools import append_content_to_html
24from osv.orm import except_orm23from osv.orm import except_orm
2524
2625
27class test_portal(test_mail.TestMailMockups):26class test_portal(test_mail_mockup.TestMailMockups):
2827
29 def setUp(self):28 def setUp(self):
30 super(test_portal, self).setUp()29 super(test_portal, self).setUp()
3130
=== modified file 'portal/wizard/portal_wizard.py'
--- portal/wizard/portal_wizard.py 2012-10-25 13:09:30 +0000
+++ portal/wizard/portal_wizard.py 2012-11-14 14:39:22 +0000
@@ -24,10 +24,9 @@
2424
25from osv import osv, fields25from osv import osv, fields
26from tools.translate import _26from tools.translate import _
27from tools.misc import email_re27from tools import email_re
28from openerp import SUPERUSER_ID28from openerp import SUPERUSER_ID
2929
30from base.res.res_partner import _lang_get
31_logger = logging.getLogger(__name__)30_logger = logging.getLogger(__name__)
3231
33# welcome email sent to portal users32# welcome email sent to portal users
3433
=== modified file 'project/project_data.xml'
--- project/project_data.xml 2012-11-02 15:41:54 +0000
+++ project/project_data.xml 2012-11-14 14:39:22 +0000
@@ -125,11 +125,11 @@
125 <field name="model">mail.group</field>125 <field name="model">mail.group</field>
126 <field name="res_id" ref="mail.group_all_employees"/>126 <field name="res_id" ref="mail.group_all_employees"/>
127 <field name="type">notification</field>127 <field name="type">notification</field>
128 <field name="subtype_id" ref="mail.mt_comment"/>
128 <field name="subject">Project Management application installed!</field>129 <field name="subject">Project Management application installed!</field>
129 <field name="body">Manage multi-level projects and tasks. You can delegate tasks, track task work, and review your planning.130 <field name="body"><![CDATA[<p>Manage multi-level projects and tasks. You can delegate tasks, track task work, and review your planning.</p>
130131<p>You can manage todo lists on tasks by installing the "Todo Lists" application, supporting the Getting Things Done (GTD) methodology.</p>
131You can manage todo lists on tasks by installing the "Todo Lists" application, supporting the Getting Things Done (GTD) methodology.132<p>You can also manage issues/bugs in projects by installing the "Issue Tracker" application.</p>]]></field>
132You can also manage issues/bugs in projects by installing the "Issue Tracker" application.</field>
133 </record>133 </record>
134 </data>134 </data>
135</openerp>135</openerp>
136136
=== modified file 'project_gtd/project_gtd_data.xml'
--- project_gtd/project_gtd_data.xml 2012-08-30 14:18:52 +0000
+++ project_gtd/project_gtd_data.xml 2012-11-14 14:39:22 +0000
@@ -30,9 +30,10 @@
30 <field name="model">mail.group</field>30 <field name="model">mail.group</field>
31 <field name="res_id" ref="mail.group_all_employees"/>31 <field name="res_id" ref="mail.group_all_employees"/>
32 <field name="type">notification</field>32 <field name="type">notification</field>
33 <field name="subtype_id" ref="mail.mt_comment"/>
33 <field name="subject">Todo Lists application installed!</field>34 <field name="subject">Todo Lists application installed!</field>
34 <field name="body">Add todo items on project tasks, to help you organize your work.35 <field name="body"><![CDATA[<p>Add todo items on project tasks, to help you organize your work.
35This application supports the Getting Things Done (GTD) methodology, based on David Allen's book.</field>36This application supports the Getting Things Done (GTD) methodology, based on David Allen's book.</p>]]></field>
36 </record>37 </record>
3738
38 </data>39 </data>
3940
=== modified file 'project_issue/project_issue_data.xml'
--- project_issue/project_issue_data.xml 2012-11-02 15:41:54 +0000
+++ project_issue/project_issue_data.xml 2012-11-14 14:39:22 +0000
@@ -36,10 +36,11 @@
36 <field name="model">mail.group</field>36 <field name="model">mail.group</field>
37 <field name="res_id" ref="mail.group_all_employees"/>37 <field name="res_id" ref="mail.group_all_employees"/>
38 <field name="type">notification</field>38 <field name="type">notification</field>
39 <field name="subtype_id" ref="mail.mt_comment"/>
39 <field name="subject">Issue Tracker application installed!</field>40 <field name="subject">Issue Tracker application installed!</field>
40 <field name="body">Manage the issues you might face in a project, such as bugs in a system, client complaints or material breakdowns.41 <field name="body"><![CDATA[<p>Manage the issues you might face in a project, such as bugs in a system, client complaints or material breakdowns.
41You can record issues, assign them to a responsible person, and keep track of their status as they evolve over time.42You can record issues, assign them to a responsible person, and keep track of their status as they evolve over time.
42Access all issues from the top Project menu, and access the issues of a specific project via the projects gallery view.</field>43Access all issues from the top Project menu, and access the issues of a specific project via the projects gallery view.</p>]]></field>
43 </record>44 </record>
4445
45 <!-- Mail subtypes -->46 <!-- Mail subtypes -->
4647
=== modified file 'purchase/purchase_data.xml'
--- purchase/purchase_data.xml 2012-10-02 20:40:23 +0000
+++ purchase/purchase_data.xml 2012-11-14 14:39:22 +0000
@@ -7,10 +7,10 @@
7 <field name="model">mail.group</field>7 <field name="model">mail.group</field>
8 <field name="res_id" ref="mail.group_all_employees"/>8 <field name="res_id" ref="mail.group_all_employees"/>
9 <field name="type">notification</field>9 <field name="type">notification</field>
10 <field name="subtype_id" ref="mail.mt_comment"/>
10 <field name="subject">Purchase Management application installed!</field>11 <field name="subject">Purchase Management application installed!</field>
11 <field name="body">From the top menu Purchases, create purchase orders to buy products from your suppliers, enter supplier invoices and manage payments.12 <field name="body"><![CDATA[<p>From the top menu Purchases, create purchase orders to buy products from your suppliers, enter supplier invoices and manage payments.</p>
1213<p>You can also manage purchase requisitions, see also the Purchase Settings.</p>]]></field>
13You can also manage purchase requisitions, see also the Purchase Settings.</field>
14 </record>14 </record>
1515
16 <record id="req_link_purchase_order" model="res.request.link">16 <record id="req_link_purchase_order" model="res.request.link">
1717
=== modified file 'sale/sale_data.xml'
--- sale/sale_data.xml 2012-10-02 20:40:23 +0000
+++ sale/sale_data.xml 2012-11-14 14:39:22 +0000
@@ -38,10 +38,10 @@
38 <field name="model">mail.group</field>38 <field name="model">mail.group</field>
39 <field name="res_id" ref="mail.group_all_employees"/>39 <field name="res_id" ref="mail.group_all_employees"/>
40 <field name="type">notification</field>40 <field name="type">notification</field>
41 <field name="subtype_id" ref="mail.mt_comment"/>
41 <field name="subject">Sales Management application installed!</field>42 <field name="subject">Sales Management application installed!</field>
42 <field name="body">This application lets you create and send quotations and process your sales orders; from delivery to invoicing.43 <field name="body"><![CDATA[<p>This application lets you create and send quotations and process your sales orders; from delivery to invoicing.</p>
4344<p>If you need to manage your sales pipeline (leads, opportunities, phonecalls), the &lt;i&gt;CRM&lt;/i&gt; application may be useful. Use the Settings menu to install it.</p>]]></field>
44If you need to manage your sales pipeline (leads, opportunities, phonecalls), the &lt;i&gt;CRM&lt;/i&gt; application may be useful. Use the Settings menu to install it.</field>
45 </record>45 </record>
46 </data>46 </data>
47</openerp>47</openerp>
4848
=== modified file 'stock/stock_data.xml'
--- stock/stock_data.xml 2012-10-02 20:40:23 +0000
+++ stock/stock_data.xml 2012-11-14 14:39:22 +0000
@@ -6,9 +6,10 @@
6 <field name="model">mail.group</field>6 <field name="model">mail.group</field>
7 <field name="res_id" ref="mail.group_all_employees"/>7 <field name="res_id" ref="mail.group_all_employees"/>
8 <field name="type">notification</field>8 <field name="type">notification</field>
9 <field name="subtype_id" ref="mail.mt_comment"/>
9 <field name="subject">Warehouse Management application installed!</field>10 <field name="subject">Warehouse Management application installed!</field>
10 <field name="body">Manage your product inventoy and stock locations: you can control stock moves history and planning,11 <field name="body"><![CDATA[<p>Manage your product inventoy and stock locations: you can control stock moves history and planning,
11watch your stock valuation, and track production lots upstream and downstream (based on serial numbers).</field>12watch your stock valuation, and track production lots upstream and downstream (based on serial numbers).</p>]]></field>
12 </record>13 </record>
1314
14 <record id="stock_journal_sequence" model="ir.sequence">15 <record id="stock_journal_sequence" model="ir.sequence">

Subscribers

People subscribed via source and target branches

to all changes: