[MERGE] forward port branch saas-14 up to 91e2264b28
This commit is contained in:
@@ -218,6 +218,19 @@ class account_payment(models.Model):
|
||||
# FIXME: ondelete='restrict' not working (eg. cancel a bank statement reconciliation with a payment)
|
||||
move_line_ids = fields.One2many('account.move.line', 'payment_id', readonly=True, copy=False, ondelete='restrict')
|
||||
|
||||
def open_payment_matching_screen(self):
|
||||
# Open reconciliation view for customers/suppliers
|
||||
action_context = {'company_ids': [self.company_id.id], 'partner_ids': [self.partner_id.commercial_partner_id.id]}
|
||||
if self.partner_type == 'customer':
|
||||
action_context.update({'mode': 'customers'})
|
||||
elif self.partner_type == 'supplier':
|
||||
action_context.update({'mode': 'suppliers'})
|
||||
return {
|
||||
'type': 'ir.actions.client',
|
||||
'tag': 'manual_reconciliation_view',
|
||||
'context': action_context,
|
||||
}
|
||||
|
||||
@api.one
|
||||
@api.depends('invoice_ids', 'payment_type', 'partner_type', 'partner_id')
|
||||
def _compute_destination_account_id(self):
|
||||
|
||||
@@ -268,7 +268,7 @@ class ResPartner(models.Model):
|
||||
all_partner_ids = []
|
||||
for partner in self:
|
||||
# price_total is in the company currency
|
||||
all_partners_and_children[partner] = self.search([('id', 'child_of', partner.id)]).ids
|
||||
all_partners_and_children[partner] = self.with_context(active_test=False).search([('id', 'child_of', partner.id)]).ids
|
||||
all_partner_ids += all_partners_and_children[partner]
|
||||
|
||||
# searching account.invoice.report via the orm is comparatively expensive
|
||||
|
||||
@@ -284,7 +284,7 @@ class HrExpense(models.Model):
|
||||
account_move.append(move_line)
|
||||
|
||||
# Calculate tax lines and adjust base line
|
||||
taxes = expense.tax_ids.compute_all(expense.unit_amount, expense.currency_id, expense.quantity, expense.product_id)
|
||||
taxes = expense.tax_ids.with_context(round=True).compute_all(expense.unit_amount, expense.currency_id, expense.quantity, expense.product_id)
|
||||
account_move[-1]['price'] = taxes['total_excluded']
|
||||
account_move[-1]['tax_ids'] = [(6, 0, expense.tax_ids.ids)]
|
||||
for tax in taxes['taxes']:
|
||||
|
||||
@@ -88,6 +88,10 @@ class HrExpenseRegisterPaymentWizard(models.TransientModel):
|
||||
for line in payment.move_line_ids + expense_sheet.account_move_id.line_ids:
|
||||
if line.account_id.internal_type == 'payable':
|
||||
account_move_lines_to_reconcile |= line
|
||||
account_move_lines_to_reconcile.reconcile()
|
||||
# DO NOT FORWARD-PORT! ONLY FOR v10
|
||||
if len(expense_sheet.expense_line_ids) > 1:
|
||||
return payment.open_payment_matching_screen()
|
||||
else:
|
||||
account_move_lines_to_reconcile.reconcile()
|
||||
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
|
||||
@@ -174,10 +174,10 @@ class MailThread(models.AbstractModel):
|
||||
RIGHT JOIN mail_channel_partner cp
|
||||
ON (cp.channel_id = rel.mail_channel_id AND cp.partner_id = %s AND
|
||||
(cp.seen_message_id IS NULL OR cp.seen_message_id < msg.id))
|
||||
WHERE msg.model = %s AND msg.res_id in %s AND
|
||||
WHERE msg.model = %s AND msg.res_id = ANY(%s) AND
|
||||
(msg.author_id IS NULL OR msg.author_id != %s) AND
|
||||
(msg.message_type != 'notification' OR msg.model != 'mail.channel')""",
|
||||
(partner_id, self._name, tuple(self.ids) or (None,), partner_id,))
|
||||
(partner_id, self._name, list(self.ids), partner_id,))
|
||||
for result in self._cr.fetchall():
|
||||
res[result[0]] += 1
|
||||
|
||||
|
||||
@@ -23,10 +23,10 @@ class pos_cache(models.Model):
|
||||
|
||||
@api.one
|
||||
def refresh_cache(self):
|
||||
products = self.env['product.product'].search(self.get_product_domain())
|
||||
Product = self.env['product.product'].sudo(self.compute_user_id.id)
|
||||
products = Product.search(self.get_product_domain())
|
||||
prod_ctx = products.with_context(pricelist=self.config_id.pricelist_id.id, display_default_code=False,
|
||||
lang=self.compute_user_id.lang)
|
||||
prod_ctx = prod_ctx.sudo(self.compute_user_id.id)
|
||||
res = prod_ctx.read(self.get_product_fields())
|
||||
datas = {
|
||||
'cache': base64.encodestring(cPickle.dumps(res)),
|
||||
|
||||
@@ -102,6 +102,5 @@ class AccountInvoiceLine(models.Model):
|
||||
'invoice_line_id', 'order_line_id',
|
||||
string='Sales Order Lines', readonly=True, copy=False)
|
||||
layout_category_id = fields.Many2one('sale.layout_category', string='Section')
|
||||
layout_category_sequence = fields.Integer(
|
||||
related='layout_category_id.sequence',
|
||||
string='Layout Sequence', store=True)
|
||||
layout_category_sequence = fields.Integer(string='Layout Sequence')
|
||||
# TODO: remove layout_category_sequence in master or make it work properly
|
||||
|
||||
@@ -802,8 +802,8 @@ class SaleOrderLine(models.Model):
|
||||
procurement_ids = fields.One2many('procurement.order', 'sale_line_id', string='Procurements')
|
||||
|
||||
layout_category_id = fields.Many2one('sale.layout_category', string='Section')
|
||||
layout_category_sequence = fields.Integer(related='layout_category_id.sequence', string='Layout Sequence', store=True)
|
||||
# Store is intentionally set in order to keep the "historic" order.
|
||||
layout_category_sequence = fields.Integer(string='Layout Sequence')
|
||||
# TODO: remove layout_category_sequence in master or make it work properly
|
||||
|
||||
@api.multi
|
||||
def _prepare_invoice_line(self, qty):
|
||||
|
||||
@@ -682,7 +682,8 @@ class QuantPackage(models.Model):
|
||||
|
||||
def action_view_picking(self):
|
||||
action = self.env.ref('stock.action_picking_tree_all').read()[0]
|
||||
pickings = self.env['stock.pack.operation'].search([('result_package_id', 'in', self.ids)]).mapped('picking_id')
|
||||
domain = ['|', ('result_package_id', 'in', self.ids), ('package_id', 'in', self.ids)]
|
||||
pickings = self.env['stock.pack.operation'].search(domain).mapped('picking_id')
|
||||
action['domain'] = [('id', 'in', pickings.ids)]
|
||||
return action
|
||||
|
||||
|
||||
@@ -2221,7 +2221,7 @@ msgstr ""
|
||||
#: code:addons/web/static/src/js/views/form_widgets.js:1199
|
||||
#, python-format
|
||||
msgid "The selected file exceed the maximum file size of %s."
|
||||
msgstr "El archivo seleccionado supera el tamaño máximo de% s."
|
||||
msgstr "El archivo seleccionado supera el tamaño máximo de %s."
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
||||
@@ -1240,7 +1240,7 @@ msgstr ""
|
||||
#: code:addons/web/static/src/js/widgets/loading.js:44
|
||||
#, python-format
|
||||
msgid "Loading (%d)"
|
||||
msgstr "लोड हो रहा है (% d)"
|
||||
msgstr "लोड हो रहा है (%d)"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
||||
@@ -6,16 +6,17 @@ from odoo.addons.website.models.website import slug
|
||||
from odoo.http import request
|
||||
|
||||
|
||||
# NB: DO NOT FORWARD PORT THE FALSY LEAVES IN 11.0
|
||||
class WebsiteHrRecruitment(http.Controller):
|
||||
@http.route([
|
||||
'/jobs',
|
||||
'/jobs/country/<model("res.country"):country>',
|
||||
'/jobs/department/<model("hr.department"):department>',
|
||||
'/jobs/country/<model("res.country"):country>/department/<model("hr.department"):department>',
|
||||
'''/jobs/country/<model("res.country", "[(0, '=', 1)]"):country>''',
|
||||
'''/jobs/department/<model("hr.department", "[(0, '=', 1)]"):department>''',
|
||||
'''/jobs/country/<model("res.country"):country>/department/<model("hr.department", "[(0, '=', 1)]"):department>''',
|
||||
'/jobs/office/<int:office_id>',
|
||||
'/jobs/country/<model("res.country"):country>/office/<int:office_id>',
|
||||
'/jobs/department/<model("hr.department"):department>/office/<int:office_id>',
|
||||
'/jobs/country/<model("res.country"):country>/department/<model("hr.department"):department>/office/<int:office_id>',
|
||||
'''/jobs/country/<model("res.country", "[(0, '=', 1)]"):country>/office/<int:office_id>''',
|
||||
'''/jobs/department/<model("hr.department", "[(0, '=', 1)]"):department>/office/<int:office_id>''',
|
||||
'''/jobs/country/<model("res.country"):country>/department/<model("hr.department", "[(0, '=', 1)]"):department>/office/<int:office_id>''',
|
||||
], type='http', auth="public", website=True)
|
||||
def jobs(self, country=None, department=None, office_id=None, **kwargs):
|
||||
env = request.env(context=dict(request.env.context, show_address=True, no_tag_br=True))
|
||||
|
||||
@@ -7,6 +7,14 @@
|
||||
tr th {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@media (max-width: @screen-xs-max) {
|
||||
display: block;
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
-ms-overflow-style: -ms-autohiding-scrollbar;
|
||||
}
|
||||
}
|
||||
|
||||
.o_my_home_content > .page-header > a:hover {
|
||||
|
||||
@@ -111,15 +111,20 @@ class SaleOrder(models.Model):
|
||||
|
||||
order_lines = [(5, 0, 0)]
|
||||
for line in template.quote_line:
|
||||
discount = 0
|
||||
if self.pricelist_id:
|
||||
price = self.pricelist_id.with_context(uom=line.product_uom_id.id).get_product_price(line.product_id, 1, False)
|
||||
if self.pricelist_id.discount_policy == 'without_discount' and line.price_unit:
|
||||
discount = (line.price_unit - price) / line.price_unit * 100
|
||||
price = line.price_unit
|
||||
|
||||
else:
|
||||
price = line.price_unit
|
||||
|
||||
data = {
|
||||
'name': line.name,
|
||||
'price_unit': price,
|
||||
'discount': line.discount,
|
||||
'discount': 100 - ((100 - discount) * (100 - line.discount)/100),
|
||||
'product_uom_qty': line.product_uom_qty,
|
||||
'product_id': line.product_id.id,
|
||||
'layout_category_id': line.layout_category_id,
|
||||
|
||||
@@ -192,7 +192,9 @@ class Product(models.Model):
|
||||
def _website_price(self):
|
||||
qty = self._context.get('quantity', 1.0)
|
||||
partner = self.env.user.partner_id
|
||||
pricelist = self.env['website'].get_current_website().get_current_pricelist()
|
||||
current_website = self.env['website'].get_current_website()
|
||||
pricelist = current_website.get_current_pricelist()
|
||||
company_id = current_website.company_id
|
||||
|
||||
context = dict(self._context, pricelist=pricelist.id, partner=partner)
|
||||
self2 = self.with_context(context) if self._context != context else self
|
||||
@@ -200,7 +202,7 @@ class Product(models.Model):
|
||||
ret = self.env.user.has_group('sale.group_show_price_subtotal') and 'total_excluded' or 'total_included'
|
||||
|
||||
for p, p2 in zip(self, self2):
|
||||
taxes = partner.property_account_position_id.map_tax(p.taxes_id)
|
||||
taxes = partner.property_account_position_id.map_tax(p.taxes_id.sudo().filtered(lambda x: x.company_id == company_id))
|
||||
p.website_price = taxes.compute_all(p2.price, pricelist.currency_id, quantity=qty, product=p2, partner=partner)[ret]
|
||||
p.website_public_price = taxes.compute_all(p2.lst_price, quantity=qty, product=p2, partner=partner)[ret]
|
||||
|
||||
|
||||
@@ -336,6 +336,10 @@
|
||||
min-width: 76px;
|
||||
}
|
||||
|
||||
.oe_cart > .oe_structure {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
div#payment_method div.list-group {
|
||||
margin-left: 40px;
|
||||
}
|
||||
|
||||
@@ -296,6 +296,8 @@
|
||||
|
||||
.oe_cart table td:first-child
|
||||
min-width: 76px
|
||||
.oe_cart > .oe_structure
|
||||
clear: both
|
||||
|
||||
div#payment_method
|
||||
div.list-group
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
</div>
|
||||
<div class="oe_product_image">
|
||||
<a itemprop="url" t-att-href="keep('/shop/product/%s' % slug(product), page=(pager['page']['num'] if pager['page']['num']>1 else None))">
|
||||
<span itemprop="image" t-field="product.image" t-options="{'widget': 'image', 'resize': None if product_image_big else '300x300', 'zoom': 'image'}" t-att-alt="product.name" />
|
||||
<span itemprop="image" t-attf-content="{{request.httprequest.url_root}}web/image/product.template/{{product.id}}/image" t-field="product.image" t-options="{'widget': 'image', 'resize': None if product_image_big else '300x300', 'zoom': 'image'}" t-att-alt="product.name" />
|
||||
</a>
|
||||
</div>
|
||||
<t t-if="show_publish">
|
||||
@@ -99,7 +99,7 @@
|
||||
<section>
|
||||
<h5>
|
||||
<strong>
|
||||
<a itemprop="name" t-att-href="keep('/shop/product/%s' % slug(product), page=(pager['page']['num'] if pager['page']['num']>1 else None))" t-field="product.name" />
|
||||
<a itemprop="name" t-att-href="keep('/shop/product/%s' % slug(product), page=(pager['page']['num'] if pager['page']['num']>1 else None))" t-att-content="product.name" t-field="product.name" />
|
||||
</strong>
|
||||
</h5>
|
||||
<div itemprop="offers" itemscope="itemscope" itemtype="http://schema.org/Offer" class="product_price" t-if="product.product_variant_ids">
|
||||
@@ -406,7 +406,7 @@
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-7">
|
||||
<span itemprop="image" t-field="product.image" t-options="{'widget': 'image', 'class': 'product_detail_img', 'alt-field': 'name', 'zoom': 'image'}" groups="!website_sale.group_website_multi_image"/>
|
||||
<span itemprop="image" t-attf-content="{{request.httprequest.url_root}}web/image/product.template/{{product.id}}/image" t-field="product.image" t-options="{'widget': 'image', 'class': 'product_detail_img', 'alt-field': 'name', 'zoom': 'image'}" groups="!website_sale.group_website_multi_image"/>
|
||||
<t groups="website_sale.group_website_multi_image">
|
||||
<t t-set="variant_img" t-value="product.product_variant_id.image_variant"/>
|
||||
<t t-set="image_ids" t-value="product.product_image_ids"/>
|
||||
@@ -450,7 +450,7 @@
|
||||
</div>
|
||||
<div class="col-sm-5 col-lg-4 col-lg-offset-1" id="product_details">
|
||||
<h1 itemprop="name" t-field="product.name">Product Name</h1>
|
||||
<span itemprop="url" style="display:none;" t-esc="'/shop/product/%s' % slug(product)" />
|
||||
<span itemprop="url" style="display:none;" t-esc="'%sshop/product/%s' % (request.httprequest.url_root, slug(product))"/>
|
||||
<t t-set="attribute_value_ids" t-value="get_attribute_value_ids(product)"/>
|
||||
<form action="/shop/cart/update" class="js_add_cart_variants" t-att-data-attribute_value_ids="attribute_value_ids" method="POST">
|
||||
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()" />
|
||||
|
||||
@@ -13,3 +13,8 @@ List of contributors:
|
||||
Alan Ramos alan.ramos@jarsa.com.mx https://github.com/alan196
|
||||
Luis Triana luis.triana@jarsa.com.mx https://github.com/xluiisx
|
||||
Luis Triana luistriana.28@gmail.com https://github.com/xluiisx
|
||||
Oscar Garza oscar.garza@jarsa.com.mx https://github.com/ougc27
|
||||
Alexis Reza alexis.reza@jarsa.com.mx https://github.com/AlexisReza
|
||||
Isabel Esparza isabel.esparza@jarsa.com.mx https://github.com/IsabelEsparza
|
||||
Miguel Ruiz miguel.ruiz@jarsa.com.mx https://github.com/lmgr0312
|
||||
Sarai Osorio sarai.osorio@jarsa.com.mx https://github.com/SaraiOsorio
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
Spain, 2015-05-28
|
||||
|
||||
I hereby agree to the terms of the Odoo Individual Contributor License Agreement v1.0.
|
||||
|
||||
I declare that I am authorized and able to make this agreement and sign this declaration.
|
||||
|
||||
Signed,
|
||||
|
||||
Carlos Dauden carlos.dauden@tecnativa.com https://github.com/carlosdauden
|
||||
@@ -1107,7 +1107,26 @@ class QWeb(object):
|
||||
|
||||
def _compile_directive_esc(self, el, options):
|
||||
field_options = self._compile_widget_options(el, 'esc')
|
||||
content = self._compile_widget(el, el.attrib.pop('t-esc'), field_options, 'escape')
|
||||
content = self._compile_widget(el, el.attrib.pop('t-esc'), field_options)
|
||||
if not field_options:
|
||||
# if content is not False and if content is not None:
|
||||
# content = escape(unicodifier(content))
|
||||
content.append(self._if_content_is_not_Falsy([
|
||||
ast.Assign(
|
||||
targets=[ast.Name(id='content', ctx=ast.Store())],
|
||||
value=ast.Call(
|
||||
func=ast.Name(id='escape', ctx=ast.Load()),
|
||||
args=[ast.Call(
|
||||
func=ast.Name(id='unicodifier', ctx=ast.Load()),
|
||||
args=[ast.Name(id='content', ctx=ast.Load())], keywords=[],
|
||||
starargs=None, kwargs=None
|
||||
)],
|
||||
keywords=[],
|
||||
starargs=None, kwargs=None
|
||||
)
|
||||
)],
|
||||
[]
|
||||
))
|
||||
return content + self._compile_widget_value(el, options)
|
||||
|
||||
def _compile_directive_raw(self, el, options):
|
||||
@@ -1115,33 +1134,8 @@ class QWeb(object):
|
||||
content = self._compile_widget(el, el.attrib.pop('t-raw'), field_options)
|
||||
return content + self._compile_widget_value(el, options)
|
||||
|
||||
# escape attribute is deprecated and will remove after v11
|
||||
def _compile_widget(self, el, expression, field_options, escape=None):
|
||||
# if isinstance(value, basestring):
|
||||
# value = escape(unicodifier(value))
|
||||
escaped = ast.If(
|
||||
test=ast.Call(
|
||||
func=ast.Name(id='isinstance', ctx=ast.Load()),
|
||||
args=[
|
||||
ast.Name(id='content', ctx=ast.Load()),
|
||||
ast.Name(id='basestring', ctx=ast.Load())
|
||||
], keywords=[],
|
||||
starargs=None, kwargs=None
|
||||
),
|
||||
body=[ast.Assign(
|
||||
targets=[ast.Name(id='content', ctx=ast.Store())],
|
||||
value=ast.Call(
|
||||
func=ast.Name(id=escape, ctx=ast.Load()),
|
||||
args=[ast.Call(
|
||||
func=ast.Name(id='unicodifier', ctx=ast.Load()),
|
||||
args=[ast.Name(id='content', ctx=ast.Load())], keywords=[],
|
||||
starargs=None, kwargs=None
|
||||
)], keywords=[],
|
||||
starargs=None, kwargs=None
|
||||
) if escape else ast.Name(id='content', ctx=ast.Load())
|
||||
)],
|
||||
orelse=[]
|
||||
)
|
||||
|
||||
if field_options:
|
||||
return [
|
||||
# value = t-(esc|raw)
|
||||
@@ -1149,7 +1143,6 @@ class QWeb(object):
|
||||
targets=[ast.Name(id='content', ctx=ast.Store())],
|
||||
value=self._compile_expr0(expression)
|
||||
),
|
||||
escaped,
|
||||
# t_attrs, content, force_display = self._get_widget(value, expression, tagName, field options, template options, values)
|
||||
ast.Assign(
|
||||
targets=[ast.Tuple(elts=[
|
||||
@@ -1193,8 +1186,7 @@ class QWeb(object):
|
||||
self._compile_expr0(expression),
|
||||
ast.Name(id='None', ctx=ast.Load()),
|
||||
], ctx=ast.Load())
|
||||
),
|
||||
escaped
|
||||
)
|
||||
]
|
||||
|
||||
# for backward compatibility to remove after v10
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
"base.lang_fr_BE","French (BE) / Français (BE)","fr_BE","fr_BE","Left-to-Right","[3,0]",",",".","%d/%m/%Y","%H:%M:%S","True"
|
||||
"base.lang_fr_CA","French (CA) / Français (CA)","fr_CA","fr_CA","Left-to-Right","[3,0]",","," ","%Y-%m-%d","%H:%M:%S","True"
|
||||
"base.lang_fr_CH","French (CH) / Français (CH)","fr_CH","fr_CH","Left-to-Right","[3,0]",".","'","%d. %m. %Y","%H:%M:%S","True"
|
||||
"base.lang_fr","French / Français","fr_FR","fr","Left-to-Right","[3,0]",","," ","%d/%m/%Y","%H:%M:%S","True"
|
||||
"base.lang_fr","French / Français","fr_FR","fr","Left-to-Right","[3,0]",","," ","%d/%m/%Y","%H:%M:%S","True"
|
||||
"base.lang_gl_ES","Galician / Galego","gl_ES","gl_ES","Left-to-Right","[]",",",,"%d/%m/%Y","%H:%M:%S","True"
|
||||
"base.lang_ka_GE","Georgian / ქართული ენა","ka_GE","ka_GE","Left-to-Right","[3,0]",",",".","%m/%d/%Y","%H:%M:%S","True"
|
||||
"base.lang_de","German / Deutsch","de_DE","de","Left-to-Right","[3,0]",",",".","%d.%m.%Y","%H:%M:%S","True"
|
||||
|
||||
|
+41
-6
@@ -60,6 +60,8 @@ def copy_cache(records, env):
|
||||
while todo:
|
||||
model_name = next(iter(todo))
|
||||
record_ids = todo.pop(model_name) - done[model_name]
|
||||
if not record_ids:
|
||||
continue
|
||||
done[model_name].update(record_ids)
|
||||
for name, field in src[model_name]._fields.items():
|
||||
src_cache = src.cache[field]
|
||||
@@ -71,6 +73,10 @@ def copy_cache(records, env):
|
||||
if field.relational and isinstance(value, tuple):
|
||||
todo[field.comodel_name].update(value)
|
||||
|
||||
def first(records):
|
||||
""" Return the first record in ``records``, with the same prefetching. """
|
||||
return next(iter(records)) if len(records) > 1 else records
|
||||
|
||||
|
||||
def resolve_mro(model, name, predicate):
|
||||
""" Return the list of successively overridden values of attribute ``name``
|
||||
@@ -567,12 +573,41 @@ class Field(object):
|
||||
""" Compute the related field ``self`` on ``records``. """
|
||||
# when related_sudo, bypass access rights checks when reading values
|
||||
others = records.sudo() if self.related_sudo else records
|
||||
for record, other in zip(records, others):
|
||||
if not record.id and record.env != other.env:
|
||||
# draft records: copy record's cache to other's cache first
|
||||
copy_cache(record, other.env)
|
||||
other, field = self.traverse_related(other)
|
||||
record[self.name] = other[field.name]
|
||||
# copy the cache of draft records into others' cache
|
||||
if records.env != others.env:
|
||||
copy_cache(records - records.filtered('id'), others.env)
|
||||
#
|
||||
# Traverse fields one by one for all records, in order to take advantage
|
||||
# of prefetching for each field access. In order to clarify the impact
|
||||
# of the algorithm, consider traversing 'foo.bar' for records a1 and a2,
|
||||
# where 'foo' is already present in cache for a1, a2. Initially, both a1
|
||||
# and a2 are marked for prefetching. As the commented code below shows,
|
||||
# traversing all fields one record at a time will fetch 'bar' one record
|
||||
# at a time.
|
||||
#
|
||||
# b1 = a1.foo # mark b1 for prefetching
|
||||
# v1 = b1.bar # fetch/compute bar for b1
|
||||
# b2 = a2.foo # mark b2 for prefetching
|
||||
# v2 = b2.bar # fetch/compute bar for b2
|
||||
#
|
||||
# On the other hand, traversing all records one field at a time ensures
|
||||
# maximal prefetching for each field access.
|
||||
#
|
||||
# b1 = a1.foo # mark b1 for prefetching
|
||||
# b2 = a2.foo # mark b2 for prefetching
|
||||
# v1 = b1.bar # fetch/compute bar for b1, b2
|
||||
# v2 = b2.bar # value already in cache
|
||||
#
|
||||
# This difference has a major impact on performance, in particular in
|
||||
# the case where 'bar' is a computed field that takes advantage of batch
|
||||
# computation.
|
||||
#
|
||||
values = list(others)
|
||||
for name in self.related[:-1]:
|
||||
values = [first(value[name]) for value in values]
|
||||
# assign final values to records
|
||||
for record, value in zip(records, values):
|
||||
record[self.name] = value[self.related_field.name]
|
||||
|
||||
def _inverse_related(self, records):
|
||||
""" Inverse the related field ``self`` on ``records``. """
|
||||
|
||||
+9
-8
@@ -3376,14 +3376,6 @@ class BaseModel(object):
|
||||
id_new, = cr.fetchone()
|
||||
self = self.browse(id_new)
|
||||
|
||||
if self.env.lang and self.env.lang != 'en_US':
|
||||
# add translations for self.env.lang
|
||||
for name, val in vals.iteritems():
|
||||
field = self._fields[name]
|
||||
if field.store and field.column_type and field.translate is True:
|
||||
tname = "%s,%s" % (self._name, name)
|
||||
self.env['ir.translation']._set_ids(tname, 'model', self.env.lang, self.ids, val, val)
|
||||
|
||||
if self._parent_store and not self._context.get('defer_parent_store_computation'):
|
||||
if self.pool._init:
|
||||
self.pool._init_parent[self._name] = True
|
||||
@@ -3445,6 +3437,15 @@ class BaseModel(object):
|
||||
self.recompute()
|
||||
|
||||
self.check_access_rule('create')
|
||||
|
||||
if self.env.lang and self.env.lang != 'en_US':
|
||||
# add translations for self.env.lang
|
||||
for name, val in vals.iteritems():
|
||||
field = self._fields[name]
|
||||
if field.store and field.column_type and field.translate is True:
|
||||
tname = "%s,%s" % (self._name, name)
|
||||
self.env['ir.translation']._set_ids(tname, 'model', self.env.lang, self.ids, val, val)
|
||||
|
||||
return id_new
|
||||
|
||||
# TODO: ameliorer avec NULL
|
||||
|
||||
Reference in New Issue
Block a user