summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristophe Simonis <chs@odoo.com>2019-01-16 17:02:34 +0100
committerChristophe Simonis <chs@odoo.com>2019-01-16 17:02:34 +0100
commit378b283c02da5e6d3425f339668edcd63ee62fe5 (patch)
treebbaecb2d1241e51e8ea5b0a10ab35ff73aff63a6
parente79c35dcbc1525196263cca6aa9da14ca30d2c0a (diff)
parent83cc046e9a90e8592d0d47c7162ab7bd923621ba (diff)
[MERGE] forward port branch saas-11.3 up to 83cc046e9a9
-rw-r--r--addons/account/static/src/scss/account_reconciliation.scss6
-rw-r--r--addons/event_sale/wizard/event_edit_registration.xml2
-rw-r--r--addons/hr_org_chart/static/src/xml/hr_org_chart.xml1
-rw-r--r--addons/l10n_be_invoice_bba/data/mail_template_data.xml2
-rw-r--r--addons/mrp/models/mrp_production.py5
-rw-r--r--addons/mrp/models/stock_move.py18
-rw-r--r--addons/mrp/tests/test_order.py46
-rw-r--r--addons/mrp/wizard/change_production_qty.py4
-rw-r--r--addons/purchase/models/res_partner.py35
-rw-r--r--addons/purchase/views/purchase_views.xml2
-rw-r--r--addons/sale/views/sale_views.xml2
-rw-r--r--addons/web/static/src/js/views/field_manager_mixin.js6
-rw-r--r--addons/web/static/src/js/views/view_dialogs.js2
-rw-r--r--addons/web/static/tests/fields/relational_fields_tests.js97
-rw-r--r--addons/website/models/website.py2
-rw-r--r--addons/website_sale/controllers/main.py2
-rw-r--r--addons/website_slides/views/website_slides_embed.xml2
-rw-r--r--doc/cla/corporate/merchise.md1
-rw-r--r--odoo/addons/base/models/ir_actions.py2
-rw-r--r--odoo/models.py6
-rw-r--r--odoo/modules/module.py6
21 files changed, 223 insertions, 26 deletions
diff --git a/addons/account/static/src/scss/account_reconciliation.scss b/addons/account/static/src/scss/account_reconciliation.scss
index 6c21d14e8f2..6e218b9f11b 100644
--- a/addons/account/static/src/scss/account_reconciliation.scss
+++ b/addons/account/static/src/scss/account_reconciliation.scss
@@ -289,6 +289,10 @@
overflow: auto;
border: 1px solid #ddd;
border-radius: 0 0 5px 5px;
+ > div.quick_add > .o_reconcile_models {
+ max-height: 54px;
+ overflow: auto;
+ }
}
.quick_add {
margin-bottom: 7px;
@@ -357,4 +361,4 @@
}
}
}
-} \ No newline at end of file
+}
diff --git a/addons/event_sale/wizard/event_edit_registration.xml b/addons/event_sale/wizard/event_edit_registration.xml
index 92a69107ba7..25422c2947a 100644
--- a/addons/event_sale/wizard/event_edit_registration.xml
+++ b/addons/event_sale/wizard/event_edit_registration.xml
@@ -12,7 +12,7 @@
<tree string="Registration" editable="top" create="false" delete="false">
<field name="event_id" readonly='1' force_save="1"/>
<field name="registration_id" readonly='1' force_save="1"/>
- <field name="event_ticket_id" domain="[('event_id', '=', event_id)]" readonly='1'/>
+ <field name="event_ticket_id" domain="[('event_id', '=', event_id)]" readonly='1' force_save="1"/>
<field name="name"/>
<field name="email"/>
<field name="phone"/>
diff --git a/addons/hr_org_chart/static/src/xml/hr_org_chart.xml b/addons/hr_org_chart/static/src/xml/hr_org_chart.xml
index e4e7f9fa231..1dfa693fa40 100644
--- a/addons/hr_org_chart/static/src/xml/hr_org_chart.xml
+++ b/addons/hr_org_chart/static/src/xml/hr_org_chart.xml
@@ -105,6 +105,7 @@
<div class="o_media_left">
<a href="#"
t-att-data-employee-id="self.id"
+ t-att-data-employee-name="self.name"
class="o_org_chart_show_more text-center o_employee_sub_redirect">&#8230;</a>
</div>
</div>
diff --git a/addons/l10n_be_invoice_bba/data/mail_template_data.xml b/addons/l10n_be_invoice_bba/data/mail_template_data.xml
index e12f7745b91..5e6bfecdfb7 100644
--- a/addons/l10n_be_invoice_bba/data/mail_template_data.xml
+++ b/addons/l10n_be_invoice_bba/data/mail_template_data.xml
@@ -25,7 +25,7 @@
This invoice is already paid.
% else:
Please remit payment at your earliest convenience.
- % if object.reference_type == 'bba' and object.reference:
+ % if object.invoice_reference_type=='structured' and object.reference:
Please use the following communication for your payment: <strong>${object.reference}</strong>.
% endif
<br /><br />
diff --git a/addons/mrp/models/mrp_production.py b/addons/mrp/models/mrp_production.py
index f14542398be..77295665439 100644
--- a/addons/mrp/models/mrp_production.py
+++ b/addons/mrp/models/mrp_production.py
@@ -486,7 +486,10 @@ class MrpProduction(models.Model):
if move:
old_qty = move[0].product_uom_qty
if quantity > 0:
- move[0].write({'product_uom_qty': quantity})
+ move[0]._decrease_reserved_quanity(quantity)
+ move[0].with_context(do_not_unreserve=True).write({'product_uom_qty': quantity})
+ move[0]._recompute_state()
+ move[0]._action_assign()
move.unit_factor = quantity / move.raw_material_production_id.product_qty
elif quantity < 0: # Do not remove 0 lines
if move[0].quantity_done > 0:
diff --git a/addons/mrp/models/stock_move.py b/addons/mrp/models/stock_move.py
index 83444b708a7..f5e931a71d5 100644
--- a/addons/mrp/models/stock_move.py
+++ b/addons/mrp/models/stock_move.py
@@ -182,6 +182,24 @@ class StockMove(models.Model):
self.sudo().unlink()
return processed_moves
+ def _decrease_reserved_quanity(self, quantity):
+ """ Decrease the reservation on move lines but keeps the
+ all other data.
+ """
+ move_line_to_unlink = self.env['stock.move.line']
+ for move in self:
+ reserved_quantity = quantity
+ for move_line in self.move_line_ids:
+ if move_line.product_uom_qty > reserved_quantity:
+ move_line.product_uom_qty = reserved_quantity
+ else:
+ move_line.product_uom_qty = 0
+ reserved_quantity -= move_line.product_uom_qty
+ if not move_line.product_uom_qty and not move_line.qty_done:
+ move_line_to_unlink |= move_line
+ move_line_to_unlink.unlink()
+ return True
+
def _prepare_phantom_move_values(self, bom_line, quantity):
return {
'picking_id': self.picking_id.id if self.picking_id else False,
diff --git a/addons/mrp/tests/test_order.py b/addons/mrp/tests/test_order.py
index e3bd7c3a72e..6dfe4c08e4b 100644
--- a/addons/mrp/tests/test_order.py
+++ b/addons/mrp/tests/test_order.py
@@ -629,6 +629,52 @@ class TestMrpOrder(TestMrpCommon):
mo.button_mark_done()
self.assertEqual(mo.state, 'done', "Production order should be in done state.")
+ def test_product_produce_5(self):
+ """ Build 5 final products with different consumed lots,
+ then edit the finished quantity and update the Manufacturing
+ order quantity. Then check if the produced quantity do not
+ change and it is possible to close the MO.
+ """
+ self.stock_location = self.env.ref('stock.stock_location_stock')
+ mo, bom, p_final, p1, p2 = self.generate_mo(tracking_base_1='lot')
+ self.assertEqual(len(mo), 1, 'MO should have been created')
+
+ lot_1 = self.env['stock.production.lot'].create({
+ 'name': 'lot1',
+ 'product_id': p1.id,
+ })
+ lot_2 = self.env['stock.production.lot'].create({
+ 'name': 'lot2',
+ 'product_id': p1.id,
+ })
+
+ self.env['stock.quant']._update_available_quantity(p1, self.stock_location, 10, lot_id=lot_1)
+ self.env['stock.quant']._update_available_quantity(p1, self.stock_location, 10, lot_id=lot_2)
+
+ self.env['stock.quant']._update_available_quantity(p2, self.stock_location, 5)
+ mo.action_assign()
+
+ produce_wizard = self.env['mrp.product.produce'].with_context({
+ 'active_id': mo.id,
+ 'active_ids': [mo.id],
+ }).create({
+ 'product_qty': 5.0,
+ })
+
+ for produce_line in produce_wizard.produce_line_ids:
+ produce_line.qty_done = produce_line.qty_to_consume
+ produce_wizard.do_produce()
+
+ mo.move_finished_ids.move_line_ids.qty_done -= 1
+ update_quantity_wizard = self.env['change.production.qty'].create({
+ 'mo_id': mo.id,
+ 'product_qty': 4,
+ })
+ update_quantity_wizard.change_prod_qty()
+
+ self.assertEqual(mo.move_raw_ids.filtered(lambda m: m.product_id == p1).quantity_done, 20, 'Update the produce quantity should not impact already produced quantity.')
+ mo.button_mark_done()
+
def test_product_produce_uom(self):
plastic_laminate = self.env.ref('mrp.product_product_plastic_laminate')
bom = self.env.ref('mrp.mrp_bom_plastic_laminate')
diff --git a/addons/mrp/wizard/change_production_qty.py b/addons/mrp/wizard/change_production_qty.py
index 6cda5d64f9b..b92616c9a50 100644
--- a/addons/mrp/wizard/change_production_qty.py
+++ b/addons/mrp/wizard/change_production_qty.py
@@ -53,7 +53,6 @@ class ChangeProductionQty(models.TransientModel):
factor = production.product_uom_id._compute_quantity(production.product_qty - qty_produced, production.bom_id.product_uom_id) / production.bom_id.product_qty
boms, lines = production.bom_id.explode(production.product_id, factor, picking_type=production.bom_id.picking_type_id)
documents = {}
- done_quantities = {move: move.quantity_done for move in production.move_raw_ids}
for line, line_data in lines:
move, old_qty, new_qty = production._update_raw_move(line, line_data)
iterate_key = production._get_document_iterate_key(move)
@@ -73,9 +72,6 @@ class ChangeProductionQty(models.TransientModel):
production._log_downside_manufactured_quantity(finished_moves_modification)
moves = production.move_raw_ids.filtered(lambda x: x.state not in ('done', 'cancel'))
moves._action_assign()
- for move in production.move_raw_ids:
- if move.quantity_done != done_quantities[move]:
- move._set_quantity_done(done_quantities[move])
for wo in production.workorder_ids:
operation = wo.operation_id
if operation_bom_qty.get(operation.id):
diff --git a/addons/purchase/models/res_partner.py b/addons/purchase/models/res_partner.py
index dd120858885..ec6fb75d5f8 100644
--- a/addons/purchase/models/res_partner.py
+++ b/addons/purchase/models/res_partner.py
@@ -11,15 +11,38 @@ class res_partner(models.Model):
@api.multi
def _compute_purchase_order_count(self):
- PurchaseOrder = self.env['purchase.order']
- for partner in self:
- partner.purchase_order_count = PurchaseOrder.search_count([('partner_id', 'child_of', partner.id)])
+ # retrieve all children partners and prefetch 'parent_id' on them
+ all_partners = self.search([('id', 'child_of', self.ids)])
+ all_partners.read(['parent_id'])
+
+ purchase_order_groups = self.env['purchase.order'].read_group(
+ domain=[('partner_id', 'in', all_partners.ids)],
+ fields=['partner_id'], groupby=['partner_id']
+ )
+ for group in purchase_order_groups:
+ partner = self.browse(group['partner_id'][0])
+ while partner:
+ if partner in self:
+ partner.purchase_order_count += group['partner_id_count']
+ partner = partner.parent_id
@api.multi
def _compute_supplier_invoice_count(self):
- Invoice = self.env['account.invoice']
- for partner in self:
- partner.supplier_invoice_count = Invoice.search_count([('partner_id', 'child_of', partner.id), ('type', '=', 'in_invoice')])
+ # retrieve all children partners and prefetch 'parent_id' on them
+ all_partners = self.search([('id', 'child_of', self.ids)])
+ all_partners.read(['parent_id'])
+
+ supplier_invoice_groups = self.env['account.invoice'].read_group(
+ domain=[('partner_id', 'in', all_partners.ids),
+ ('type', '=', 'in_invoice')],
+ fields=['partner_id'], groupby=['partner_id']
+ )
+ for group in supplier_invoice_groups:
+ partner = self.browse(group['partner_id'][0])
+ while partner:
+ if partner in self:
+ partner.supplier_invoice_count += group['partner_id_count']
+ partner = partner.parent_id
@api.model
def _commercial_fields(self):
diff --git a/addons/purchase/views/purchase_views.xml b/addons/purchase/views/purchase_views.xml
index 5679d565c9c..65729354471 100644
--- a/addons/purchase/views/purchase_views.xml
+++ b/addons/purchase/views/purchase_views.xml
@@ -218,6 +218,7 @@
<field name="taxes_id" widget="many2many_tags" domain="[('type_tax_use', '=', 'purchase')]" options="{'no_create': True}"/>
<field name="date_planned" widget="date"/>
<field name="account_analytic_id" colspan="2" groups="analytic.group_analytic_accounting"/>
+ <field name="analytic_tag_ids" groups="purchase.group_analytic_accounting" widget="many2many_tags" options="{'color_field': 'color'}"/>
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/>
</group>
</group>
@@ -227,6 +228,7 @@
</page>
<page string="Invoices and Incoming Shipments">
<field name="invoice_lines"/>
+ <field name="move_dest_ids" invisible="1"/>
</page>
</notebook>
</sheet>
diff --git a/addons/sale/views/sale_views.xml b/addons/sale/views/sale_views.xml
index e980ad2e61d..258beba4b91 100644
--- a/addons/sale/views/sale_views.xml
+++ b/addons/sale/views/sale_views.xml
@@ -313,6 +313,7 @@
<field name="qty_to_invoice" invisible="1"/>
<field name="qty_delivered_manual" invisible="1"/>
<field name="qty_delivered_method" invisible="1"/>
+ <field name="price_total" invisible="1"/>
<field name="price_subtotal" invisible="1"/>
<label for="product_uom_qty" string="Ordered Quantity"/>
<div>
@@ -479,6 +480,7 @@
<field name="product_uom_qty"/>
<field name="product_uom" groups="uom.group_uom"/>
<field name="price_subtotal"/>
+ <field name="price_total" invisible="1"/>
<field name="price_unit"/>
<field name="display_type"/>
<templates>
diff --git a/addons/web/static/src/js/views/field_manager_mixin.js b/addons/web/static/src/js/views/field_manager_mixin.js
index 343730cc7a4..bc61e92a89a 100644
--- a/addons/web/static/src/js/views/field_manager_mixin.js
+++ b/addons/web/static/src/js/views/field_manager_mixin.js
@@ -130,8 +130,10 @@ var FieldManagerMixin = {
if ('offset' in data) {
params.offset = data.offset;
}
- this.model.reload(data.id, params).then(function (db_id) {
- data.on_success(self.model.get(db_id));
+ this.mutex.exec(function () {
+ return self.model.reload(data.id, params).then(function (db_id) {
+ data.on_success(self.model.get(db_id));
+ });
});
},
/**
diff --git a/addons/web/static/src/js/views/view_dialogs.js b/addons/web/static/src/js/views/view_dialogs.js
index ee11afbc3bd..3df17bbf155 100644
--- a/addons/web/static/src/js/views/view_dialogs.js
+++ b/addons/web/static/src/js/views/view_dialogs.js
@@ -303,7 +303,7 @@ var SelectCreateDialog = ViewDialog.extend({
event.stopPropagation(); // prevent this event from bubbling up to the action manager
var d = event.data;
var searchData = this._process_search_data(d.domains, d.contexts, d.groupbys);
- this.list_controller.reload(searchData);
+ this.list_controller.reload(_.extend({offset: 0}, searchData));
},
get_controller_context: '_onGetControllerContext',
}),
diff --git a/addons/web/static/tests/fields/relational_fields_tests.js b/addons/web/static/tests/fields/relational_fields_tests.js
index 17fe5788663..e0ab5ae7a5f 100644
--- a/addons/web/static/tests/fields/relational_fields_tests.js
+++ b/addons/web/static/tests/fields/relational_fields_tests.js
@@ -524,6 +524,61 @@ QUnit.module('relational_fields', {
form.destroy();
});
+ QUnit.test('search more pager is reset when doing a new search', function (assert) {
+ assert.expect(6);
+ for(var i = 10; i < 180; i++) {
+ this.data.partner.records.push({
+ id: i,
+ display_name: "Partner " + i,
+ });
+ }
+
+ function stringToEvent ($element, string) {
+ for (var i = 0; i < string.length; i++) {
+ var keyAscii = string.charCodeAt(i);
+ $element.val($element.val()+string[i]);
+ $element.trigger($.Event('keyup', {which: keyAscii, keyCode:keyAscii}));
+ }
+ $element.trigger($.Event('keyup', {which: $.ui.keyCode.ENTER, keyCode:$.ui.keyCode.ENTER}));
+ }
+
+ this.data.partner.fields.datetime.searchable = true;
+ var form = createView({
+ View: FormView,
+ model: 'partner',
+ data: this.data,
+ arch: '<form string="Partners">' +
+ '<sheet>' +
+ '<group>' +
+ '<field name="trululu"/>' +
+ '</group>' +
+ '</sheet>' +
+ '</form>',
+ archs: {
+ 'partner,false,list': '<tree><field name="display_name"/></tree>',
+ 'partner,false,search': '<search><field name="datetime"/><field name="display_name"/></search>',
+ },
+ res_id: 1,
+ });
+
+ form.$buttons.find('.o_form_button_edit').click();
+ var $dropdown = form.$('.o_field_many2one input').autocomplete('widget');
+ form.$('.o_field_many2one input').click();
+ $dropdown.find('.o_m2o_dropdown_option:contains(Search)').mouseenter().click();
+ $('.modal .o_pager_next').click();
+
+ assert.strictEqual($('.o_pager_limit').text(), "1173", "there should be 173 records");
+ assert.strictEqual($('.o_pager_value').text(), "181-160", "should display the second page");
+ assert.strictEqual($('tr.o_data_row').length, 80, "should display 80 record");
+
+ stringToEvent($('.modal .o_searchview_input'), 'first');
+
+ assert.strictEqual($('.o_pager_limit').text(), "11", "there should be 1 record");
+ assert.strictEqual($('.o_pager_value').text(), "11-1", "should display the first page");
+ assert.strictEqual($('tr.o_data_row').length, 1, "should display 1 record");
+ form.destroy();
+ });
+
QUnit.test('onchanges on many2ones trigger when editing record in form view', function (assert) {
assert.expect(10);
@@ -10906,6 +10961,48 @@ QUnit.module('relational_fields', {
form.destroy();
});
+ QUnit.test('quickly switch between pages in one2many list', function (assert) {
+ assert.expect(2);
+
+ this.data.partner.records[0].turtles = [1, 2, 3];
+
+ var readDefs = [$.when(), $.Deferred(), $.Deferred()];
+ var form = createView({
+ View: FormView,
+ model: 'partner',
+ data: this.data,
+ arch: '<form string="Partners">' +
+ '<field name="turtles">' +
+ '<tree limit="1">' +
+ '<field name="display_name"/>' +
+ '</tree>' +
+ '</field>' +
+ '</form>',
+ mockRPC: function (route, args) {
+ var result = this._super.apply(this, arguments);
+ if (args.method === 'read') {
+ var recordID = args.args[0][0];
+ return $.when(readDefs[recordID - 1]).then(_.constant(result));
+ }
+ return result;
+ },
+ res_id: 1,
+ });
+
+ form.$('.o_field_widget[name=turtles] .o_pager_next').click();
+ form.$('.o_field_widget[name=turtles] .o_pager_next').click();
+
+ readDefs[1].resolve();
+
+ assert.strictEqual(form.$('.o_field_widget[name=turtles] .o_data_cell').text(), 'donatello');
+
+ readDefs[2].resolve();
+
+ assert.strictEqual(form.$('.o_field_widget[name=turtles] .o_data_cell').text(), 'raphael');
+
+ form.destroy();
+ });
+
QUnit.module('FieldMany2Many');
QUnit.test('many2many kanban: edition', function (assert) {
diff --git a/addons/website/models/website.py b/addons/website/models/website.py
index ee2d4322782..252ec58ee14 100644
--- a/addons/website/models/website.py
+++ b/addons/website/models/website.py
@@ -1254,7 +1254,7 @@ class WebsiteRedirect(models.Model):
_order = "sequence, id"
_rec_name = 'url_from'
- type = fields.Selection([('301', 'Moved permanently (301)'), ('302', 'Moved temporarily (302)')], string='Redirection Type', required=True)
+ type = fields.Selection([('301', 'Moved permanently (301)'), ('302', 'Moved temporarily (302)')], string='Redirection Type', required=True, default='301')
url_from = fields.Char('Redirect From', required=True)
url_to = fields.Char('Redirect To', required=True)
website_id = fields.Many2one('website', 'Website')
diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py
index 0b5ed81a6e5..4f0f84cebf6 100644
--- a/addons/website_sale/controllers/main.py
+++ b/addons/website_sale/controllers/main.py
@@ -568,7 +568,7 @@ class WebsiteSale(ProductConfiguratorController):
except ValidationError:
error["vat"] = 'error'
- if [err for err in error.items() if err == 'missing']:
+ if [err for err in error.values() if err == 'missing']:
error_message.append(_('Some required fields are empty.'))
return error, error_message
diff --git a/addons/website_slides/views/website_slides_embed.xml b/addons/website_slides/views/website_slides_embed.xml
index 35731f1f4cc..7470c27dbd0 100644
--- a/addons/website_slides/views/website_slides_embed.xml
+++ b/addons/website_slides/views/website_slides_embed.xml
@@ -124,7 +124,7 @@
</a>
</div>
<div class="col-auto text-right ml-auto mt-2 mb-2">
- <a t-if="slide.download_security and not is_embedded" target="_top" t-attf-href="/slides/slide/#{slug(slide)}/download" title="Download" id="download">
+ <a t-if="slide.download_security != 'none' and not is_embedded" target="_top" t-attf-href="/slides/slide/#{slug(slide)}/download" title="Download" id="download">
<i class="fa fa-download fa-2x" role="img" aria-label="Download"></i>
</a>
<span id="fullscreen" title="View fullscreen" role="img" aria-label="Fullscreen">
diff --git a/doc/cla/corporate/merchise.md b/doc/cla/corporate/merchise.md
index e4cbd3c3f95..64d5b277ccd 100644
--- a/doc/cla/corporate/merchise.md
+++ b/doc/cla/corporate/merchise.md
@@ -21,3 +21,4 @@ Medardo Rodríguez med@merchise.org https://github.com/med-merchise
Abel Firvida firvida@merchise.org
Abel Firvida abel@merchise.org
Mónica Díaz Pena monicadp@merchise.org https://github.com/mdpena
+Larisa González larisa@merchise.org
diff --git a/odoo/addons/base/models/ir_actions.py b/odoo/addons/base/models/ir_actions.py
index 428fabd6dcf..aa64b207407 100644
--- a/odoo/addons/base/models/ir_actions.py
+++ b/odoo/addons/base/models/ir_actions.py
@@ -394,7 +394,7 @@ class IrActionsServer(models.Model):
# Create
crud_model_id = fields.Many2one('ir.model', string='Create/Write Target Model',
oldname='srcmodel_id', help="Model for record creation / update. Set this field only to specify a different model than the base model.")
- crud_model_name = fields.Char(related='crud_model_id.name', readonly=True)
+ crud_model_name = fields.Char(related='crud_model_id.model', string='Target Model', readonly=True)
link_field_id = fields.Many2one('ir.model.fields', string='Link using field',
help="Provide the field used to link the newly created record "
"on the record on used by the server action.")
diff --git a/odoo/models.py b/odoo/models.py
index d426789c757..96c6d5c3d76 100644
--- a/odoo/models.py
+++ b/odoo/models.py
@@ -2766,14 +2766,16 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
# retrieve results from records; this takes values from the cache and
# computes remaining fields
+ self = self.with_prefetch(self._prefetch.copy())
data = {record: {'id': record.id} for record in self}
missing = set()
use_name_get = (load == '_classic_read')
for name in (stored + inherited + computed):
convert = self._fields[name].convert_to_read
- # read every field with prefetching limited to self; this avoids
+ # restrict the prefetching of self's model to self; this avoids
# computing fields on a larger recordset than self
- for record in self.with_prefetch():
+ self._prefetch[self._name] = set(self._ids)
+ for record in self:
try:
data[record][name] = convert(record[name], record, use_name_get)
except MissingError:
diff --git a/odoo/modules/module.py b/odoo/modules/module.py
index 93be467b0f3..e732104f3f2 100644
--- a/odoo/modules/module.py
+++ b/odoo/modules/module.py
@@ -128,17 +128,17 @@ def initialize_sys_path():
global ad_paths
global hooked
- dd = tools.config.addons_data_dir
+ dd = os.path.normcase(tools.config.addons_data_dir)
if os.access(dd, os.R_OK) and dd not in ad_paths:
ad_paths.append(dd)
for ad in tools.config['addons_path'].split(','):
- ad = os.path.abspath(tools.ustr(ad.strip()))
+ ad = os.path.normcase(os.path.abspath(tools.ustr(ad.strip())))
if ad not in ad_paths:
ad_paths.append(ad)
# add base module path
- base_path = os.path.abspath(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'addons'))
+ base_path = os.path.normcase(os.path.abspath(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'addons')))
if base_path not in ad_paths and os.path.isdir(base_path):
ad_paths.append(base_path)