diff options
| author | Christophe Simonis <chs@odoo.com> | 2018-09-26 19:37:29 +0200 |
|---|---|---|
| committer | Christophe Simonis <chs@odoo.com> | 2018-09-26 19:37:29 +0200 |
| commit | 5f08d82bcd7fa0eaed7c0b0f35c7221c5e0b657a (patch) | |
| tree | 1d1be253f568f18ffd0f7b2bd67577b77afaa3bd /addons | |
| parent | 7b13888c8e258a05a8044b7566b949071a911eab (diff) | |
| parent | fd122aec52166a2d19fe80579dbf9c98c6ab41fa (diff) | |
[MERGE] forward port branch 11.0 up to fd122aec521
Diffstat (limited to 'addons')
48 files changed, 427 insertions, 66 deletions
diff --git a/addons/account/controllers/mail.py b/addons/account/controllers/mail.py index 564856b909c..71c06faa44d 100644 --- a/addons/account/controllers/mail.py +++ b/addons/account/controllers/mail.py @@ -24,7 +24,7 @@ class MailController(MailController): except AccessError: if record_sudo.access_token and consteq(record_sudo.access_token, access_token): record_action = record_sudo.with_context( - force_website=True).get_access_action(uid) + force_website=True).get_access_action() if record_action['type'] == 'ir.actions.act_url': return werkzeug.utils.redirect(record_action['url']) return super(MailController, cls)._redirect_to_record(model, res_id, access_token=access_token) diff --git a/addons/account/models/account.py b/addons/account/models/account.py index cc303ec1309..7179b7f05f9 100644 --- a/addons/account/models/account.py +++ b/addons/account/models/account.py @@ -177,6 +177,8 @@ class AccountAccount(models.Model): @api.onchange('internal_type') def onchange_internal_type(self): self.reconcile = self.internal_type in ('receivable', 'payable') + if self.internal_type == 'liquidity': + self.reconcile = False @api.onchange('code') def onchange_code(self): diff --git a/addons/account/models/account_invoice.py b/addons/account/models/account_invoice.py index 4baac419a5f..249480c0ee4 100644 --- a/addons/account/models/account_invoice.py +++ b/addons/account/models/account_invoice.py @@ -1475,7 +1475,7 @@ class AccountInvoiceLine(models.Model): ondelete='set null', index=True, oldname='uos_id') product_id = fields.Many2one('product.product', string='Product', ondelete='restrict', index=True) - product_image = fields.Binary('Product Image', related="product_id.image", store=False) + product_image = fields.Binary('Product Image', related="product_id.image", store=False, readonly=True) account_id = fields.Many2one('account.account', string='Account', required=True, domain=[('deprecated', '=', False)], default=_default_account, diff --git a/addons/account/views/account_view.xml b/addons/account/views/account_view.xml index 40f01b1e1bc..c0aa8478ca1 100644 --- a/addons/account/views/account_view.xml +++ b/addons/account/views/account_view.xml @@ -22,8 +22,8 @@ <field name="company_id" options="{'no_create': True}" groups="base.group_multi_company"/> <field name="currency_id" options="{'no_create': True}" groups="base.group_multi_currency"/> <field name="internal_type" invisible="1" readonly="1"/> - <label for="reconcile"/> - <div> + <label for="reconcile" attrs="{'invisible': [('internal_type','=','liquidity')]}"/> + <div attrs="{'invisible': [('internal_type','=','liquidity')]}"> <field name="reconcile"/> <button name="action_open_reconcile" class="oe_link" type="object" string=" -> Reconcile" attrs="{'invisible': [('reconcile', '=', False)]}"/> </div> diff --git a/addons/account_payment/controllers/payment.py b/addons/account_payment/controllers/payment.py index 5d6ab903cb2..d34d29266c9 100644 --- a/addons/account_payment/controllers/payment.py +++ b/addons/account_payment/controllers/payment.py @@ -27,7 +27,7 @@ class PaymentPortal(http.Controller): except: return False - if request.env.user == request.env.ref('base.public_user'): + if request.env.user._is_public(): save_token = False # we avoid to create a token for the public user token = request.env['payment.token'].sudo() # currently no support of payment tokens diff --git a/addons/account_payment/controllers/portal.py b/addons/account_payment/controllers/portal.py index 28bca2a12a8..c5b86c47250 100644 --- a/addons/account_payment/controllers/portal.py +++ b/addons/account_payment/controllers/portal.py @@ -11,7 +11,7 @@ class PortalAccount(PortalAccount): values = super(PortalAccount, self)._invoice_get_page_view_values(invoice, access_token, **kwargs) payment_inputs = request.env['payment.acquirer']._get_available_payment_input(company=invoice.company_id) # if not connected (using public user), the method _get_available_payment_input will return public user tokens - is_public_user = request.env.ref('base.public_user') == request.env.user + is_public_user = request.env.user._is_public() if is_public_user: # we should not display payment tokens owned by the public user payment_inputs.pop('pms', None) diff --git a/addons/calendar/models/calendar.py b/addons/calendar/models/calendar.py index 81512af9b2e..04eb4013642 100644 --- a/addons/calendar/models/calendar.py +++ b/addons/calendar/models/calendar.py @@ -1082,9 +1082,8 @@ class Meeting(models.Model): else: sort_fields[field] = self[field] if isinstance(self[field], models.BaseModel): - name_get = self[field].name_get() - if len(name_get) and len(name_get[0]) >= 2: - sort_fields[field] = name_get[0][1] + name_get = self[field].mapped('display_name') + sort_fields[field] = name_get and name_get[0] or '' if r_date: sort_fields['sort_start'] = r_date.strftime(VIRTUALID_DATETIME_FORMAT) else: diff --git a/addons/document/static/src/js/document.js b/addons/document/static/src/js/document.js index 98bfe4e5ef3..5c33a3f3cff 100644 --- a/addons/document/static/src/js/document.js +++ b/addons/document/static/src/js/document.js @@ -50,10 +50,9 @@ Sidebar.include({ * @override */ updateEnv: function (env) { - if (this.hasAttachments) { - this.env = env; - this._updateAttachments().then(this._redraw.bind(this)); - } + var _super = _.bind(this._super, this, env); + var def = this.hasAttachments ? this._updateAttachments() : $.when(); + def.then(_super); }, //-------------------------------------------------------------------------- diff --git a/addons/iap/models/iap.py b/addons/iap/models/iap.py index 6f24205f8d4..2f7053b7c74 100644 --- a/addons/iap/models/iap.py +++ b/addons/iap/models/iap.py @@ -146,7 +146,8 @@ class IapAccount(models.Model): def get(self, service_name): account = self.search([('service_name', '=', service_name), ('company_id', 'in', [self.env.user.company_id.id, False])]) if not account: - account = self.create({'service_name': service_name}) + # TODO: remove this sudo in v12 as we change the user rights. + account = self.sudo().create({'service_name': service_name}).with_env(self.env) # Since the account did not exist yet, we will encounter a NoCreditError, # which is going to rollback the database and undo the account creation, # preventing the process to continue any further. diff --git a/addons/l10n_co/data/account.account.template.csv b/addons/l10n_co/data/account.account.template.csv index b68f925a074..6eb0e2372ac 100644 --- a/addons/l10n_co/data/account.account.template.csv +++ b/addons/l10n_co/data/account.account.template.csv @@ -1,5 +1,5 @@ id,code,name,reconcile,user_type_id:id,chart_template_id:id -co_puc_110505,110505,Caja General,TRUE,account.data_account_type_liquidity,l10n_co_chart_template_generic +co_puc_110505,110505,Caja General,FALSE,account.data_account_type_liquidity,l10n_co_chart_template_generic co_puc_120535,120535,Comercio al Por Mayor y al Por Menor,FALSE,account.data_account_type_current_assets,l10n_co_chart_template_generic co_puc_129595,129595,Diversas,FALSE,account.data_account_type_current_assets,l10n_co_chart_template_generic co_puc_130505,130505,Nacionales,TRUE,account.data_account_type_receivable,l10n_co_chart_template_generic diff --git a/addons/l10n_cr/data/account_template_data.xml b/addons/l10n_cr/data/account_template_data.xml index ba4ac297c0e..fcc4426b84a 100644 --- a/addons/l10n_cr/data/account_template_data.xml +++ b/addons/l10n_cr/data/account_template_data.xml @@ -8,7 +8,7 @@ <field name="code">0-111301</field> <field name="name">0-Cuenta PayPal 1</field> <field name="user_type_id" ref="account.data_account_type_liquidity"/> - <field name="reconcile" eval="True"/> + <field name="reconcile" eval="False"/> <field name="chart_template_id" ref="account_chart_template_0"/> </record> <record id="account_account_template_0_111401" model="account.account.template"> diff --git a/addons/l10n_in/views/report_invoice.xml b/addons/l10n_in/views/report_invoice.xml index f20fee72efd..452fc1e1c02 100644 --- a/addons/l10n_in/views/report_invoice.xml +++ b/addons/l10n_in/views/report_invoice.xml @@ -26,7 +26,7 @@ </t> </xpath> <xpath expr="//table[@name='invoice_line_table']" position="replace"> - <table class="table table-condensed" name="invoice_line_table"> + <table class="table table-condensed" name="invoice_line_table" groups="!sale.group_sale_layout"> <thead> <tr> <th>Description</th> diff --git a/addons/mail/models/mail_thread.py b/addons/mail/models/mail_thread.py index 99aa3a2df2f..f21de36c28f 100644 --- a/addons/mail/models/mail_thread.py +++ b/addons/mail/models/mail_thread.py @@ -1193,6 +1193,7 @@ class MailThread(models.AbstractModel): # if a new thread is created, parent is irrelevant message_dict.pop('parent_id', None) thread = MessageModel.message_new(message_dict, custom_values) + thread_id = thread.id else: if thread_id: raise ValueError("Posting a message without model should be with a null res_id, to create a private message.") diff --git a/addons/mass_mailing/models/mass_mailing.py b/addons/mass_mailing/models/mass_mailing.py index 59901756398..9ea923168a1 100644 --- a/addons/mass_mailing/models/mass_mailing.py +++ b/addons/mass_mailing/models/mass_mailing.py @@ -235,7 +235,7 @@ class MassMailingCampaign(models.Model): mass_mailing_ids = fields.One2many( 'mail.mass_mailing', 'mass_mailing_campaign_id', string='Mass Mailings') - unique_ab_testing = fields.Boolean(string='Allow A/B Testing', default=True, + unique_ab_testing = fields.Boolean(string='Allow A/B Testing', default=False, help='If checked, recipients will be mailed only once for the whole campaign. ' 'This lets you send different mailings to randomly selected recipients and test ' 'the effectiveness of the mailings, without causing duplicate messages.') diff --git a/addons/point_of_sale/models/pos_order.py b/addons/point_of_sale/models/pos_order.py index 8eb6b272f24..c2211e894c7 100644 --- a/addons/point_of_sale/models/pos_order.py +++ b/addons/point_of_sale/models/pos_order.py @@ -465,7 +465,7 @@ class PosOrder(models.Model): def _filtered_for_reconciliation(self): filter_states = ['invoiced', 'done'] - if self.env['ir.config_parameter'].get_param('point_of_sale.order_reconcile_mode', 'all') == 'partner_only': + if self.env['ir.config_parameter'].sudo().get_param('point_of_sale.order_reconcile_mode', 'all') == 'partner_only': return self.filtered(lambda order: order.state in filter_states and order.partner_id) return self.filtered(lambda order: order.state in filter_states) diff --git a/addons/point_of_sale/tests/test_anglo_saxon.py b/addons/point_of_sale/tests/test_anglo_saxon.py index b6d27af9505..8bc642ab7ce 100644 --- a/addons/point_of_sale/tests/test_anglo_saxon.py +++ b/addons/point_of_sale/tests/test_anglo_saxon.py @@ -36,9 +36,13 @@ class TestAngloSaxonCommon(common.TransactionCase): self.product = self.product.copy({'name': 'New product','standard_price': 100}) self.company.anglo_saxon_accounting = True self.product.categ_id = self.category + self.product.property_account_expense_id = account_expense + self.product.property_account_income_id = self.account sale_journal = self.env['account.journal'].create({'name': 'POS journal', 'type': 'sale', 'code': 'POS00'}) self.pos_config.journal_id = sale_journal self.cash_journal = self.env['account.journal'].create({'name': 'CASH journal', 'type': 'cash', 'code': 'CSH00'}) + self.pos_config.invoice_journal_id = False + self.pos_config.journal_ids = [self.cash_journal.id] class TestAngloSaxonFlow(TestAngloSaxonCommon): diff --git a/addons/portal/controllers/mail.py b/addons/portal/controllers/mail.py index 89dbded3676..1abf05b4e63 100644 --- a/addons/portal/controllers/mail.py +++ b/addons/portal/controllers/mail.py @@ -37,7 +37,7 @@ def _message_post_helper(res_model='', res_id=None, message='', token='', nosubs access_as_sudo = _has_token_access(res_model, res_id, token=token) if access_as_sudo: record = record.sudo() - if request.env.user == request.env.ref('base.public_user'): + if request.env.user._is_public(): author_id = record.partner_id.id if hasattr(record, 'partner_id') else author_id else: if not author_id: diff --git a/addons/product/models/product.py b/addons/product/models/product.py index 525fed94200..98d1e3392c5 100644 --- a/addons/product/models/product.py +++ b/addons/product/models/product.py @@ -123,6 +123,7 @@ class ProductProduct(models.Model): image_medium = fields.Binary( "Medium-sized image", compute='_compute_images', inverse='_set_image_medium', help="Image of the product variant (Medium-sized image of product template if false).") + is_product_variant = fields.Boolean(compute='_compute_is_product_variant') standard_price = fields.Float( 'Cost', company_dependent=True, @@ -150,6 +151,10 @@ class ProductProduct(models.Model): def _get_invoice_policy(self): return False + def _compute_is_product_variant(self): + for product in self: + product.is_product_variant = True + def _compute_product_price(self): prices = {} pricelist_id_or_name = self._context.get('pricelist') diff --git a/addons/product/models/product_template.py b/addons/product/models/product_template.py index 34fc7b6f978..c4566a7d981 100644 --- a/addons/product/models/product_template.py +++ b/addons/product/models/product_template.py @@ -239,10 +239,7 @@ class ProductTemplate(models.Model): def _compute_is_product_variant(self): for template in self: - if template._name == 'product.template': - template.is_product_variant = False - else: - template.is_product_variant = True + template.is_product_variant = False @api.model def _get_weight_uom_id_from_ir_config_parameter(self): diff --git a/addons/product/tests/common.py b/addons/product/tests/common.py index cc812db81a2..559b8b9dcfa 100644 --- a/addons/product/tests/common.py +++ b/addons/product/tests/common.py @@ -36,6 +36,7 @@ class TestProductCommon(common.SavepointCase): cls.product_1 = Product.create({ 'name': 'Courage', 'type': 'consu', + 'default_code': 'PROD-1', 'uom_id': cls.uom_dunit.id, 'uom_po_id': cls.uom_dunit.id}) diff --git a/addons/product/tests/test_variants.py b/addons/product/tests/test_variants.py index 804bbc55c95..92ca4522566 100644 --- a/addons/product/tests/test_variants.py +++ b/addons/product/tests/test_variants.py @@ -60,6 +60,14 @@ class TestVariants(common.TestProductCommon): self.size_attr_value_l = self.env['product.attribute.value'].create({'name': 'L', 'attribute_id': self.size_attr.id}) return res + def test_variants_is_product_variant(self): + template = self.product_7_template + variants = template.product_variant_ids + self.assertFalse(template.is_product_variant, + 'Product template is not a variant') + self.assertEqual({True}, set(v.is_product_variant for v in variants), + 'Product variants are variants') + def test_variants_creation_mono(self): test_template = self.env['product.template'].create({ 'name': 'Sofa', diff --git a/addons/project/models/project.py b/addons/project/models/project.py index abfee026479..896e972f6d5 100644 --- a/addons/project/models/project.py +++ b/addons/project/models/project.py @@ -271,7 +271,9 @@ class Project(models.Model): def map_tasks(self, new_project_id): """ copy and map tasks from old to new project """ tasks = self.env['project.task'] - for task in self.tasks: + # We want to copy archived task, but do not propagate an active_test context key + task_ids = self.env['project.task'].with_context(active_test=False).search([('project_id', '=', self.id)]).ids + for task in self.env['project.task'].browse(task_ids): # preserve task name and stage, normally altered during copy defaults = {'stage_id': task.stage_id.id, 'name': task.name} @@ -283,7 +285,6 @@ class Project(models.Model): def copy(self, default=None): if default is None: default = {} - self = self.with_context(active_test=False) if not default.get('name'): default['name'] = _("%s (copy)") % (self.name) project = super(Project, self).copy(default) diff --git a/addons/project/views/project_views.xml b/addons/project/views/project_views.xml index 8d85df10b3d..7b524b9513a 100644 --- a/addons/project/views/project_views.xml +++ b/addons/project/views/project_views.xml @@ -731,7 +731,7 @@ <field name="name">Project's tasks</field> <field name="view_type">form</field> <field name="view_mode">tree,form,calendar,graph,kanban</field> - <field name="domain">[('project_id', 'child_of', [active_id])]</field> + <field name="domain">[('project_id', '=', active_id)]</field> <field name="context">{'project_id':active_id}</field> </record> diff --git a/addons/purchase/tests/test_create_picking.py b/addons/purchase/tests/test_create_picking.py index c4c4e78e342..8441ce3bbab 100644 --- a/addons/purchase/tests/test_create_picking.py +++ b/addons/purchase/tests/test_create_picking.py @@ -119,6 +119,7 @@ class TestCreatePicking(common.TestProductCommon): 'route_ids': [(4, self.ref('stock.route_warehouse0_mto')), (4, self.ref('purchase.route_warehouse0_buy'))], 'seller_ids': [(6, 0, [seller.id])], 'categ_id': self.env.ref('product.product_category_all').id, + 'supplier_taxes_id': [(6, 0, [])], }) customer_move = self.env['stock.move'].create({ diff --git a/addons/purchase/views/purchase_views.xml b/addons/purchase/views/purchase_views.xml index d21314ad09f..66936967998 100644 --- a/addons/purchase/views/purchase_views.xml +++ b/addons/purchase/views/purchase_views.xml @@ -218,6 +218,7 @@ </tree> <form string="Purchase Order Line"> <sheet> + <field name="state" invisible="1"/> <group> <group> <field name="product_id" diff --git a/addons/sale/controllers/mail.py b/addons/sale/controllers/mail.py index d257bfa2736..6b82146d400 100644 --- a/addons/sale/controllers/mail.py +++ b/addons/sale/controllers/mail.py @@ -24,7 +24,7 @@ class MailController(MailController): except AccessError: if record_sudo.access_token and consteq(record_sudo.access_token, access_token): record_action = record_sudo.with_context( - force_website=True).get_access_action(uid) + force_website=True).get_access_action() if record_action['type'] == 'ir.actions.act_url': return werkzeug.utils.redirect(record_action['url']) return super(MailController, cls)._redirect_to_record(model, res_id, access_token=access_token) diff --git a/addons/sale_payment/controllers/payment.py b/addons/sale_payment/controllers/payment.py index db94060df40..585399c63d8 100644 --- a/addons/sale_payment/controllers/payment.py +++ b/addons/sale_payment/controllers/payment.py @@ -30,7 +30,7 @@ class PaymentPortal(http.Controller): # we check if the order need to create a payment token save_token = save_token or order_sudo._get_payment_type() == "form_save" - if request.env.user == request.env.ref('base.public_user'): + if request.env.user._is_public(): save_token = False token = request.env['payment.token'].sudo() # currently no support of payment tokens @@ -74,7 +74,7 @@ class PaymentPortal(http.Controller): except (ValueError, TypeError): token = False - token_owner = order_sudo.partner_id if request.env.user == request.env.ref('base.public_user') else request.env.user.partner_id + token_owner = order_sudo.partner_id if request.env.user._is_public() else request.env.user.partner_id if not token or token.partner_id != token_owner: params['error'] = 'pay_sale_invalid_token' return request.redirect(_build_url_w_params(error_url, params)) diff --git a/addons/sale_payment/controllers/portal.py b/addons/sale_payment/controllers/portal.py index 9b554c19c34..14a44786f44 100644 --- a/addons/sale_payment/controllers/portal.py +++ b/addons/sale_payment/controllers/portal.py @@ -12,7 +12,7 @@ class CustomerPortal(CustomerPortal): if values['portal_confirmation'] == 'pay': payment_inputs = request.env['payment.acquirer']._get_available_payment_input(order.partner_id, order.company_id) # if not connected (using public user), the method _get_available_payment_input will return public user tokens - is_public_user = request.env.ref('base.public_user') == request.env.user + is_public_user = request.env.user._is_public() if is_public_user: # we should not display payment tokens owned by the public user payment_inputs.pop('pms', None) diff --git a/addons/sale_stock/models/sale_order.py b/addons/sale_stock/models/sale_order.py index 6ce7ead5762..5a2b57e39c4 100644 --- a/addons/sale_stock/models/sale_order.py +++ b/addons/sale_stock/models/sale_order.py @@ -235,7 +235,10 @@ class SaleOrderLine(models.Model): return {} if self.product_id.type == 'product': precision = self.env['decimal.precision'].precision_get('Product Unit of Measure') - product = self.product_id.with_context(warehouse=self.order_id.warehouse_id.id) + product = self.product_id.with_context( + warehouse=self.order_id.warehouse_id.id, + lang=self.order_id.partner_id.lang or self.env.user.lang or 'en_US' + ) product_qty = self.product_uom._compute_quantity(self.product_uom_qty, self.product_id.uom_id) if float_compare(product.virtual_available, product_qty, precision_digits=precision) == -1: is_available = self._check_routing() diff --git a/addons/stock/data/stock_demo.xml b/addons/stock/data/stock_demo.xml index 982d24fc9ad..50084be790a 100644 --- a/addons/stock/data/stock_demo.xml +++ b/addons/stock/data/stock_demo.xml @@ -14,26 +14,31 @@ <field name="location_id" ref="stock_location_suppliers"/> <field name="usage">supplier</field> <field name="barcode">2601985</field> + <field name="company_id"></field> </record> <record id="stock_location_4" model="stock.location"> <field name="name">Big Vendors</field> <field name="location_id" ref="stock_location_3"/> <field name="usage">supplier</field> + <field name="company_id"></field> </record> <record id="stock_location_5" model="stock.location"> <field name="name">Generic IT Vendors</field> <field name="location_id" ref="stock_location_3"/> <field name="usage">supplier</field> + <field name="company_id"></field> </record> <record id="stock_location_7" model="stock.location"> <field name="name">European Customers</field> <field name="location_id" ref="stock_location_customers"/> <field name="usage">customer</field> + <field name="company_id"></field> </record> <record id="stock_location_8" model="stock.location"> <field name="name">Non European Customers</field> <field name="location_id" ref="stock_location_customers"/> <field name="usage">customer</field> + <field name="company_id"></field> </record> diff --git a/addons/stock/i18n/stock.pot b/addons/stock/i18n/stock.pot index c6eb1b71d00..14c13da3e5b 100644 --- a/addons/stock/i18n/stock.pot +++ b/addons/stock/i18n/stock.pot @@ -3333,6 +3333,11 @@ msgid "One product only" msgstr "" #. module: stock +#: model:ir.ui.view,arch_db:stock.view_quant_package_form +msgid "Ongoing Package Creation: Content" +msgstr "" + +#. module: stock #: model:ir.model.fields,field_description:stock.field_stock_location_path__name msgid "Operation Name" msgstr "" diff --git a/addons/stock/models/product.py b/addons/stock/models/product.py index ffe8b54e3a5..2ee2bc1ce90 100644 --- a/addons/stock/models/product.py +++ b/addons/stock/models/product.py @@ -159,7 +159,7 @@ class Product(models.Model): if self.env.context.get('company_owned', False): company_id = self.env.user.company_id.id return ( - [('location_id.company_id', '=', company_id)], + [('location_id.company_id', '=', company_id), ('location_id.usage', 'in', ['internal', 'transit'])], [('location_id.company_id', '=', False), ('location_dest_id.company_id', '=', company_id)], [('location_id.company_id', '=', company_id), ('location_dest_id.company_id', '=', False), ]) diff --git a/addons/stock/models/stock_move.py b/addons/stock/models/stock_move.py index 47451caeb09..434137c1ada 100644 --- a/addons/stock/models/stock_move.py +++ b/addons/stock/models/stock_move.py @@ -1033,7 +1033,7 @@ class StockMove(models.Model): if move.propagate: # only cancel the next move if all my siblings are also cancelled if all(state == 'cancel' for state in siblings_states): - move.move_dest_ids._action_cancel() + move.move_dest_ids.filtered(lambda m: m.state != 'done')._action_cancel() else: if all(state in ('done', 'cancel') for state in siblings_states): move.move_dest_ids.write({'procure_method': 'make_to_stock'}) @@ -1043,6 +1043,7 @@ class StockMove(models.Model): def _prepare_extra_move_vals(self, qty): vals = { + 'origin_returned_move_id': self.origin_returned_move_id.id, 'product_uom_qty': qty, 'picking_id': self.picking_id.id, 'price_unit': self.price_unit, @@ -1098,8 +1099,7 @@ class StockMove(models.Model): def _action_done(self): self.filtered(lambda move: move.state == 'draft')._action_confirm() # MRP allows scrapping draft moves - - moves = self.filtered(lambda x: x.state not in ('done', 'cancel')) + moves = self.exists().filtered(lambda x: x.state not in ('done', 'cancel')) moves_todo = self.env['stock.move'] # Cancel moves where necessary ; we should do it before creating the extra moves because diff --git a/addons/stock/models/stock_quant.py b/addons/stock/models/stock_quant.py index 4ee66d50af6..c1a7d55300e 100644 --- a/addons/stock/models/stock_quant.py +++ b/addons/stock/models/stock_quant.py @@ -460,7 +460,7 @@ class QuantPackage(models.Model): return action def _get_contained_quants(self): - return self.env['stock.quant'].search([('package_id', 'child_of', self.ids)]) + return self.env['stock.quant'].search([('package_id', 'in', self.ids)]) def _get_all_products_quantities(self): '''This function computes the different product quantities for the given package diff --git a/addons/stock/tests/test_move2.py b/addons/stock/tests/test_move2.py index 1f9cb8bcfdb..08329bd39aa 100644 --- a/addons/stock/tests/test_move2.py +++ b/addons/stock/tests/test_move2.py @@ -185,6 +185,30 @@ class TestPickShip(TestStockCommon): # the client picking should not be assigned anymore, as we returned partially what we took self.assertEqual(picking_client.state, 'confirmed') + def test_mto_moves_return_extra(self): + picking_pick, picking_client = self.create_pick_ship() + stock_location = self.env['stock.location'].browse(self.stock_location) + self.env['stock.quant']._update_available_quantity(self.productA, stock_location, 10.0) + + picking_pick.action_assign() + picking_pick.move_lines[0].move_line_ids[0].qty_done = 10.0 + picking_pick.action_done() + self.assertEqual(picking_pick.state, 'done') + self.assertEqual(picking_client.state, 'assigned') + + # return more than we've done + stock_return_picking = self.env['stock.return.picking']\ + .with_context(active_ids=picking_pick.ids, active_id=picking_pick.ids[0])\ + .create({}) + stock_return_picking.product_return_moves.quantity = 12.0 # Return 2 extra + stock_return_picking_action = stock_return_picking.create_returns() + return_pick = self.env['stock.picking'].browse(stock_return_picking_action['res_id']) + + # Verify the extra move has been merged with the original move + self.assertAlmostEqual(return_pick.move_lines.product_uom_qty, 12.0) + self.assertAlmostEqual(return_pick.move_lines.quantity_done, 0.0) + self.assertAlmostEqual(return_pick.move_lines.reserved_availability, 10.0) + def test_mto_resupply_cancel_ship(self): """ This test simulates a pick pack ship with a resupply route set. Pick and pack are validated, ship is cancelled. This test diff --git a/addons/stock/tests/test_warehouse.py b/addons/stock/tests/test_warehouse.py index 09214990028..9959d125b42 100644 --- a/addons/stock/tests/test_warehouse.py +++ b/addons/stock/tests/test_warehouse.py @@ -62,7 +62,7 @@ class TestWarehouse(TestStockCommon): # Check inventory obj details (1 inventory with 1 line, because 1 product change) inventory = self.env['stock.inventory'].search([('id', 'not in', self.existing_inventories.ids)]) self.assertEqual(len(inventory), 1) - self.assertIn('INV: %s' % self.product_1.name, inventory.name) + self.assertIn('INV: %s' % self.product_1.display_name, inventory.name) self.assertEqual(len(inventory.line_ids), 1) self.assertEqual(inventory.line_ids.product_id, self.product_1) self.assertEqual(inventory.line_ids.product_qty, 50.0) @@ -457,4 +457,4 @@ class TestResupply(TestStockCommon): 'product_min_qty': 10, 'product_max_qty': 100, 'product_uom': self.uom_unit.id, - })
\ No newline at end of file + }) diff --git a/addons/stock/views/stock_quant_views.xml b/addons/stock/views/stock_quant_views.xml index ba34ef03001..bc296eacda1 100644 --- a/addons/stock/views/stock_quant_views.xml +++ b/addons/stock/views/stock_quant_views.xml @@ -191,7 +191,7 @@ <field name="location_id"/> </group> </group> - <separator string="Content" /> + <separator string="Ongoing Package Creation: Content" attrs="{'invisible': [('current_picking_id', '=', False)]}"/> <field name="current_picking_id" invisible="1"/> <field name="current_picking_move_line_ids" readonly="1" attrs="{'invisible': [('current_picking_id', '=', False)]}"> <tree> @@ -201,6 +201,7 @@ <field name="product_uom_id" groups="uom.group_uom"/> </tree> </field> + <separator string="Content" attrs="{'invisible': [('current_picking_id', '=', True)]}"/> <field name="quant_ids" attrs="{'invisible': [('current_picking_id', '=', True)]}"> <tree> <field name="product_id"/> diff --git a/addons/stock_account/models/stock.py b/addons/stock_account/models/stock.py index 9b9e4239b05..00fd9b257bd 100644 --- a/addons/stock_account/models/stock.py +++ b/addons/stock_account/models/stock.py @@ -383,7 +383,8 @@ class StockMove(models.Model): qty_done = 0.0 if float_is_zero(product_tot_qty_available, precision_rounding=rounding): new_std_price = move._get_price_unit() - elif float_is_zero(product_tot_qty_available + move.product_qty, precision_rounding=rounding): + elif float_is_zero(product_tot_qty_available + move.product_qty, precision_rounding=rounding) or \ + float_is_zero(product_tot_qty_available + qty_done, precision_rounding=rounding): new_std_price = move._get_price_unit() else: # Get the standard price diff --git a/addons/stock_account/tests/test_stockvaluation.py b/addons/stock_account/tests/test_stockvaluation.py index ada1b155a93..dcf0b271ac1 100644 --- a/addons/stock_account/tests/test_stockvaluation.py +++ b/addons/stock_account/tests/test_stockvaluation.py @@ -3144,7 +3144,7 @@ class TestStockValuation(TransactionCase): self.assertEqual(move1.remaining_value, 10) self.assertEqual(move1.remaining_qty, 1) self.assertAlmostEqual(self.product1.qty_available, 0.0) - self.assertAlmostEqual(self.product1.qty_at_date, 2.0) + self.assertAlmostEqual(self.product1.qty_at_date, 1.0) self.assertEqual(self.product1.stock_value, 10) self.assertTrue(len(move1.account_move_ids), 1) diff --git a/addons/stock_landed_costs/models/stock_landed_cost.py b/addons/stock_landed_costs/models/stock_landed_cost.py index 2137b111a9e..df9757e3919 100644 --- a/addons/stock_landed_costs/models/stock_landed_cost.py +++ b/addons/stock_landed_costs/models/stock_landed_cost.py @@ -107,9 +107,9 @@ class LandedCost(models.Model): new_landed_cost_value = line.move_id.landed_cost_value + line.additional_landed_cost line.move_id.write({ 'landed_cost_value': new_landed_cost_value, - 'value': line.move_id.value + cost_to_add, + 'value': line.move_id.value + line.additional_landed_cost, 'remaining_value': line.move_id.remaining_value + cost_to_add, - 'price_unit': (line.move_id.value + cost_to_add) / line.move_id.product_qty, + 'price_unit': (line.move_id.value + line.additional_landed_cost) / line.move_id.product_qty, }) # `remaining_qty` is negative if the move is out and delivered proudcts that were not # in stock. diff --git a/addons/website/data/website_demo.xml b/addons/website/data/website_demo.xml index cf4f9453755..e1e67a2cbc6 100644 --- a/addons/website/data/website_demo.xml +++ b/addons/website/data/website_demo.xml @@ -243,5 +243,293 @@ response = request.render("website.template_partner_comment", { <field name="website_id" ref="website2"/> <field name="page_id" ref="website2_contactus_page" /> </record> + + <!-- BS Debug Page --> + <!-- Showcase all (most?) BS components and utilities --> + <record id="bs_debug_page" model="website.page"> + <field name="name">BS Debug</field> + <field name="url">/website/demo/bootstrap</field> + <field name="website_published">False</field> + <field name="type">qweb</field> + <field name="key">website.bs_debug_page_view</field> + <field name="arch" type="xml"> + <t name="Debug" t-name="website.bs_debug_page_view"> + <t t-call="website.layout"> + <t t-set="odoo_theme_colors" t-value="[['alpha', 'Alpha'], ['beta', 'Beta'], ['gamma', 'Gamma'], ['delta', 'Delta'], ['epsilon', 'Epsilon']]"/> + <t t-set="bs_basic_colors" t-value="[['primary', 'Primary'], ['default', 'Default']]"/> + <t t-set="bs_state_colors" t-value="[['success', 'Success'], ['info', 'Info'], ['warning', 'Warning'], ['danger', 'Danger']]"/> + <t t-set="bs_theme_colors" t-value="bs_basic_colors + bs_state_colors"/> + <t t-set="bs_gray_colors" t-value="[['white', 'White'], ['gray-lighter', 'Gray Lighter'], ['gray-light', 'Gray Light'], ['gray', 'Gray'], ['gray-dark', 'Gray Dark'], ['gray-darker', 'Gray Darker'], ['black', 'Black']]"/> + <div id="wrap oe_structure"> + <section class="py-2"> + <div class="container"> + <h1>Components</h1> + <div class="row"> + <div class="col-md-9"> + <h2>Badge</h2> + <span class="badge mb4">This is a badge</span> + + <h2 class="mt8">Label</h2> + <t t-foreach="bs_theme_colors" t-as="color"> + <span t-attf-class="label mb4 label-#{color[0]}"><t t-esc="color[1]"/></span> + </t> + <h3 class="mt8 h5">Link</h3> + <t t-foreach="bs_theme_colors" t-as="color"> + <a href="#" t-attf-class="label mb4 label-#{color[0]}"><t t-esc="color[1]"/></a> + </t> + <h3 class="mt8 h5">Autosizing</h3> + <div class="mt0 h3"> + <t t-foreach="bs_theme_colors" t-as="color"> + <span t-attf-class="label mb4 label-#{color[0]}"><t t-esc="color[1]"/></span> + </t> + </div> + + <h2 class="mt16">Button</h2> + <t t-foreach="odoo_theme_colors" t-as="color"> + <button type="button" t-attf-class="btn mb4 btn-#{color[0]}"><t t-esc="color[1]"/></button> + </t> + <br/> + <t t-foreach="bs_theme_colors" t-as="color"> + <button type="button" t-attf-class="btn mb4 btn-#{color[0]}"><t t-esc="color[1]"/></button> + </t> + <h3 class="mt8 h6">Extra Small</h3> + <t t-foreach="odoo_theme_colors" t-as="color"> + <button type="button" t-attf-class="btn mb4 btn-xs btn-#{color[0]}"><t t-esc="color[1]"/></button> + </t> + <br/> + <t t-foreach="bs_theme_colors" t-as="color"> + <button type="button" t-attf-class="btn mb4 btn-xs btn-#{color[0]}"><t t-esc="color[1]"/></button> + </t> + <h3 class="mt8 h5">Small</h3> + <t t-foreach="odoo_theme_colors" t-as="color"> + <button type="button" t-attf-class="btn mb4 btn-sm btn-#{color[0]}"><t t-esc="color[1]"/></button> + </t> + <br/> + <t t-foreach="bs_theme_colors" t-as="color"> + <button type="button" t-attf-class="btn mb4 btn-sm btn-#{color[0]}"><t t-esc="color[1]"/></button> + </t> + <h3 class="mt8 h5">Large</h3> + <t t-foreach="odoo_theme_colors" t-as="color"> + <button type="button" t-attf-class="btn mb4 btn-lg btn-#{color[0]}"><t t-esc="color[1]"/></button> + </t> + <br/> + <t t-foreach="bs_theme_colors" t-as="color"> + <button type="button" t-attf-class="btn mb4 btn-lg btn-#{color[0]}"><t t-esc="color[1]"/></button> + </t> + + <h2 class="mt16">Dropdown</h2> + <div class="dropdown"> + <button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown">Toggle <span class="caret"/></button> + <ul class="dropdown-menu"> + <li class="dropdown-header">Header</li> + <li><a href="#">Action</a></li> + <li><a href="#">Something else here</a></li> + <li class="divider"/> + <li><a href="#">Separated link</a></li> + </ul> + </div> + + <h2 class="mt16">Navbar</h2> + <nav class="navbar navbar-default"> + <div class="navbar-header"> + <a class="navbar-brand" href="#">Navbar</a> + <button class="navbar-toggle collapsed" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> + <span class="sr-only">Toggle navigation</span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + </button> + </div> + + <div class="collapse navbar-collapse" id="navbarSupportedContent"> + <ul class="nav navbar-nav"> + <li class="active"> + <a href="#">Home <span class="sr-only">(current)</span></a> + </li> + <li> + <a href="#">Link</a> + </li> + <li> + <a class="disabled" href="#">Disabled</a> + </li> + </ul> + <form class="navbar-form navbar-right"> + <input class="form-control" type="search" placeholder="Search" aria-label="Search"/> + <button class="btn btn-success" type="submit">Search</button> + </form> + </div> + </nav> + + <h2 class="mt16">Form</h2> + <form> + <div class="form-group"> + <label for="exampleInputEmail1">Email address</label> + <input type="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" placeholder="Enter email"/> + <small id="emailHelp" class="help-block text-muted">We'll never share your email with anyone else.</small> + </div> + </form> + + <h2 class="mt16">Pagination</h2> + <nav> + <ul class="pagination"> + <li class="disabled"> + <a href="#" tabindex="-1">Previous</a> + </li> + <li> + <a href="#">1</a> + </li> + <li class="active"> + <a href="#">2 <span class="sr-only">(current)</span></a> + </li> + <li> + <a href="#">3</a> + </li> + <li> + <a href="#">Next</a> + </li> + </ul> + </nav> + </div> + <div class="col-md-3"> + <h2>Alert</h2> + <t t-foreach="bs_state_colors" t-as="color"> + <div t-attf-class="alert alert-#{color[0]}"> + This is a "<t t-esc="color[1]"/>" alert with a <a href="#" class="alert-link">link</a>. + </div> + </t> + + <h2 class="mt16">Breadcrumb</h2> + <nav aria-label="breadcrumb"> + <ol class="breadcrumb"> + <li><a href="#">Home</a></li> + <li><a href="#">Library</a></li> + <li class="active" aria-current="page">Data</li> + </ol> + </nav> + + <h2 class="mt16">Card</h2> + <div class="panel panel-default"> + <div class="panel-heading"> + Card Header + </div> + <div class="panel-body"> + Card Body + </div> + <ul class="list-group"> + <li class="list-group-item">Item 1</li> + <li class="list-group-item">Item 2</li> + </ul> + <div class="panel-footer"> + Card Footer + </div> + </div> + </div> + </div> + </div> + </section> + <section class="py-2"> + <div class="container"> + <h1>Utilities & Typography</h1> + <div class="row"> + <div class="col-md-9"> + <div> + <t t-foreach="odoo_theme_colors" t-as="color"> + <div t-attf-class="bg-#{color[0]}" style="display: inline-block; padding: 4px 12px;"> + <t t-esc="color[1]"/> + </div> + </t> + </div> + <div class="mt8"> + <t t-foreach="bs_theme_colors" t-as="color"> + <div t-attf-class="bg-#{color[0]}" style="display: inline-block; padding: 4px 12px;"> + <t t-esc="color[1]"/> + </div> + </t> + </div> + <div class="mt8"> + <t t-foreach="bs_gray_colors" t-as="color"> + <div t-attf-class="bg-#{color[0]}" style="display: inline-block; padding: 4px 12px;"> + <t t-esc="color[1]"/> + </div> + </t> + </div> + <div class="mt16"> + <t t-foreach="odoo_theme_colors" t-as="color"> + <div t-attf-class="text-#{color[0]}" style="display: inline-block; padding: 4px 12px;"> + <t t-esc="color[1]"/> + </div> + </t> + </div> + <div class="mt8"> + <t t-foreach="bs_theme_colors" t-as="color"> + <div t-attf-class="text-#{color[0]}" style="display: inline-block; padding: 4px 12px;"> + <t t-esc="color[1]"/> + </div> + </t> + </div> + <div class="mt8"> + <t t-foreach="bs_gray_colors" t-as="color"> + <div t-attf-class="text-#{color[0]}" style="display: inline-block; padding: 4px 12px;"> + <t t-esc="color[1]"/> + </div> + </t> + </div> + </div> + <div class="col-md-3"> + <h1>Headings 1</h1> + <h2>Headings 2</h2> + <h3>Headings 3</h3> + <h4>Headings 4</h4> + <h5>Headings 5</h5> + <h6>Headings 6</h6> + <p>Paragraph with <strong>bold</strong>, <span class="text-muted">muted</span> and <em>italic</em> texts</p> + <p><a href="#">Link</a></p> + <p><button type="button" class="btn btn-link">Link button</button></p> + </div> + </div> + </div> + </section> + </div> + </t> + </t> + </field> + </record> + + <!-- Snippet Debug Page --> + <!-- Showcase all snippets --> + <record id="snippets_debug_page" model="website.page"> + <field name="name">Snippet Debug</field> + <field name="url">/website/demo/snippets</field> + <field name="website_published">False</field> + <field name="type">qweb</field> + <field name="key">website.snippets_debug_page_view</field> + <field name="arch" type="xml"> + <t name="Debug" t-name="website.snippets_debug_page_view"> + <t t-call="website.layout"> + <style> + #snippets_menu, #o_scroll > .o_panel > .o_panel_header { + display: none !important; + } + [data-oe-type="snippet"]:not([data-module-id])::before { + content: attr(name); + display: block; + padding: 16px; + background-color: lightgray; + color: black; + font-size: 24px; + } + [data-oe-type="snippet"]:not([data-module-id])::after { + content: ""; + display: table; + clear: both; + } + </style> + <div id="wrap oe_structure"> + <t t-call="website.snippets"/> + </div> + </t> + </t> + </field> + </record> </data> </odoo> diff --git a/addons/website/static/src/js/content/snippets.animation.js b/addons/website/static/src/js/content/snippets.animation.js index 602556c03cc..e28e1e0d14f 100644 --- a/addons/website/static/src/js/content/snippets.animation.js +++ b/addons/website/static/src/js/content/snippets.animation.js @@ -699,6 +699,7 @@ registry.gallery = Animation.extend({ * @param {Event} ev */ _onClickImg: function (ev) { + var self = this; var $cur = $(ev.currentTarget); var urls = []; @@ -743,7 +744,12 @@ registry.gallery = Animation.extend({ $modal.find('.modal-content, .modal-body.o_slideshow').css('height', '100%'); $modal.appendTo(document.body); - this.carousel = new registry.gallery_slider($modal.find('.carousel').carousel()); + $modal.one('shown.bs.modal', function () { + self.trigger_up('animation_start_demand', { + editableMode: false, + $target: $modal.find('.modal-body.o_slideshow'), + }); + }); }, }); diff --git a/addons/website/static/src/less/website.less b/addons/website/static/src/less/website.less index 4fdbb8db726..a8918608751 100644 --- a/addons/website/static/src/less/website.less +++ b/addons/website/static/src/less/website.less @@ -411,30 +411,27 @@ div.carousel .container { border-width: 0; position: absolute; bottom: 0; + width: 100%; + margin-left: 0; + left: 0%; > * { list-style-image: none; display: inline-block; width: 40px; height: 40px; - margin: 0 0px 5px 5px; + margin: 2.5px 2.5px 2.5px 2.5px; padding: 0; border: 1px solid #aaa; text-indent: initial; background-size: cover; background-color: #fff; border-radius: 0; + vertical-align: bottom; &:not(.active) { opacity: 0.8; - -webkit-filter: grayscale(100%); - filter: grayscale(100%); - filter: gray; - filter: url("data:image/svg+xml;utf8,<svg version='1.1' xmlns='http://www.w3.org/2000/svg' height='0'><filter id='greyscale'><feColorMatrix type='matrix' values='0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0' /></filter></svg>#greyscale"); - } - - &:first-child { - margin-left: 0; + filter: grayscale(1); } } } @@ -444,6 +441,12 @@ div.carousel .container { background-image: none; background-color: transparent; } + &.left * { + right: 0%; + } + &.right * { + left: 0%; + } } } } diff --git a/addons/website/static/src/xml/website.gallery.xml b/addons/website/static/src/xml/website.gallery.xml index 76bf650e76d..919da3c53d4 100644 --- a/addons/website/static/src/xml/website.gallery.xml +++ b/addons/website/static/src/xml/website.gallery.xml @@ -20,11 +20,11 @@ </div> <ul class="carousel-indicators"> - <li class="fa fa-chevron-left o_indicators_left" style="overflow: hidden; padding: 12px; border: 0;"></li> + <li class="fa fa-chevron-left o_indicators_left" style="overflow: hidden; padding: 12px; border: 0; visibility: hidden;"></li> <t t-foreach="srcs" t-as="src"> - <li t-attf-data-target="##{id}" t-att-data-slide-to="src_index" t-att-class="src_index == index and 'active'" t-attf-style="background-image: url(#{src})"></li> + <li t-attf-data-target="##{id}" t-att-data-slide-to="src_index" t-att-class="'hidden ' + (src_index == index and 'active')" t-attf-style="background-image: url(#{src})"></li> </t> - <li class="fa fa-chevron-right o_indicators_right" style="overflow: hidden; padding: 12px; border: 0;"></li> + <li class="fa fa-chevron-right o_indicators_right" style="overflow: hidden; padding: 12px; border: 0; visibility: hidden;"></li> </ul> <a class="carousel-control left" t-attf-href="##{id}" data-slide="prev"><span class="fa fa-chevron-left" /></a> diff --git a/addons/website_event/models/event.py b/addons/website_event/models/event.py index 25d2c5cf69f..8a3489100e7 100644 --- a/addons/website_event/models/event.py +++ b/addons/website_event/models/event.py @@ -26,7 +26,7 @@ class Event(models.Model): def _compute_is_participating(self): # we don't allow public user to see participating label - if self.env.user != self.env.ref('base.public_user'): + if not self.env.user._is_public(): email = self.env.user.partner_id.email for event in self: domain = ['&', '|', ('email', '=', email), ('partner_id', '=', self.env.user.partner_id.id), ('event_id', '=', event.id)] diff --git a/addons/website_sale/models/sale_order.py b/addons/website_sale/models/sale_order.py index 987bdaa6a66..6933805a136 100644 --- a/addons/website_sale/models/sale_order.py +++ b/addons/website_sale/models/sale_order.py @@ -17,8 +17,9 @@ class SaleOrder(models.Model): _inherit = "sale.order" website_order_line = fields.One2many( - 'sale.order.line', 'order_id', - string='Order Lines displayed on Website', readonly=True, + 'sale.order.line', + compute='_compute_website_order_line', + string='Order Lines displayed on Website', help='Order Lines to be displayed on the website. They should not be used for computation purpose.', ) cart_quantity = fields.Integer(compute='_compute_cart_info', string='Cart Quantity') @@ -36,6 +37,10 @@ class SaleOrder(models.Model): for order in self: order.can_directly_mark_as_paid = order.state in ['sent', 'sale'] and order.payment_tx_id and order.payment_acquirer_id.provider in ['transfer', 'manual'] + @api.one + def _compute_website_order_line(self): + self.website_order_line = self.order_line + @api.multi @api.depends('website_order_line.product_uom_qty', 'website_order_line.product_id') def _compute_cart_info(self): diff --git a/addons/website_sale/models/website.py b/addons/website_sale/models/website.py index bb98d753590..1d6d3217811 100644 --- a/addons/website_sale/models/website.py +++ b/addons/website_sale/models/website.py @@ -168,7 +168,7 @@ class Website(models.Model): 'partner_id': partner.id, 'pricelist_id': pricelist.id, 'payment_term_id': self.sale_get_payment_term(partner), - 'team_id': self.salesteam_id.id, + 'team_id': self.salesteam_id.id or partner.parent_id.team_id.id or partner.team_id.id, 'partner_invoice_id': addr['invoice'], 'partner_shipping_id': addr['delivery'], 'user_id': salesperson_id or self.salesperson_id.id or default_user_id, diff --git a/addons/website_sale_delivery/models/sale_order.py b/addons/website_sale_delivery/models/sale_order.py index 461a70f5496..fb318b16477 100644 --- a/addons/website_sale_delivery/models/sale_order.py +++ b/addons/website_sale_delivery/models/sale_order.py @@ -17,11 +17,11 @@ class SaleOrder(models.Model): has_delivery = fields.Boolean( compute='_compute_has_delivery', string='Has delivery', help="Has an order line set for delivery", store=True) - website_order_line = fields.One2many( - 'sale.order.line', 'order_id', - string='Order Lines displayed on Website', readonly=True, - domain=[('is_delivery', '=', False)], - help='Order Lines to be displayed on the website. They should not be used for computation purpose.') + + @api.one + def _compute_website_order_line(self): + super(SaleOrder, self)._compute_website_order_line() + self.website_order_line = self.website_order_line.filtered(lambda l: not l.is_delivery) @api.depends('order_line.price_unit', 'order_line.tax_id', 'order_line.discount', 'order_line.product_uom_qty') def _compute_amount_delivery(self): |
