[FIX] account: reconciliation model support tags in widget
Activate analytic tags Create an reconciliation model on which you set at least one tag Create a bank statement and a line Click on reconcile (or access the reconciliation widget by another means) Quick Create a writeoff line Click on the button corresponding to the reconciliation model Before this commit: The many2many tags was buggy, there was one empty tag, corresponding to nothing clicking on the field triggered errors validating the reconciliation by clicking on reconcile triggered a server traceback in the real backend, opening the tag form view triggered an access error This was because the data were not formatted the right way to be passed to the m2m_tag_field through notifyChanges After this commit, the reconciliation model's tag renders and behaves well Validating the reconciliation works OPW 2033350 As a side note, in the future, the reconciliation widget Model should fully implement basicModel or not at all. Some of the heavy plumbing that the ReconciliationModel does (fetch records, data...) is imitating what fetchRecord does closes odoo/odoo#34838 Signed-off-by: Lucas Perais (lpe) <lpe@odoo.com>
This commit is contained in:
@@ -384,14 +384,7 @@ var StatementModel = BasicModel.extend({
|
||||
if (context && context.active_model === 'account.journal' && context.active_ids) {
|
||||
domainReconcile.push(['journal_id', 'in', [false].concat(context.active_ids)]);
|
||||
}
|
||||
var def_reconcileModel = this._rpc({
|
||||
model: 'account.reconcile.model',
|
||||
method: 'search_read',
|
||||
domain: domainReconcile,
|
||||
})
|
||||
.then(function (reconcileModels) {
|
||||
self.reconcileModels = reconcileModels;
|
||||
});
|
||||
var def_reconcileModel = this._loadReconciliationModel({domainReconcile: domainReconcile});
|
||||
var def_account = this._rpc({
|
||||
model: 'account.account',
|
||||
method: 'search_read',
|
||||
@@ -411,7 +404,59 @@ var StatementModel = BasicModel.extend({
|
||||
return self._formatLine(self.statement.lines);
|
||||
});
|
||||
},
|
||||
|
||||
_readAnalyticTags: function (params) {
|
||||
var self = this;
|
||||
this.analyticTags = {};
|
||||
if (!params || !params.res_ids || !params.res_ids.length) {
|
||||
return $.when();
|
||||
}
|
||||
var fields = (params && params.fields || []).concat(['id', 'display_name']);
|
||||
return this._rpc({
|
||||
model: 'account.analytic.tag',
|
||||
method: 'read',
|
||||
args: [
|
||||
params.res_ids,
|
||||
fields,
|
||||
],
|
||||
}).then(function (tags) {
|
||||
for (var i=0; i<tags.length; i++) {
|
||||
var tag = tags[i];
|
||||
self.analyticTags[tag.id] = tag;
|
||||
}
|
||||
});
|
||||
},
|
||||
_loadReconciliationModel: function (params) {
|
||||
var self = this;
|
||||
return this._rpc({
|
||||
model: 'account.reconcile.model',
|
||||
method: 'search_read',
|
||||
domain: params.domainReconcile || [],
|
||||
})
|
||||
.then(function (reconcileModels) {
|
||||
var analyticTagIds = [];
|
||||
for (var i=0; i<reconcileModels.length; i++) {
|
||||
var modelTags = reconcileModels[i].analytic_tag_ids || [];
|
||||
for (var j=0; j<modelTags.length; j++) {
|
||||
if (analyticTagIds.indexOf(modelTags[j]) === -1) {
|
||||
analyticTagIds.push(modelTags[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return self._readAnalyticTags({res_ids: analyticTagIds}).then(function () {
|
||||
for (var i=0; i<reconcileModels.length; i++) {
|
||||
var recModel = reconcileModels[i];
|
||||
var analyticTagData = [];
|
||||
var modelTags = reconcileModels[i].analytic_tag_ids || [];
|
||||
for (var j=0; j<modelTags.length; j++) {
|
||||
var tagId = modelTags[j];
|
||||
analyticTagData.push([tagId, self.analyticTags[tagId].display_name])
|
||||
}
|
||||
recModel.analytic_tag_ids = analyticTagData;
|
||||
}
|
||||
self.reconcileModels = reconcileModels;
|
||||
});
|
||||
});
|
||||
},
|
||||
_loadTaxes: function(){
|
||||
var self = this;
|
||||
self.taxes = {};
|
||||
@@ -949,7 +994,7 @@ var StatementModel = BasicModel.extend({
|
||||
_formatMany2ManyTags: function (value) {
|
||||
var res = [];
|
||||
for (var i=0, len=value.length; i<len; i++) {
|
||||
res[i] = {data: {'id': value[i][0], 'display_name': value[i][1]}};
|
||||
res[i] = {'id': value[i][0], 'display_name': value[i][1]};
|
||||
}
|
||||
return res;
|
||||
},
|
||||
@@ -1290,15 +1335,7 @@ var ManualModel = StatementModel.extend({
|
||||
if (company_ids) {
|
||||
domainReconcile.push(['company_id', 'in', company_ids]);
|
||||
}
|
||||
var def_reconcileModel = this._rpc({
|
||||
model: 'account.reconcile.model',
|
||||
method: 'search_read',
|
||||
domain: domainReconcile,
|
||||
})
|
||||
.then(function (reconcileModels) {
|
||||
self.reconcileModels = reconcileModels;
|
||||
});
|
||||
|
||||
var def_reconcileModel = this._loadReconciliationModel({domainReconcile: domainReconcile});
|
||||
var def_taxes = this._loadTaxes();
|
||||
|
||||
return $.when(def_reconcileModel, def_account, def_taxes).then(function () {
|
||||
|
||||
@@ -136,8 +136,14 @@ var db = {
|
||||
]
|
||||
},
|
||||
'account.analytic.tag': {
|
||||
fields: {},
|
||||
records: []
|
||||
fields: {
|
||||
id: {string: 'id', type: 'integer'},
|
||||
display_name: {string: 'display_name', type: 'char'},
|
||||
},
|
||||
records: [
|
||||
{id: 1, display_name: 'Come together'},
|
||||
{id: 2, display_name: 'Right now'},
|
||||
],
|
||||
},
|
||||
'account.bank.statement': {
|
||||
fields: {},
|
||||
@@ -179,7 +185,8 @@ var db = {
|
||||
second_amount: {string: "Second Amount", type: 'float', digits:0, help:"Fixed amount will count as a debit if it is negative, as a credit if it is positive.", default:100.0},
|
||||
second_tax_id: {string: "Second Tax", type: 'many2one', relation:'account.tax', domain:[('type_tax_use', '=', 'purchase')]},
|
||||
second_analytic_account_id: {string: "Second Analytic Account", type: 'many2one', relation:'account.analytic.account'},
|
||||
match_journal_ids: {string: "Journal Ids", type: 'many2many', relation: 'account.journal'}
|
||||
match_journal_ids: {string: "Journal Ids", type: 'many2many', relation: 'account.journal'},
|
||||
analytic_tag_ids: {string: 'Analytic tags', type: 'many2many', relation: 'account.analytic.tag'},
|
||||
},
|
||||
records: [
|
||||
{'second_analytic_account_id': false, 'second_amount_type': "percentage", 'second_journal_id': false, 'id': 4, 'analytic_account_id': false, 'display_name': "Int\u00e9rrets", 'rule_type': 'writeoff_button', 'second_tax_id': false, 'has_second_line': false, 'journal_id': false, 'label': false, 'second_label': false, 'second_account_id': false, 'account_id': 282, 'company_id': [1, "Demo SPRL"], 'tax_id': false, 'amount_type': "fixed", 'name': "Int\u00e9rrets", 'amount': 0.0, 'second_amount': 100.0, 'match_journal_ids': []},
|
||||
@@ -187,7 +194,7 @@ var db = {
|
||||
{'second_analytic_account_id': false, 'second_amount_type': "percentage", 'second_journal_id': false, 'id': 5, 'analytic_account_id': false, 'display_name': "Fs bank", 'rule_type': 'writeoff_button', 'second_tax_id': false, 'has_second_line': false, 'journal_id': false, 'label': false, 'second_label': false, 'second_account_id': false, 'account_id': 284, 'company_id': [1, "Demo SPRL"], 'tax_id': false, 'amount_type': "percentage", 'name': "Fs bank", 'amount': 100.0, 'second_amount': 100.0},
|
||||
{'second_analytic_account_id': false, 'second_amount_type': "percentage", 'second_journal_id': false, 'id': 8, 'analytic_account_id': false, 'display_name': "Caisse Sand.", 'rule_type': 'writeoff_button', 'second_tax_id': false, 'has_second_line': false, 'journal_id': false, 'label': "Caisse Sand.", 'second_label': false, 'second_account_id': false, 'account_id': 308, 'company_id': [1, "Demo SPRL"], 'tax_id': false, 'amount_type': "percentage", 'name': "Caisse Sand.", 'amount': 100.0, 'second_amount': 100.0, 'match_journal_ids': []},
|
||||
{'second_analytic_account_id': false, 'second_amount_type': "percentage", 'second_journal_id': false, 'id': 3, 'analytic_account_id': false, 'display_name': "ATOS", 'rule_type': 'writeoff_button', 'second_tax_id': 7, 'has_second_line': true, 'journal_id': false, 'label': "ATOS Banque", 'second_label': "ATOS Frais", 'second_account_id': 286, 'account_id': 285, 'company_id': [1, "Demo SPRL"], 'tax_id': 6, 'amount_type': "percentage", 'name': "ATOS", 'amount': 97.5, 'second_amount': 2.5},
|
||||
{'second_analytic_account_id': false, 'second_amount_type': "percentage", 'second_journal_id': false, 'id': 10, 'analytic_account_id': false, 'display_name': "Double", 'rule_type': 'writeoff_button', 'second_tax_id': false, 'has_second_line': true, 'journal_id': false, 'label': "Double Banque", 'second_label': "Double Frais", 'second_account_id': 286, 'account_id': 285, 'company_id': [1, "Demo SPRL"], 'tax_id': false, 'amount_type': "percentage", 'name': "Double", 'amount': 97.5, 'second_amount': 2.5, 'match_journal_ids': []},
|
||||
{'second_analytic_account_id': false, 'second_amount_type': "percentage", 'second_journal_id': false, 'id': 10, 'analytic_account_id': false, 'display_name': "Double", 'rule_type': 'writeoff_button', 'second_tax_id': false, 'has_second_line': true, 'journal_id': false, 'label': "Double Banque", 'second_label': "Double Frais", 'second_account_id': 286, 'account_id': 285, 'company_id': [1, "Demo SPRL"], 'tax_id': false, 'amount_type': "percentage", 'name': "Double", 'amount': 97.5, 'second_amount': 2.5, 'match_journal_ids': [], 'analytic_tag_ids': [1,2]},
|
||||
]
|
||||
},
|
||||
'account.reconciliation.widget': {
|
||||
@@ -589,6 +596,7 @@ var ReconciliationRenderer = require('account.ReconciliationRenderer');
|
||||
var demoData = require('account.reconciliation_tests.data');
|
||||
|
||||
var testUtils = require('web.test_utils');
|
||||
var testUtilsDom = require('web.test_utils_dom');
|
||||
|
||||
QUnit.module('account', {
|
||||
beforeEach: function () {
|
||||
@@ -1768,5 +1776,54 @@ QUnit.module('account', {
|
||||
|
||||
clientAction.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('Reconciliation Models handle analytic tags', function (assert) {
|
||||
assert.expect(6);
|
||||
|
||||
var clientAction = new ReconciliationClientAction.StatementAction(null, this.params.options);
|
||||
testUtils.addMockEnvironment(clientAction, {
|
||||
data: this.params.data,
|
||||
mockRPC: function (route, args) {
|
||||
if (args.method === 'process_bank_statement_line') {
|
||||
var new_aml_dicts = args.args[1][0].new_aml_dicts;
|
||||
assert.strictEqual(new_aml_dicts.length, 2);
|
||||
// I personnally judge the following use case rotten, since
|
||||
// the first and the second line wouldn't have the same tags
|
||||
assert.deepEqual(new_aml_dicts[0].analytic_tag_ids, [[6, null, [1, 2]]]);
|
||||
assert.deepEqual(new_aml_dicts[1].analytic_tag_ids, [[6, null, [2]]]);
|
||||
}
|
||||
return this._super(route, args);
|
||||
},
|
||||
session: {
|
||||
currencies: {
|
||||
3: {
|
||||
digits: [69, 2],
|
||||
position: "before",
|
||||
symbol: "$"
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
clientAction.appendTo($('#qunit-fixture'));
|
||||
|
||||
// The first reconciliation "line" is where it happens
|
||||
var widget = clientAction.widgets[0];
|
||||
|
||||
testUtilsDom.click(widget.$('.toggle_create'));
|
||||
testUtilsDom.click(widget.$('.quick_add button:contains("Double")'));
|
||||
assert.containsN(widget, '.create_analytic_tag_ids .o_field_many2manytags .badge', 2,
|
||||
'Two tags are loaded');
|
||||
assert.containsOnce(widget, '.create_analytic_tag_ids .o_field_many2manytags .badge:contains("Come together")',
|
||||
'Tags should have a name');
|
||||
assert.containsOnce(widget, '.create_analytic_tag_ids .o_field_many2manytags .badge:contains("Right now")',
|
||||
'Tags should have a name');
|
||||
|
||||
testUtilsDom.click(widget.$('.create_analytic_tag_ids .o_field_many2manytags .badge a.o_delete:first()'));
|
||||
|
||||
testUtilsDom.click(widget.$('.o_reconcile'));
|
||||
|
||||
clientAction.destroy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user