diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py index 71e34b94a2..2295a012d6 100644 --- a/addons/account/models/account_move.py +++ b/addons/account/models/account_move.py @@ -882,6 +882,7 @@ class AccountMove(models.Model): 'name': _('%s (rounding)', biggest_tax_line.name), 'account_id': biggest_tax_line.account_id.id, 'tax_repartition_line_id': biggest_tax_line.tax_repartition_line_id.id, + 'tax_tag_ids': [(6, 0, biggest_tax_line.tax_tag_ids.ids)], 'tax_exigible': biggest_tax_line.tax_exigible, 'exclude_from_invoice_tab': True, }) diff --git a/addons/account/tests/test_account_move_in_invoice.py b/addons/account/tests/test_account_move_in_invoice.py index 8540107b6d..74d24c9ebf 100644 --- a/addons/account/tests/test_account_move_in_invoice.py +++ b/addons/account/tests/test_account_move_in_invoice.py @@ -857,6 +857,7 @@ class TestAccountMoveInInvoiceOnchanges(AccountTestInvoicingCommon): }) def test_in_invoice_line_onchange_cash_rounding_1(self): + # Test 'add_invoice_line' rounding move_form = Form(self.invoice) # Add a cash rounding having 'add_invoice_line'. move_form.invoice_cash_rounding_id = self.cash_rounding_a @@ -911,12 +912,45 @@ class TestAccountMoveInInvoiceOnchanges(AccountTestInvoicingCommon): self.term_line_vals_1, ], self.move_vals) - move_form = Form(self.invoice) - # Change the cash rounding to one having 'biggest_tax'. - move_form.invoice_cash_rounding_id = self.cash_rounding_b - move_form.save() + # Test 'biggest_tax' rounding - self.assertInvoiceValues(self.invoice, [ + self.company_data['company'].country_id = self.env.ref('base.us') + + # Add a tag to product_a's default tax + tax_line_tag = self.env['account.account.tag'].create({ + 'name': "Tax tag", + 'applicability': 'taxes', + 'country_id': self.company_data['company'].country_id.id, + }) + + repartition_line = self.tax_purchase_a.invoice_repartition_line_ids.filtered(lambda x: x.repartition_type == 'tax') + repartition_line.write({'tag_ids': [(4, tax_line_tag.id, 0)]}) + + # Create the invoice + biggest_tax_invoice = self.env['account.move'].create({ + 'move_type': 'in_invoice', + 'invoice_date': '2019-01-01', + 'partner_id': self.partner_a.id, + 'invoice_cash_rounding_id': self.cash_rounding_b.id, + 'invoice_payment_term_id': self.pay_terms_a.id, + 'invoice_line_ids': [ + (0, 0, { + 'product_id': self.product_a.id, + 'price_unit': 799.99, + 'tax_ids': [(6, 0, self.product_a.supplier_taxes_id.ids)], + 'product_uom_id': self.product_a.uom_id.id, + }), + + (0, 0, { + 'product_id': self.product_b.id, + 'price_unit': self.product_b.standard_price, + 'tax_ids': [(6, 0, self.product_b.supplier_taxes_id.ids)], + 'product_uom_id': self.product_b.uom_id.id, + }), + ], + }) + + self.assertInvoiceValues(biggest_tax_invoice, [ { **self.product_line_vals_1, 'price_unit': 799.99, @@ -924,10 +958,24 @@ class TestAccountMoveInInvoiceOnchanges(AccountTestInvoicingCommon): 'price_total': 919.99, 'amount_currency': 799.99, 'debit': 799.99, + 'tax_repartition_line_id': None, + 'tax_tag_ids': [], + }, + { + **self.product_line_vals_2, + 'tax_repartition_line_id': None, + 'tax_tag_ids': [], + }, + { + **self.tax_line_vals_1, + 'tax_repartition_line_id': repartition_line.id, + 'tax_tag_ids': tax_line_tag.ids, + }, + { + **self.tax_line_vals_2, + 'tax_repartition_line_id': self.tax_purchase_b.invoice_repartition_line_ids.filtered(lambda x: x.repartition_type == 'tax').id, + 'tax_tag_ids': [], }, - self.product_line_vals_2, - self.tax_line_vals_1, - self.tax_line_vals_2, { 'name': '%s (rounding)' % self.tax_purchase_a.name, 'product_id': False, @@ -941,6 +989,8 @@ class TestAccountMoveInInvoiceOnchanges(AccountTestInvoicingCommon): 'price_total': -0.04, 'tax_ids': [], 'tax_line_id': self.tax_purchase_a.id, + 'tax_repartition_line_id': repartition_line.id, + 'tax_tag_ids': tax_line_tag.ids, 'currency_id': self.company_data['currency'].id, 'amount_currency': -0.04, 'debit': 0.0, @@ -955,6 +1005,8 @@ class TestAccountMoveInInvoiceOnchanges(AccountTestInvoicingCommon): 'price_total': -1127.95, 'amount_currency': -1127.95, 'credit': 1127.95, + 'tax_repartition_line_id': None, + 'tax_tag_ids': [], }, ], { **self.move_vals, diff --git a/addons/account/tests/test_account_move_in_refund.py b/addons/account/tests/test_account_move_in_refund.py index e459eb4c65..3d01654736 100644 --- a/addons/account/tests/test_account_move_in_refund.py +++ b/addons/account/tests/test_account_move_in_refund.py @@ -539,6 +539,7 @@ class TestAccountMoveInRefundOnchanges(AccountTestInvoicingCommon): }) def test_in_refund_line_onchange_cash_rounding_1(self): + # Test 'add_invoice_line' rounding move_form = Form(self.invoice) # Add a cash rounding having 'add_invoice_line'. move_form.invoice_cash_rounding_id = self.cash_rounding_a @@ -593,12 +594,45 @@ class TestAccountMoveInRefundOnchanges(AccountTestInvoicingCommon): self.term_line_vals_1, ], self.move_vals) - move_form = Form(self.invoice) - # Change the cash rounding to one having 'biggest_tax'. - move_form.invoice_cash_rounding_id = self.cash_rounding_b - move_form.save() + # Test 'biggest_tax' rounding - self.assertInvoiceValues(self.invoice, [ + self.company_data['company'].country_id = self.env.ref('base.us') + + # Add a tag to product_a's default tax + tax_line_tag = self.env['account.account.tag'].create({ + 'name': "Tax tag", + 'applicability': 'taxes', + 'country_id': self.company_data['company'].country_id.id, + }) + + repartition_line = self.tax_purchase_a.refund_repartition_line_ids.filtered(lambda x: x.repartition_type == 'tax') + repartition_line.write({'tag_ids': [(4, tax_line_tag.id, 0)]}) + + # Create the invoice + biggest_tax_invoice = self.env['account.move'].create({ + 'move_type': 'in_refund', + 'invoice_date': '2019-01-01', + 'partner_id': self.partner_a.id, + 'invoice_cash_rounding_id': self.cash_rounding_b.id, + 'invoice_payment_term_id': self.pay_terms_a.id, + 'invoice_line_ids': [ + (0, 0, { + 'product_id': self.product_a.id, + 'price_unit': 799.99, + 'tax_ids': [(6, 0, self.product_a.supplier_taxes_id.ids)], + 'product_uom_id': self.product_a.uom_id.id, + }), + + (0, 0, { + 'product_id': self.product_b.id, + 'price_unit': self.product_b.standard_price, + 'tax_ids': [(6, 0, self.product_b.supplier_taxes_id.ids)], + 'product_uom_id': self.product_b.uom_id.id, + }), + ], + }) + + self.assertInvoiceValues(biggest_tax_invoice, [ { **self.product_line_vals_1, 'price_unit': 799.99, @@ -606,10 +640,24 @@ class TestAccountMoveInRefundOnchanges(AccountTestInvoicingCommon): 'price_total': 919.99, 'amount_currency': -799.99, 'credit': 799.99, + 'tax_repartition_line_id': None, + 'tax_tag_ids': [], + }, + { + **self.product_line_vals_2, + 'tax_repartition_line_id': None, + 'tax_tag_ids': [], + }, + { + **self.tax_line_vals_1, + 'tax_repartition_line_id': repartition_line.id, + 'tax_tag_ids': tax_line_tag.ids, + }, + { + **self.tax_line_vals_2, + 'tax_repartition_line_id': self.tax_purchase_b.refund_repartition_line_ids.filtered(lambda x: x.repartition_type == 'tax').id, + 'tax_tag_ids': [], }, - self.product_line_vals_2, - self.tax_line_vals_1, - self.tax_line_vals_2, { 'name': '%s (rounding)' % self.tax_purchase_a.name, 'product_id': False, @@ -623,6 +671,8 @@ class TestAccountMoveInRefundOnchanges(AccountTestInvoicingCommon): 'price_total': -0.04, 'tax_ids': [], 'tax_line_id': self.tax_purchase_a.id, + 'tax_repartition_line_id': repartition_line.id, + 'tax_tag_ids': tax_line_tag.ids, 'currency_id': self.company_data['currency'].id, 'amount_currency': 0.04, 'debit': 0.04, @@ -637,6 +687,8 @@ class TestAccountMoveInRefundOnchanges(AccountTestInvoicingCommon): 'price_total': -1127.95, 'amount_currency': 1127.95, 'debit': 1127.95, + 'tax_repartition_line_id': None, + 'tax_tag_ids': [], }, ], { **self.move_vals, diff --git a/addons/account/tests/test_account_move_out_invoice.py b/addons/account/tests/test_account_move_out_invoice.py index 49f8c90f04..2e320504af 100644 --- a/addons/account/tests/test_account_move_out_invoice.py +++ b/addons/account/tests/test_account_move_out_invoice.py @@ -1460,6 +1460,7 @@ class TestAccountMoveOutInvoiceOnchanges(AccountTestInvoicingCommon): ]) def test_out_invoice_line_onchange_cash_rounding_1(self): + # Test 'add_invoice_line' rounding move_form = Form(self.invoice) # Add a cash rounding having 'add_invoice_line'. move_form.invoice_cash_rounding_id = self.cash_rounding_a @@ -1514,12 +1515,45 @@ class TestAccountMoveOutInvoiceOnchanges(AccountTestInvoicingCommon): self.term_line_vals_1, ], self.move_vals) - move_form = Form(self.invoice) - # Change the cash rounding to one having 'biggest_tax'. - move_form.invoice_cash_rounding_id = self.cash_rounding_b - move_form.save() + # Test 'biggest_tax' rounding - self.assertInvoiceValues(self.invoice, [ + self.company_data['company'].country_id = self.env.ref('base.us') + + # Add a tag to product_a's default tax + tax_line_tag = self.env['account.account.tag'].create({ + 'name': "Tax tag", + 'applicability': 'taxes', + 'country_id': self.company_data['company'].country_id.id, + }) + + repartition_line = self.tax_sale_a.invoice_repartition_line_ids.filtered(lambda x: x.repartition_type == 'tax') + repartition_line.write({'tag_ids': [(4, tax_line_tag.id, 0)]}) + + # Create the invoice + biggest_tax_invoice = self.env['account.move'].create({ + 'move_type': 'out_invoice', + 'invoice_date': '2019-01-01', + 'partner_id': self.partner_a.id, + 'invoice_cash_rounding_id': self.cash_rounding_b.id, + 'invoice_payment_term_id': self.pay_terms_a.id, + 'invoice_line_ids': [ + (0, 0, { + 'product_id': self.product_a.id, + 'price_unit': 999.99, + 'tax_ids': [(6, 0, self.product_a.taxes_id.ids)], + 'product_uom_id': self.product_a.uom_id.id, + }), + + (0, 0, { + 'product_id': self.product_b.id, + 'price_unit': self.product_b.lst_price, + 'tax_ids': [(6, 0, self.product_b.taxes_id.ids)], + 'product_uom_id': self.product_b.uom_id.id, + }), + ], + }) + + self.assertInvoiceValues(biggest_tax_invoice, [ { **self.product_line_vals_1, 'price_unit': 999.99, @@ -1527,10 +1561,24 @@ class TestAccountMoveOutInvoiceOnchanges(AccountTestInvoicingCommon): 'price_total': 1149.99, 'amount_currency': -999.99, 'credit': 999.99, + 'tax_repartition_line_id': None, + 'tax_tag_ids': [], + }, + { + **self.product_line_vals_2, + 'tax_repartition_line_id': None, + 'tax_tag_ids': [], + }, + { + **self.tax_line_vals_1, + 'tax_repartition_line_id': repartition_line.id, + 'tax_tag_ids': tax_line_tag.ids, + }, + { + **self.tax_line_vals_2, + 'tax_repartition_line_id': self.tax_sale_b.invoice_repartition_line_ids.filtered(lambda x: x.repartition_type == 'tax').id, + 'tax_tag_ids': [], }, - self.product_line_vals_2, - self.tax_line_vals_1, - self.tax_line_vals_2, { 'name': '%s (rounding)' % self.tax_sale_a.name, 'product_id': False, @@ -1544,6 +1592,8 @@ class TestAccountMoveOutInvoiceOnchanges(AccountTestInvoicingCommon): 'price_total': -0.04, 'tax_ids': [], 'tax_line_id': self.tax_sale_a.id, + 'tax_repartition_line_id': repartition_line.id, + 'tax_tag_ids': tax_line_tag.ids, 'currency_id': self.company_data['currency'].id, 'amount_currency': 0.04, 'debit': 0.04, @@ -1558,6 +1608,8 @@ class TestAccountMoveOutInvoiceOnchanges(AccountTestInvoicingCommon): 'price_total': -1409.95, 'amount_currency': 1409.95, 'debit': 1409.95, + 'tax_repartition_line_id': None, + 'tax_tag_ids': [], }, ], { **self.move_vals, diff --git a/addons/account/tests/test_account_move_out_refund.py b/addons/account/tests/test_account_move_out_refund.py index dca6164bc6..ca992fec1d 100644 --- a/addons/account/tests/test_account_move_out_refund.py +++ b/addons/account/tests/test_account_move_out_refund.py @@ -539,6 +539,7 @@ class TestAccountMoveOutRefundOnchanges(AccountTestInvoicingCommon): }) def test_out_refund_line_onchange_cash_rounding_1(self): + # Test 'add_invoice_line' rounding move_form = Form(self.invoice) # Add a cash rounding having 'add_invoice_line'. move_form.invoice_cash_rounding_id = self.cash_rounding_a @@ -593,12 +594,45 @@ class TestAccountMoveOutRefundOnchanges(AccountTestInvoicingCommon): self.term_line_vals_1, ], self.move_vals) - move_form = Form(self.invoice) - # Change the cash rounding to one having 'biggest_tax'. - move_form.invoice_cash_rounding_id = self.cash_rounding_b - move_form.save() + # Test 'biggest_tax' rounding - self.assertInvoiceValues(self.invoice, [ + self.company_data['company'].country_id = self.env.ref('base.us') + + # Add a tag to product_a's default tax + tax_line_tag = self.env['account.account.tag'].create({ + 'name': "Tax tag", + 'applicability': 'taxes', + 'country_id': self.company_data['company'].country_id.id, + }) + + repartition_line = self.tax_sale_a.refund_repartition_line_ids.filtered(lambda x: x.repartition_type == 'tax') + repartition_line.write({'tag_ids': [(4, tax_line_tag.id, 0)]}) + + # Create the invoice + biggest_tax_invoice = self.env['account.move'].create({ + 'move_type': 'out_refund', + 'invoice_date': '2019-01-01', + 'partner_id': self.partner_a.id, + 'invoice_cash_rounding_id': self.cash_rounding_b.id, + 'invoice_payment_term_id': self.pay_terms_a.id, + 'invoice_line_ids': [ + (0, 0, { + 'product_id': self.product_a.id, + 'price_unit': 999.99, + 'tax_ids': [(6, 0, self.product_a.taxes_id.ids)], + 'product_uom_id': self.product_a.uom_id.id, + }), + + (0, 0, { + 'product_id': self.product_b.id, + 'price_unit': self.product_b.lst_price, + 'tax_ids': [(6, 0, self.product_b.taxes_id.ids)], + 'product_uom_id': self.product_b.uom_id.id, + }), + ], + }) + + self.assertInvoiceValues(biggest_tax_invoice, [ { **self.product_line_vals_1, 'price_unit': 999.99, @@ -606,10 +640,24 @@ class TestAccountMoveOutRefundOnchanges(AccountTestInvoicingCommon): 'price_total': 1149.99, 'amount_currency': 999.99, 'debit': 999.99, + 'tax_repartition_line_id': None, + 'tax_tag_ids': [], + }, + { + **self.product_line_vals_2, + 'tax_repartition_line_id': None, + 'tax_tag_ids': [], + }, + { + **self.tax_line_vals_1, + 'tax_repartition_line_id': repartition_line.id, + 'tax_tag_ids': tax_line_tag.ids, + }, + { + **self.tax_line_vals_2, + 'tax_repartition_line_id': self.tax_sale_b.refund_repartition_line_ids.filtered(lambda x: x.repartition_type == 'tax').id, + 'tax_tag_ids': [], }, - self.product_line_vals_2, - self.tax_line_vals_1, - self.tax_line_vals_2, { 'name': '%s (rounding)' % self.tax_sale_a.name, 'product_id': False, @@ -623,6 +671,8 @@ class TestAccountMoveOutRefundOnchanges(AccountTestInvoicingCommon): 'price_total': -0.04, 'tax_ids': [], 'tax_line_id': self.tax_sale_a.id, + 'tax_repartition_line_id': repartition_line.id, + 'tax_tag_ids': tax_line_tag.ids, 'currency_id': self.company_data['currency'].id, 'amount_currency': -0.04, 'debit': 0.0, @@ -637,6 +687,8 @@ class TestAccountMoveOutRefundOnchanges(AccountTestInvoicingCommon): 'price_total': -1409.95, 'amount_currency': -1409.95, 'credit': 1409.95, + 'tax_repartition_line_id': None, + 'tax_tag_ids': [], }, ], { **self.move_vals, diff --git a/addons/account/views/account_move_views.xml b/addons/account/views/account_move_views.xml index 481efce500..4624bb91d5 100644 --- a/addons/account/views/account_move_views.xml +++ b/addons/account/views/account_move_views.xml @@ -1078,7 +1078,7 @@ widget="email" attrs="{'invisible': ['|', ('move_type', 'not in', ('in_invoice', 'in_refund')), ('invoice_source_email', '=', False)]}"/> + attrs="{'readonly': [('state','!=','draft')]}"/> @@ -1088,7 +1088,7 @@ + attrs="{'invisible': [('move_type', '!=', 'entry')], 'readonly': [('state','!=','draft')]}"/> returns the complete vat number """ dom_tom_group = self.env.ref('l10n_fr.dom-tom') is_dom_tom = company.country_id.code in dom_tom_group.country_ids.mapped('code') - if not company.vat or is_dom_tom: - return {'siren': ''} + if is_dom_tom: + return '' + elif company.country_id.code == 'FR': + if not company.vat: + raise UserError(_("Missing VAT number for company %s") % company.display_name) + elif len(company.vat) < 13 or not siren.is_valid(company.vat[4:13]): + raise UserError(_("Invalid VAT number for company %s") % company.display_name) + else: + return company.vat[4:13] else: - return {'siren': company.vat[4:13]} + return '' if not company.vat else company.vat + def generate_fec(self): self.ensure_one() @@ -383,7 +395,7 @@ class AccountFrFec(models.TransientModel): self.write({ 'fec_data': base64.encodebytes(fecvalue), # Filename = FECYYYYMMDD where YYYMMDD is the closing date - 'filename': '%sFEC%s%s.csv' % (company_legal_data['siren'], end_date, suffix), + 'filename': '%sFEC%s%s.csv' % (company_legal_data, end_date, suffix), }) # Set fiscal year lock date to the end date (not in test) diff --git a/addons/mail/models/mail_template.py b/addons/mail/models/mail_template.py index c460844568..2c2bcbf774 100644 --- a/addons/mail/models/mail_template.py +++ b/addons/mail/models/mail_template.py @@ -67,15 +67,20 @@ class MailTemplate(models.Model): help="Sidebar action to make this template available on records " "of the related document model") - @api.model - def create(self, values): - result = super().create(values) + def _fix_attachment_ownership(self): + for record in self: + record.attachment_ids.write({'res_model': record._name, 'res_id': record.id}) + return self - # fix attachment ownership - if result.attachment_ids: - result.attachment_ids.write({'res_model': self._name, 'res_id': result.id}) + @api.model_create_multi + def create(self, values_list): + return super().create(values_list)\ + ._fix_attachment_ownership() - return result + def write(self, vals): + super().write(vals) + self._fix_attachment_ownership() + return True def unlink(self): self.unlink_action() diff --git a/addons/mass_mailing/models/mailing.py b/addons/mass_mailing/models/mailing.py index ccdc140482..1a8f7b0314 100644 --- a/addons/mass_mailing/models/mailing.py +++ b/addons/mass_mailing/models/mailing.py @@ -270,18 +270,20 @@ class MassMailing(models.Model): values['name'] = "%s %s" % (values['subject'], datetime.strftime(fields.datetime.now(), tools.DEFAULT_SERVER_DATETIME_FORMAT)) if values.get('body_html'): values['body_html'] = self._convert_inline_images_to_urls(values['body_html']) - result = super().create(values) - - # fix attachment ownership - if result.attachment_ids: - result.attachment_ids.write({'res_model': self._name, 'res_id': result.id}) - - return result + return super().create(values)\ + ._fix_attachment_ownership() def write(self, values): if values.get('body_html'): values['body_html'] = self._convert_inline_images_to_urls(values['body_html']) - return super(MassMailing, self).write(values) + super().write(values) + self._fix_attachment_ownership() + return True + + def _fix_attachment_ownership(self): + for record in self: + record.attachment_ids.write({'res_model': record._name, 'res_id': record.id}) + return self @api.returns('self', lambda value: value.id) def copy(self, default=None): diff --git a/addons/point_of_sale/static/src/js/Screens/ProductScreen/CashBoxOpening.js b/addons/point_of_sale/static/src/js/Screens/ProductScreen/CashBoxOpening.js index f5a678ff46..ce492667d3 100644 --- a/addons/point_of_sale/static/src/js/Screens/ProductScreen/CashBoxOpening.js +++ b/addons/point_of_sale/static/src/js/Screens/ProductScreen/CashBoxOpening.js @@ -4,19 +4,27 @@ flectra.define('point_of_sale.CashBoxOpening', function(require) { const PosComponent = require('point_of_sale.PosComponent'); const Registries = require('point_of_sale.Registries'); const { Gui } = require('point_of_sale.Gui'); + const field_utils = require('web.field_utils'); class CashBoxOpening extends PosComponent { constructor() { super(...arguments); this.changes = {}; - this.defaultValue = this.env.pos.bank_statement.balance_start || 0; + this.defaultValue = this.env.pos.format_currency_no_symbol( + this.env.pos.bank_statement.balance_start || 0 + ); this.symbol = this.env.pos.currency.symbol; } captureChange(event) { this.changes[event.target.name] = event.target.value; } startSession() { - let cashOpening = this.changes.cashBoxValue? this.changes.cashBoxValue: this.defaultValue; + let cashOpening = this.changes.cashBoxValue ? this.changes.cashBoxValue : this.defaultValue; + try { + cashOpening = field_utils.parse.float(cashOpening); + } catch (err) { + cashOpening = NaN; + } if(isNaN(cashOpening)) { Gui.showPopup('ErrorPopup',{ 'title': 'Wrong value', diff --git a/addons/sale_stock/controllers/portal.py b/addons/sale_stock/controllers/portal.py index 0d096ef0a9..22ac7b228a 100644 --- a/addons/sale_stock/controllers/portal.py +++ b/addons/sale_stock/controllers/portal.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details. -from flectra import exceptions +from flectra import exceptions, SUPERUSER_ID from flectra.addons.sale.controllers.portal import CustomerPortal from flectra.http import request, route from flectra.tools import consteq @@ -29,8 +29,8 @@ class SaleStockPortal(CustomerPortal): except exceptions.AccessError: return request.redirect('/my') - # print report as sudo, since it require access to product, taxes, payment term etc.. and portal does not have those access rights. - pdf = request.env.ref('stock.action_report_delivery').sudo()._render_qweb_pdf([picking_sudo.id])[0] + # print report as SUPERUSER, since it require access to product, taxes, payment term etc.. and portal does not have those access rights. + pdf = request.env.ref('stock.action_report_delivery').with_user(SUPERUSER_ID)._render_qweb_pdf([picking_sudo.id])[0] pdfhttpheaders = [ ('Content-Type', 'application/pdf'), ('Content-Length', len(pdf)), diff --git a/addons/sale_stock/models/account_move.py b/addons/sale_stock/models/account_move.py index 97d8b286d4..98b298979b 100644 --- a/addons/sale_stock/models/account_move.py +++ b/addons/sale_stock/models/account_move.py @@ -29,8 +29,9 @@ class AccountMove(models.Model): if self.state == 'draft': return [] - sale_orders = self.mapped('invoice_line_ids.sale_line_ids.order_id') - stock_move_lines = sale_orders.mapped('picking_ids.move_lines.move_line_ids') + sale_lines = self.invoice_line_ids.sale_line_ids + sale_orders = sale_lines.order_id + stock_move_lines = sale_lines.move_ids.filtered(lambda r: r.state == 'done').move_line_ids # Get the other customer invoices and refunds. ordered_invoice_ids = sale_orders.mapped('invoice_ids')\ @@ -46,27 +47,33 @@ class AccountMove(models.Model): break i += 1 - # Get the previous invoice if any. + # Get the previous invoices if any. previous_invoices = ordered_invoice_ids[:self_index] - last_invoice = previous_invoices[-1] if len(previous_invoices) else None - # Get the incoming and outgoing sml between self.invoice_date and the previous invoice (if any). + # Get the incoming and outgoing sml between self.invoice_date and the previous invoice (if any) of the related product. write_dates = [wd for wd in self.invoice_line_ids.mapped('write_date') if wd] self_datetime = max(write_dates) if write_dates else None - last_write_dates = last_invoice and [wd for wd in last_invoice.invoice_line_ids.mapped('write_date') if wd] - last_invoice_datetime = max(last_write_dates) if last_write_dates else None + last_invoice_datetime = dict() + for product in self.invoice_line_ids.product_id: + last_invoice = previous_invoices.filtered(lambda inv: product in inv.invoice_line_ids.product_id) + last_invoice = last_invoice[-1] if len(last_invoice) else None + last_write_dates = last_invoice and [wd for wd in last_invoice.invoice_line_ids.mapped('write_date') if wd] + last_invoice_datetime[product] = max(last_write_dates) if last_write_dates else None + def _filter_incoming_sml(ml): if ml.state == 'done' and ml.location_id.usage == 'customer' and ml.lot_id: - if last_invoice_datetime: - return last_invoice_datetime <= ml.date <= self_datetime + last_date = last_invoice_datetime.get(ml.product_id) + if last_date: + return last_date <= ml.date <= self_datetime else: return ml.date <= self_datetime return False def _filter_outgoing_sml(ml): if ml.state == 'done' and ml.location_dest_id.usage == 'customer' and ml.lot_id: - if last_invoice_datetime: - return last_invoice_datetime <= ml.date <= self_datetime + last_date = last_invoice_datetime.get(ml.product_id) + if last_date: + return last_date <= ml.date <= self_datetime else: return ml.date <= self_datetime return False diff --git a/addons/test_mass_mailing/tests/test_performance.py b/addons/test_mass_mailing/tests/test_performance.py index 20a737327d..b6f5896fce 100644 --- a/addons/test_mass_mailing/tests/test_performance.py +++ b/addons/test_mass_mailing/tests/test_performance.py @@ -61,7 +61,7 @@ class TestMassMailPerformance(TestMassMailPerformanceBase): }) # runbot needs +51 compared to local - with self.assertQueryCount(__system__=1717, marketing=1718): # test_mass_mailing_only: 1665 - 1666 + with self.assertQueryCount(__system__=1718, marketing=1720): # test_mass_mailing_only: 1665 - 1666 mailing.action_send_mail() self.assertEqual(mailing.sent, 50) @@ -101,7 +101,7 @@ class TestMassMailBlPerformance(TestMassMailPerformanceBase): }) # runbot needs +63 compared to local - with self.assertQueryCount(__system__=1994, marketing=1995): # test_mass_mailing only: 1931 - 1932 + with self.assertQueryCount(__system__=1995, marketing=1997): # test_mass_mailing only: 1931 - 1932 mailing.action_send_mail() self.assertEqual(mailing.sent, 50)