[MERGE] forward port branch saas-15 up to cecb1ec77d

This commit is contained in:
Christophe Simonis
2019-05-16 18:19:49 +02:00
14 changed files with 99 additions and 27 deletions
+1 -1
View File
@@ -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
+17 -8
View File
@@ -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):
+15
View File
@@ -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:
+4 -1
View File
@@ -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) {
+1 -1
View File
@@ -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
@@ -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>
@@ -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>
+4 -4
View File
@@ -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):
+1
View File
@@ -0,0 +1 @@
from . import models
+1
View File
@@ -5,4 +5,5 @@
'name': 'test_convert',
'description': "Data for xml conversion tests",
'version': '0.0.1',
'data': ['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
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_test_convert_test_model access_test_convert_test_model model_test_convert_test_model 1 1 1 1
+16
View File
@@ -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
@@ -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")),
+4 -3
View File
@@ -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, {})