From bc71e85c9ff6d8b03c3a68a582a4f12f713dc46d Mon Sep 17 00:00:00 2001 From: David Arnold Date: Thu, 16 Aug 2018 20:36:17 +0000 Subject: [PATCH 1/3] [FIX] point_of_sale: align with backend fp mapping The backend allows to map one source tax to various target taxes. The POS diverged from this behaviour. This commit alignes the behaviours and lets the point of sale handle mapping to multiple taxes the same way the backend does. --- addons/point_of_sale/static/src/js/models.js | 39 +++++++++++++------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/addons/point_of_sale/static/src/js/models.js b/addons/point_of_sale/static/src/js/models.js index 800b4600d00..718fc431c02 100644 --- a/addons/point_of_sale/static/src/js/models.js +++ b/addons/point_of_sale/static/src/js/models.js @@ -1665,20 +1665,26 @@ exports.Orderline = Backbone.Model.extend({ return taxes; }, _map_tax_fiscal_position: function(tax) { + var self = this; var current_order = this.pos.get_order(); var order_fiscal_position = current_order && current_order.fiscal_position; + var taxes = []; if (order_fiscal_position) { - var mapped_tax = _.find(order_fiscal_position.fiscal_position_taxes_by_id, function (fiscal_position_tax) { + var tax_mappings = _.filter(order_fiscal_position.fiscal_position_taxes_by_id, function (fiscal_position_tax) { return fiscal_position_tax.tax_src_id[0] === tax.id; }); - if (mapped_tax) { - tax = this.pos.taxes_by_id[mapped_tax.tax_dest_id[0]]; + if (tax_mappings) { + _.each(tax_mappings, function(tm) { + taxes.push(self.pos.taxes_by_id[tm.tax_dest_id[0]]); + }); } + } else { + taxes.push(tax); } - return tax; + return taxes; }, _compute_all: function(tax, base_amount, quantity) { if (tax.amount_type === 'fixed') { @@ -1706,13 +1712,18 @@ exports.Orderline = Backbone.Model.extend({ var total_excluded = round_pr(price_unit * quantity, currency_rounding); var total_included = total_excluded; var base = total_excluded; - _(taxes).each(function(tax) { - if (!no_map_tax){ - tax = self._map_tax_fiscal_position(tax); - } - if (!tax){ - return; - } + var taxes_mapped = []; + + if (!no_map_tax){ + _(taxes).each(function(tax){ + _(self._map_tax_fiscal_position(tax)).each(function(tax){ + taxes_mapped.push(tax); + }); + }); + } else { + taxes_mapped = taxes; + } + _(taxes_mapped).each(function(tax) { if (tax.amount_type === 'group'){ var ret = self.compute_all(tax.children_tax_ids, price_unit, quantity, currency_rounding); total_excluded = ret.total_excluded; @@ -2285,12 +2296,12 @@ exports.Order = Backbone.Model.extend({ var taxes = line.get_taxes(); var mapped_included_taxes = []; _(taxes).each(function(tax) { - var line_tax = line._map_tax_fiscal_position(tax); - if(tax.price_include && tax.id != line_tax.id){ + var line_taxes = line._map_tax_fiscal_position(tax); + if(tax.price_include && _.contains(line_taxes, tax)){ mapped_included_taxes.push(tax); } - }) + }); if (mapped_included_taxes.length > 0) { unit_price = line.compute_all(mapped_included_taxes, unit_price, 1, this.pos.currency.rounding, true).total_excluded; From 202ed1bf7d480f1c2744924fb314fc840c612fe4 Mon Sep 17 00:00:00 2001 From: David Arnold Date: Thu, 16 Aug 2018 22:57:08 +0000 Subject: [PATCH 2/3] [IMP] account: add fp2m unit test --- addons/account/tests/test_fiscal_position.py | 24 ++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/addons/account/tests/test_fiscal_position.py b/addons/account/tests/test_fiscal_position.py index 320c94cca80..ded27e530a9 100644 --- a/addons/account/tests/test_fiscal_position.py +++ b/addons/account/tests/test_fiscal_position.py @@ -125,3 +125,27 @@ class TestFiscalPosition(common.TransactionCase): # Dedicated position has max precedence george.property_account_position_id = self.be_nat assert_fp(george, self.be_nat, "Forced position has max precedence") + + + def test_20_fp_one_tax_2m(self): + + self.src_tax = self.env['account.tax'].create({'name': "SRC", 'amount': 0.0}) + self.dst1_tax = self.env['account.tax'].create({'name': "DST1", 'amount': 0.0}) + self.dst2_tax = self.env['account.tax'].create({'name': "DST2", 'amount': 0.0}) + + self.fp2m = self.fp.create({ + 'name': "FP-TAX2TAXES", + 'tax_ids': [ + (0,0,{ + 'tax_src_id': self.src_tax.id, + 'tax_dest_id': self.dst1_tax.id + }), + (0,0,{ + 'tax_src_id': self.src_tax.id, + 'tax_dest_id': self.dst2_tax.id + }) + ] + }) + mapped_taxes = self.fp2m.map_tax(self.src_tax) + + self.assertEqual(mapped_taxes, self.dst1_tax | self.dst2_tax) From 453f957d8d15d925009830d9d5f4f83bf688b604 Mon Sep 17 00:00:00 2001 From: David Arnold Date: Sun, 19 Aug 2018 19:26:46 +0000 Subject: [PATCH 3/3] [ADD] point_of_sale: js test for 2m fp --- addons/point_of_sale/static/src/js/tests.js | 20 ++++++++++++++++++++ addons/point_of_sale/static/src/xml/pos.xml | 2 +- addons/point_of_sale/tests/test_frontend.py | 15 +++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/addons/point_of_sale/static/src/js/tests.js b/addons/point_of_sale/static/src/js/tests.js index 2048d3d8271..59738e08179 100644 --- a/addons/point_of_sale/static/src/js/tests.js +++ b/addons/point_of_sale/static/src/js/tests.js @@ -230,6 +230,20 @@ odoo.define('point_of_sale.tour.acceptance', function (require) { }]; } + function set_fiscal_position_on_order(fp_name) { + return [{ + content: 'set fiscal position', + trigger: '.control-button.o_fiscal_position_button', + }, { + content: 'choose fiscal position ' + fp_name + ' to add to the order', + trigger: '.popups .popup .selection .selection-item:contains("' + fp_name + '")', + }, { + content: 'the fiscal position ' + fp_name + ' has been set to the order', + trigger: '.control-button.o_fiscal_position_button:contains("' + fp_name + '")', + run: function () {}, // it's a check + }]; + } + function generate_keypad_steps(amount_str, keypad_selector) { var i, steps = [], current_char; for (i = 0; i < amount_str.length; ++i) { @@ -321,6 +335,12 @@ odoo.define('point_of_sale.tour.acceptance', function (require) { steps = steps.concat(generate_payment_screen_keypad_steps("10")); steps = steps.concat(finish_order()); + // Test fiscal position one2many map (align with backend) + steps = steps.concat(add_product_to_order('Letter Tray')); + steps = steps.concat(verify_order_total('5.28')); + steps = steps.concat(set_fiscal_position_on_order('FP-POS-2M')); + steps = steps.concat(verify_order_total('5.52')); + steps = steps.concat([{ content: "close the Point of Sale frontend", trigger: ".header-button", diff --git a/addons/point_of_sale/static/src/xml/pos.xml b/addons/point_of_sale/static/src/xml/pos.xml index fcfc7981155..d427f310b7f 100644 --- a/addons/point_of_sale/static/src/xml/pos.xml +++ b/addons/point_of_sale/static/src/xml/pos.xml @@ -124,7 +124,7 @@ -
+
diff --git a/addons/point_of_sale/tests/test_frontend.py b/addons/point_of_sale/tests/test_frontend.py index 4cbb3e79996..6e178919ed3 100644 --- a/addons/point_of_sale/tests/test_frontend.py +++ b/addons/point_of_sale/tests/test_frontend.py @@ -265,7 +265,22 @@ class TestUi(odoo.tests.HttpCase): all_pricelists = env['product.pricelist'].search([('id', '!=', excluded_pricelist.id)]) all_pricelists.write(dict(currency_id=main_company.currency_id.id)) + src_tax = env['account.tax'].create({'name': "SRC", 'amount': 10}) + dst_tax = env['account.tax'].create({'name': "DST", 'amount': 5}) + + env.ref('point_of_sale.letter_tray').taxes_id = [(6, 0, [src_tax.id])] + + main_pos_config.write({ + 'tax_regime_selection': True, + 'fiscal_position_ids': [(0, 0, { + 'name': "FP-POS-2M", + 'tax_ids': [ + (0,0,{'tax_src_id': src_tax.id, + 'tax_dest_id': src_tax.id}), + (0,0,{'tax_src_id': src_tax.id, + 'tax_dest_id': dst_tax.id})] + })], 'journal_id': test_sale_journal.id, 'invoice_journal_id': test_sale_journal.id, 'journal_ids': [(0, 0, {'name': 'Cash Journal - Test',