[FIX] account: missing tax computation in reconciliation

Install the accounting module, create a new payment for a customer
go to payment matching, reconcile the payment for the account
'Account recievable' and select a tax. There is a traceback
because of a incomplete implementation of the tax computation.

This commit complete the implementation and add the missing tests.

opw-1903172

closes odoo/odoo#28591
This commit is contained in:
Julien (juc) Castiaux
2018-11-19 08:55:56 +00:00
parent 7765689f63
commit ccd1552b83
2 changed files with 154 additions and 16 deletions
@@ -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':
@@ -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();
});
});
});