diff --git a/addons/account/static/src/js/reconciliation/reconciliation_model.js b/addons/account/static/src/js/reconciliation/reconciliation_model.js index 3c9174546cf..b3e6d56c2f4 100644 --- a/addons/account/static/src/js/reconciliation/reconciliation_model.js +++ b/addons/account/static/src/js/reconciliation/reconciliation_model.js @@ -399,20 +399,7 @@ var StatementModel = BasicModel.extend({ .then(function (accounts) { self.accounts = _.object(_.pluck(accounts, 'id'), _.pluck(accounts, 'code')); }); - self.taxes = {}; - var def_taxes = this._rpc({ - model: 'account.tax', - method: 'search_read', - fields: ['price_include', 'amount_type'], - }) - .then(function (taxes) { - _.each(taxes, function(tax){ - self.taxes[tax.id] = { - price_include: tax.price_include, - amount_type: tax.amount_type, - } - }) - }); + var def_taxes = self._loadTaxes(); return $.when(def_statement, def_reconcileModel, def_account, def_taxes).then(function () { _.each(self.lines, function (line) { line.reconcileModels = self.reconcileModels; @@ -423,6 +410,23 @@ var StatementModel = BasicModel.extend({ return self._formatLine(self.statement.lines); }); }, + + _loadTaxes: function(){ + var self = this; + self.taxes = {}; + return this._rpc({ + model: 'account.tax', + method: 'search_read', + fields: ['price_include', 'amount_type'], + }).then(function (taxes) { + _.each(taxes, function(tax){ + self.taxes[tax.id] = { + price_include: tax.price_include, + amount_type: tax.amount_type, + } + }) + }); + }, /** * Load more bank statement line * @@ -1275,7 +1279,9 @@ var ManualModel = StatementModel.extend({ self.reconcileModels = reconcileModels; }); - return $.when(def_reconcileModel, def_account).then(function () { + var def_taxes = this._loadTaxes(); + + return $.when(def_reconcileModel, def_account, def_taxes).then(function () { switch(context.mode) { case 'customers': case 'suppliers': diff --git a/addons/account/static/tests/reconciliation_tests.js b/addons/account/static/tests/reconciliation_tests.js index 6feac45cf0a..6cf6d5b400e 100644 --- a/addons/account/static/tests/reconciliation_tests.js +++ b/addons/account/static/tests/reconciliation_tests.js @@ -113,7 +113,9 @@ var db = { display_name: {string: "Displayed name", type: 'char'}, company_id: {string: "Company", type: 'many2one', relation: 'res.company'}, }, - records: [] + records: [ + {id: 8, display_name: "company 1 journal", company_id: 1} + ] }, 'account.analytic.account': { fields: { @@ -1620,5 +1622,135 @@ QUnit.module('account', { clientAction.destroy(); }); + + QUnit.test('Tax on account receivable', function(assert){ + assert.expect(21); + + delete this.params.data_for_manual_reconciliation_widget['[null,null]'].accounts; + var clientAction = new ReconciliationClientAction.ManualAction(null, this.params.options); + testUtils.addMockEnvironment(clientAction, { + data: this.params.data, + session: {}, + mockRPC: function(route, args) { + if (args.method === "name_search") { + switch (args.model) { + // mock the default mock to do the minimal processing required + // to get the available values for the droplists. + case 'account.account': + assert.step("Account"); + return $.when( + _.map(this.data[args.model].records, function (record) { + return [record.id, record.name]; + }) + ); + case 'account.tax': + assert.step("Tax"); + return $.when( + _.map(this.data[args.model].records, function (record) { + return [record.id, record.display_name]; + }) + ); + case 'account.journal': + assert.step("Journal"); + return $.when( + _.map(this.data[args.model].records, function (record) { + return [record.id, record.display_name]; + }) + ); + } + } + if (args.method === 'process_move_lines') { + var mv_line_ids = args.args[0][0].mv_line_ids.slice(0); + mv_line_ids.sort(function(a, b) {return a - b}); + assert.deepEqual(mv_line_ids, [6, 19, 21], + "Reconciliation rpc payload, mv_line_ids are correct"); + + // Index aiming at the correct object in the list + var idx = _.has(args.args[0][0].new_mv_line_dicts[0], 'journal_id') ? 0 : 1; + assert.deepEqual( + _.pick(args.args[0][0].new_mv_line_dicts[idx], + 'account_id', 'name', 'credit', 'debit', 'journal_id'), + {account_id: 287, name: "dummy text", credit: 0, debit: 180, journal_id: 8}, + "Reconciliation rpc payload, new_mv_line_dicts.gift is correct" + ); + assert.deepEqual( + _.pick(args.args[0][0].new_mv_line_dicts[1 - idx], + 'account_id', 'name', 'credit', 'debit', 'tax_line_id'), + {account_id: 287, name: "Tax 20.00%", credit: 0, debit: 36, tax_line_id: 6}, + "Reconciliation rpc payload, new_mv_line_dicts.tax is correct" + ); + } + return this._super.apply(this, arguments); + } + }); + + clientAction.appendTo($('#qunit-fixture')); + + var widget = clientAction.widgets[0]; + + // Select invoice of 1k$, payment of 1k$ and payment of 180$ + var $tableToReconcile = widget.$('.match'); + _.each([6, 19, 21], function(id) { + $tableToReconcile.find('tr.mv_line[data-line-id='+id+']:first td:first-child').click(); + }); + + assert.verifySteps([], "No rpc done"); + + // Store the money in excess to the "account receivable" account with 20% taxes + widget.$("table tfoot tr td:first").click(); + var $reconcileForm = widget.$(".create"); + $reconcileForm.find('.create_account_id input').click(); + $('.ui-autocomplete .ui-menu-item a:contains(101200 Account Receivable)') + .trigger('mouseover') + .trigger('click'); + assert.verifySteps(["Account"], "Account rpc done"); + + $reconcileForm.find('.create_tax_id input').click(); + $('.ui-autocomplete .ui-menu-item a:contains(Tax 20.00%)') + .trigger('mouseover') + .trigger('click'); + assert.verifySteps(["Account", "Tax"], "Tax rpc done"); + + $reconcileForm.find('.create_journal_id input').click(); + $('.ui-autocomplete .ui-menu-item a:contains(company 1 journal)') + .trigger('mouseover') + .trigger('click'); + $reconcileForm.find('.create_label input').val('dummy text').trigger('input'); + assert.verifySteps(["Account", "Tax", "Journal"], "Journal rpc done"); + + // Verify the two (gift + tax) lines were added to the list + var $newLines = widget.$('tr.mv_line[data-line-id^=createLine]'); + var idx = ($($($newLines[0]).find("td")[3]).text().trim() === "dummy text") ? 0 : 1; + + var $newLineGiftTds = $($newLines[idx]).find("td"); + assert.equal($($newLineGiftTds[1]).text().trim(), "101200", + "Gift line account number is valid"); + assert.equal($($newLineGiftTds[2]).text().trim(), "New", + "Gift line is flagged as new"); + assert.equal($($newLineGiftTds[3]).text().trim(), "dummy text", + "Gift line has the correct label"); + assert.equal($($newLineGiftTds[4]).text().trim(), "180.00", + "Gift line has the correct left amount"); + assert.equal($($newLineGiftTds[5]).text().trim(), "", + "Gift line has the correct right amount"); + + var $newLineTaxeTds = $($newLines[1 - idx]).find("td"); + assert.equal($($newLineTaxeTds[1]).text().trim(), "101200", + "Tax line account number is valid"); + assert.equal($($newLineTaxeTds[2]).text().trim(), "New", + "Tax line is flagged as new"); + assert.equal($($newLineTaxeTds[3]).text().trim(), "Tax 20.00%", + "Tax line has the correct label"); + assert.equal($($newLineTaxeTds[4]).text().trim(), "36.00", + "Tax line has the correct left amount"); + assert.equal($($newLineTaxeTds[5]).text().trim(), "", + "Tax line has the correct right amount"); + + // Reconcile + widget.$("button.o_reconcile.btn.btn-primary:first").click(); + assert.ok(true, "No error in reconciliation"); + + clientAction.destroy(); + }); }); });