summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristophe Simonis <chs@odoo.com>2019-05-16 18:19:49 +0200
committerChristophe Simonis <chs@odoo.com>2019-05-16 18:19:49 +0200
commit7b9aa21576798d7f8ffe2b2f73e403e276c4b39a (patch)
tree68d438edff5535b124bac4d6f4e308341eaee122
parent3b3f85670f40231768a409e3aebb636ad6871b56 (diff)
parentcecb1ec77d56fefdab53f3ef0bdda9a9c51c14be (diff)
[MERGE] forward port branch saas-15 up to cecb1ec77d5
-rw-r--r--addons/account/models/account_move.py2
-rw-r--r--addons/hw_escpos/escpos/escpos.py25
-rw-r--r--addons/mail/models/mail_mail.py15
-rw-r--r--addons/point_of_sale/static/src/js/gui.js5
-rw-r--r--addons/sale/models/sale.py2
-rw-r--r--addons/website_crm_partner_assign/views/website_crm_partner_assign_templates.xml12
-rw-r--r--addons/website_customer/views/website_customer_templates.xml9
-rw-r--r--odoo/addons/base/res/res_users.py8
-rw-r--r--odoo/addons/test_convert/__init__.py1
-rw-r--r--odoo/addons/test_convert/__manifest__.py1
-rw-r--r--odoo/addons/test_convert/ir.model.access.csv2
-rw-r--r--odoo/addons/test_convert/models.py16
-rw-r--r--odoo/addons/test_convert/tests/test_convert.py21
-rw-r--r--odoo/tools/convert.py7
14 files changed, 99 insertions, 27 deletions
diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py
index 08afcf0e071..3d3f85276a6 100644
--- a/addons/account/models/account_move.py
+++ b/addons/account/models/account_move.py
@@ -342,7 +342,7 @@ class AccountMoveLine(models.Model):
else:
date = partial_line.credit_move_id.date if partial_line.debit_move_id == line else partial_line.debit_move_id.date
rate = line.currency_id.with_context(date=date).rate
- amount_residual_currency += sign_partial_line * line.currency_id.round(partial_line.amount * rate)
+ amount_residual_currency += sign_partial_line * partial_line.amount * rate
#computing the `reconciled` field.
reconciled = False
diff --git a/addons/hw_escpos/escpos/escpos.py b/addons/hw_escpos/escpos/escpos.py
index 3573efb1d98..bc1c5e1842f 100644
--- a/addons/hw_escpos/escpos/escpos.py
+++ b/addons/hw_escpos/escpos/escpos.py
@@ -888,14 +888,23 @@ class Escpos:
self._raw(PAPER_FULL_CUT)
- def cashdraw(self, pin):
- """ Send pulse to kick the cash drawer """
- if pin == 2:
- self._raw(CD_KICK_2)
- elif pin == 5:
- self._raw(CD_KICK_5)
- else:
- raise CashDrawerError()
+ def cashdraw(self, pin, tries=5):
+ """ Send pulse to kick the cash drawer
+
+ With some printers the drawer will not open after one pulse, for this reason we will check
+ the drawer status up to 'tries' times and send a new pulse if the drawer is still closed. If the
+ drawer status is open, we will stop sending pulses.
+ """
+ for i in range(tries):
+ if pin == 2:
+ self._raw(CD_KICK_2)
+ elif pin == 5:
+ self._raw(CD_KICK_5)
+ else:
+ raise CashDrawerError()
+
+ if i != tries - 1 and not self.get_printer_status()['printer']['drawer_pin_high']:
+ break
def hw(self, hw):
diff --git a/addons/mail/models/mail_mail.py b/addons/mail/models/mail_mail.py
index 3027fc43edc..9fde6ebe773 100644
--- a/addons/mail/models/mail_mail.py
+++ b/addons/mail/models/mail_mail.py
@@ -153,6 +153,7 @@ class MailMail(models.Model):
if notif_emails:
notifications = self.env['mail.notification'].search([
('mail_message_id', 'in', notif_emails.mapped('mail_message_id').ids),
+ ('res_partner_id', 'in', notif_emails.mapped('recipient_ids').ids),
('is_email', '=', True)])
if mail_sent:
notifications.write({
@@ -320,6 +321,20 @@ class MailMail(models.Model):
})
mail_sent = False
+ # Update notification in a transient exception state to avoid concurrent
+ # update in case an email bounces while sending all emails related to current
+ # mail record.
+ notifs = self.env['mail.notification'].search([
+ ('is_email', '=', True),
+ ('mail_message_id', 'in', mail.mapped('mail_message_id').ids),
+ ('res_partner_id', 'in', mail.mapped('recipient_ids').ids),
+ ('email_status', 'not in', ('sent', 'canceled'))
+ ])
+ if notifs:
+ notifs.sudo().write({
+ 'email_status': 'exception',
+ })
+
# build an RFC2822 email.message.Message object and send it without queuing
res = None
for email in email_list:
diff --git a/addons/point_of_sale/static/src/js/gui.js b/addons/point_of_sale/static/src/js/gui.js
index b5cff2f233a..0d8c67bc3d9 100644
--- a/addons/point_of_sale/static/src/js/gui.js
+++ b/addons/point_of_sale/static/src/js/gui.js
@@ -458,7 +458,7 @@ var Gui = core.Class.extend({
}
} else if (input === '-') {
if (options.firstinput) {
- newbuf = '-';
+ newbuf = '-0';
} else if ( newbuf[0] === '-' ) {
newbuf = newbuf.substring(1,newbuf.length);
} else {
@@ -473,6 +473,9 @@ var Gui = core.Class.extend({
newbuf += input;
}
}
+ if (newbuf === "-") {
+ newbuf = "";
+ }
// End of input buffer at 12 characters.
if (newbuf.length > buffer.length && newbuf.length > 12) {
diff --git a/addons/sale/models/sale.py b/addons/sale/models/sale.py
index 4b92f183fd6..9fca947f6f1 100644
--- a/addons/sale/models/sale.py
+++ b/addons/sale/models/sale.py
@@ -1269,7 +1269,7 @@ class SaleOrderLine(models.Model):
value_to_write.setdefault(so_line, 0.0)
uom = self.env['product.uom'].browse(item['product_uom_id'][0])
if so_line.product_uom.category_id == uom.category_id:
- qty = uom._compute_quantity(item['unit_amount'], so_line.product_uom)
+ qty = uom._compute_quantity(item['unit_amount'], so_line.product_uom, rounding_method='HALF-UP')
else:
qty = item['unit_amount']
value_to_write[so_line] += qty
diff --git a/addons/website_crm_partner_assign/views/website_crm_partner_assign_templates.xml b/addons/website_crm_partner_assign/views/website_crm_partner_assign_templates.xml
index 96346a3814d..bdc28c2fa25 100644
--- a/addons/website_crm_partner_assign/views/website_crm_partner_assign_templates.xml
+++ b/addons/website_crm_partner_assign/views/website_crm_partner_assign_templates.xml
@@ -170,18 +170,12 @@
<template id="references_block" name="Partner References Block">
<t t-if="any([p.website_published for p in partner.implemented_partner_ids])">
<h3 id="references">References</h3>
- <div t-foreach="partner.implemented_partner_ids" t-as="reference" class="media">
- <t t-if="reference.website_published">
- <a class="pull-left" t-attf-href="/customers/#{slug(reference)}">
- <span t-field="reference.image_small" t-options='{"widget": "image", "class": "center-block"}'/>
- </a>
+ <div t-foreach="partner.implemented_partner_ids" t-if="reference.website_published" t-as="reference" class="media">
+ <span t-field="reference.image_small" t-options='{"widget": "image", "class": "center-block pull-left"}'/>
<div class="media-body" style="min-height: 64px;">
- <a class="media-heading" t-attf-href="/customers/#{slug(reference)}">
- <span t-field="reference.self"/>
- </a>
+ <span class="media-heading" t-field="reference.self"/>
<div t-field='reference.website_short_description'/>
</div>
- </t>
</div>
</t>
</template>
diff --git a/addons/website_customer/views/website_customer_templates.xml b/addons/website_customer/views/website_customer_templates.xml
index 5674f3d3440..ccd0732839d 100644
--- a/addons/website_customer/views/website_customer_templates.xml
+++ b/addons/website_customer/views/website_customer_templates.xml
@@ -239,4 +239,13 @@
</t>
</template>
+<template id="references_block_href" inherit_id="website_crm_partner_assign.references_block" name="Partner References Block">
+ <xpath expr="//div/span" position="replace">
+ <a class="pull-left" t-attf-href="/customers/#{slug(reference)}">$0</a>
+ </xpath>
+ <xpath expr="//div[@class='media-body']/span" position="replace">
+ <a class="media-heading" t-attf-href="/customers/#{slug(reference)}">$0</a>
+ </xpath>
+</template>
+
</odoo>
diff --git a/odoo/addons/base/res/res_users.py b/odoo/addons/base/res/res_users.py
index 30eba4f3c0d..8032dc0e15c 100644
--- a/odoo/addons/base/res/res_users.py
+++ b/odoo/addons/base/res/res_users.py
@@ -875,9 +875,9 @@ class UsersView(models.Model):
group_multi_company = self.env.ref('base.group_multi_company', False)
if group_multi_company and 'company_ids' in values:
if len(user.company_ids) <= 1 and user.id in group_multi_company.users.ids:
- group_multi_company.write({'users': [(3, user.id)]})
+ user.write({'groups_id': [(3, group_multi_company.id)]})
elif len(user.company_ids) > 1 and user.id not in group_multi_company.users.ids:
- group_multi_company.write({'users': [(4, user.id)]})
+ user.write({'groups_id': [(4, group_multi_company.id)]})
return user
@api.multi
@@ -888,9 +888,9 @@ class UsersView(models.Model):
if group_multi_company and 'company_ids' in values:
for user in self:
if len(user.company_ids) <= 1 and user.id in group_multi_company.users.ids:
- group_multi_company.write({'users': [(3, user.id)]})
+ user.write({'groups_id': [(3, group_multi_company.id)]})
elif len(user.company_ids) > 1 and user.id not in group_multi_company.users.ids:
- group_multi_company.write({'users': [(4, user.id)]})
+ user.write({'groups_id': [(4, group_multi_company.id)]})
return res
def _remove_reified_groups(self, values):
diff --git a/odoo/addons/test_convert/__init__.py b/odoo/addons/test_convert/__init__.py
index e69de29bb2d..0650744f6bc 100644
--- a/odoo/addons/test_convert/__init__.py
+++ b/odoo/addons/test_convert/__init__.py
@@ -0,0 +1 @@
+from . import models
diff --git a/odoo/addons/test_convert/__manifest__.py b/odoo/addons/test_convert/__manifest__.py
index af6cd1af6e4..a9c67447615 100644
--- a/odoo/addons/test_convert/__manifest__.py
+++ b/odoo/addons/test_convert/__manifest__.py
@@ -5,4 +5,5 @@
'name': 'test_convert',
'description': "Data for xml conversion tests",
'version': '0.0.1',
+ 'data': ['ir.model.access.csv'],
}
diff --git a/odoo/addons/test_convert/ir.model.access.csv b/odoo/addons/test_convert/ir.model.access.csv
new file mode 100644
index 00000000000..014e4d1c827
--- /dev/null
+++ b/odoo/addons/test_convert/ir.model.access.csv
@@ -0,0 +1,2 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_test_convert_test_model,access_test_convert_test_model,model_test_convert_test_model,,1,1,1,1 \ No newline at end of file
diff --git a/odoo/addons/test_convert/models.py b/odoo/addons/test_convert/models.py
new file mode 100644
index 00000000000..0f059e56e86
--- /dev/null
+++ b/odoo/addons/test_convert/models.py
@@ -0,0 +1,16 @@
+from odoo import api, models
+
+class TestModel(models.Model):
+ _name = 'test_convert.test_model'
+
+ @api.model
+ def action_test_date(self, today_date):
+ return True
+
+ @api.model
+ def action_test_time(self, cur_time):
+ return True
+
+ @api.model
+ def action_test_timezone(self, timezone):
+ return True
diff --git a/odoo/addons/test_convert/tests/test_convert.py b/odoo/addons/test_convert/tests/test_convert.py
index e81526dd43c..1bb79619c21 100644
--- a/odoo/addons/test_convert/tests/test_convert.py
+++ b/odoo/addons/test_convert/tests/test_convert.py
@@ -4,8 +4,10 @@
import collections
import unittest
+from lxml import etree as ET
from lxml.builder import E
+import odoo
from odoo.tests import common
from odoo.tools.convert import _eval_xml
@@ -16,6 +18,25 @@ class TestEvalXML(common.TransactionCase):
def eval_xml(self, node, obj=None):
return _eval_xml(obj, node, self.env)
+ def test_function_eval(self):
+ def id_get(): pass
+ Obj = collections.namedtuple('Obj', ['module', 'idref', 'id_get'])
+ obj = Obj('test_convert', {}, id_get)
+
+ try:
+ test_datetime = ET.XML("<function name='action_test_date' model='test_convert.test_model' eval='[datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\")]'/>")
+ self.eval_xml(node=test_datetime, obj=obj)
+ test_time = ET.XML("<function name='action_test_time' model='test_convert.test_model' eval='[time.strftime(\"%Y-%m-%d %H:%M:%S\")]'/>")
+ self.eval_xml(node=test_time, obj=obj)
+ test_timedelta = ET.XML("<function name='action_test_date' model='test_convert.test_model' eval='[(datetime.today()-timedelta(days=365)).strftime(\"%Y-%m-%d %H:%M:%S\")]'/>")
+ self.eval_xml(node=test_timedelta, obj=obj)
+ test_relativedelta = ET.XML("<function name='action_test_date' model='test_convert.test_model' eval='[(datetime.today()+relativedelta(months=3)).strftime(\"%Y-%m-%d %H:%M:%S\")]'/>")
+ self.eval_xml(node=test_relativedelta, obj=obj)
+ test_timezone = ET.XML("<function name='action_test_timezone' model='test_convert.test_model' eval='[pytz.timezone(\"Asia/Calcutta\")]'/>")
+ self.eval_xml(node=test_timezone, obj=obj)
+ except ValueError as e:
+ self.fail(e.message)
+
def test_char(self):
self.assertEqual(
self.eval_xml(Field("foo")),
diff --git a/odoo/tools/convert.py b/odoo/tools/convert.py
index 97fb2be7330..222c847ba52 100644
--- a/odoo/tools/convert.py
+++ b/odoo/tools/convert.py
@@ -180,15 +180,16 @@ def _eval_xml(self, node, env):
elif node.tag == "function":
args = []
a_eval = node.get('eval')
+ model_str = node.get('model')
# FIXME: should probably be exclusive
if a_eval:
- self.idref['ref'] = self.id_get
- args = safe_eval(a_eval, self.idref)
+ idref2 = _get_idref(self, env, model_str, self.idref)
+ args = safe_eval(a_eval, idref2)
for n in node:
return_val = _eval_xml(self, n, env)
if return_val is not None:
args.append(return_val)
- model = env[node.get('model')]
+ model = env[model_str]
method = node.get('name')
# this one still depends on the old API
return odoo.api.call_kw(model, method, args, {})